Aiuto proteggere la Grande Barriera Corallina con tensorflow sul Kaggle Join Sfida

Alberi potenziati usando gli stimatori

Visualizza su TensorFlow.org Esegui in Google Colab Visualizza la fonte su GitHub Scarica taccuino

Questo tutorial è un walkthrough end-to-end di formazione di un modello di amplificazione gradiente utilizzando alberi decisionali con il tf.estimator API. I modelli Boosted Trees sono tra gli approcci di machine learning più popolari ed efficaci sia per la regressione che per la classificazione. È una tecnica di insieme che combina le previsioni di diversi modelli di alberi (si pensi a 10, 100 o addirittura 1000).

I modelli Boosted Trees sono apprezzati da molti professionisti dell'apprendimento automatico in quanto possono ottenere prestazioni impressionanti con un'ottimizzazione minima degli iperparametri.

Carica il set di dati Titanic

Utilizzerai il set di dati titanic, in cui l'obiettivo (piuttosto morboso) è prevedere la sopravvivenza dei passeggeri, date caratteristiche come sesso, età, classe, ecc.

import numpy as np
import pandas as pd
from IPython.display import clear_output
from matplotlib import pyplot as plt

# Load dataset.
dftrain = pd.read_csv('https://storage.googleapis.com/tf-datasets/titanic/train.csv')
dfeval = pd.read_csv('https://storage.googleapis.com/tf-datasets/titanic/eval.csv')
y_train = dftrain.pop('survived')
y_eval = dfeval.pop('survived')
import tensorflow as tf
tf.random.set_seed(123)

Il dataset è costituito da un training set e da un assessment set:

  • dftrain e y_train sono la formazione impostata -I dati gli usi del modello da imparare.
  • Il modello è stato testato contro il set di eval, dfeval e y_eval .

Per la formazione utilizzerai le seguenti funzionalità:

Nome funzione Descrizione
sesso Sesso del passeggero
età Età del passeggero
n_siblings_spouses fratelli e partner a bordo
parch di genitori e bambini a bordo
tariffa Tariffa passeggero pagata.
classe Classe del passeggero sulla nave
ponte Su quale passeggero si trovava sul ponte
imbarcarsi in città Da quale città si è imbarcato il passeggero
solo Se il passeggero fosse solo

Esplora i dati

Per prima cosa vediamo in anteprima alcuni dati e creiamo statistiche riassuntive sul training set.

dftrain.head()
dftrain.describe()

Ci sono 627 e 264 esempi rispettivamente nei set di formazione e valutazione.

dftrain.shape[0], dfeval.shape[0]
(627, 264)

La maggior parte dei passeggeri ha tra i 20 ei 30 anni.

dftrain.age.hist(bins=20)
plt.show()

png

A bordo ci sono circa il doppio dei passeggeri maschili rispetto alle femmine.

dftrain.sex.value_counts().plot(kind='barh')
plt.show()

png

La maggior parte dei passeggeri era nella "terza" classe.

dftrain['class'].value_counts().plot(kind='barh')
plt.show()

png

La maggior parte dei passeggeri si imbarcava da Southampton.

dftrain['embark_town'].value_counts().plot(kind='barh')
plt.show()

png

Le femmine hanno una probabilità molto più alta di sopravvivere rispetto ai maschi. Questa sarà chiaramente una caratteristica predittiva per il modello.

pd.concat([dftrain, y_train], axis=1).groupby('sex').survived.mean().plot(kind='barh').set_xlabel('% survive')
plt.show()

png

Crea colonne di funzioni e funzioni di input

Lo stimatore Gradient Boosting può utilizzare sia caratteristiche numeriche che categoriali. Le colonne feature funzionano con tutti gli stimatori TensorFlow e il loro scopo è definire le feature utilizzate per la modellazione. Inoltre forniscono alcune funzionalità di ingegneria delle funzionalità come la codifica one-hot, la normalizzazione e la bucketizzazione. In questo tutorial, i campi di CATEGORICAL_COLUMNS si trasformano da colonne categoriali a one-hot-encoded colonne ( indicatore di colonna ):

CATEGORICAL_COLUMNS = ['sex', 'n_siblings_spouses', 'parch', 'class', 'deck',
                       'embark_town', 'alone']
NUMERIC_COLUMNS = ['age', 'fare']

def one_hot_cat_column(feature_name, vocab):
  return tf.feature_column.indicator_column(
      tf.feature_column.categorical_column_with_vocabulary_list(feature_name,
                                                 vocab))
feature_columns = []
for feature_name in CATEGORICAL_COLUMNS:
  # Need to one-hot encode categorical features.
  vocabulary = dftrain[feature_name].unique()
  feature_columns.append(one_hot_cat_column(feature_name, vocabulary))

for feature_name in NUMERIC_COLUMNS:
  feature_columns.append(tf.feature_column.numeric_column(feature_name,
                                           dtype=tf.float32))

È possibile visualizzare la trasformazione prodotta da una colonna di funzioni. Ad esempio, ecco l'uscita quando si utilizza indicator_column una singola esempio:

example = dict(dftrain.head(1))
class_fc = tf.feature_column.indicator_column(tf.feature_column.categorical_column_with_vocabulary_list('class', ('First', 'Second', 'Third')))
print('Feature value: "{}"'.format(example['class'].iloc[0]))
print('One-hot encoded: ', tf.keras.layers.DenseFeatures([class_fc])(example).numpy())
Feature value: "Third"
One-hot encoded:  [[0. 0. 1.]]

Inoltre, puoi visualizzare tutte le trasformazioni della colonna caratteristica insieme:

tf.keras.layers.DenseFeatures(feature_columns)(example).numpy()
array([[22.  ,  1.  ,  0.  ,  1.  ,  0.  ,  0.  ,  1.  ,  0.  ,  0.  ,

         0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  1.  ,  0.  ,  0.  ,  0.  ,
         7.25,  1.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  1.  ,
         0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  1.  ,  0.  ]], dtype=float32)

Successivamente è necessario creare le funzioni di input. Questi specificheranno come i dati verranno letti nel nostro modello sia per l'addestramento che per l'inferenza. Si utilizzerà il from_tensor_slices metodo nel tf.data API per leggere i dati direttamente da Panda. Questo è adatto per set di dati in memoria più piccoli. Per set di dati più grandi, l'API tf.data supporta una varietà di formati di file (tra cui CSV ) in modo da poter elaborare insiemi di dati che non rientrano nella memoria.

# Use entire batch since this is such a small dataset.
NUM_EXAMPLES = len(y_train)

def make_input_fn(X, y, n_epochs=None, shuffle=True):
  def input_fn():
    dataset = tf.data.Dataset.from_tensor_slices((dict(X), y))
    if shuffle:
      dataset = dataset.shuffle(NUM_EXAMPLES)
    # For training, cycle thru dataset as many times as need (n_epochs=None).
    dataset = dataset.repeat(n_epochs)
    # In memory training doesn't use batching.
    dataset = dataset.batch(NUM_EXAMPLES)
    return dataset
  return input_fn

# Training and evaluation input functions.
train_input_fn = make_input_fn(dftrain, y_train)
eval_input_fn = make_input_fn(dfeval, y_eval, shuffle=False, n_epochs=1)

Addestra e valuta il modello

Di seguito eseguirai i seguenti passaggi:

  1. Inizializzare il modello, specificando le caratteristiche e gli iperparametri.
  2. Alimentare i dati di allenamento al modello utilizzando il train_input_fn e formare il modello utilizzando il train funzioni.
  3. Potrai valutare l'andamento modello utilizzando la valutazione set-in questo esempio, il dfeval dataframe. Si verifica che le previsioni corrispondono alle etichette dal y_eval array.

Prima di addestrare un modello Boosted Trees, addestriamo prima un classificatore lineare (modello di regressione logistica). È buona norma iniziare con un modello più semplice per stabilire un punto di riferimento.

linear_est = tf.estimator.LinearClassifier(feature_columns)

# Train model.
linear_est.train(train_input_fn, max_steps=100)

# Evaluation.
result = linear_est.evaluate(eval_input_fn)
clear_output()
print(pd.Series(result))
accuracy                  0.765152
accuracy_baseline         0.625000
auc                       0.832844
auc_precision_recall      0.789631
average_loss              0.478908
label/mean                0.375000
loss                      0.478908
precision                 0.703297
prediction/mean           0.350790
recall                    0.646465
global_step             100.000000
dtype: float64

Quindi addestriamo un modello di alberi potenziati. Per gli alberi potenziato, la regressione ( BoostedTreesRegressor ) e classificazione ( BoostedTreesClassifier sono supportati). Dal momento che l'obiettivo è quello di prevedere una classe - sopravvivere o non sopravvive, si utilizza la BoostedTreesClassifier .

# Since data fits into memory, use entire dataset per layer. It will be faster.
# Above one batch is defined as the entire dataset.
n_batches = 1
est = tf.estimator.BoostedTreesClassifier(feature_columns,
                                          n_batches_per_layer=n_batches)

# The model will stop training once the specified number of trees is built, not
# based on the number of steps.
est.train(train_input_fn, max_steps=100)

# Eval.
result = est.evaluate(eval_input_fn)
clear_output()
print(pd.Series(result))
accuracy                  0.837121
accuracy_baseline         0.625000
auc                       0.871993
auc_precision_recall      0.858760
average_loss              0.406563
label/mean                0.375000
loss                      0.406563
precision                 0.797872
prediction/mean           0.384452
recall                    0.757576
global_step             100.000000
dtype: float64

Ora puoi utilizzare il modello del treno per fare previsioni su un passeggero dal set di valutazione. I modelli TensorFlow sono ottimizzati per fare previsioni su un batch, o raccolta, di esempi contemporaneamente. In precedenza, eval_input_fn viene definito mediante l'intero set di valutazione.

pred_dicts = list(est.predict(eval_input_fn))
probs = pd.Series([pred['probabilities'][1] for pred in pred_dicts])

probs.plot(kind='hist', bins=20, title='predicted probabilities')
plt.show()
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from /tmp/tmp98s7_n3y/model.ckpt-100
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
Exception ignored in: <function CapturableResource.__del__ at 0x7ff2fb5bd950>
Traceback (most recent call last):
  File "/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/training/tracking/tracking.py", line 269, in __del__
    with self._destruction_context():
AttributeError: 'TreeEnsemble' object has no attribute '_destruction_context'

png

Infine puoi anche guardare la caratteristica operativa del ricevitore (ROC) dei risultati, che ci darà un'idea migliore del compromesso tra il tasso di veri positivi e il tasso di falsi positivi.

from sklearn.metrics import roc_curve

fpr, tpr, _ = roc_curve(y_eval, probs)
plt.plot(fpr, tpr)
plt.title('ROC curve')
plt.xlabel('false positive rate')
plt.ylabel('true positive rate')
plt.xlim(0,)
plt.ylim(0,)
plt.show()

png