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.
- Om etiketten bara har två klasser är inlärningsalgoritmen en binär klassificerare.
- 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:
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: 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.
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.
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.
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.
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.
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
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.
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:
- Funktionskolumner. Om kontinuerlig: tf.feature_column.numeric_column(). Du kan fylla i en lista med python-listförståelse
- Uppskattaren: tf.estimator.LinearClassifier(feature_columns, model_dir, n_classes = 2)
- 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