O TensorFlow Decision Forests ( TF-DF ) é uma coleção de algoritmos Decision Forest ( DF ) disponíveis no TensorFlow. As Florestas de Decisão funcionam de maneira diferente das Redes Neurais ( NN ): os DFs geralmente não treinam com retropropagação ou em mini-lotes. Portanto, os pipelines TF-DF têm algumas diferenças em relação a outros pipelines do TensorFlow.
Este documento é uma lista dessas diferenças e um guia para atualizar os pipelines do TF para usar o TF-DF
Este documento pressupõe familiaridade com o colab iniciante .
Conjunto de dados e recursos
Conjunto de dados de validação
Ao contrário do paradigma de treinamento de rede neural padrão, os modelos TF-DF não precisam de um conjunto de dados de validação para monitorar o overfitting ou interromper o treinamento antecipadamente. Se você já tem uma divisão de trem/validação/teste e está usando a validação por um desses motivos, é seguro treinar seu TF-DF em trem+validação (a menos que a divisão de validação também seja usada para outra coisa, como ajuste de hiperparâmetro).
- model.fit(train_ds, validation_data=val_ds)
+ model.fit(train_ds.concatenate(val_ds))
# Or just don't create a validation dataset
Justificativa: A estrutura do TF-DF é composta por vários algoritmos. Alguns deles não usam um conjunto de dados de validação (por exemplo, Random Forest), enquanto outros usam (por exemplo, Gradient Boosted Trees). Algoritmos que fazem isso podem se beneficiar de diferentes tipos e tamanhos de conjuntos de dados de validação. Portanto, se for necessário um conjunto de dados de validação, ele será extraído automaticamente do conjunto de dados de treinamento.
E/S do conjunto de dados
Treine por exatamente 1 época
# Number of epochs in Keras
- model.fit(train_ds, num_epochs=5)
# Number of epochs in the dataset
- train_ds = train_ds.repeat(5)
- model.fit(train_ds)
+ model.fit(train_ds)
Justificativa: Os usuários de redes neurais geralmente treinam um modelo para N etapas (o que pode envolver loop no conjunto de dados > 1 vez), devido à natureza do SGD . O TF-DF treina lendo todo o conjunto de dados e executando o treinamento no final. 1 época é necessária para ler o conjunto de dados completo, e quaisquer etapas extras resultarão em E/S de dados desnecessária, bem como em treinamento mais lento.
Não embaralhe o conjunto de dados
Os conjuntos de dados não precisam ser embaralhados (a menos que input_fn esteja lendo apenas uma amostra do conjunto de dados).
- train_ds = train_ds.shuffle(5)
- model.fit(train_ds)
+ model.fit(train_ds)
Justificativa: O TF-DF embaralha o acesso aos dados internamente após ler o conjunto de dados completo na memória. Os algoritmos TF-DF são determinísticos (se o usuário não alterar a semente aleatória). Ativar o embaralhamento apenas tornará o algoritmo não determinístico. O embaralhamento faz sentido se o conjunto de dados de entrada for ordenado e o input_fn for ler apenas uma amostra dele (a amostra deve ser aleatória). No entanto, isso tornará o procedimento de treinamento não determinístico.
Não ajuste o tamanho do lote
O tamanho do lote não afetará a qualidade do modelo
- train_ds = train_ds.batch(hyper_parameter_batch_size())
- model.fit(train_ds)
# The batch size does not matter.
+ train_ds = train_ds.batch(64)
+ model.fit(train_ds)
Justificativa: Como o TF-DF é sempre treinado no conjunto de dados completo após ser lido, a qualidade do modelo não varia com base no tamanho do lote (ao contrário de algoritmos de treinamento de minilote como SGD, onde parâmetros como taxa de aprendizado precisam ser ajustados em conjunto). Assim, ele deve ser removido das varreduras de hiperparâmetros. O tamanho do lote terá impacto apenas na velocidade de E/S do conjunto de dados.
Grandes conjuntos de dados
Ao contrário das redes neurais, que podem fazer um loop infinito em minilotes de um grande conjunto de dados, as florestas de decisão exigem um conjunto de dados finito que caiba na memória para seus procedimentos de treinamento. O tamanho do conjunto de dados tem implicações de desempenho e memória.
Há retornos decrescentes para aumentar o tamanho do conjunto de dados, e os algoritmos DF provavelmente precisam de menos exemplos para convergência do que grandes modelos NN. Em vez de dimensionar o número de etapas de treinamento (como em um NN), você pode tentar dimensionar a quantidade de dados para ver onde a compensação de computação faz sentido. Portanto, é uma boa ideia tentar primeiro treinar em um (pequeno) subconjunto do conjunto de dados.
A solução alternativa é usar treinamento distribuído . O treinamento distribuído é uma ótima maneira de aumentar o tamanho do conjunto de dados se várias máquinas estiverem disponíveis. Embora todos os algoritmos distribuídos estejam disponíveis para distribuir a computação, nem todos são capazes de distribuir o uso de RAM. Verifique a documentação para mais detalhes.
Quantos exemplos usar
Ele deve caber na memória da máquina em que o modelo está treinando :
Observe que isso não é o mesmo que o tamanho dos exemplos no disco.
Como regra geral, um valor numérico ou categórico usa 4 bytes de memória. Portanto, um conjunto de dados com 100 recursos e 25 milhões de exemplos ocupará ~ 10 GB (= 100 * 25 * 10^6 * 4 bytes) de memória.
Recursos de conjunto categórico (por exemplo, texto tokenizado) ocupam mais memória (4 bytes por token + 12 bytes por recurso).
Considere seu orçamento de tempo de treinamento
Embora geralmente mais rápido que NN para conjuntos de dados menores (por exemplo, <100 mil exemplos), os algoritmos de treinamento DF não são dimensionados linearmente com o tamanho do conjunto de dados; em vez disso, ~O(features x num_examples x log(num_examples)) na maioria dos casos.
O tempo de treinamento depende dos hiperparâmetros. Os parâmetros mais impactantes são: (1) o número de árvores (
num_trees
), (2) a taxa de amostragem do exemplo (subsample
para GBT) e (3) a taxa de amostragem do atributo (num_candidate_attributes_ratio
)Os recursos de conjunto categórico são mais caros do que outros recursos. O custo é controlado pelo parâmetro
categorical_set_split_greedy_sampling
.Os recursos Sparse Oblique (desativados por padrão) fornecem bons resultados, mas são caros para calcular.
Regras de ouro para escalonar dados
Sugerimos começar com uma pequena fatia dos dados (<10 mil exemplos), o que deve permitir que você treine um modelo TF-DF em segundos ou alguns minutos na maioria dos casos. Em seguida, você pode aumentar os dados a uma taxa fixa (por exemplo, 40% a mais a cada vez), parando quando o desempenho do conjunto de validação não melhorar ou o conjunto de dados não cabe mais na memória.
Normalização / Pré-processamento de Recursos
Não transforme dados com colunas de recursos
Os modelos TF-DF não exigem o fornecimento explícito de semântica e transformações de recursos. Por padrão, todos os recursos no conjunto de dados (exceto o rótulo) serão detectados e usados pelo modelo. A semântica do recurso será detectada automaticamente e pode ser substituída manualmente, se necessário.
# Estimator code
- feature_columns = [
- tf.feature_column.numeric_column(feature_1),
- tf.feature_column.categorical_column_with_vocabulary_list(feature_2, ['First', 'Second', 'Third'])
- ]
- model = tf.estimator.LinearClassifier(feature_columns=feature_columnes)
# Use all the available features. Detect the type automatically.
+ model = tfdf.keras.GradientBoostedTreesModel()
Você também pode especificar um subconjunto de recursos de entrada:
+ features = [
+ tfdf.keras.FeatureUsage(name="feature_1"),
+ tfdf.keras.FeatureUsage(name="feature_2")
+ ]
+ model = tfdf.keras.GradientBoostedTreesModel(features=features, exclude_non_specified_features=True)
Se necessário, você pode forçar a semântica de um recurso.
+ forced_features = [
+ tfdf.keras.FeatureUsage(name="feature_1", semantic=tfdf.keras.FeatureSemantic.CATEGORICAL),
+ ]
+ model = tfdf.keras.GradientBoostedTreesModel(features=features)
Justificativa: Enquanto certos modelos (como Redes Neurais) exigem uma camada de entrada padronizada (por exemplo, mapeamentos de diferentes tipos de recursos → embeddings), os modelos TF-DF podem consumir recursos categóricos e numéricos nativamente, bem como detectar automaticamente os tipos semânticos dos recursos com base nos dados.
Não pré-processe os recursos
Os algoritmos de árvore de decisão não se beneficiam de alguns dos recursos clássicos de pré-processamento usados para redes neurais. Abaixo, algumas das estratégias de processamento de recursos mais comuns são listadas explicitamente, mas um ponto de partida seguro é remover todo o pré-processamento que foi projetado para ajudar no treinamento da rede neural.
Não normalize recursos numéricos
- def zscore(value):
- return (value-mean) / sd
- feature_columns = [tf.feature_column.numeric_column("feature_1",normalizer_fn=zscore)]
Racional: Os algoritmos de floresta de decisão suportam nativamente recursos numéricos não normalizados, uma vez que os algoritmos de divisão não fazem nenhuma transformação numérica da entrada. Alguns tipos de normalização (por exemplo, normalização de zscore) não ajudarão na estabilidade numérica do procedimento de treinamento, e alguns (por exemplo, recorte de outlier) podem prejudicar a expressividade do modelo final.
Não codifique recursos categóricos (por exemplo, hashing, one-hot ou embedding)
- integerized_column = tf.feature_column.categorical_column_with_hash_bucket("feature_1",hash_bucket_size=100)
- feature_columns = [tf.feature_column.indicator_column(integerized_column)]
- integerized_column = tf.feature_column.categorical_column_with_vocabulary_list('feature_1', ['bob', 'george', 'wanda'])
- feature_columns = [tf.feature_column.indicator_column(integerized_column)]
Justificativa: O TF-DF tem suporte nativo para recursos categóricos e tratará um item de vocabulário “transformado” como apenas mais um item em seu vocabulário interno (que pode ser configurado por meio de hiperparâmetros de modelo). Algumas transformações (como hashing) podem causar perdas. Embeddings não são suportados a menos que sejam pré-treinados, pois os modelos de Decision Forest não são diferenciáveis (consulte colab intermediário ). Observe que estratégias de vocabulário específicas de domínio (por exemplo, remoção de palavras irrelevantes, normalização de texto) ainda podem ser úteis.
Como lidar com recursos de texto
O TF-DF suporta recursos de conjunto categórico nativamente. Portanto, sacos de n-grams tokenizados podem ser consumidos nativamente.
Como alternativa, o texto também pode ser consumido por meio de uma incorporação pré-treinada .
Os conjuntos categóricos são eficientes em amostras em conjuntos de dados pequenos, mas caros para treinar em conjuntos de dados grandes. A combinação de conjuntos categóricos e uma incorporação pré-treinada geralmente pode produzir melhores resultados do que se um deles for usado sozinho.
Não substitua recursos ausentes por valores mágicos
Justificativa: O TF-DF tem suporte nativo para valores ausentes. Ao contrário das redes neurais, que podem propagar NaNs para os gradientes se houver NaNs na entrada, o TF-DF treinará de maneira otimizada se o algoritmo perceber a diferença entre o valor ausente e o valor sentinela.
- feature_columns = [
- tf.feature_column.numeric_column("feature_1", default_value=0),
- tf.feature_column.numeric_column("feature_1_is_missing"),
- ]
Manipulando Imagens e Séries Temporais
Não há algoritmo padrão para consumir recursos de imagens ou séries temporais no Decision Forests, portanto, é necessário algum trabalho extra para usá-los.
Justificativa: Convolução, LSTM, atenção e outros algoritmos de processamento de sequência são arquiteturas específicas de redes neurais.
É possível lidar com esses recursos usando as seguintes estratégias:
Engenharia de recursos
Imagens: Usar imagem com Random Forest foi popular em algum momento (por exemplo,
Microsoft Kinect , mas hoje as redes neurais são de última geração.
Séries temporais: [ Estatísticas móveis ] podem funcionar surpreendentemente bem para dados de séries temporais que têm relativamente poucos exemplos (por exemplo, sinais vitais no domínio médico).
Módulos de incorporação: Os módulos de incorporação de rede neural podem fornecer recursos avançados para um algoritmo de floresta de decisão. A colab intermediária mostra como combinar uma incorporação tf-hub e um modelo TF-DF.
Pipeline de treinamento
Não use aceleradores de hardware, por exemplo, GPU, TPU
O treinamento do TF-DF (ainda) não suporta aceleradores de hardware. Todo o treinamento e inferência é feito na CPU (às vezes usando SIMD).
Observe que a inferência de TF-DF na CPU (especialmente quando fornecida usando bibliotecas Yggdrasil C++) pode ser surpreendentemente rápida (sub-microssegundo por exemplo por núcleo de cpu).
Não use pontos de verificação ou ganchos no meio do treinamento
O TF-DF não suporta (atualmente) o ponto de verificação do modelo, o que significa que os ganchos que esperam que o modelo seja utilizável antes da conclusão do treinamento não são amplamente suportados. O modelo só estará disponível após treinar o número de árvores solicitado (ou parar mais cedo).
Os ganchos Keras que dependem da etapa de treinamento também não funcionarão - devido à natureza do treinamento do TF-DF, o modelo treina no final da primeira época e será constante após essa época. A etapa corresponde apenas à E/S do conjunto de dados.
Determinismo Modelo
O algoritmo de treinamento TF-DF é determinístico, ou seja, treinar duas vezes no mesmo conjunto de dados fornecerá exatamente o mesmo modelo. Isso é diferente das redes neurais treinadas com o TensorFlow. Para preservar esse determinismo, os usuários devem garantir que as leituras do conjunto de dados também sejam determinísticas.
Configuração de treinamento
Especifique uma tarefa (por exemplo, classificação, classificação) em vez de uma perda (por exemplo, entropia cruzada binária)
- model = tf.keras.Sequential()
- model.add(Dense(64, activation=relu))
- model.add(Dense(1)) # One output for binary classification
- model.compile(loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
- optimizer='adam',
- metrics=['accuracy'])
# The loss is automatically determined from the task.
+ model = tfdf.keras.GradientBoostedTreesModel(task=tf.keras.Task.CLASSIFICATION)
# Optional if you want to report the accuracy.
+ model.compile(metrics=['accuracy'])
Justificativa: Nem todos os algoritmos de aprendizado do TF-DF usam uma perda. Para aqueles que o fazem, a perda é detectada automaticamente na tarefa e impressa no resumo do modelo. Você também pode substituí-lo com o hiperparâmetro de perda.
Os hiperparâmetros são semanticamente estáveis
Todos os hiperparâmetros têm valores padrão. Esses valores são os primeiros candidatos razoáveis a serem testados. Os valores de hiperparâmetros padrão são garantidos para nunca mudar. Por esse motivo, novos hiperparâmetros ou melhorias de algoritmo são desabilitados por padrão.
Os usuários que desejam usar os algoritmos mais recentes, mas que não desejam otimizar os próprios hiperparâmetros, podem usar os "modelos de hiperparâmetros" fornecidos pelo TF-DF. Novos modelos de hiperparâmetros serão lançados com atualizações no pacote.
# Model with default hyper-parameters.
model = tfdf.keras.GradientBoostedTreesModel()
# List the hyper-parameters (with default value) and hyper-parameters templates of the GBT learning algorithm (in colab)
?tfdf.keras.GradientBoostedTreesModel
# Use a hyper-parameter template.
model = tfdf.keras.GradientBoostedTreesModel(hp_template="winner_1")
# Change one of the hyper-parameters.
model = tfdf.keras.GradientBoostedTreesModel(num_trees=500)
# List all the learning algorithms available
tfdf.keras.get_all_models()
Depuração de modelo
Esta seção apresenta algumas maneiras de olhar/depurar/interpretar o modelo. A colab iniciante contém um exemplo de ponta a ponta.
Resumo do modelo simples
# Text description of the model, training logs, feature importances, etc.
model.summary()
Registros de treinamento e Tensorboard
# List of metrics
logs = model.make_inspector().training_logs()
print(logs)
Ou usando o TensorBoard:
% load_ext
tensorboard
model.make_inspector().export_to_tensorboard("/tmp/tensorboard_logs")
% tensorboard - -logdir
"/tmp/tensorboard_logs"
Importância do recurso
model.make_inspector().variable_importances()
Traçando as árvores
tfdf.model_plotter.plot_model_in_colab(model, tree_idx=0)
Acesse a estrutura em árvore
tree = model.make_inspector().extract_tree(tree_idx=0)
print(tree)
(Veja colab avançada )
Não use estratégias de distribuição do TensorFlow
O TF-DF ainda não suporta estratégias de distribuição de TF. As configurações de vários trabalhadores serão ignoradas e o treinamento acontecerá apenas no gerente.
- with tf.distribute.MirroredStrategy():
- model = ...
+ model = ....
Modelos de empilhamento
Os modelos TF-DF não retropropagam gradientes. Como resultado, eles não podem ser compostos com modelos NN, a menos que os NNs já estejam treinados.
Migrando de tf.estimator.BoostedTrees {Classifier/Regressor/Estimator}
Apesar de parecerem semelhantes, as árvores impulsionadas do TF-DF e do Estimator são algoritmos diferentes. O TF-DF implementa os papéis clássicos Random Forest e Gradient Boosted Machine (usando árvores) . O tf.estimator.BoostedTreesEstimator é um algoritmo aproximado de Gradient Boosted Trees com um procedimento de treinamento de mini-lote descrito neste artigo
Alguns hiperparâmetros têm semânticas semelhantes (por exemplo, num_trees), mas têm implicações de qualidade diferentes. Se você ajustou os hiperparâmetros em seu tf.estimator.BoostedTreesEstimator, precisará reajustar seus hiperparâmetros no TF-DF para obter os melhores resultados.
Para usuários do Yggdrasil
Yggdrasil Decision Forest é a biblioteca central de treinamento e inferência usada pelo TF-DF. A configuração e os modelos de treinamento são compatíveis entre si (ou seja, modelos treinados com TF-DF podem ser usados com inferência Yggdrasil).
No entanto, alguns dos algoritmos Yggdrasil não estão (ainda) disponíveis no TF-DF.
- Gradient Boosted Tree com amostragem fragmentada.