Pular para o conteúdo

Classificador de clientes

Treinar, medir no que o modelo não viu, e explicar o que ele aprendeu.

O erro mais caro em aprendizado de máquina não é o modelo ruim: é o modelo medido nos mesmos dados em que treinou, que parece ótimo até a primeira semana em produção. Este projeto separa antes de olhar, mede no conjunto de teste e compara com a linha de base — “sempre responder a classe mais comum” — que é o número que o modelo precisa bater.

PeçaO que ela exercita
ML.dividirseparar treino e teste antes de tudo
ML.florestao modelo
ML.avaliaracurácia e F1 no que ele não viu
a linha de baseo número que ele precisa bater

Estrutura#

text
churn/
  src/
    dados.df       ler e limpar
    treinar.df     dividir, treinar, avaliar
    prever.df      carregar o modelo salvo e responder
  modelos/         o .json treinado (versionado com a data)
  tests/
forge.toml
[project]
name = "churn"
version = "0.1.0"
description = "Classificador de cancelamento"
entry = "src/main.df"
dataforge = ">=1.1"

[dependencies]

[scripts]
start = "run src/main.df"
test = "test tests/"

O núcleo#

Este bloco roda sozinho — copie para um arquivo e rode dataforge run. Ele termina com assert, e é assim que esta página é conferida a cada build.

src/treinar.df
adopt Arcane.Cortex as ML

// Dados sinteticos: quem visita pouco e tem plano barato cancela mais.
clientes := []
cycle i from 1 to 240:
    visitas := i % 12
    plano := [29, 59, 99][i % 3]
    cancela := "sim" given visitas smaller 4 and plano is 29 otherwise "nao"
    clientes.append({"visitas": visitas, "plano": plano, "meses": i % 24, "cancela": cancela})

treino, teste := ML.dividir(clientes, 0.25, 42, "cancela")
modelo := ML.floresta(treino, "cancela", ["visitas", "plano", "meses"], 20)
r := ML.avaliar(modelo, teste)

// A linha de base: responder sempre a classe mais comum.
nao := len(teste >> sift c: c["cancela"] is "nao")
base := nao / len(teste)
out $"acuracia {round(r['acuracia'], 3)} contra linha de base {round(base, 3)}"

assert r["acuracia"] bigger base
assert len(treino) + len(teste) is len(clientes)

O teste#

No projeto, a regra mora em src/ e o teste a importa pelo caminho relativo — dataforge test tests/ descobre o arquivo sozinho.

tests/nucleo_test.df
adopt ../src/treinar as T

crucible "modelo":
    trial "ganha da linha de base":
        expect T.r["acuracia"] bigger T.base

    trial "nenhum cliente fica de fora da divisao":
        expect len(T.treino) + len(T.teste) is len(T.clientes)

As decisões#

DecisãoSem ela
dividir antes de olhara acurácia de 99% é memória, não aprendizado
semente fixa (42)cada execução dá um número, e ninguém sabe se melhorou
comparar com a linha de base90% de acerto num conjunto com 90% de “não” não aprendeu nada
estratificar pela classeo teste sai sem nenhum “sim”, e o F1 não tem o que medir

Para ir além#

  • Importância de cada variável e matriz de confusão: ML.
  • Salvar e versionar o modelo: ML.salvar com a data no nome.
  • Os açúcares train e predict da linguagem: Arcane.Cortex.

Volte para todos os tipos de projeto.