Ga naar hoofdinhoud

Kaggle-competitietutorial: Machine learning met de Titanic

Bereid je voor op je eerste Kaggle-competitie met deze stapsgewijze tutorial.
· 9 min lezen

Verken met AI

In deze tutorial lopen we de Titanic-dataset door, analyseren we die en dienen we de resultaten in voor de echte competitie. Je hebt al geleerd hoe je de data ophaalt en in je Kaggle Notebook importeert in deze tutorial. Nu gebruiken we DataLab als dataswetenotebook. Je leert beide tools op verschillende platforms gebruiken, zodat je je favoriet kunt kiezen.

Ga eerst naar de sectie "Competitions" in Kaggle en zoek op Titanic (Figuur 5.4). Voordat je meteen in het notebook duikt, is het goed om alle informatie in de secties "Description" en "Rules" te begrijpen. Het is ook belangrijk om notebooks van andere gebruikers te bekijken; dat kan je extra ideeën geven voor je oplossing.

Figuur 5.4: Titanic - Machine Learning from Disaster

De competitie draait om het gebruik van machine learning om te voorspellen welke passagiers de schipbreuk van de Titanic zouden hebben overleefd. We gebruiken een dataset met passagiersinformatie zoals naam, geslacht, leeftijd, enzovoort. We gebruiken 2 verschillende datasets. De eerste heet 'train.csv'. In deze dataset staan naast de passagiersinformatie ook de groundtruth-waarden zoals 'survived' en 'not survived'. In de tweede dataset, 'test.csv', staan geen ground truth-waarden, omdat we die moeten voorspellen en onze resultaten moeten indienen.

Het inzendbestand heeft slechts 2 kolommen: PassengerId en Survived. Het inzendsysteem geeft fouten als je een bestand met meer dan 2 waarden probeert te uploaden. Let op: je kunt 10 inzendingen per dag doen.

Met de informatie uit de sectie "Competition Description" is de volgende stap om de data naar onze DataLab te halen en te analyseren.

Download eerst de dataset in Data Explorer via het tabblad Data (Figuur 5.5). Je moet zowel 'train.csv' als 'test.csv' downloaden.

Ga na het downloaden van de bestanden naar DataLab. Let op: je moet eerst een account aanmaken. Een account aanmaken en DataLab gebruiken is gratis.

Je kunt bestanden eenvoudig slepen en neerzetten aan de linkerkant van het notebook (Figuur 5.6).

Figuur 5.5: De dataset downloaden
Figuur 5.6: De dataset toevoegen aan DataLab

De volgende stap is het bekijken van de datadictionary in de beschrijving van de dataset. Dit helpt ons te bepalen welke kolommen we willen visualiseren.

  • survival: Overleving
  • pclass: Ticketklasse
  • sex: Geslacht
  • Age: Leeftijd in jaren
  • sibsp: # broers/zussen / partners aan boord van de Titanic
  • parch: # ouders / kinderen aan boord van de Titanic
  • ticket: Ticketnummer
  • fare: Ticketprijs
  • cabin: Hutcijfer
  • embarked: Instaphaven

De data importeren

Je kunt bash-commando's gebruiken in jupyter-notebooks door een uitroepteken vooraan in de cel te zetten. We controleren de locatie van de geüploade datasetbestanden met de commando's pwd en ls.

!pwd; ls

/work/files/workspace

notebook.ipynb test.csv train.csv

Pandas is een Python-bibliotheek voor datamanipulatie en -analyse. We hebben nu de kolommen Ticket, Name en PassengerId verwijderd, omdat die geen betekenisvolle numerieke of categorische data bevatten. Nu zie je de overige features die we gaan gebruiken.

In de volgende regels worden de trainings- en testbestanden ingelezen met de read_csv-methode van Pandas. Let op dat de kolommen Survived en PassengerId respectievelijk aan de train- en test-dataframes zijn toegevoegd. We voeren het model apart met de features in columns_to_be_added_as_features en de labels in de kolom Survived. Maar om de preprocessing te vereenvoudigen, kunnen we ze nu combineren. De variabele test_df_matcher bevat ook PassengerId. Die gebruiken we om PassengerId te koppelen aan de voorspellingen op de testset, om het CSV-bestand te genereren dat we op Kaggle uploaden als ons resultaat.

import pandas as pd
columns_to_be_added_as_features = ['Sex','Age','SibSp','Parch','Pclass','Fare','Embarked']
train_df = pd.read_csv('train.csv', usecols=columns_to_be_added_as_features + ['Survived'])
test_df_matcher = pd.read_csv('test.csv', usecols=columns_to_be_added_as_features + ['PassengerId'])
test_df = test_df[columns_to_be_added_as_features]

Met de head()-methode kunnen we de eerste 5 rijen en hun kolomnamen bekijken. Je kunt het aantal eerste rijen dat wordt getoond als parameter meegeven aan head(). Het aantal rijen in de trainingsset en in de testset wordt respectievelijk afgedrukt in de volgende cel.

print(train_df.head())
Figuur 5.7: Dataframe
print("Number of rows in training set: {}".format(len(train_df)))
print("Number of rows in test set: {}".format(len(test_df)))

Number of rows in training set: 891 Number of rows in test set: 418

Preprocessing

We moeten de typewaardes omzetten naar float, die als features in het model worden gebruikt. Deze conversie maakt het mogelijk om numerieke bewerkingen uit te voeren bij het normaliseren van de data.

for column_title in columns_to_be_added_as_features:
    if column_title in ['Embarked', "Sex"]:
        continue
    train_df[column_title] = pd.to_numeric(train_df[column_title], downcast="float")
    test_df[column_title] = pd.to_numeric(test_df[column_title], downcast="float")

train_df["Survived"] = pd.to_numeric(train_df["Survived"], downcast="float")

We moeten het model voeden met numerieke waarden. In het onderstaande codeblok worden strings naar numerieke waarden omgezet

train_df['Embarked'].replace('Q', 0,inplace=True)
train_df['Embarked'].replace('S', 1,inplace=True)
train_df['Embarked'].replace('C', 2,inplace=True)

test_df['Embarked'].replace('Q', 0,inplace=True)
test_df['Embarked'].replace('S', 1,inplace=True)
test_df['Embarked'].replace('C', 2,inplace=True)

train_df['Sex'].replace('male', 0,inplace=True)
train_df['Sex'].replace('female', 1,inplace=True)

test_df['Sex'].replace('male', 0,inplace=True)
test_df['Sex'].replace('female', 1,inplace=True)

print(train_df.head())
Figuur 5.8: Dataframe met numerieke waarden

Hieronder worden alle features genormaliseerd, in dit geval geschaald tussen 0 en 1.

#Credit: Michael Aquilina,
#https://stackoverflow.com/questions/26414913/normalize-columns-of-pandas-data-frame
def normalize(df):
    result = df.copy()
    for feature_name in df.columns:
        max_value = df[feature_name].max()
        min_value = df[feature_name].min()
        result[feature_name] = (df[feature_name] - min_value) / (max_value - min_value)
    return result

train_df = normalize(train_df)
test_df = normalize(test_df)

print(train_df.head())
Figuur 5.9: Genormaliseerd dataframe

Omdat de dataset wordt gesplitst in training en validatie, schudden we eerst de dataset om groepsvorming in slechts één set te vermijden.

#Credit: Kris, https://stackoverflow.com/questions/29576430/shuffle-dataframe-rows
train_df = train_df.sample(frac=1).reset_index(drop=True)

Alle lege waarden worden vervangen door 0; deze keuze is gemaakt om tijd te besparen. Je kunt echter deze tutorial lezen om te leren hoe je ontbrekende waarden in machine learning aanpakt.

train_df = train_df.fillna(0)
test_df = test_df.fillna(0)

Hieronder is de validatieratio ingesteld op 0,2, wat betekent dat 20% van de data wordt gebruikt ter validatie. Om de dataset te splitsen in trainings- en validatiesets gebruiken we Sklearns train_test_split-methode. Daarna splitsen we de features en labels, zoals te zien is in de laatste 4 regels van het onderstaande codeblok.

validation_set_ratio = 0.2
validation_set_size = int(len(train_df)*validation_set_ratio)
training_set_size = len(train_df) - validation_set_size

print("Total set size: {}".format(len(train_df)))
print("Training set size: {}".format(training_set_size))
print("Validation set size: {}".format(validation_set_size))

from sklearn.model_selection import train_test_split

train, val = train_test_split(train_df, test_size=validation_set_ratio)

train_X = train[columns_to_be_added_as_features]
train_Label = train[['Survived']]

val_X = val[columns_to_be_added_as_features]
val_Label = val[['Survived']]

Training

Support vector machines zijn supervised learning-modellen die worden gebruikt voor classificatie en regressie. Dit model is gekozen met de onderstaande parameters. Je zou ook andere modellen met verschillende parametercombinaties moeten proberen. Je hoeft de code niet telkens te starten en te stoppen als je een parameter wilt wijzigen of een ander model wilt proberen; je kunt dit proces automatiseren. Als je geïnteresseerd bent in Support Vector Machines, bekijk dan de tutorial Support Vector Machines met Scikit-learn op DataCamp.

from sklearn.svm import SVC

SVM_KERNEL = "linear"
SVM_C = 10
SVM_GAMMA = 0.00001

svm_model = SVC(kernel = SVM_KERNEL, C = SVM_C, gamma = SVM_GAMMA)
svm_model.fit(train_X, train_Label)

Voorspellingen voor de validatieset ophalen

In dit deel voeren we de features van de validatieset aan het model en halen we de voorspellingen op. Vervolgens vergelijken we die met de groundtruth-waarden. De methode metrics.accuracy_score van Sklearn is gebruikt om de nauwkeurigheid eenvoudig te berekenen. De nauwkeurigheid op de validatieset is 0,799, wat een goed begin is.

from sklearn import metrics

y_pred = svm_model.predict(val_X)
print("Accuracy:",metrics.accuracy_score(val_Label, y_pred))

Accuracy: 0.7988826815642458

Voorspellingen voor de testset ophalen

Nu gaan we verder met de voorspellingen voor de echte testset. Omdat er geen groundtruth-waarden voor de testset zijn, weten we de nauwkeurigheid pas nadat het voorspellingsbestand naar Kaggle is geüpload.

test_pred = svm_model.predict(test_df)

Het uitvoerdataframe genereren

De kolom PassengerId wordt opgehaald uit het dataframe test_df_matcher. Als die direct wordt teruggegeven, is het retourtype Series. Daarom casten we die naar het Pandas DataFrame-type. Vervolgens voegen we de voorspellingen voor de testset in als tweede kolom van het dataframe.

result = pd.DataFrame(test_df_matcher['PassengerId'])
print(result.head(10))
Figuur 5.10: PassengerId-dataframe
result.insert(1, "Survived", test_pred, True)
result["Survived"] = pd.to_numeric(result["Survived"], downcast="integer")
print(result.head(10))
Figuur 5.11: Definitief dataframe

Het uitvoerbestand genereren

Tot slot is het uitvoerformaat klaar. Als laatste stap verwijderen we de indexwaarden door False door te geven aan de parameter index. Nu kun je het gegenereerde bestand downloaden en uploaden naar Kaggle. Zo leer je de nauwkeurigheid op de testset en krijg je een plek op het leaderboard.

result.to_csv("out.csv", index=False)

We gaan nu terug naar de competitiepagina, klikken op "Submit Predictions" en uploaden vervolgens het voorspellingsbestand. Na een paar seconden krijg je je testnauwkeurigheid (Figuur 5.12).

Figuur 5.12: Nauwkeurigheid van de testset

Conclusie

In deze tutorial heb je geleerd hoe je een dataset analyseert en je resultaten indient voor een Kaggle-competitie. Als je het leuk vindt om aan dataswetecompetities mee te doen, kun je meer leren over DataCamp Competitions hier.

Onderwerpen

Gerelateerd