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 ): DFs geralmente não treinam com retropropagação ou em minilotes. 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 pipelines TF para usar TF-DF
Este documento pressupõe familiaridade com o colab para iniciantes .
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 para interromper o treinamento antecipadamente. Se você já possui uma divisão de treinamento/validação/teste e está usando a validação por um desses motivos, é seguro treinar seu TF-DF em treinamento+validação (a menos que a divisão de validação também seja usada para outra coisa, como ajuste de hiperparâmetros).
- 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 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 o fazem (por exemplo, Gradient Boosted Trees). Os algoritmos que o fazem 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. É necessária 1 época 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 a leitura do 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 estiver ordenado e input_fn 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 variará com base no tamanho do lote (ao contrário dos algoritmos de treinamento de minilote, como SGD, onde parâmetros como a taxa de aprendizagem precisam ser ajustados em conjunto). Portanto, 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 percorrer infinitamente 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 de convergência do que grandes modelos NN. Em vez de dimensionar o número de etapas de treinamento (como em uma NN), você pode tentar dimensionar a quantidade de dados para ver onde a compensação computacional 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 eles são capazes de distribuir o uso de RAM. Verifique a documentação para mais detalhes.
Quantos exemplos usar
Deve caber na memória da máquina em que o modelo está treinando :
Observe que este não é igual ao tamanho dos exemplos no disco.
Como regra geral, um valor numérico ou categórico utiliza 4 bytes de memória. Portanto, um conjunto de dados com 100 recursos e 25 milhões de exemplos ocupará aproximadamente 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 escalonados 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 de exemplo (subsample
para GBT) e (3) a taxa de amostragem de atributos (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 básicas para ampliar dados
Sugerimos começar com uma pequena fatia dos dados (<10 mil exemplos), o que deve permitir treinar um modelo TF-DF em segundos ou alguns minutos na maioria dos casos. Então você pode aumentar os dados a uma taxa fixa (por exemplo, 40% a mais de cada vez), parando quando o desempenho do conjunto de validação não melhorar ou o conjunto de dados não caber 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 do conjunto de dados (exceto o rótulo) serão detectados e usados pelo modelo. A semântica do recurso será detectada automaticamente e poderá 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: Embora certos modelos (como redes neurais) exijam uma camada de entrada padronizada (por exemplo, mapeamentos de diferentes tipos de recursos → incorporações), 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 pré-processamentos clássicos de recursos 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 zscore) não ajudarão na estabilidade numérica do procedimento de treinamento, e alguns (por exemplo, recorte de valores discrepantes) podem prejudicar a expressividade do modelo final.
Não codifique recursos categóricos (por exemplo, hash, one-hot ou incorporação)
- 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 possui 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 do modelo). Algumas transformações (como hashing) podem causar perdas. As incorporações não são suportadas, a menos que sejam pré-treinadas, uma vez que os modelos da Floresta de Decisão 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
TF-DF oferece suporte nativo a recursos de conjunto categórico . Portanto, sacos de n-gramas tokenizados podem ser consumidos nativamente.
Alternativamente, o texto também pode ser consumido por meio de uma incorporação pré-treinada .
Conjuntos categóricos são eficientes em termos de amostragem 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 muitas vezes pode produzir melhores resultados do que se qualquer um deles fosse usado sozinho.
Não substitua recursos ausentes por valores mágicos
Justificativa: TF-DF possui 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 ideal se o algoritmo perceber a diferença entre um valor ausente e um valor sentinela.
- feature_columns = [
- tf.feature_column.numeric_column("feature_1", default_value=0),
- tf.feature_column.numeric_column("feature_1_is_missing"),
- ]
Tratamento de imagens e séries temporais
Não existe um algoritmo padrão para consumir recursos de imagens ou séries temporais em 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 imagens com Random Forest era 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 possuem relativamente poucos exemplos (por exemplo, sinais vitais no domínio médico).
Incorporação de módulos: 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 TF-DF (ainda) não oferece suporte a aceleradores de hardware. Todo o treinamento e inferência são feitos na CPU (às vezes usando SIMD).
Observe que a inferência TF-DF na CPU (especialmente quando servida usando bibliotecas Yggdrasil C++) pode ser surpreendentemente rápida (menos de microssegundo por exemplo por núcleo da CPU).
Não use checkpoints ou ganchos no meio do treinamento
O TF-DF (atualmente) não suporta checkpoint de 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 em grande parte suportados. O modelo só estará disponível após treinar o número solicitado de árvores (ou parar antecipadamente).
Os ganchos Keras que dependem da etapa de treinamento também não funcionarão – devido à natureza do treinamento 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 do 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 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 aprendizagem 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 pelo hiperparâmetro de perda.
Os hiperparâmetros são semanticamente estáveis
Todos os hiperparâmetros possuem valores padrão. Esses valores são os primeiros candidatos razoáveis a serem experimentados. É garantido que os valores padrão dos hiperparâmetros nunca serão alterados. 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 não desejam otimizar os hiperparâmetros por conta própria, podem usar os "modelos de hiperparâmetros" fornecidos pelo TF-DF. Novos modelos de hiperparâmetros serão lançados com atualizações do 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 visualizar/depurar/interpretar o modelo. O colab para iniciantes contém um exemplo completo.
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çado )
Não use estratégias de distribuição do TensorFlow
O TF-DF ainda não apoia 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 de NN, a menos que os NNs já estejam treinados.
Migrando de tf.estimator.BoostedTrees {Classificador/Regressor/Estimador}
Apesar de parecerem semelhantes, as árvores impulsionadas pelo TF-DF e pelo Estimador são algoritmos diferentes. 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 minilote descrito neste artigo
Alguns hiperparâmetros têm semântica semelhante (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 resultados ideais.
Para usuários Yggdrasil
Yggdrasil Decision Forest é a principal biblioteca 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 (ainda) não estão disponíveis no TF-DF.
- Árvore Gradient Boosted com amostragem fragmentada.