[PYTHON] Überlebensvorhersage mit Kaggles Titanic XG Boost [80,1%]

Einführung

Beim letzten Mal habe ich mir die Zugdaten der Titanic angesehen, um festzustellen, welche Merkmale mit der Überlebensrate zusammenhängen. Letztes Mal: Datenanalyse vor der Generierung von Titanic-Features von Kaggle (Ich hoffe, Sie können diesen Artikel auch lesen)

Basierend auf dem Ergebnis erstellen wir dieses Mal ** einen Datenrahmen, der die fehlenden Werte ergänzt und dem Vorhersagemodell die erforderlichen Funktionen hinzufügt **.

Dieses Mal werden wir als Vorhersagemodell "** GBDT (Gradient Boosting Tree) xg Boost **" verwenden, das häufig in Kaggle-Wettbewerben verwendet wird, damit wir die Daten dafür geeignet machen.

1. Datenerfassung und Bestätigung fehlender Werte

import pandas as pd
import numpy as np

train = pd.read_csv('/kaggle/input/titanic/train.csv')
test = pd.read_csv('/kaggle/input/titanic/test.csv')
#Kombinieren Sie Zugdaten und Testdaten zu einem
data = pd.concat([train,test]).reset_index(drop=True)
#Überprüfen Sie die Anzahl der Zeilen, die fehlende Werte enthalten
train.isnull().sum()
test.isnull().sum()

Die Nummer jedes fehlenden Werts ist wie folgt.

Zugdaten Testdaten
PassengerId 0 0
Survived 0
Pclass 0 0
Name 0 0
Sex 0 0
Age 177 86
SibSp 0 0
Parch 0 0
Ticket 0 0
Fare 0 1
Cabin 687 327
Embarked 2 0

2. Fehlende Werte ergänzen und Features erstellen

2.1 Ergänzung und Klassifizierung der Tarife

Die fehlende Reihe hatte eine ** Klasse von 3 ** und ** eingeschifft war S **. スクリーンショット 2020-10-01 12.01.00.png Daher wird es durch den Medianwert unter denjenigen ergänzt, die diese beiden Bedingungen erfüllen. Danach wird die Klassifizierung unter Berücksichtigung des Unterschieds in der Überlebensrate in Abhängigkeit vom Tarifwert und der P-Klasse durchgeführt.

#Fehlende Wertvervollständigung
data['Fare'] = data['Fare'].fillna(data.query('Pclass==3 & Embarked=="S"')['Fare'].median())
#Klassifiziert'Fare_bin'Einstellen
data['Fare_bin'] = 0
data.loc[(data['Fare']>=10) & (data['Fare']<50), 'Fare_bin'] = 1
data.loc[(data['Fare']>=50) & (data['Fare']<100), 'Fare_bin'] = 2
data.loc[(data['Fare']>=100), 'Fare_bin'] = 3

2.2 Unterschied zwischen Leben und Tod zwischen Gruppen Schaffung von "Family_Survival"

Titanic [0.82] - [0.83] Erstellt die in diesem Code eingeführte Feature-Menge 'Family_survival'. Ich werde.

** Familie und Freunde agieren eher zusammen an Bord **, daher kann gesagt werden, dass unabhängig davon, ob sie überlebt haben oder nicht **, innerhalb der Gruppe tendenziell das gleiche Ergebnis erzielt wird **.

Daher wird die Gruppierung anhand des Vor- und Nachnamens sowie der Ticketnummer durchgeführt, und der Wert wird dadurch bestimmt, ob die Mitglieder der Gruppe am Leben sind oder nicht.

#Holen Sie sich den Nachnamen des Namens'Last_name'Einstellen
data['Last_name'] = data['Name'].apply(lambda x: x.split(",")[0])


data['Family_survival'] = 0.5 #Standardwert
#Last_Gruppierung nach Name und Tarif
for grp, grp_df in data.groupby(['Last_name', 'Fare']):
                               
    if (len(grp_df) != 1):
        #(Gleicher Nachname)Und(Der Fahrpreis ist der gleiche)Wenn zwei oder mehr Personen anwesend sind
        for index, row in grp_df.iterrows():
            smax = grp_df.drop(index)['Survived'].max()
            smin = grp_df.drop(index)['Survived'].min()
            passID = row['PassengerId']
            
            if (smax == 1.0):
                data.loc[data['PassengerId'] == passID, 'Family_survival'] = 1
            elif (smin == 0.0):
                data.loc[data['PassengerId'] == passID, 'Family_survival'] = 0
            #Über andere Mitglieder als Sie selbst in der Gruppe
            #Sogar eine Person lebt → 1
            #Keine Überlebenden(Einschließlich NaN) → 0
            #Alle NaN → 0.5

#Gruppierung nach Ticketnummer
for grp, grp_df in data.groupby('Ticket'):
    if (len(grp_df) != 1):
        #Wenn zwei oder mehr Personen dieselbe Ticketnummer haben
        #Wenn es überhaupt einen Überlebenden in der Gruppe gibt'Family_survival'Bis 1
        for ind, row in grp_df.iterrows():
            if (row['Family_survival'] == 0) | (row['Family_survival']== 0.5):
                smax = grp_df.drop(ind)['Survived'].max()
                smin = grp_df.drop(ind)['Survived'].min()
                passID = row['PassengerId']
                if (smax == 1.0):
                    data.loc[data['PassengerId'] == passID, 'Family_survival'] = 1
                elif (smin == 0.0):
                    data.loc[data['PassengerId'] == passID, 'Family_survival'] = 0

2.3 Erstellung und Klassifizierung der Merkmalsmenge'Family_size ', die die Anzahl der Familienmitglieder darstellt

Unter Verwendung der Werte von SibSp und Parch erstellen wir eine charakteristische Größe "Family_size", die angibt, wie viele Familien an Bord der Titanic gegangen sind, und klassifizieren sie nach ihren Überlebensraten.

#Family_Größe schaffen
data['Family_size'] = data['SibSp']+data['Parch']+1
#1, 2~4, 5~In drei Teile teilen
data['Family_size_bin'] = 0
data.loc[(data['Family_size']>=2) & (data['Family_size']<=4),'Family_size_bin'] = 1
data.loc[(data['Family_size']>=5) & (data['Family_size']<=7),'Family_size_bin'] = 2
data.loc[(data['Family_size']>=8),'Family_size_bin'] = 3

2.4 Erstellen des Titeltitels 'Titel'

Holen Sie sich Titel wie "Mr", "Miss" aus der Spalte "Name". Integrieren Sie kleinere Titel ('Mme', 'Mlle' usw.) in Titel mit derselben Bedeutung.

#Holen Sie sich den Titel des Namens'Title'Einstellen
data['Title'] = data['Name'].map(lambda x: x.split(', ')[1].split('. ')[0])
#Integrieren Sie einige Titel
data['Title'].replace(['Capt', 'Col', 'Major', 'Dr', 'Rev'], 'Officer', inplace=True)
data['Title'].replace(['Don', 'Sir',  'the Countess', 'Lady', 'Dona'], 'Royalty', inplace=True)
data['Title'].replace(['Mme', 'Ms'], 'Mrs', inplace=True)
data['Title'].replace(['Mlle'], 'Miss', inplace=True)
data['Title'].replace(['Jonkheer'], 'Master', inplace=True)

2.5 Kennzeichnung der Ticketnummer

Einige Ticketnummern sind nur Zahlen, andere enthalten Zahlen und Buchstaben. Nach der Trennung der beiden werden wir jede Art von Ticketnummer kennzeichnen.

#Teilen Sie in Tickets mit nur Zahlen und Tickets mit Zahlen und Alphabeten
#Holen Sie sich ein Ticket nur für Nummern
num_ticket = data[data['Ticket'].str.match('[0-9]+')].copy()
num_ticket_index = num_ticket.index.values.tolist()
#Tickets, bei denen nur Nummern aus den Originaldaten entfernt wurden und der Rest Alphabete enthält
num_alpha_ticket = data.drop(num_ticket_index).copy()

#Klassifizierung von Tickets nur mit Nummern
#Da die Ticketnummer eine Zeichenfolge ist, wird sie in einen numerischen Wert konvertiert
num_ticket['Ticket'] = num_ticket['Ticket'].apply(lambda x:int(x))

num_ticket['Ticket_bin'] = 0
num_ticket.loc[(num_ticket['Ticket']>=100000) & (num_ticket['Ticket']<200000),
               'Ticket_bin'] = 1
num_ticket.loc[(num_ticket['Ticket']>=200000) & (num_ticket['Ticket']<300000),
               'Ticket_bin'] = 2
num_ticket.loc[(num_ticket['Ticket']>=300000),'Ticket_bin'] = 3

#Klassifizierung von Tickets einschließlich Nummern und Alphabeten
num_alpha_ticket['Ticket_bin'] = 4
num_alpha_ticket.loc[num_alpha_ticket['Ticket'].str.match('A.+'),'Ticket_bin'] = 5
num_alpha_ticket.loc[num_alpha_ticket['Ticket'].str.match('C.+'),'Ticket_bin'] = 6
num_alpha_ticket.loc[num_alpha_ticket['Ticket'].str.match('C\.*A\.*.+'),'Ticket_bin'] = 7
num_alpha_ticket.loc[num_alpha_ticket['Ticket'].str.match('F\.C.+'),'Ticket_bin'] = 8
num_alpha_ticket.loc[num_alpha_ticket['Ticket'].str.match('PC.+'),'Ticket_bin'] = 9
num_alpha_ticket.loc[num_alpha_ticket['Ticket'].str.match('S\.+.+'),'Ticket_bin'] = 10
num_alpha_ticket.loc[num_alpha_ticket['Ticket'].str.match('SC.+'),'Ticket_bin'] = 11
num_alpha_ticket.loc[num_alpha_ticket['Ticket'].str.match('SOTON.+'),'Ticket_bin'] = 12 
num_alpha_ticket.loc[num_alpha_ticket['Ticket'].str.match('STON.+'),'Ticket_bin'] = 13
num_alpha_ticket.loc[num_alpha_ticket['Ticket'].str.match('W\.*/C.+'),'Ticket_bin'] = 14

data = pd.concat([num_ticket,num_alpha_ticket]).sort_values('PassengerId')

2.6 Altersergänzung und Klassifizierung

Für den fehlenden Wert von Alter gibt es eine Methode zum ** Median ** oder ** Ermitteln und Ergänzen des Durchschnittsalters für jeden Titel des Namens **, aber als ich ihn nachgeschlagen habe, fehlte er ** unter Verwendung einer zufälligen Gesamtstruktur. Es gab eine Methode **, um das Alter des Teils vorherzusagen, in dem es sich befindet, also werde ich diesmal dieses verwenden.

from sklearn.preprocessing import LabelEncoder
from sklearn.ensemble import RandomForestRegressor
#Beschriften des Feature-Betrags, der eine Zeichenfolge ist
le = LabelEncoder()
data['Sex'] = le.fit_transform(data['Sex']) #Da es zur Vorhersage der Überlebensrate verwendet wird, ist die Markierung zufällig
data['Title'] = le.fit_transform(data['Title'])
#Die Feature-Menge, die zur Vorhersage des Alters verwendet wird'age_data'Einstellen
age_data = data[['Age','Pclass','Family_size',
                 'Fare_bin','Title']].copy()
#Teilen Sie in Zeilen, in denen das Alter fehlt, und in Zeilen, in denen das Alter nicht fehlt
known_age = age_data[age_data['Age'].notnull()].values  
unknown_age = age_data[age_data['Age'].isnull()].values

x = known_age[:, 1:]  
y = known_age[:, 0]
#Lerne in einem zufälligen Wald
rfr = RandomForestRegressor(random_state=0, n_estimators=100, n_jobs=-1)
rfr.fit(x, y)
#Reflektieren Sie den vorhergesagten Wert im ursprünglichen Datenrahmen
age_predict = rfr.predict(unknown_age[:, 1:])
data.loc[(data['Age'].isnull()), 'Age'] = np.round(age_predict,1)

Sie haben jetzt den fehlenden Wert für Alter vervollständigt. スクリーンショット 2020-10-15 21.37.08.png

Und das Alter wird ebenfalls klassifiziert.

data['Age_bin'] = 0
data.loc[(data['Age']>18) & (data['Age']<=60),'Age_bin'] = 1
data.loc[(data['Age']>60),'Age_bin'] = 2

Reduzieren Sie schließlich unnötige Funktionen.

data = data.drop(['PassengerId','Name','Age','SibSp','Parch','Ticket',
                  'Fare','Cabin','Embarked','Last_name','Family_size'], axis=1)

Am Ende sieht der Datenrahmen so aus.

Survived Pclass Sex Fare_bin Family_survival Family_size_bin Title Ticket_bin Age_bin
0 0.0 3 1 0 0.5 1 2 5 1
1 1.0 1 0 2 0.5 1 3 9 1
2 1.0 3 0 0 0.5 0 1 13 1
3 1.0 1 0 2 0.0 1 3 1 1
4 0.0 3 1 0 0.5 0 2 3 1
... ... ... ... ... ... ... ... ... ...
1304 NaN 3 1 0 0.5 0 2 5 1
1305 NaN 1 0 3 1.0 0 5 9 1
1306 NaN 3 1 0 0.5 0 2 12 1
1307 NaN 3 1 0 0.5 0 2 3 1
1308 NaN 3 1 1 1.0 1 0 0 0

1309 rows × 9 columns

Die integrierten Daten werden in Zugdaten und Testdaten unterteilt, und die Merkmalsverarbeitung ist abgeschlossen.

model_train = data[:891]
model_test = data[891:]

X = model_train.drop('Survived', axis=1)
Y = pd.DataFrame(model_train['Survived'])
x_test = model_test.drop('Survived', axis=1)

3 xg Boost Vorhersage

Schauen wir uns die Leistung des Modells an, indem wir zwei suchen: ** logloss ** und ** Genauigkeit **.

from sklearn.metrics import log_loss
from sklearn.metrics import accuracy_score
from sklearn.model_selection import KFold
import xgboost as xgb
#Parameter einstellen
params = {'objective':'binary:logistic',
          'max_depth':5,
          'eta': 0.1, 
          'min_child_weight':1.0,
          'gamma':0.0,
          'colsample_bytree':0.8,
          'subsample':0.8}

num_round = 1000

logloss = []
accuracy = []

kf = KFold(n_splits=4, shuffle=True, random_state=0)
for train_index, valid_index in kf.split(X):
    x_train, x_valid = X.iloc[train_index], X.iloc[valid_index] 
    y_train, y_valid = Y.iloc[train_index], Y.iloc[valid_index]
    #Konvertieren Sie den Datenrahmen in eine Form, die für xg boost geeignet ist
    dtrain = xgb.DMatrix(x_train, label=y_train)
    dvalid = xgb.DMatrix(x_valid, label=y_valid)
    dtest = xgb.DMatrix(x_test)
    #Lerne mit xgboost
    model = xgb.train(params, dtrain, num_round,evals=[(dtrain,'train'),(dvalid,'eval')],
                      early_stopping_rounds=50)
    
    valid_pred_proba = model.predict(dvalid)
    #Fragen Sie nach Protokollverlust
    score = log_loss(y_valid, valid_pred_proba)
    logloss.append(score)
    #Finden Sie Genauigkeit
    #valid_pred_Da proba ein Wahrscheinlichkeitswert ist, wird er in 0 und 1 konvertiert.
    valid_pred = np.where(valid_pred_proba >0.5,1,0)
    acc = accuracy_score(y_valid, valid_pred)
    accuracy.append(acc)
    
print(f'log_loss:{np.mean(logloss)}')
print(f'accuracy:{np.mean(accuracy)}')

Mit diesem Code log_loss : 0.39114 accuracy : 0.8338 Das Ergebnis war das.

Nachdem das Modell vollständig ist, erstellen Sie die Prognosedaten, die an kaggle gesendet werden sollen.

#Vorhersagen mit Vorhersagen
y_pred_proba = model.predict(dtest)
y_pred= np.where(y_pred_proba > 0.5,1,0)
#Erstellen Sie einen Datenrahmen
submission = pd.DataFrame({'PassengerId':test['PassengerId'], 'Survived':y_pred})
submission.to_csv('titanic_xgboost.csv', index=False)

スクリーンショット 2020-10-15 21.54.44.png Die korrekte Rücklaufquote betrug ** 80,1% ** und erreichte damit die Grenze von 80%.

Zusammenfassung

Dieses Mal habe ich versucht, den vorhergesagten Wert tatsächlich an kaggle zu senden.

Zuerst wurde Cabin auch beschriftet und als Merkmalsgröße verwendet, aber ** die Vorhersagegenauigkeit verbesserte sich, wenn Cabin nicht verwendet wurde **. Immerhin scheint es zu viele fehlende Werte zu geben und es war nicht sehr geeignet für xg Boost.

Wenn Sie Vorhersagen treffen, ohne Merkmale wie Tarif und Alter zu klassifizieren, verbessern sich ** Logloss- und Genauigkeitswerte **, ** aber die Genauigkeitsrate der vorhergesagten Werte verbessert sich nicht **. Ich war der Meinung, dass es möglich sein würde, ein geeignetes Modell ohne Überlernen zu erstellen, indem man es anhand des Unterschieds in der Überlebensrate klassifiziert, anstatt die Merkmalsmenge so zu verwenden, wie sie ist.

Wenn Sie Meinungen oder Vorschläge haben, würden wir uns freuen, wenn Sie einen Kommentar abgeben oder eine Anfrage bearbeiten könnten.

Websites und Bücher, auf die ich mich bezog

Kaggle Tutorial Das Top 2% Know-how der Titanic pyhaya’s diary Titanic [0.82] - [0.83] [Datenanalysetechnologie, die mit Kaggle gewinnt](https://www.amazon.co.jp/Kaggle%E3%81%A7%E5%8B%9D%E3%81%A4%E3%83%87%E3% 83% BC% E3% 82% BF% E5% 88% 86% E6% 9E% 90% E3% 81% AE% E6% 8A% 80% E8% A1% 93-% E9% 96% 80% E8% 84 % 87-% E5% A4% A7% E8% BC% 94-ebook / dp / B07YTDBC3Z)

Recommended Posts

Überlebensvorhersage mit Kaggles Titanic XG Boost [80,1%]
Überlebensvorhersage unter Verwendung des titanischen neuronalen Netzes von Kaggle [80,8%]
[Kaggle] Versuchen Sie es mit xg boost
So stellen Sie xg boost mit Optuna ein
Probieren Sie Kaggles Titanic-Tutorial aus
Titanic-Überlebensprognose mit dem Workflow-Management-Tool Kedro für maschinelles Lernen