Coleção aprendizado

Separar treino e teste

Divide as linhas em duas tabelas reprodutivelmente e pode preservar a proporção de cada classe.

O que o bloco faz

Divide as linhas em duas tabelas reprodutivelmente e pode preservar a proporção de cada classe.

Antes de continuar

Termos que esta página usa, em poucas palavras. As definições completas estão no glossário.

Amostra
A parte da população que é de fato observada. Quando é sorteada com probabilidades conhecidas, permite estimar características da população e medir a incerteza dessa estimativa.
Estrato
Um grupo da população definido antes do sorteio (região, porte, turno), dentro do qual se sorteia separadamente. Estratificar garante que todos os grupos apareçam na amostra e costuma reduzir a variância quando as unidades de um mesmo estrato se parecem.
Treino e teste
Dividir os dados em uma parte para ajustar o modelo (treino) e outra, guardada, para medir o desempenho (teste). O teste só é honesto se o modelo nunca o viu durante o ajuste.
Validação cruzada
Repetir a divisão treino/teste várias vezes, cada vez deixando uma parte diferente dos dados de fora, e fazer a média do desempenho. Dá uma estimativa mais estável do erro em dados novos do que uma única divisão.
Vazamento de dados
Quando informação que não estaria disponível na hora de prever entra no ajuste do modelo, por exemplo dados do conjunto de teste usados para padronizar variáveis. O desempenho medido fica melhor do que o real.

Quando usar

Reserve um conjunto de teste antes do ajuste para estimar desempenho em linhas não usadas no treino.

Pressupostos

  • A estratégia de divisão respeita a dependência entre linhas: aleatoria supõe linhas independentes; com medidas no tempo o teste deve ser todo posterior ao treino (temporal), e com várias linhas do mesmo indivíduo, lote ou área nenhum grupo pode cair dos dois lados (grupo). Senão o teste mede memorização, não generalização (Roberts et al. 2017).

    Se falhar: Troque estrategia para temporal (com ordem) ou grupo (com grupo) e use a mesma no ml/tune.

  • Na divisão temporal, o teste representa o futuro em que o modelo será usado: o corte no tempo cai onde a proporção pede, com instantes empatados todos do mesmo lado.

    Se falhar: Se houver mudança de regime depois do corte, o teste mede também essa mudança; leia o desempenho junto do período.

  • Na divisão grupo, proporcao é a fração dos grupos; com grupos de tamanhos muito diferentes, a fração das linhas pode se afastar dela, e a estratificação por classe não é feita.

    Verificar:Agrupar e resumir

    Se falhar: Conte linhas e classes por lado no data/group_summarise; se uma classe faltar no teste, mude a semente ou a proporção.

  • As saídas levam a proveniência (atributo tr_ml_origem: papel treino/teste, um id da divisão e as impressões digitais das linhas do teste, com a contagem de cópias): ajustar no teste, ou numa tabela que junta treino e teste, é recusado; prever o teste com um modelo que viu linhas dele no ajuste é recusado; avaliar o treino, ou um teste misturado a linhas de fora, exige permitir_treino — o vazamento treino-teste de Kaufman et al. (2012) barrado por construção. A marca sobrevive ao cache, a filtros e a colunas novas.

    Se falhar: Faça a divisão sempre no ml/split, antes de qualquer escolha.

  • A marca não cobre: juntar com o teste à direita (data/join com o teste como segunda tabela), remodelar (pivot_longer/pivot_wider), recriar a tabela à mão, reescrever ou tirar colunas da divisão, e dividir fora do ml/split. Nesses casos os blocos seguem como sem marca.

    Se falhar: Divida primeiro e transforme cada lado depois; se precisar de uma dessas operações, mantenha o teste longe dos ajustes você mesmo.

  • O resultado depende da semente: outra semente muda a divisão, os folds ou o próprio ajuste, e com poucos dados a diferença pode ser grande.

    Se falhar: Repita com outras sementes e leia a variação; não escolha a semente pelo resultado.

Configuração

resposta identifica a resposta; proporcao define a fração aproximada de treino; estratificar mantém classes nos dois lados; seed reproduz a amostra. estrategia respeita a dependência entre linhas: aleatoria (padrão) sorteia linhas; temporal põe no treino tudo até o instante da linha ⌊n · proporção⌋ na ordem de ordem (instantes empatados ficam juntos) e no teste o que vem depois; grupo sorteia ⌊G · proporção⌋ grupos inteiros de grupo, de modo que nenhum indivíduo, lote ou área aparece dos dois lados. Nas duas últimas, estratificar é ignorado.

Exemplo

d <- trama.ml::tr_ml_example("iris_binaria")
s <- trama.ml::tr_ml_split(d, resposta = "Species", proporcao = 0.75, seed = 42)
nrow(s$treino); nrow(s$teste)

# Dados com tempo: todo o teste é posterior ao treino.
e <- data.frame(dia = rep(1:20, each = 3), y = factor(rep(c("a", "b"), 30)), x = 1:60)
t <- trama.ml::tr_ml_split(e, resposta = "y", proporcao = 0.7, estrategia = "temporal", ordem = "dia")
range(t$treino$dia); range(t$teste$dia)   # 1-14 e 15-20

Como interpretar

As saídas treino e teste não duplicam nem perdem linhas. A proporção final pode variar por arredondamento em cada classe.

Proveniência: o teste fica isolado por construção

As duas saídas levam uma marca (atributo tr_ml_origem, com o papel treino/teste, um id da divisão e as impressões digitais das linhas do teste) que sobrevive ao cache e a filtros ou colunas novas. A impressão é um hash (xxHash64) do conteúdo de cada linha nas colunas da divisão, guardado com a contagem de cópias — assim uma linha repetida que o sorteio pôs dos dois lados não é confundida com uma linha do teste que voltou ao treino. Todo modelo guarda as impressões das suas linhas de treino. Com isso:

  • ajustar um modelo, o ml/tune ou o ml/nested_cv na saída teste é recusado (tr_ml_error_test_leak), e também numa tabela que junta treino e teste (rbind, bind_rows, data/bind_rows), mesmo que ela venha com a marca de treino;
  • o ml/predict recusa prever o teste com um modelo que viu linhas dele no ajuste — por exemplo, ajustado na tabela inteira antes de dividir, ou numa cópia do teste sem a marca (tr_ml_error_test_leak) — e o teste de outra divisão com um modelo ajustado no treino desta (tr_ml_error_split_mismatch);
  • ml/evaluate, ml/confusion, ml/roc e ml/pr_curve recusam previsões das linhas de treino, e também uma tabela marcada como teste que traz linhas de fora dele (previsões do treino juntadas às do teste, ou o teste repetido) (tr_ml_error_train_eval), a menos que se ligue permitir_treino — aí o resultado sai com a nota “avaliação no treino é otimista”.

Custo: em 100 mil linhas, calcular as impressões leva cerca de 1 segundo e ocupa uns 7 MB no modelo; os folds internos do ml/tune não as recalculam.

O que a marca não cobre

A marca é um atributo: só viaja quando a operação copia os atributos da tabela que o leva, e a impressão só confere quando as colunas da divisão continuam lá com os mesmos valores. Ficam de fora, por construção:

  • juntar com o teste à direita — data/join ou left_join(outra, teste) ficam com os atributos de outra, sem marca;
  • remodelar — pivot_longer/pivot_wider mudam o que é uma linha e as colunas;
  • recriar à mão — copiar os valores para uma tabela nova, exportar para planilha e ler de volta;
  • reescrever ou tirar colunas da divisão — arredondar, converter para texto, select que remove uma coluna: as impressões deixam de conferir e só a checagem de papel continua;
  • dividir fora do ml/split.

Nesses casos os blocos seguem como sem marca: não têm como saber de onde vieram as linhas, e o isolamento fica com você. Divida primeiro, no ml/split, e só então transforme cada lado.

Implementação

  • trama.ml::tr_ml_split() versão 0.5.7Implementação própria: sorteio estratificado pela classe (aleatoria); corte no instante da linha floor(n·proporção) na ordem do tempo, todas as linhas até ele no treino (temporal); sorteio de floor(G·proporção) grupos inteiros (grupo); proveniência por atributo e impressões digitais xxHash64 das linhas do teste (cli).

No código O bloco chama trama.ml::tr_ml_split(), em trama.ml/R/workflow.R:30.

A conta é implementada pelo próprio trama, sem um pacote R de referência por trás.

Referências

Teoria

  • Kaufman, S.; Rosset, S.; Perlich, C.; Stitelman, O. (2012). Leakage in data mining: Formulation, detection, and avoidance. ACM Transactions on Knowledge Discovery from Data, 6(4), 1-21. doi:10.1145/2382577.2382579
  • Roberts, D. R.; Bahn, V.; Ciuti, S.; Boyce, M. S.; Elith, J.; Guillera-Arroita, G.; Hauenstein, S.; Lahoz-Monfort, J. J.; Schröder, B.; Thuiller, W.; Warton, D. I.; Wintle, B. A.; Hartig, F.; Dormann, C. F. (2017). Cross-validation strategies for data with temporal, spatial, hierarchical, or phylogenetic structure. Ecography, 40(8), 913-929. doi:10.1111/ecog.02881
  • Tashman, L. J. (2000). Out-of-sample tests of forecasting accuracy: an analysis and review. International Journal of Forecasting, 16(4), 437-450. doi:10.1016/S0169-2070(00)00065-0

Livro-texto

Ver a bibliografia completa do trama