Guida completa a TensorForest in TensorFlow

11 dicembre 2017
Vectra AI Team di ricerca sulla sicurezza
Sicurezza informatica
Guida completa a TensorForest in TensorFlow

Capire la foresta casuale: Un metodo d'insieme

Il modello random forest (RF), proposto per la prima volta da Tin Kam Ho nel 1995, è una sottoclasse di metodi di apprendimento in ensemble che viene applicata alla classificazione e alla regressione. Un metodo ensemble costruisce un insieme di classificatori - un gruppo di alberi decisionali, nel caso di RF - e determina l'etichetta per ogni istanza di dati prendendo la media ponderata dei risultati di ciascun classificatore.

L'algoritmo di apprendimento utilizza l'approccio divide et impera e riduce la varianza intrinseca di una singola istanza del modello attraverso il bootstrapping. Pertanto, l'"assemblaggio" di un gruppo di classificatori più deboli aumenta le prestazioni e il classificatore aggregato risultante è un modello più forte.

La foresta decisionale casuale è una modifica del bagging - aggregazione bootstrap, proposta da Leo Breiman nel 2001 - che assembla una grande collezione di alberi decorrelati su caratteristiche selezionate casualmente[1]. Il ``numero di alberi`` che compongono la foresta è legato alla varianza del modello, mentre la ``profondità dell'albero`` o il ``numero massimo di nodi di cui ogni albero è composto`` è associato al bias irriducibile presente nel modello.

La RF presenta una serie di vantaggi: È molto veloce da implementare ed eseguire (funziona in modo efficiente su grandi insiemi di dati), è uno degli algoritmi di apprendimento più accurati e resistente all'overfitting e agli outlier[2]. Le prestazioni di RF sono simili, ma più robuste, di quelle degli alberi decisionali potenziati dal gradiente (GBDT), un'altra sottoclasse di metodi ad albero. Inoltre, poiché RF ha un numero inferiore di iperparametri rispetto a GBDT, è più facile da addestrare e mettere a punto. Di conseguenza, RF è molto popolare ed è supportato in vari linguaggi, come R e SAS, e in molti pacchetti in Python, tra cui scikit-learn e TensorFlow.

Stimatore TensorForest: Compatibilità e utilizzo

TensorFlow ha recentemente incluso il supporto per RF nella base di codice contribuita - tf.contrib - attraverso un modulo chiamato tensor_forest (definito in https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/tensor_forest/__init__.py, si noti che il link a tensor_forest sul sito ufficiale di TensorFlow indirizza l'utente al ramo con la versione più recente e non al ramo master). La versione 1.3.0 di tensor_forest è stata modificata in modo significativo rispetto alla versione 1.2.0 e la struttura del codice e i parametri da discutere sono conformi alla versione 1.2.0.

Struttura e implementazione di TensorForest

I seguenti moduli devono essere importati per utilizzare tensor_forest:

  • ‍from tensorflow.contrib.learn.python.learn import metric_spec
  • ‍from tensorflow.contrib.learn.python.learn.estimators import estimator
  • ‍from tensorflow.contrib.tensor_forest.client import eval_metrics
  • ‍from tensorflow.contrib.tensor_forest.client import random_forest
  • ‍from tensorflow.contrib.tensor_forest.python import tensor_forest

Il passo iniziale per eseguire RF in TensorFlow è la costruzione del modello. Per costruire uno stimatore RF, specificare innanzitutto gli iperparametri di RF come segue:

hparams = tensor_forest.ForestHParams(num_classes=NUM_CLASSES,num_features=NUM_FEATURES,num_trees=NUM_TREES,max_nodes=MAX_NODES,min_split_samples=MIN_NODE_SIZE).fill()

Ciascuno degli iperparametri per la foresta tensoriale sopra menzionati è descritto di seguito:

``num_classes``: Il numero di classi possibili per le etichette

``num_features``: Il numero di caratteristiche. Sia ``num_splits_to_consider`` che ``num_features`` dovrebbero

Secondo i collaboratori del codice di tensor_forest, il modello è più accurato.

quando ``num_splits_to_consider`` == ``num_features``[4].

``num_trees``: Il numero di alberi da costruire per prendere la modalità [per la classificazione] o la media [per

regressione] delle previsioni. Gli alberi sono "notoriamente rumorosi", quindi "traggono grande beneficio dalla media"[5]. Più alberi compongono la foresta, più bassa è la varianza del modello e quindi più accurati sono i risultati. Tuttavia, esiste un compromesso tra prestazioni e velocità di esecuzione. L'utilizzo di un numero elevato di alberi comporta un maggiore costo computazionale e potrebbe rallentare significativamente il codice. Di solito, dopo un certo numero di alberi, le prestazioni del modello si stabilizzano e il miglioramento è trascurabile[6].

Mi piace costruire una foresta a cinque alberi per testare il mio codice a scopo di debug, una a 100 alberi per avere un'idea iniziale di accuratezza, precisione, richiamo, auc, ecc. e una a 500 alberi per un modello finale che non necessita di grandi aggiustamenti. In generale, l'uso di un modello a 1000 alberi non aumenta significativamente le prestazioni rispetto a una foresta a 500 alberi.

*Default: 100

I due iperparametri seguenti determinano la profondità dell'albero in una foresta. Limitare la profondità dell'albero non dà alcun vantaggio aggiuntivo, se non quello di limitare il tempo di calcolo, e non è raccomandato[7]. Maggiore profondità significa minore polarizzazione. Quando gli alberi "crescono sufficientemente in profondità, [hanno] un bias relativamente basso"[8].

``max_nodes``: Il numero massimo di nodi consentito per ogni albero. Un numero maggiore di ``max_nodes``

permette di avere alberi più profondi.

*Valore predefinito: 10000.

``min_split_samples``: "Il numero minimo di campioni richiesti per dividere un nodo interno" secondo

SKlearn[9]. ``min_split_samples'' è legato alla dimensione minima dei nodi. Minore è il numero di campioni necessari per dividere un nodo, maggiore è la profondità dell'albero.

*Default: 5

Visualizzazione 1: Un albero con dimensione minima dei nodi pari a 10.

Quindi, determinare il tipo di grafo da utilizzare con RF; esistono due tipi di grafi: Il grafo RF predefinito [``RandomForestGraphs``] e il grafo delle perdite di addestramento [``TrainingLossForest``][11]. Per quanto riguarda l'antecedente, l'utente può aumentare il peso delle istanze positive, di solito per insiemi di dati sbilanciati, passando un vettore di pesi.

[Nota: ``SKCompat`` è il wrapper di scikit-learn per TensorFlow[12]. ``model_dir`` deve essere una directory in cui vengono salvati il RF e il file di log per la visualizzazione con tensorboard].

Se è selezionato il grafico RF:

Per specificare un sovrappeso:

graph_builder_class = tensor_forest.RandomForestGraphs

est = estimator.SKCompat(random_forest.TensorForestEstimator(

params,

graph_builder_class=graph_builder_class,

model_dir=MODEL_DIRECTORY,

nome_pesi='pesi'))

Oppure mantenere la ponderazione predefinita di 1:1 tra i punti di dati positivi e negativi:

graph_builder_class = tensor_forest.RandomForestGraphs

est = estimator.SKCompat(random_forest.TensorForestEstimator(

params,

graph_builder_class=graph_builder_class,

model_dir=MODEL_DIRECTORY))

Nel caso della foresta di perdita di addestramento, la perdita di addestramento calcolata dalla funzione di perdita predefinita [``log_loss``] o da una funzione di perdita specificata viene utilizzata per regolare i pesi[13].

Usa la funzione di perdita predefinita ``log loss`` come funzione di perdita:

classe_di_costruttore_di_grafo = tensor_forest.TrainingLossForest

Oppure specificare una funzione di perdita da utilizzare nel grafico delle perdite di addestramento[14]:

da tensorflow.contrib.losses.python.losses import loss_ops

# Le funzioni di perdita valide sono:

#["absolute_difference",

#"add_loss",

#"coseno_distanza",

#"compute_weighted_loss",

#"get_losses",

#"get_regularization_losses",

#"get_total_loss",

#"hinge_loss",

#"log_loss",

#"mean_pairwise_squared_error",

#"mean_squared_error",

#"sigmoid_cross_entropy",

#"softmax_cross_entropy",

#"sparse_softmax_cross_entropy"]

def loss_fn(val, pred):

_loss = loss_ops.hinge_lss(val, pred)

restituire _loss

def _build_graph(params, **kwargs):

return tensor_forest.TrainingLossForest(params,

loss_fn=_loss_fn, **kwargs)

graph_builder_class = _build_graph

Infine, costruire lo stimatore RF con gli iperparametri e il grafico specificati in precedenza. est= estimator.SKCompat(random_forest.TensorForestEstimator(

hparams,

graph_builder_class=graph_builder_class,

model_dir=MODEL_DIRECTORY))

Dopo aver costruito il RF, è necessario adattare il modello ai dati di allenamento con il metodo ``fit``.

Per il grafico RF con peso massimo specificato*:

est.fit(x={‘x’:x_train, ‘weights’:train_weights},

y={‘y’:y_train},

batch_size=BATCH_SIZE,

max_steps=MAX_STEPS)

*Nota: `pesi` deve essere la stessa chiave passata in ``TensorForestEstimator`` in precedenza.

``train_weights`` dovrebbe essere dimensione: (numero di campioni, )

Per la ponderazione predefinita 1:1 o la foresta di perdita di formazione:

est.fit(x=x_train, y=y_train

batch_size=BATCH_SIZE,

max_steps=MAX_STEPS)

Per valutare i risultati prodotti dal modello, occorre identificare le metriche desiderate e passarle alla funzione ``evaluate``[15].

# Altre metriche includono:

# veri positivi: tf.contrib.metrics.streaming_true_positives

# veri negativi: tf.contrib.metrics.streaming_true_negatives

# falsi positivi: tf.contrib.metrics.streaming_false_positives

# falsi negativi: tf.contrib.metrics.streaming_false_negatives

# auc: tf.contrib.metrics.streaming_auc

# r2: eval_metrics.get_metric('r2')

# precisione: eval_metrics.get_metric('precision')

# richiamo: eval_metrics.get_metric('recall')

metric = {‘accuracy’:metric_spec.MetricSpec(eval_metris.get_metric(‘accuracy’),

prediction_key=eval_metrics.get_prediction_key('accuracy')}

Se viene somministrato il sovrappeso:

model_stats = est.score(x={‘x’:x_test, ‘weights’:test_weights},

y={‘y’:y_test},

batch_size=BATCH_SIZE,

max_steps=MAX_STEPS,

metriche=metriche)

per metrica in model_stats:

print('%s: %s' % (metrica, model_stats[metrica])

Per la ponderazione predefinita e la foresta di perdita di formazione:

model_stats = est.score(x=x_test, y=y_test

batch_size=BATCH_SIZE,

max_steps=MAX_STEPS,

metriche=metriche)

per metrica in model_stats:

print('%s: %0.4f' % (metrica, model_stats[metrica])

Per l'etichetta prevista e la probabilità di ogni classe per ogni istanza di dati:

[Nota: ``predicted_prob`` e ``predicted_class`` sono array numpy che conservano l'ordine dell'input originale].

Peso massimo specificato:

predictions = dict(est.predict({‘x’:x_test, ‘weights’:test_weights}))

predicted_prob = predictions[eval_metrics.INFERENCE_PROB_NAME]

predicted_class = predictions[eval_metrics.INFERENCE_PRED_NAME]

Ponderazione predefinita e foresta di perdita di formazione:

previsioni = dict(est.predict(x=x_test))

predicted_prob = predictions[eval_metrics.INFERENCE_PROB_NAME]

predicted_class = predictions[eval_metrics.INFERENCE_PRED_NAME]

Infine, avviare tensorboard tramite il terminale per visualizzare il processo di addestramento e il grafico TensorFlow:

Deve essere fornita la directory precedentemente passata a ``model_dir``.

$ tensorboard --logdir="./"

Aprire http://localhost:6006/ o il link ottenuto eseguendo il comando precedente nel browser per visualizzare tensorboard.

Visualizzazione 2: Tensorboard per tensor_forest

Confronto tra TensorFlow e Scikit-Learn per i modelli di foresta casuale

Attualmente, TensorFlow e scikit-learn sono entrambi pacchetti molto popolari, ciascuno con team di esperti che contribuiscono e mantengono la base di codice, una miriade di tutorial sull'uso del codice online e in stampa, la copertura della maggior parte degli algoritmi di apprendimento automatico. Tuttavia, questi due moduli non sono destinati agli stessi compiti.

scikit-learn

Visualizzazione 3: Diagramma di flusso di Scikit-learn sulla selezione del giusto stimatore[16].

Scikit è da tempo considerato il "framework ufficiale di apprendimento automatico generale di Python"[17]. Offre una base di codice completa di algoritmi di apprendimento automatico che appartengono a varie categorie: classificazione, regressione, clustering, riduzione della dimensionalità, ecc[18]. Questi algoritmi ben confezionati forniscono agli utenti un accesso immediato a un'analisi facile e veloce del set di dati. Ad esempio, sklearn include un modulo RF che può essere implementato su set di dati con poche righe:

Visualizzazione 4: Un modello RF implementato con scikit-learn[19]

Oltre alla sua semplicità d'uso e alle API standardizzate, scikit-learn è anche straordinariamente ben documentato. Per ogni libreria, ci sono pagine dedicate non solo ai dettagli dell'interfaccia, ai parametri di ingresso e al formato di uscita, ma anche alla dimostrazione dell'uso del codice con esempi accuratamente costruiti. Utilizziamo ancora una volta il modulo RF di sklearn come illustrazione specifica:

Visualizzazione 5: Descrizione dettagliata di Scikit-learn di ogni parametro di input per ``RandomForestClassifier``[20]

Visualizzazione 6: rappresentazione completa da parte di Scikit-learn della struttura di un modulo RF[21]

Sebbene scikit-learn presenti numerosi vantaggi di rilievo, come la "brevità sintattica"[22], ha una particolare lacuna: sklearn non supporta e non supporterà le GPU nel prossimo futuro[23]. "Il supporto delle GPU introdurrà molte dipendenze software e problemi specifici della piattaforma. [...] Al di fuori delle reti neurali, le GPU non svolgono oggi un ruolo importante nell'apprendimento automatico", secondo il sito ufficiale di sklearn. D'altra parte, il supporto nativo di TensorFlow per le GPU lo rende particolarmente adatto al deep learning.

TensorFlow

La potenza di TensorFlow è data dalla sua scalabilità che permette di "addestrare reti neurali profonde su GPU[ e] possibilmente su cluster di più macchine"[24] e dalla libertà concessa agli utenti nell'assemblare i propri algoritmi di deep learning. Gli utenti specificano non solo il tipo di modello utilizzato, ma anche il modo in cui viene implementato utilizzando le primitive fornite dal framework[25]. Essi definiscono esattamente "come [...] i dati devono essere trasformati [e] quale funzione di perdita deve ottimizzare il modello"[26]. Inoltre, TensorFlow è altamente flessibile e portatile; è disponibile su numerose piattaforme - tra cui Ubuntu, Mac OS X, Windows, Android, iOS - e su una varietà di linguaggi, come Python, Java, C, Go[27]. Sebbene sembri particolarmente attraente per la sua scalabilità e integrabilità, la complicata struttura del codice di TensorFlow, i misteriosi messaggi di errore e, in alcuni casi, i moduli scarsamente documentati appesantiscono il processo di debug. Pertanto, l'utilizzo di TensorFlow per "la maggior parte delle attività pratiche di apprendimento automatico" è probabilmente eccessivo[28].

Introduzione a Scikit Flow: collegamento tra TensorFlow e Scikit-Learn

[https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/learn/python/learn]

Scikit flow (SKFlow) è stato introdotto come soluzione al dilemma scikit-TensorFlow: sfrutta la "potenza di modellazione di TensorFlow incanalando la brevità sintattica di scikit-learn"[29]. SKFlow è un progetto ufficiale sviluppato da Google che fornisce un wrapper semplificato di alto livello per TensorFlow[30].

Una rete neurale a tre strati con 10, 20 e 10 unità nascoste rispettivamente può essere implementata con quattro linee in SKFlow:

Visualizzazione 7: Rete neurale profonda in SKFlow[31]

Oppure costruire un modello personalizzato con SKFlow con circa 10 righe di codice:

Visualizzazione 8: Creazione di un modello personalizzato con SKFlo

[1] Gli elementi dell'apprendimento statistico
[2] Predrag Radenkovìc
[3] https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/learn/random_forest_mnist.py
[4] https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/tensor_forest/python/tensor_forest.py
[5] Gli elementi dell'apprendimento statistico
[6] https://stackoverflow.com/questions/34997134/random-forest-tuning-tree-depth-and-number-of-trees
[7]https://stackoverflow.com/questions/34997134/random-forest-tuning-tree-depth-and-number-of-trees?answertab=active#tab-top
[8] Gli elementi dell'apprendimento statistico
[9] http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html
[10] https://stats.stackexchange.com/questions/158583/what-does-node-size-refer-to-in-the-random-forest
[11]https://github.com/aymericdamien/TensorFlow-Examples/blob/master/examples/2_BasicModels/random_forest.py
[12] https://github.com/tensorflow/tensorflow/blob/r1.2/tensorflow/contrib/learn/python/learn/estimators/estimator.py
[13] https://stackoverflow.com/questions/44672832/what-does-the-training-loss-mean-in-machine-learning
[14] https://stackoverflow.com/questions/44930699/tensor-forest-estimator-value-error-at-fitting-the-training-part
[15]https://github.com/aymericdamien/TensorFlow-Examples/blob/master/examples/2_BasicModels/random_forest.py
[16] http://scikit-learn.org/stable/tutorial/machine_learning_map/index.html
[17] http://www.kdnuggets.com/2016/02/scikit-flow-easy-deep-learning-tensorflow-scikit-learn.html
[18] http://scikit-learn.org/stable/
[19] http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html
[20] http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html
[21] http://scikit-learn.org/stable/modules/ensemble.html#forest
[22] http://www.kdnuggets.com/2016/02/scikit-flow-easy-deep-learning-tensorflow-scikit-learn.html
[23] http://scikit-learn.org/stable/faq.html
[24] https://www.quora.com/Which-is-better-Tensorflow-or-Scikit
[25] https://www.quora.com/Which-is-better-Tensorflow-or-Scikit
[26] https://www.quora.com/Which-is-better-Tensorflow-or-Scikit
[27] https://qconsf.com/sf2016/system/files/presentation-slides/tensorflow_-_qcon_sf_2016.pdf
[28]https://www.quora.com/What-are-the-advantages-and-disadvantages-of-using-TensorFlow-over-Scikit-learn-for-unsupervised-learning
[29] http://www.kdnuggets.com/2016/02/scikit-flow-easy-deep-learning-tensorflow-scikit-learn.html
[30] https://testpypi.python.org/pypi/skflow
[31] https://testpypi.python.org/pypi/skflow

DOMANDE FREQUENTI

Che cos'è TensorForest in TensorFlow?

TensorForest è un modulo di TensorFlow che implementa modelli random forest per la classificazione e la regressione.

Quali sono i vantaggi dell'utilizzo di TensorForest?

TensorForest offre un'elevata precisione, resistenza all'overfitting ed efficienza di esecuzione su grandi insiemi di dati.

Che cos'è Scikit Flow?

Scikit Flow è un progetto che combina la potenza di modellazione di TensorFlow con la semplicità di scikit-learn.

Quali sono gli iperparametri chiave di TensorForest?

Gli iperparametri chiave includono il numero di alberi, i nodi massimi e i campioni minimi divisi.

Perché il supporto GPU è importante in TensorFlow?

Il supporto delle GPU è fondamentale per accelerare la formazione e la gestione di modelli di deep learning su larga scala.

Come funziona la foresta casuale?

La foresta casuale è un metodo di apprendimento collettivo che costruisce più alberi decisionali e aggrega i loro risultati.

In che modo TensorFlow è diverso da scikit-learn?

TensorFlow è ottimizzato per l'apprendimento profondo e il supporto delle GPU, mentre scikit-learn si concentra sull'apprendimento automatico generale.

Come si implementa una foresta casuale in TensorFlow?

Implementare una foresta casuale in TensorFlow utilizzando lo stimatore TensorForest, definendo iperparametri e grafici.

Quali sono gli iperparametri chiave di TensorForest?

TensorForest gestisce in modo efficiente grandi insiemi di dati grazie all'elaborazione parallela e ai metodi di apprendimento in ensemble.

In che modo la flessibilità di TensorFlow può favorire i progetti di apprendimento automatico?

La flessibilità di TensorFlow consente agli utenti di definire modelli personalizzati, ottimizzare le funzioni di perdita e scalare tra le varie piattaforme.