TensorFlow binär klassificering: Linjär klassificeringsexempel

De två vanligaste övervakad inlärning uppgifter är linjär regression och linjär klassificerare. Linjär regression förutsäger ett värde medan den linjära klassificeraren förutsäger en klass. Denna handledning är fokuserad på linjära klassificerare.

Vad är linjär klassificerare?

A Linjär klassificerare i Machine Learning är en metod för att hitta ett objekts klass baserat på dess egenskaper för statistisk klassificering. Den fattar klassificeringsbeslut baserat på värdet av en linjär kombination av egenskaper hos ett objekt. Linjär klassificerare används i praktiska problem som dokumentklassificering och problem med många variabler.

Klassificeringsproblem representerar ungefär 80 procent av maskininlärningsuppgiften. Klassificering syftar till att förutsäga sannolikheten för varje klass givet en uppsättning indata. Etiketten (dvs. den beroende variabeln) är ett diskret värde som kallas en klass.

  1. Om etiketten bara har två klasser är inlärningsalgoritmen en binär klassificerare.
  2. Multiclass classifier hanterar etiketter med mer än två klasser.

Ett typiskt problem med binär klassificering är till exempel att förutsäga sannolikheten för att en kund gör ett andra köp. Förutsäga vilken typ av djur som visas på en bild är flerklassklassificeringsproblem eftersom det finns fler än två varianter av djur.

Den teoretiska delen av denna handledning lägger primärt fokus på den binära klassen. Du kommer att lära dig mer om multiclass output-funktionen i en framtida handledning.

Hur fungerar binär klassificerare?

Du lärde dig i föregående handledning att en funktion är sammansatt av två sorters variabler, en beroende variabel och en uppsättning funktioner (oberoende variabler). I linjär regression är en beroende variabel ett reellt tal utan intervall. Det primära målet är att förutsäga dess värde genom att minimera medelkvadratfelet.

För TensorFlow Binary Classifier kan etiketten ha haft två möjliga heltalsvärden. I de flesta fall är det antingen [0,1] eller [1,2]. Målet är till exempel att förutsäga om en kund kommer att köpa en produkt eller inte. Etiketten definieras enligt följande:

  • Y = 1 (kunden köpte produkten)
  • Y = 0 (kunden köper inte produkten)

Modellen använder funktionerna X för att klassificera varje kund i den mest sannolika klass han tillhör, nämligen potentiell köpare eller inte.

Sannolikheten för framgång beräknas med logistisk återgång. Algoritmen kommer att beräkna en sannolikhet baserad på funktionen X och förutspår en framgång när denna sannolikhet är över 50 procent. Mer formellt beräknas sannolikheten enligt nedanstående TensorFlow Binary Classification-exempel:

Exempel på binär klassificering

där 0 är mängden vikter, egenskaperna och b förspänningen.

Funktionen kan delas upp i två delar:

  • Den linjära modellen
  • Den logistiska funktionen

Linjär modell

Du är redan bekant med hur vikterna beräknas. Vikter beräknas med hjälp av en punktprodukt:Punkt produkt Y är en linjär funktion av alla funktioner xi. Om modellen inte har funktioner är förutsägelsen lika med bias, b.

Vikterna anger riktningen för korrelationen mellan egenskaperna xi och etiketten y. En positiv korrelation ökar sannolikheten för den positiva klassen medan en negativ korrelation leder sannolikheten närmare 0, (dvs negativ klass).

Den linjära modellen returnerar endast reella tal, vilket inte är förenligt med sannolikhetsmåttet för intervall [0,1]. Den logistiska funktionen krävs för att konvertera den linjära modellens utdata till en sannolikhet,

Logistisk funktion

Logistikfunktionen, eller sigmoidfunktionen, har en S-form och utgången för denna funktion är alltid mellan 0 och 1.

Exempel på logistisk funktion

Logistisk funktion Exempel
Exempel på logistisk funktion

Det är lätt att ersätta utsignalen från den linjära regressionen med sigmoidfunktionen. Det resulterar i ett nytt tal med en sannolikhet mellan 0 och 1.

Klassificeraren kan omvandla sannolikheten till en klass

  • Värden mellan 0 och 0.49 blir klass 0
  • Värden mellan 0.5 och 1 blir klass 1

Hur mäter man prestandan hos Linear Classifier?

Noggrannhet

Den totala prestandan för en klassificerare mäts med noggrannhetsmåttet. Noggrannhet samlar in alla korrekta värden dividerat med det totala antalet observationer. Till exempel betyder ett noggrannhetsvärde på 80 procent att modellen är korrekt i 80 procent av fallen.

Noggrannhetsmått
Mät prestandan för Linear Classifier med hjälp av noggrannhetsmått

Du kan notera en brist med detta mått, särskilt för obalansklass. En obalansdatauppsättning uppstår när antalet observationer per grupp inte är lika. Låt oss säga; du försöker klassificera en sällsynt händelse med en logistisk funktion. Föreställ dig att klassificeraren försöker uppskatta en patients död efter en sjukdom. I uppgifterna avlider 5 procent av patienterna. Du kan träna en klassificerare att förutsäga antalet dödsfall och använda noggrannhetsmåttet för att utvärdera prestationerna. Om klassificeraren förutsäger 0 dödsfall för hela datasetet kommer det att vara korrekt i 95 procent av fallet.

Förvirringsmatris

Ett bättre sätt att bedöma prestandan hos en klassificerare är att titta på förvirringsmatrisen.

Förvirringsmatris
Mät prestandan för Linear Classifier med förvirringsmatris

Smakämnen förvirringsmatris visualiserar noggrannheten hos en klassificerare genom att jämföra de faktiska och förutsagda klasserna som visas i exemplet ovan linjär klassificerare. Den binära förväxlingsmatrisen är sammansatt av kvadrater:

  • TP: Sant positiv: Förutspådda värden korrekt förutsagda som faktiska positiva
  • FP: Förutspådda värden förutspådde felaktigt ett verkligt positivt. dvs negativa värden förutspådde som positiva
  • FN: Falskt negativt: Positiva värden förutspådda som negativa
  • TN: True Negative: Förutspådda värden korrekt förutsagda som faktiska negativa

Från förvirringsmatrisen är det lätt att jämföra den faktiska klassen och den förutsagda klassen.

Precision och känslighet

Förvirringsmatrisen ger en bra inblick i det sanna positiva och falska positiva. I vissa fall är det att föredra att ha ett mer kortfattat mått.

Precision

Precisionsmåttet visar noggrannheten för den positiva klassen. Det mäter hur sannolikt förutsägelsen av den positiva klassen är korrekt.

Precision

Maxpoängen är 1 när klassificeraren klassificerar alla positiva värden perfekt. Precision ensam är inte till stor hjälp eftersom den ignorerar den negativa klassen. Mätvärdet är vanligtvis ihopkopplat med Recall-måttet. Återkallelse kallas också känslighet eller sann positiv frekvens.

Känslighet

Känslighet beräknar förhållandet mellan positiva klasser som detekterats korrekt. Detta mått visar hur bra modellen är för att känna igen en positiv klass.

Känslighet

Linjär klassificerare med TensorFlow

För den här handledningen kommer vi att använda folkräkningsdataset. Syftet är att använda variablerna i folkräkningsdataset för att förutsäga inkomstnivån. Observera att inkomsten är en binär variabel

  • med ett värde av 1 om inkomsten > 50k
  • 0 om inkomst < 50k.

Denna variabel är din etikett

Denna datauppsättning innehåller åtta kategoriska variabler:

  • arbetsplatsen
  • utbildning
  • äktenskaplig
  • ockupation
  • relation
  • lopp
  • kön
  • hemland

dessutom sex kontinuerliga variabler:

  • ålder
  • fnlwgt
  • utbildningsnummer
  • kapitalvinsten
  • kapitalförlust
  • timmar_vecka

Genom detta TensorFlow-klassificeringsexempel kommer du att förstå hur man tränar linjära TensorFlow-klassificerare med TensorFlow-skattaren och hur man förbättrar noggrannhetsmåttet.

Vi kommer att gå tillväga enligt följande:

  • Steg 1) Importera data
  • Steg 2) Datakonvertering
  • Steg 3) Träna klassificeraren
  • Steg 4) Förbättra modellen
  • Steg 5) Hyperparameter:Lasso & Ridge

Steg 1) Importera data

Du importerar först de bibliotek som användes under handledningen.

import tensorflow as tf
import pandas as pd

Därefter importerar du data från UCIs arkiv och definierar kolumnernas namn. Du kommer att använda kolumnerna för att namnge kolumnerna i en pandas dataram.

Observera att du kommer att träna klassificeraren med hjälp av en Pandas dataram.

## 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"

De data som lagras online är redan uppdelade mellan ett tågset och ett testset.

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)

Tågsetet innehåller 32,561 16,281 observationer och testsetet XNUMX XNUMX

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 kräver ett booleskt värde för att träna klassificeraren. Du måste casta värdena från sträng till heltal. Etiketten lagras som ett objekt, men du måste konvertera den till ett numeriskt värde. Koden nedan skapar en ordbok med värden som ska konverteras och loop över kolumnobjektet. Observera att du utför denna operation två gånger, en för tågtestet, en för testsetet

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]

I tågdata finns 24,720 50 inkomster lägre än 7841k och XNUMX ovan. Förhållandet är nästan detsamma för testsetet. Se den här handledningen om Facets för mer.

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

Steg 2) Datakonvertering

Några steg krävs innan du tränar en linjär klassificerare med Tensorflow. Du måste förbereda de funktioner som ska inkluderas i modellen. I benchmark-regressionen kommer du att använda originaldata utan att tillämpa någon transformation.

Estimatorn måste ha en lista med funktioner för att träna modellen. Därför måste kolumnens data omvandlas till en tensor.

En bra praxis är att definiera två listor med funktioner baserat på deras typ och sedan skicka dem till funktionskolumnerna i skattaren.

Du börjar med att konvertera kontinuerliga funktioner och definierar sedan en hink med kategoridata.

Funktionerna i datasetet har två format:

  • Heltal
  • Ändamålet

Varje funktion listas i de följande två variablerna enligt deras typ.

## 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']

Feature_column är utrustad med en objekt numeric_column för att hjälpa till med omvandlingen av de kontinuerliga variablerna till tensor. I koden nedan omvandlar du alla variabler från CONTI_FEATURES till en tensor med ett numeriskt värde. Detta är obligatoriskt för att konstruera modellen. Alla oberoende variabler måste omvandlas till rätt typ av tensor.

Nedan skriver vi en kod som låter dig se vad som händer bakom feature_column.numeric_column. Vi kommer att skriva ut det konverterade värdet för ålder. Det är i förklarande syfte, så det finns inget behov av att förstå pythonkoden. Du kan hänvisa till den officiella dokumentationen för att förstå koderna.

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.]]

Värdena är exakt samma som i df_train

continuous_features = [tf.feature_column.numeric_column(k) for k in CONTI_FEATURES]

Enligt TensorFlow-dokumentationen finns det olika sätt att konvertera kategoridata. Om ordlistan för en funktion är känd och inte har många värden, är det möjligt att skapa den kategoriska kolumnen med categorical_column_with_vocabulary_list. Det kommer att tilldela alla unika ordlistor ett ID.

Till exempel, om en variabelstatus har tre distinkta värden:

  • Man
  • Fru
  • Single

Då kommer tre ID att tilldelas. Till exempel kommer Maken att ha ID 1, Hustru ID 2 och så vidare.

I illustrationssyfte kan du använda den här koden för att konvertera en objektvariabel till en kategorisk kolumn i TensorFlow.

Funktionen kön kan bara ha två värden: man eller kvinna. När vi ska konvertera funktionskönet kommer Tensorflow att skapa 2 nya kolumner, en för manlig och en för kvinnlig. Om kön är lika med man, kommer den nya kolumnen man att vara lika med 1 och hona med 0. Detta exempel visas i tabellen nedan:

rader kön efter transformation man kvinna
1 man => 1 0
2 man => 1 0
3 kvinna => 0 1

I tensorflöde:

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'])

Nedan har vi lagt till Python kod för att skriva ut kodningen. Återigen, du behöver inte förstå koden, syftet är att se transformationen

Ett snabbare sätt att transformera data är dock att använda metoden categorical_column_with_hash_bucket. Att ändra strängvariabler i en gles matris kommer att vara användbart. En gles matris är en matris med mestadels noll. Metoden tar hand om allt. Du behöver bara ange antalet hinkar och nyckelkolumnen. Antalet hinkar är det maximala antalet grupper som Tensorflow kan skapa. Nyckelkolumnen är helt enkelt namnet på kolumnen som ska konverteras.

I koden nedan skapar du en loop över alla kategoriska funktioner.

categorical_features = [tf.feature_column.categorical_column_with_hash_bucket(k, hash_bucket_size=1000) for k in CATE_FEATURES]

Steg 3) Träna klassificeraren

TensorFlow tillhandahåller för närvarande en estimator för linjär regression och linjär klassificering.

  • Linjär regression: Linjär regression
  • Linjär klassificering: LinearClassifier

Syntaxen för den linjära klassificeraren är densamma som i handledningen på linjär regression förutom ett argument, n_class. Du måste definiera funktionskolumnen, modellkatalogen och jämföra med den linjära regressorn; du har definiera antalet klasser. För en logit-regression är antalet klasser lika med 2.

Modellen kommer att beräkna vikten av kolumnerna som finns i continuous_features och categorical_features.

model = tf.estimator.LinearClassifier(
    n_classes = 2,
    model_dir="ongoing/train", 
    feature_columns=categorical_features+ continuous_features)

Produktion

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}

Nu när klassificeraren är definierad kan du skapa inmatningsfunktionen. Metoden är densamma som i den linjära regressorhandledningen. Här använder du en batchstorlek på 128 och du blandar data.

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)

Du skapar en funktion med de argument som krävs av den linjära skattaren, dvs antal epoker, antal batcher och blandar datasetet eller anteckningen. Eftersom du använder pandas metod för att skicka data till modellen, måste du definiera X-variablerna som en pandas-dataram. Observera att du går över all data som lagras i FEATURES.

Låt oss träna modellen med objektet model.train. Du använder den tidigare definierade funktionen för att mata modellen med lämpliga värden. Observera att du ställer in batchstorleken till 128 och antalet epoker till Ingen. Modellen kommer att tränas över tusen steg.

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>

Observera att förlusten minskade därefter under de senaste 100 stegen, dvs från 901 till 1000.

Den slutliga förlusten efter tusen iterationer är 5444. Du kan uppskatta din modell på testsetet och se prestandan. För att utvärdera prestandan för din modell måste du använda objektutvärderingen. Du matar modellen med testsetet och ställer in antalet epoker till 1, dvs data kommer bara att gå till modellen en gång.

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 returnerar alla mätvärden du lärt dig i den teoretiska delen. Utan överraskning är noggrannheten stor på grund av den obalanserade etiketten. Egentligen presterar modellen något bättre än en slumpmässig gissning. Föreställ dig att modellen förutsäger alla hushåll med inkomst lägre än 50K, då har modellen en träffsäkerhet på 70 procent. Vid en närmare analys kan du se att förutsägelsen och återkallelsen är ganska låg.

Steg 4) Förbättra modellen

Nu när du har en benchmarkmodell kan du försöka förbättra den, det vill säga öka noggrannheten. I den tidigare handledningen lärde du dig hur du förbättrar förutsägelsekraften med en interaktionsterm. I den här handledningen kommer du att återvända till den här idén genom att lägga till en polynomterm till regressionen.

Polynomregression är instrumentell när det finns icke-linjäritet i data. Det finns två sätt att fånga icke-linjäritet i data.

  • Lägg till polynomterm
  • Bucketisera den kontinuerliga variabeln till en kategorisk variabel

Polynom term

Från bilden nedan kan du se vad en polynomregression är. Det är en ekvation med X-variabler med olika styrka. En andragrads polynomregression har två variabler, X och X i kvadrat. Tredje graden har tre variabler, X, X2, och X3

Polynomregression
Vad är polynomregression

Nedan har vi konstruerat en graf med två variabler, X och Y. Det är uppenbart att sambandet inte är linjärt. Om vi ​​lägger till en linjär regression kan vi se att modellen inte kan fånga mönstret (vänster bild).

Titta nu på den vänstra bilden från bilden nedan, vi lade till fem termer till regressionen (det vill säga y=x+x2+x3+x4+x5. Modellen fångar nu mönstret mycket bättre. Detta är kraften i polynomregression.

Polynomregression

Låt oss gå tillbaka till vårt exempel. Ålder står inte i ett linjärt samband med inkomst. Tidig ålder kan ha en platt inkomst nära noll eftersom barn eller ungdomar inte arbetar. Sedan ökar den i arbetsför ålder och minskar vid pensioneringen. Det är vanligtvis en Inversed-U-form. Ett sätt att fånga detta mönster är att lägga till en potens två till regressionen.

Låt oss se om det ökar noggrannheten.

Du måste lägga till den här nya funktionen i datasetet och i listan över kontinuerliga funktioner.

Du lägger till den nya variabeln i tåg- och testdataset, så det är bekvämare att skriva en funktion.

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

Funktionen har 3 argument:

  • df_t: definiera träningsuppsättningen
  • df_te: definiera testuppsättningen
  • var_name = 'ålder': Definiera variabeln som ska transformeras

Du kan använda objektet pow(2) för att kvadrera variabeln ålder. Observera att den nya variabeln heter "ny"

Nu när funktionen square_var är skriven kan du skapa de nya datamängderna.

df_train_new, df_test_new = square_var(df_train, df_test, var_name = 'age')

Som du kan se har den nya datamängden ytterligare en funktion.

print(df_train_new.shape, df_test_new.shape)			
(32561, 16) (16281, 16)

Den kvadratiska variabeln kallas ny i datasetet. Du måste lägga till den i listan över kontinuerliga funktioner.

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]

Anmärkningar att du ändrade katalogen för grafen. Du kan inte träna olika modeller i samma katalog. Det betyder att du måste ändra sökvägen till argumentet model_dir. Om du inte gör det kommer TensorFlow att skapa ett fel.

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)

Nu när klassificeraren är designad med den nya datamängden kan du träna och utvärdera modellen.

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}

Den kvadratiska variabeln förbättrade noggrannheten från 0.76 till 0.79. Låt oss se om du kan bli bättre genom att kombinera bucketization och interaktionsterm tillsammans.

Bucketisering och interaktion

Som du såg tidigare kan en linjär klassificerare inte fånga åldersinkomstmönstret korrekt. Det beror på att den lär sig en enda vikt för varje funktion. För att göra det enklare för klassificeraren är en sak du kan göra att buckla funktionen. Bucking omvandlar en numerisk funktion till flera vissa baserat på intervallet den faller inom, och var och en av dessa nya funktioner indikerar om en persons ålder faller inom det intervallet.

Med dessa nya funktioner kan den linjära modellen fånga förhållandet genom att lära sig olika vikter för varje hink.

I TensorFlow görs det med bucketized_column. Du måste lägga till värdeintervallet i gränserna.

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])

Du vet redan att ålder är icke-linjär med inkomst. Ett annat sätt att förbättra modellen är genom interaktion. Med TensorFlows ord är det funktionskorsning. Funktionskorsning är ett sätt att skapa nya funktioner som är kombinationer av befintliga, vilket kan vara användbart för en linjär klassificerare som inte kan modellera interaktioner mellan funktioner.

Du kan dela upp ålder med en annan funktion som utbildning. Det vill säga, vissa grupper har sannolikt en hög inkomst och andra låg (Tänk på doktoranden).

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)]

För att skapa en korsfunktionskolumn använder du crossed_column med variablerna att korsa inom en parentes. hash_bucket_size anger de maximala korsningsmöjligheterna. För att skapa interaktion mellan variabler (minst en variabel måste vara kategorisk) kan du använda tf.feature_column.crossed_column. För att använda det här objektet måste du lägga till inom hakparentes variabeln för att interagera och ett andra argument, hinkstorleken. Hinkstorleken är det maximala antalet möjliga grupper inom en variabel. Här sätter du den på 1000 då du inte vet exakt antal grupper

age_buckets måste kvadreras innan för att lägga till det i funktionskolumnerna. Du lägger också till de nya funktionerna i funktionskolumnerna och förbereder skattaren

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)

Produktion

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)

Du är redo att uppskatta den nya modellen och se om den förbättrar noggrannheten.

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}

Den nya noggrannhetsnivån är 83.58 procent. Det är fyra procent högre än den tidigare modellen.

Slutligen kan du lägga till en regleringsterm för att förhindra överanpassning.

Steg 5) Hyperparameter:Lasso & Ridge

Din modell kan drabbas av överanpassning or undermontering.

  • Överanpassning: Modellen kan inte generalisera förutsägelsen till nya data
  • Underpassning: Modellen kan inte fånga mönstret för data. dvs linjär regression när data är icke-linjär

När en modell har många parametrar och en relativt liten mängd data leder det till dåliga förutsägelser. Föreställ dig, en grupp har bara tre observationer; modellen kommer att beräkna en vikt för denna grupp. Vikten används för att göra en förutsägelse; om observationerna av testuppsättningen för denna speciella grupp skiljer sig helt från träningsuppsättningen, kommer modellen att göra en felaktig förutsägelse. Under utvärderingen med träningssetet är noggrannheten bra, men inte bra med testsetet eftersom de beräknade vikterna inte är den sanna för att generalisera mönstret. I det här fallet gör den inte en rimlig förutsägelse om osynliga data.

För att förhindra överanpassning ger regularisering dig möjligheterna att kontrollera för sådan komplexitet och göra den mer generaliserbar. Det finns två regleringstekniker:

  • L1: Lasso
  • L2: Ås

I TensorFlow kan du lägga till dessa två hyperparametrar i optimeraren. Till exempel, ju högre hyperparameter L2 är, tenderar vikten att vara mycket låg och nära noll. Den anpassade linjen kommer att vara mycket platt, medan en L2 nära noll innebär att vikterna är nära den vanliga linjära regressionen.

Du kan själv prova olika värden på hyperparametrarna och se om du kan öka noggrannhetsnivån.

Anmärkningar att om du ändrar hyperparametern måste du ta bort mappen ongoing/train4 annars startar modellen med den tidigare tränade modellen.

Låt oss se hur noggrannheten är med hypen

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))

UTGÅNG

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)

UTGÅNG

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)

Produktion

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}

Med denna hyperparameter ökar du noggrannhetsmåtten något. I nästa handledning kommer du att lära dig hur du förbättrar en linjär klassificerare med hjälp av en kärnmetod.

Sammanfattning

För att träna en modell behöver du:

  • Definiera funktionerna: Oberoende variabler: X
  • Definiera etiketten: Beroende variabel: y
  • Konstruera ett tåg/testset
  • Definiera den ursprungliga vikten
  • Definiera förlustfunktionen: MSE
  • Optimera modellen: Gradient descent
  • Definiera:
    • Lärningshastighet
    • Antal epok
    • Satsstorlek
    • Antal klasser

I den här handledningen lärde du dig hur du använder API:et på hög nivå för en linjär regressionsklassificerare. Du måste definiera:

  1. Funktionskolumner. Om kontinuerlig: tf.feature_column.numeric_column(). Du kan fylla i en lista med python-listförståelse
  2. Uppskattaren: tf.estimator.LinearClassifier(feature_columns, model_dir, n_classes = 2)
  3. En funktion för att importera data, batchstorlek och epok: input_fn()

Efter det är du redo att träna, utvärdera och göra en förutsägelse med train(), evaluate() och predict()

För att förbättra modellens prestanda kan du:

  • Använd polynomregression
  • Interaktionsterm: tf.feature_column.crossed_column
  • Lägg till regulariseringsparameter