Classificazione binaria TensorFlow: esempio di classificatore lineare
I due più comuni apprendimento supervisionato i compiti sono la regressione lineare e il classificatore lineare. La regressione lineare prevede un valore mentre il classificatore lineare prevede una classe. Questo tutorial è incentrato sui classificatori lineari.
Cos'è il classificatore lineare?
A Classificatore lineare in Machine Learning è un metodo per trovare la classe di un oggetto in base alle sue caratteristiche per la classificazione statistica. Prende decisioni di classificazione in base al valore di una combinazione lineare di caratteristiche di un oggetto. Il classificatore lineare viene utilizzato in problemi pratici come la classificazione dei documenti e problemi con molte variabili.
I problemi di classificazione rappresentano circa l’80% delle attività di machine learning. La classificazione mira a prevedere la probabilità di ciascuna classe dato un insieme di input. L'etichetta (cioè la variabile dipendente) è un valore discreto, chiamato classe.
- Se l'etichetta ha solo due classi, l'algoritmo di apprendimento è un classificatore binario.
- Il classificatore multiclasse affronta le etichette con più di due classi.
Ad esempio, un tipico problema di classificazione binaria consiste nel prevedere la probabilità che un cliente effettui un secondo acquisto. Prevedere il tipo di animale visualizzato su un'immagine è un problema di classificazione multiclasse poiché esistono più di due varietà di animali.
La parte teorica di questo tutorial si concentra principalmente sulla classe binaria. Imparerai di più sulla funzione di output multiclasse in un tutorial futuro.
Come funziona il classificatore binario?
Nel tutorial precedente hai imparato che una funzione è composta da due tipi di variabili, una variabile dipendente e un insieme di caratteristiche (variabili indipendenti). Nella regressione lineare, una variabile dipendente è un numero reale senza intervallo. L'obiettivo primario è prevederne il valore minimizzando l'errore quadratico medio.
Per TensorFlow Binary Classifier, l'etichetta può avere due possibili valori interi. Nella maggior parte dei casi è [0,1] o [1,2]. Ad esempio, l’obiettivo è prevedere se un cliente acquisterà o meno un prodotto. L'etichetta è definita come segue:
- Y = 1 (il cliente ha acquistato il prodotto)
- Y = 0 (il cliente non acquista il prodotto)
Il modello utilizza le caratteristiche X per classificare ciascun cliente nella classe più probabile di appartenenza, ovvero potenziale acquirente o meno.
Si calcola la probabilità di successo regressione logistica. L'algoritmo calcolerà una probabilità basata sulla caratteristica X e prevederà un successo quando questa probabilità sarà superiore al 50%. Più formalmente, la probabilità viene calcolata come mostrato nell'esempio di classificazione binaria TensorFlow riportato di seguito:
dove 0 è l'insieme dei pesi, delle caratteristiche eb il bias.
La funzione può essere scomposta in due parti:
- Il modello lineare
- La funzione logistica
Modello lineare
Conosci già il modo in cui vengono calcolati i pesi. I pesi vengono calcolati utilizzando un prodotto scalare: Y è una funzione lineare di tutte le caratteristiche xi. Se il modello non ha caratteristiche, la previsione è uguale al bias, b.
I pesi indicano la direzione della correlazione tra le caratteristiche xi e l'etichetta y. Una correlazione positiva aumenta la probabilità della classe positiva mentre una correlazione negativa porta la probabilità più vicino a 0 (cioè classe negativa).
Il modello lineare restituisce solo un numero reale, che non è coerente con la misura di probabilità dell'intervallo [0,1]. La funzione logistica è necessaria per convertire l'output del modello lineare in una probabilità,
Funzione logistica
La funzione logistica, o funzione sigmoide, ha una forma a S e l'output di questa funzione è sempre compreso tra 0 e 1.
È facile sostituire l'output della regressione lineare nella funzione sigmoidea. Il risultato è un nuovo numero con una probabilità compresa tra 0 e 1.
Il classificatore può trasformare la probabilità in una classe
- I valori compresi tra 0 e 0.49 diventano classe 0
- I valori compresi tra 0.5 e 1 diventano classe 1
Come misurare le prestazioni del classificatore lineare?
Precisione
Le prestazioni complessive di un classificatore vengono misurate con la metrica dell'accuratezza. L'accuratezza raccoglie tutti i valori corretti divisi per il numero totale di osservazioni. Ad esempio, un valore di precisione dell'80% significa che il modello è corretto nell'80% dei casi.
Si può notare una lacuna con questa metrica, specialmente per la classe di squilibrio. Un set di dati di squilibrio si verifica quando il numero di osservazioni per gruppo non è uguale. Diciamo; provi a classificare un evento raro con una funzione logistica. Immagina che il classificatore provi a stimare la morte di un paziente a seguito di una malattia. Nei dati, il 5 percento dei pazienti muore. Puoi addestrare un classificatore a prevedere il numero di decessi e usare la metrica di accuratezza per valutare le prestazioni. Se il classificatore prevede 0 decessi per l'intero set di dati, sarà corretto nel 95 percento dei casi.
Matrice di confusione
Un modo migliore per valutare le prestazioni di un classificatore è guardare la matrice di confusione.
Le matrice di confusione visualizza l'accuratezza di un classificatore confrontando le classi effettive e previste come mostrato nell'esempio di classificatore lineare sopra. La matrice di confusione binaria è composta da quadrati:
- TP: Vero positivo: valori previsti correttamente previsti come positivi effettivi
- FP: I valori previsti prevedevano erroneamente un positivo effettivo. cioè, valori negativi previsti come positivi
- FN: Falso negativo: valori positivi previsti come negativi
- TN: vero negativo: valori previsti correttamente previsti come negativi effettivi
Dalla matrice di confusione è facile confrontare la classe effettiva e la classe prevista.
Precisione e sensibilità
La matrice di confusione fornisce una buona visione del vero positivo e del falso positivo. In alcuni casi, è preferibile avere una metrica più concisa.
Precisione
La metrica di precisione mostra l'accuratezza della classe positiva. Misura la probabilità che la previsione della classe positiva sia corretta.
Il punteggio massimo è 1 quando il classificatore classifica perfettamente tutti i valori positivi. La precisione da sola non è molto utile perché ignora la classe negativa. La metrica è solitamente abbinata alla metrica di richiamo. Il richiamo è anche chiamato sensibilità o tasso di vero positivo.
Sensibilità
La sensibilità calcola il rapporto delle classi positive rilevate correttamente. Questa metrica indica quanto è buono il modello nel riconoscere una classe positiva.
Classificatore lineare con TensorFlow
Per questo tutorial utilizzeremo il set di dati del censimento. Lo scopo è utilizzare le variabili nel set di dati del censimento per prevedere il livello di reddito. Si noti che il reddito è una variabile binaria
- con valore 1 se reddito > 50k
- 0 se reddito < 50k.
Questa variabile è la tua etichetta
Questo set di dati include otto variabili categoriali:
- sul posto di lavoro
- continua
- coniugale
- occupazione
- rapporto
- gara
- sesso
- Paese d'origine
inoltre, sei variabili continue:
- fnlwgt
- numero_istruzione
- plusvalenza
- perdita_capitale
- ore_settimana
Attraverso questo esempio di classificazione TensorFlow, capirai come addestrare i classificatori TensorFlow lineari con lo stimatore TensorFlow e come migliorare la metrica di precisione.
Procederemo come segue:
- Passaggio 1) Importa i dati
- Passaggio 2) Conversione dei dati
- Passaggio 3) Addestrare il classificatore
- Passaggio 4) Migliorare il modello
- Passaggio 5) Iperparametro: Lazo e Ridge
Passaggio 1) Importa i dati
Per prima cosa importi le librerie utilizzate durante il tutorial.
import tensorflow as tf import pandas as pd
Successivamente, importi i dati dall'archivio di UCI e definisci i nomi delle colonne. Utilizzerai COLUMNS per nominare le colonne in un data frame pandas.
Tieni presente che addestrerai il classificatore utilizzando un dataframe Pandas.
## Define path data COLUMNS = ['age','workclass', 'fnlwgt', 'education', 'education_num', 'marital', 'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss', 'hours_week', 'native_country', 'label'] PATH = "https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data" PATH_test = "https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.test"
I dati memorizzati online sono già suddivisi tra treno e set di prova.
df_train = pd.read_csv(PATH, skipinitialspace=True, names = COLUMNS, index_col=False) df_test = pd.read_csv(PATH_test,skiprows = 1, skipinitialspace=True, names = COLUMNS, index_col=False)
Il set di treni contiene 32,561 osservazioni e il set di test 16,281
print(df_train.shape, df_test.shape) print(df_train.dtypes) (32561, 15) (16281, 15) age int64 workclass object fnlwgt int64 education object education_num int64 marital object occupation object relationship object race object sex object capital_gain int64 capital_loss int64 hours_week int64 native_country object label object dtype: object
Tensorflow richiede un valore booleano per addestrare il classificatore. È necessario trasmettere i valori da stringa a numero intero. L'etichetta viene memorizzata come oggetto, tuttavia è necessario convertirla in un valore numerico. Il codice seguente crea un dizionario con i valori da convertire ed eseguire il loop sull'elemento della colonna. Tieni presente che questa operazione viene eseguita due volte, una per il test del treno e una per il test set
label = {'<=50K': 0,'>50K': 1} df_train.label = [label[item] for item in df_train.label] label_t = {'<=50K.': 0,'>50K.': 1} df_test.label = [label_t[item] for item in df_test.label]
Nei dati dei treni risultano 24,720 redditi inferiori a 50mila e 7841 superiori. Il rapporto è quasi lo stesso per il set di prova. Per ulteriori informazioni, fare riferimento a questo tutorial su Facets.
print(df_train["label"].value_counts()) ### The model will be correct in atleast 70% of the case print(df_test["label"].value_counts()) ## Unbalanced label print(df_train.dtypes) 0 24720 1 7841 Name: label, dtype: int64 0 12435 1 3846 Name: label, dtype: int64 age int64 workclass object fnlwgt int64 education object education_num int64 marital object occupation object relationship object race object sex object capital_gain int64 capital_loss int64 hours_week int64 native_country object label int64 dtype: object
Passaggio 2) Conversione dei dati
Sono necessari alcuni passaggi prima di addestrare un classificatore lineare con Tensorflow. È necessario preparare le feature da includere nel modello. Nella regressione benchmark utilizzerai i dati originali senza applicare alcuna trasformazione.
Lo stimatore deve disporre di un elenco di funzionalità per addestrare il modello. Pertanto, i dati della colonna devono essere convertiti in un tensore.
Una buona pratica è definire due elenchi di funzionalità in base al loro tipo e quindi passarli nella feature_columns dello stimatore.
Inizierai convertendo le feature continue, quindi definirai un bucket con i dati categorici.
Le funzionalità del set di dati hanno due formati:
- Numero intero
- Oggetto
Ciascuna caratteristica è elencata nelle due variabili successive in base al tipo.
## Add features to the bucket: ### Define continuous list CONTI_FEATURES = ['age', 'fnlwgt','capital_gain', 'education_num', 'capital_loss', 'hours_week'] ### Define the categorical list CATE_FEATURES = ['workclass', 'education', 'marital', 'occupation', 'relationship', 'race', 'sex', 'native_country']
La feature_column è dotata di un oggetto numeric_column per aiutare nella trasformazione delle variabili continue in tensore. Nel codice seguente, converti tutte le variabili da CONTI_FEATURES in un tensore con un valore numerico. Questo è obbligatorio per costruire il modello. Tutte le variabili indipendenti devono essere convertite nel tipo corretto di tensore.
Di seguito scriviamo un codice per farti vedere cosa sta succedendo dietro feature_column.numeric_column. Stamperemo il valore convertito per age. È a scopo esplicativo, quindi non è necessario comprendere il codice Python. È possibile fare riferimento alla documentazione ufficiale per comprendere i codici.
def print_transformation(feature = "age", continuous = True, size = 2): #X = fc.numeric_column(feature) ## Create feature name feature_names = [ feature] ## Create dict with the data d = dict(zip(feature_names, [df_train[feature]])) ## Convert age if continuous == True: c = tf.feature_column.numeric_column(feature) feature_columns = [c] else: c = tf.feature_column.categorical_column_with_hash_bucket(feature, hash_bucket_size=size) c_indicator = tf.feature_column.indicator_column(c) feature_columns = [c_indicator] ## Use input_layer to print the value input_layer = tf.feature_column.input_layer( features=d, feature_columns=feature_columns ) ## Create lookup table zero = tf.constant(0, dtype=tf.float32) where = tf.not_equal(input_layer, zero) ## Return lookup tble indices = tf.where(where) values = tf.gather_nd(input_layer, indices) ## Initiate graph sess = tf.Session() ## Print value print(sess.run(input_layer)) print_transformation(feature = "age", continuous = True) [[39.] [50.] [38.] ... [58.] [22.] [52.]]
I valori sono esattamente gli stessi di df_train
continuous_features = [tf.feature_column.numeric_column(k) for k in CONTI_FEATURES]
Secondo la documentazione di TensorFlow, esistono diversi modi per convertire i dati categorici. Se l'elenco dei vocaboli di una funzionalità è noto e non ha molti valori, è possibile creare la colonna categoriale con categorical_column_with_vocabulary_list. Assegnerà a tutti gli elenchi di vocaboli univoci un ID.
Ad esempio, se lo stato di una variabile ha tre valori distinti:
- Marito
- Moglie
- Singolo
Verranno quindi attribuiti tre ID. Ad esempio, il marito avrà l'ID 1, la moglie l'ID 2 e così via.
A scopo illustrativo, puoi utilizzare questo codice per convertire una variabile oggetto in una colonna categoriale in TensorFlow.
La caratteristica sesso può avere solo due valori: maschile o femminile. Quando convertiremo la funzione sesso, Tensorflow creerà 2 nuove colonne, una per maschio e una per femmina. Se il sesso è uguale a maschio, la nuova colonna maschile sarà uguale a 1 e femminile a 0. Questo esempio è visualizzato nella tabella seguente:
righe | sesso | dopo la trasformazione | maschio | la donna |
---|---|---|---|---|
1 | maschio | => | 1 | 0 |
2 | maschio | => | 1 | 0 |
3 | la donna | => | 0 | 1 |
Nel tensorflusso:
print_transformation(feature = "sex", continuous = False, size = 2) [[1. 0.] [1. 0.] [1. 0.] ... [0. 1.] [1. 0.] [0. 1.]] relationship = tf.feature_column.categorical_column_with_vocabulary_list( 'relationship', [ 'Husband', 'Not-in-family', 'Wife', 'Own-child', 'Unmarried', 'Other-relative'])
Di seguito, abbiamo aggiunto Python code per stampare la codifica. Ancora una volta, non è necessario comprendere il codice, lo scopo è vedere la trasformazione
Tuttavia, un modo più rapido per trasformare i dati è utilizzare il metodo categorical_column_with_hash_bucket. Sarà utile modificare le variabili stringa in una matrice sparsa. Una matrice sparsa è una matrice con prevalentemente zero. Il metodo si occupa di tutto. Devi solo specificare il numero di bucket e la colonna chiave. Il numero di bucket è la quantità massima di gruppi che Tensorflow può creare. La colonna chiave è semplicemente il nome della colonna da convertire.
Nel codice seguente, crei un ciclo su tutte le funzionalità categoriali.
categorical_features = [tf.feature_column.categorical_column_with_hash_bucket(k, hash_bucket_size=1000) for k in CATE_FEATURES]
Passaggio 3) Addestrare il classificatore
TensorFlow attualmente fornisce uno stimatore per la regressione lineare e la classificazione lineare.
- Regressione lineare: LinearRegressor
- Classificazione lineare: LinearClassifier
La sintassi del classificatore lineare è la stessa del tutorial su regressione lineare tranne un argomento, n_class. È necessario definire la colonna delle caratteristiche, la directory del modello e confrontarla con il regressore lineare; devi definire il numero di classe. Per una regressione logit, il numero di classi è uguale a 2.
Il modello calcolerà i pesi delle colonne contenute in Continuous_features e categorical_features.
model = tf.estimator.LinearClassifier( n_classes = 2, model_dir="ongoing/train", feature_columns=categorical_features+ continuous_features)
Uscita
INFO:tensorflow:Using default config. INFO:tensorflow:Using config: {'_model_dir': 'ongoing/train', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': None, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_service': None, '_cluster_spec': <tensorflow.python.training.server_lib.ClusterSpec object at 0x181f24c898>, '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}
Ora che il classificatore è definito, puoi creare la funzione di input. Il metodo è lo stesso del tutorial sul regressore lineare. In questo caso si utilizza una dimensione batch di 128 e si mescolano i dati.
FEATURES = ['age','workclass', 'fnlwgt', 'education', 'education_num', 'marital', 'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss', 'hours_week', 'native_country'] LABEL= 'label' def get_input_fn(data_set, num_epochs=None, n_batch = 128, shuffle=True): return tf.estimator.inputs.pandas_input_fn( x=pd.DataFrame({k: data_set[k].values for k in FEATURES}), y = pd.Series(data_set[LABEL].values), batch_size=n_batch, num_epochs=num_epochs, shuffle=shuffle)
Crei una funzione con gli argomenti richiesti dallo stimatore lineare, ovvero numero di epoche, numero di lotti e mescola il set di dati o la nota. Dal momento che usi il Pandas metodo per passare i dati nel modello, è necessario definire le variabili X come frame di dati panda. Tieni presente che esegui il loop su tutti i dati memorizzati in FEATURES.
Addestriamo il modello con l'oggetto model.train. Si utilizza la funzione definita in precedenza per alimentare il modello con i valori appropriati. Tieni presente che imposti la dimensione batch su 128 e il numero di epoche su Nessuna. Il modello verrà addestrato su mille passaggi.
model.train(input_fn=get_input_fn(df_train, num_epochs=None, n_batch = 128, shuffle=False), steps=1000)
INFO:tensorflow:Calling model_fn. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Create CheckpointSaverHook. INFO:tensorflow: Graph was finalized. INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Saving checkpoints for 1 into ongoing/train/model.ckpt. INFO:tensorflow:loss = 88.722855, step = 1 INFO:tensorflow:global_step/sec: 65.8282 INFO:tensorflow:loss = 52583.64, step = 101 (1.528 sec) INFO:tensorflow:global_step/sec: 118.386 INFO:tensorflow:loss = 25203.816, step = 201 (0.837 sec) INFO:tensorflow:global_step/sec: 110.542 INFO:tensorflow:loss = 54924.312, step = 301 (0.905 sec) INFO:tensorflow:global_step/sec: 199.03 INFO:tensorflow:loss = 68509.31, step = 401 (0.502 sec) INFO:tensorflow:global_step/sec: 167.488 INFO:tensorflow:loss = 9151.754, step = 501 (0.599 sec) INFO:tensorflow:global_step/sec: 220.155 INFO:tensorflow:loss = 34576.06, step = 601 (0.453 sec) INFO:tensorflow:global_step/sec: 199.016 INFO:tensorflow:loss = 36047.117, step = 701 (0.503 sec) INFO:tensorflow:global_step/sec: 197.531 INFO:tensorflow:loss = 22608.148, step = 801 (0.505 sec) INFO:tensorflow:global_step/sec: 208.479 INFO:tensorflow:loss = 22201.918, step = 901 (0.479 sec) INFO:tensorflow:Saving checkpoints for 1000 into ongoing/train/model.ckpt. INFO:tensorflow:Loss for final step: 5444.363. <tensorflow.python.estimator.canned.linear.LinearClassifier at 0x181f223630>
Da notare che la perdita è diminuita successivamente durante gli ultimi 100 passi, cioè da 901 a 1000.
La perdita finale dopo mille iterazioni è 5444. Puoi stimare il tuo modello sul set di test e vedere le prestazioni. Per valutare le prestazioni del tuo modello, devi utilizzare l'oggettovaluta. Si alimenta il modello con il set di test e si imposta il numero di epoche su 1, ovvero i dati verranno inviati al modello solo una volta.
model.evaluate(input_fn=get_input_fn(df_test, num_epochs=1, n_batch = 128, shuffle=False), steps=1000)
INFO:tensorflow:Calling model_fn. WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to "careful_interpolation" instead. WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to "careful_interpolation" instead. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Starting evaluation at 2018-06-02-08:28:22 INFO:tensorflow:Graph was finalized. INFO:tensorflow:Restoring parameters from ongoing/train/model.ckpt-1000 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Evaluation [100/1000] INFO:tensorflow:Finished evaluation at 2018-06-02-08:28:23 INFO:tensorflow:Saving dict for global step 1000: accuracy = 0.7615626, accuracy_baseline = 0.76377374, auc = 0.63300294, auc_precision_recall = 0.50891197, average_loss = 47.12155, global_step = 1000, label/mean = 0.23622628, loss = 5993.6406, precision = 0.49401596, prediction/mean = 0.18454961, recall = 0.38637546 {'accuracy': 0.7615626, 'accuracy_baseline': 0.76377374, 'auc': 0.63300294, 'auc_precision_recall': 0.50891197, 'average_loss': 47.12155, 'global_step': 1000, 'label/mean': 0.23622628, 'loss': 5993.6406, 'precision': 0.49401596, 'prediction/mean': 0.18454961, 'recall': 0.38637546}
TensorFlow restituisce tutte le metriche apprese nella parte teorica. Senza sorpresa, la precisione è elevata a causa dell'etichetta sbilanciata. In realtà, il modello funziona leggermente meglio di un'ipotesi casuale. Immagina che il modello preveda tutte le famiglie con reddito inferiore a 50, quindi il modello ha una precisione del 70%. Ad un'analisi più attenta, puoi vedere che la previsione e il richiamo sono piuttosto bassi.
Passaggio 4) Migliorare il modello
Ora che hai un modello di riferimento, puoi provare a migliorarlo, ovvero ad aumentare la precisione. Nel tutorial precedente hai imparato come migliorare il potere di previsione con un termine di interazione. In questo tutorial rivisiterai questa idea aggiungendo un termine polinomiale alla regressione.
La regressione polinomiale è strumentale quando è presente non linearità nei dati. Esistono due modi per acquisire la non linearità nei dati.
- Aggiungi termine polinomiale
- Dividere la variabile continua in una variabile categoriale
Termine polinomiale
Dall'immagine qui sotto puoi vedere cos'è una regressione polinomiale. È un'equazione con X variabili con potenza diversa. Una regressione polinomiale di secondo grado ha due variabili, X e X al quadrato. Il terzo grado ha tre variabili, X, X2, e X3
Di seguito, abbiamo costruito un grafico con due variabili, X e Y. È ovvio che la relazione non è lineare. Se aggiungiamo una regressione lineare, possiamo vedere che il modello non è in grado di catturare il modello (immagine a sinistra).
Ora, guarda l'immagine a sinistra dell'immagine qui sotto, abbiamo aggiunto cinque termini alla regressione (ovvero y=x+x2+x3+x4+x5. Il modello ora cattura molto meglio il modello. Questo è il potere della regressione polinomiale.
Torniamo al nostro esempio. L’età non è in una relazione lineare con il reddito. La giovane età potrebbe avere un reddito piatto vicino allo zero perché i bambini o i giovani non lavorano. Poi aumenta in età lavorativa e diminuisce durante la pensione. Tipicamente è una forma a U rovesciata. Un modo per catturare questo modello è aggiungere una potenza due alla regressione.
Vediamo se aumenta la precisione.
È necessario aggiungere questa nuova funzionalità al set di dati e nell'elenco delle funzionalità continue.
Aggiungi la nuova variabile nel set di dati train e test, quindi è più conveniente scrivere una funzione.
def square_var(df_t, df_te, var_name = 'age'): df_t['new'] = df_t[var_name].pow(2) df_te['new'] = df_te[var_name].pow(2) return df_t, df_te
La funzione ha 3 argomenti:
- df_t: definisce il set di addestramento
- df_te: definisce il set di test
- var_name = 'age': definisce la variabile da trasformare
Puoi usare l'oggetto pow(2) per elevare al quadrato la variabile età. Tieni presente che la nuova variabile si chiama "new"
Ora che la funzione sq_var è stata scritta, puoi creare i nuovi set di dati.
df_train_new, df_test_new = square_var(df_train, df_test, var_name = 'age')
Come puoi vedere, il nuovo set di dati ha un'altra funzionalità.
print(df_train_new.shape, df_test_new.shape) (32561, 16) (16281, 16)
La variabile quadrata è chiamata new nel set di dati. È necessario aggiungerlo all'elenco delle funzionalità continue.
CONTI_FEATURES_NEW = ['age', 'fnlwgt','capital_gain', 'education_num', 'capital_loss', 'hours_week', 'new'] continuous_features_new = [tf.feature_column.numeric_column(k) for k in CONTI_FEATURES_NEW]
Note: che hai cambiato la directory di Graph. Non è possibile addestrare modelli diversi nella stessa directory. Significa che devi cambiare il percorso dell'argomento model_dir. In caso contrario, TensorFlow genererà un errore.
model_1 = tf.estimator.LinearClassifier( model_dir="ongoing/train1", feature_columns=categorical_features+ continuous_features_new)
INFO:tensorflow:Using default config. INFO:tensorflow:Using config: {'_model_dir': 'ongoing/train1', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': None, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_service': None, '_cluster_spec': <tensorflow.python.training.server_lib.ClusterSpec object at 0x1820f04b70>, '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1} FEATURES_NEW = ['age','workclass', 'fnlwgt', 'education', 'education_num', 'marital', 'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss', 'hours_week', 'native_country', 'new'] def get_input_fn(data_set, num_epochs=None, n_batch = 128, shuffle=True): return tf.estimator.inputs.pandas_input_fn( x=pd.DataFrame({k: data_set[k].values for k in FEATURES_NEW}), y = pd.Series(data_set[LABEL].values), batch_size=n_batch, num_epochs=num_epochs, shuffle=shuffle)
Ora che il classificatore è stato progettato con il nuovo set di dati, puoi addestrare e valutare il modello.
model_1.train(input_fn=get_input_fn(df_train, num_epochs=None, n_batch = 128, shuffle=False), steps=1000)
INFO:tensorflow:Calling model_fn. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Create CheckpointSaverHook. INFO:tensorflow:Graph was finalized. INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Saving checkpoints for 1 into ongoing/train1/model.ckpt. INFO:tensorflow:loss = 88.722855, step = 1 INFO:tensorflow:global_step/sec: 81.487 INFO:tensorflow:loss = 70077.66, step = 101 (1.228 sec) INFO:tensorflow:global_step/sec: 111.169 INFO:tensorflow:loss = 49522.082, step = 201 (0.899 sec) INFO:tensorflow:global_step/sec: 128.91 INFO:tensorflow:loss = 107120.57, step = 301 (0.776 sec) INFO:tensorflow:global_step/sec: 132.546 INFO:tensorflow:loss = 12814.152, step = 401 (0.755 sec) INFO:tensorflow:global_step/sec: 162.194 INFO:tensorflow:loss = 19573.898, step = 501 (0.617 sec) INFO:tensorflow:global_step/sec: 204.852 INFO:tensorflow:loss = 26381.986, step = 601 (0.488 sec) INFO:tensorflow:global_step/sec: 188.923 INFO:tensorflow:loss = 23417.719, step = 701 (0.529 sec) INFO:tensorflow:global_step/sec: 192.041 INFO:tensorflow:loss = 23946.049, step = 801 (0.521 sec) INFO:tensorflow:global_step/sec: 197.025 INFO:tensorflow:loss = 3309.5786, step = 901 (0.507 sec) INFO:tensorflow:Saving checkpoints for 1000 into ongoing/train1/model.ckpt. INFO:tensorflow:Loss for final step: 28861.898. <tensorflow.python.estimator.canned.linear.LinearClassifier at 0x1820f04c88>
model_1.evaluate(input_fn=get_input_fn(df_test_new, num_epochs=1, n_batch = 128, shuffle=False), steps=1000)
INFO:tensorflow:Calling model_fn. WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to "careful_interpolation" instead. WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to "careful_interpolation" instead. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Starting evaluation at 2018-06-02-08:28:37 INFO:tensorflow:Graph was finalized. INFO:tensorflow:Restoring parameters from ongoing/train1/model.ckpt-1000 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Evaluation [100/1000] INFO:tensorflow:Finished evaluation at 2018-06-02-08:28:39 INFO:tensorflow:Saving dict for global step 1000: accuracy = 0.7944229, accuracy_baseline = 0.76377374, auc = 0.6093755, auc_precision_recall = 0.54885805, average_loss = 111.0046, global_step = 1000, label/mean = 0.23622628, loss = 14119.265, precision = 0.6682401, prediction/mean = 0.09116262, recall = 0.2576703 {'accuracy': 0.7944229, 'accuracy_baseline': 0.76377374, 'auc': 0.6093755, 'auc_precision_recall': 0.54885805, 'average_loss': 111.0046, 'global_step': 1000, 'label/mean': 0.23622628, 'loss': 14119.265, 'precision': 0.6682401, 'prediction/mean': 0.09116262, 'recall': 0.2576703}
La variabile quadrata ha migliorato la precisione da 0.76 a 0.79. Vediamo se riesci a fare meglio combinando insieme il termine bucketizzazione e interazione.
Secchizzazione e interazione
Come hai visto prima, un classificatore lineare non è in grado di catturare correttamente il modello età-reddito. Questo perché apprende un singolo peso per ciascuna funzione. Per semplificare il compito del classificatore, una cosa che puoi fare è inserire la funzionalità in un bucket. Il bucket trasforma una caratteristica numerica in diverse determinate in base all'intervallo in cui rientra e ciascuna di queste nuove funzionalità indica se l'età di una persona rientra in tale intervallo.
Con queste nuove funzionalità, il modello lineare può catturare la relazione apprendendo pesi diversi per ciascun segmento.
In TensorFlow, viene eseguito con bucketized_column. È necessario aggiungere l'intervallo di valori nei limiti.
age = tf.feature_column.numeric_column('age') age_buckets = tf.feature_column.bucketized_column( age, boundaries=[18, 25, 30, 35, 40, 45, 50, 55, 60, 65])
Sai già che l'età non è lineare con il reddito. Un altro modo per migliorare il modello è attraverso l'interazione. In termini di TensorFlow, si tratta di incrocio di funzionalità. L'incrocio di funzionalità è un modo per creare nuove funzionalità che sono combinazioni di quelle esistenti, il che può essere utile per un classificatore lineare che non può modellare le interazioni tra le funzionalità.
Puoi scomporre l'età con un'altra caratteristica come l'istruzione. Cioè, è probabile che alcuni gruppi abbiano un reddito alto e altri basso (si pensi allo studente di dottorato).
education_x_occupation = [tf.feature_column.crossed_column( ['education', 'occupation'], hash_bucket_size=1000)] age_buckets_x_education_x_occupation = [tf.feature_column.crossed_column( [age_buckets, 'education', 'occupation'], hash_bucket_size=1000)]
Per creare una colonna con caratteristiche incrociate, utilizzare cross_column con le variabili da incrociare tra parentesi. L'hash_bucket_size indica le massime possibilità di incrocio. Per creare interazione tra variabili (almeno una variabile deve essere categorica), puoi utilizzare tf.feature_column.crossed_column. Per utilizzare questo oggetto è necessario aggiungere tra parentesi quadre la variabile con cui interagire e un secondo argomento, la dimensione del bucket. La dimensione del bucket è il numero massimo di gruppi possibili all'interno di una variabile. Qui lo imposti su 1000 poiché non conosci il numero esatto di gruppi
age_buckets deve essere elevato al quadrato prima di aggiungerlo alle colonne delle funzionalità. Aggiungi anche le nuove funzionalità alle colonne delle funzionalità e prepari lo stimatore
base_columns = [ age_buckets, ] model_imp = tf.estimator.LinearClassifier( model_dir="ongoing/train3", feature_columns=categorical_features+base_columns+education_x_occupation+age_buckets_x_education_x_occupation)
Uscita
INFO:tensorflow:Using default config. INFO:tensorflow:Using config: {'_model_dir': 'ongoing/train3', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': None, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_service': None, '_cluster_spec': <tensorflow.python.training.server_lib.ClusterSpec object at 0x1823021be0>, '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}
FEATURES_imp = ['age','workclass', 'education', 'education_num', 'marital', 'occupation', 'relationship', 'race', 'sex', 'native_country', 'new'] def get_input_fn(data_set, num_epochs=None, n_batch = 128, shuffle=True): return tf.estimator.inputs.pandas_input_fn( x=pd.DataFrame({k: data_set[k].values for k in FEATURES_imp}), y = pd.Series(data_set[LABEL].values), batch_size=n_batch, num_epochs=num_epochs, shuffle=shuffle)
Sei pronto per stimare il nuovo modello e vedere se migliora la precisione.
model_imp.train(input_fn=get_input_fn(df_train_new, num_epochs=None, n_batch = 128, shuffle=False), steps=1000)
INFO:tensorflow:Calling model_fn. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Create CheckpointSaverHook. INFO:tensorflow:Graph was finalized. INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Saving checkpoints for 1 into ongoing/train3/model.ckpt. INFO:tensorflow:loss = 88.722855, step = 1 INFO:tensorflow:global_step/sec: 94.969 INFO:tensorflow:loss = 50.334488, step = 101 (1.054 sec) INFO:tensorflow:global_step/sec: 242.342 INFO:tensorflow:loss = 56.153225, step = 201 (0.414 sec) INFO:tensorflow:global_step/sec: 213.686 INFO:tensorflow:loss = 45.792007, step = 301 (0.470 sec) INFO:tensorflow:global_step/sec: 174.084 INFO:tensorflow:loss = 37.485672, step = 401 (0.572 sec) INFO:tensorflow:global_step/sec: 191.78 INFO:tensorflow:loss = 56.48449, step = 501 (0.524 sec) INFO:tensorflow:global_step/sec: 163.436 INFO:tensorflow:loss = 32.528934, step = 601 (0.612 sec) INFO:tensorflow:global_step/sec: 164.347 INFO:tensorflow:loss = 37.438057, step = 701 (0.607 sec) INFO:tensorflow:global_step/sec: 154.274 INFO:tensorflow:loss = 61.1075, step = 801 (0.647 sec) INFO:tensorflow:global_step/sec: 189.14 INFO:tensorflow:loss = 44.69645, step = 901 (0.531 sec) INFO:tensorflow:Saving checkpoints for 1000 into ongoing/train3/model.ckpt. INFO:tensorflow:Loss for final step: 44.18133. <tensorflow.python.estimator.canned.linear.LinearClassifier at 0x1823021cf8>
model_imp.evaluate(input_fn=get_input_fn(df_test_new, num_epochs=1, n_batch = 128, shuffle=False), steps=1000)
INFO:tensorflow:Calling model_fn. WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to "careful_interpolation" instead. WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to "careful_interpolation" instead. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Starting evaluation at 2018-06-02-08:28:52 INFO:tensorflow:Graph was finalized. INFO:tensorflow:Restoring parameters from ongoing/train3/model.ckpt-1000 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Evaluation [100/1000] INFO:tensorflow:Finished evaluation at 2018-06-02-08:28:54 INFO:tensorflow:Saving dict for global step 1000: accuracy = 0.8358209, accuracy_baseline = 0.76377374, auc = 0.88401634, auc_precision_recall = 0.69599575, average_loss = 0.35122654, global_step = 1000, label/mean = 0.23622628, loss = 44.67437, precision = 0.68986726, prediction/mean = 0.23320661, recall = 0.55408216 {'accuracy': 0.8358209, 'accuracy_baseline': 0.76377374, 'auc': 0.88401634, 'auc_precision_recall': 0.69599575, 'average_loss': 0.35122654, 'global_step': 1000, 'label/mean': 0.23622628, 'loss': 44.67437, 'precision': 0.68986726, 'prediction/mean': 0.23320661, 'recall': 0.55408216}
Il nuovo livello di precisione è pari all'83.58%. È del XNUMX% più alto rispetto al modello precedente.
Infine, è possibile aggiungere un termine di regolarizzazione per evitare un overfitting.
Passaggio 5) Iperparametro: Lazo e Ridge
Il tuo modello può soffrirne overfitting or inadeguato.
- Overfitting: il modello non è in grado di generalizzare la previsione a nuovi dati
- Underfitting: il modello non è in grado di catturare il modello dei dati. cioè, regressione lineare quando i dati non sono lineari
Quando un modello ha molti parametri e una quantità relativamente bassa di dati, porta a previsioni inadeguate. Immagina, un gruppo ha solo tre osservazioni; il modello calcolerà un peso per questo gruppo. Il peso viene utilizzato per fare una previsione; se le osservazioni del set di test per questo particolare gruppo sono completamente diverse dal set di addestramento, il modello farà una previsione sbagliata. Durante la valutazione con il set di addestramento, la precisione è buona, ma non buona con il set di test perché i pesi calcolati non sono quelli reali per generalizzare il modello. In questo caso, non fa una previsione ragionevole su dati invisibili.
Per evitare l'overfitting, la regolarizzazione ti dà la possibilità di controllare tale complessità e renderla più generalizzabile. Esistono due tecniche di regolarizzazione:
- L1: Lazo
- L2: Cresta
In TensorFlow, puoi aggiungere questi due iperparametri nell'ottimizzatore. Ad esempio, quanto più alto è l'iperparametro L2, tanto più il peso tende ad essere molto basso e prossimo allo zero. La linea adattata sarà molto piatta, mentre una L2 vicina allo zero implica che i pesi siano vicini alla regressione lineare regolare.
Puoi provare tu stesso i diversi valori degli iperparametri e vedere se riesci ad aumentare il livello di precisione.
Note: che se si modifica l'iperparametro, è necessario eliminare la cartella going/train4 altrimenti il modello partirà con il modello precedentemente addestrato.
Vediamo come è la precisione con l'hype
model_regu = tf.estimator.LinearClassifier( model_dir="ongoing/train4", feature_columns=categorical_features+base_columns+education_x_occupation+age_buckets_x_education_x_occupation, optimizer=tf.train.FtrlOptimizer( learning_rate=0.1, l1_regularization_strength=0.9, l2_regularization_strength=5))
USCITA
INFO:tensorflow:Using default config. INFO:tensorflow:Using config: {'_model_dir': 'ongoing/train4', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': None, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_service': None, '_cluster_spec': <tensorflow.python.training.server_lib.ClusterSpec object at 0x1820d9c128>, '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}
model_regu.train(input_fn=get_input_fn(df_train_new, num_epochs=None, n_batch = 128, shuffle=False), steps=1000)
USCITA
INFO:tensorflow:Calling model_fn. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Create CheckpointSaverHook. INFO:tensorflow:Graph was finalized. INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Saving checkpoints for 1 into ongoing/train4/model.ckpt. INFO:tensorflow:loss = 88.722855, step = 1 INFO:tensorflow:global_step/sec: 77.4165 INFO:tensorflow:loss = 50.38778, step = 101 (1.294 sec) INFO:tensorflow:global_step/sec: 187.889 INFO:tensorflow:loss = 55.38014, step = 201 (0.535 sec) INFO:tensorflow:global_step/sec: 201.895 INFO:tensorflow:loss = 46.806694, step = 301 (0.491 sec) INFO:tensorflow:global_step/sec: 217.992 INFO:tensorflow:loss = 38.68271, step = 401 (0.460 sec) INFO:tensorflow:global_step/sec: 193.676 INFO:tensorflow:loss = 56.99398, step = 501 (0.516 sec) INFO:tensorflow:global_step/sec: 202.195 INFO:tensorflow:loss = 33.263622, step = 601 (0.497 sec) INFO:tensorflow:global_step/sec: 216.756 INFO:tensorflow:loss = 37.7902, step = 701 (0.459 sec) INFO:tensorflow:global_step/sec: 240.215 INFO:tensorflow:loss = 61.732605, step = 801 (0.416 sec) INFO:tensorflow:global_step/sec: 220.336 INFO:tensorflow:loss = 46.938225, step = 901 (0.456 sec) INFO:tensorflow:Saving checkpoints for 1000 into ongoing/train4/model.ckpt. INFO:tensorflow:Loss for final step: 43.4942. <tensorflow.python.estimator.canned.linear.LinearClassifier at 0x181ff39e48>
model_regu.evaluate(input_fn=get_input_fn(df_test_new, num_epochs=1, n_batch = 128, shuffle=False), steps=1000)
Uscita
INFO:tensorflow:Calling model_fn. WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to "careful_interpolation" instead. WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to "careful_interpolation" instead. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Starting evaluation at 2018-06-02-08:29:07 INFO:tensorflow:Graph was finalized. INFO:tensorflow:Restoring parameters from ongoing/train4/model.ckpt-1000 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Evaluation [100/1000] INFO:tensorflow:Finished evaluation at 2018-06-02-08:29:09 INFO:tensorflow:Saving dict for global step 1000: accuracy = 0.83833915, accuracy_baseline = 0.76377374, auc = 0.8869794, auc_precision_recall = 0.7014905, average_loss = 0.34691378, global_step = 1000, label/mean = 0.23622628, loss = 44.12581, precision = 0.69720596, prediction/mean = 0.23662092, recall = 0.5579823 {'accuracy': 0.83833915, 'accuracy_baseline': 0.76377374, 'auc': 0.8869794, 'auc_precision_recall': 0.7014905, 'average_loss': 0.34691378, 'global_step': 1000, 'label/mean': 0.23622628, 'loss': 44.12581, 'precision': 0.69720596, 'prediction/mean': 0.23662092, 'recall': 0.5579823}
Con questo iperparametro aumenti leggermente le metriche di precisione. Nel prossimo tutorial imparerai come migliorare un classificatore lineare utilizzando un metodo kernel.
Sommario
Per addestrare un modello, è necessario:
- Definire le caratteristiche: Variabili indipendenti: X
- Definire l'etichetta: Variabile dipendente: y
- Costruisci un set di treni/test
- Definire il peso iniziale
- Definire la funzione di perdita: MSE
- Ottimizza il modello: discesa del gradiente
- Definire:
- Tasso di apprendimento
- Numero di epoche
- Dimensione del lotto
- Numero di classe
In questo tutorial hai imparato come utilizzare l'API di alto livello per un classificatore di regressione lineare. È necessario definire:
- Colonne di funzionalità. Se continuo: tf.feature_column.numeric_column(). Puoi popolare un elenco con la comprensione dell'elenco Python
- Lo stimatore: tf.estimator.LinearClassifier(feature_columns, model_dir, n_classes = 2)
- Una funzione per importare i dati, la dimensione del batch e l'epoca: input_fn()
Successivamente, sei pronto per allenarti, valutare e fare una previsione con train(),valuta() e predit()
Per migliorare le prestazioni del modello è possibile:
- Utilizzare la regressione polinomiale
- Termine di interazione: tf.feature_column.crossed_column
- Aggiungi parametro di regolarizzazione