[PYTHON] Datenvorhersagewettbewerb in 3 Schritten (titanisch)

Nachdem ich Kaggles Artikel gelesen hatte, dachte ich persönlich, dass die Datenanalyse in den folgenden drei Schritten zusammengefasst werden könnte.

Schritt 1: Feature Engineering Schritt 2: Auswahl der Lernenden und Anpassung der Hyperparameter Schritt 3: Ensemble

Nach Abschluss der oben genannten drei Schritte wird das Modell festgelegt. Wenden Sie daher Testdaten (Daten zum Einreichen von Prognosen) auf das Modell an, um Vorhersagen zu treffen und zu senden. (Senden und bewerten Sie die Leistung bis dahin nicht anhand des Kreuzvalidierungswerts.) Da die Kreuzvalidierung mindestens einmal in einem Schritt durchgeführt wird, wird die Kreuzvalidierung insgesamt mindestens dreimal durchgeführt.

Schritt 1: Feature Engineering

Berücksichtigen Sie Funktionen, die in EDA (Exploratory Data Analysis) usw. verwendet werden können, und erstellen Sie bei Bedarf neue Funktionen. Berücksichtigen Sie auch Datenlecks. Es führt auch eine Vorverarbeitung durch, z. B. die Verarbeitung fehlender Werte. Schließlich wird der Lernende eingerichtet und RFE (rekursive Feature-Eliminierung) entfernt unnötige Features. Zu diesem Zeitpunkt wird die Kreuzvalidierung zur Bewertung verwendet. Sie können die Wichtigkeit der Merkmalsmenge auch beim Lernenden vom Typ Entscheidungsbaum erkennen. Ziehen Sie bei komplexen Daten wie Bildern und Text in Betracht, Features mithilfe eines neuronalen Netzes zu extrahieren.

Schritt 2: Auswahl der Lernenden und Anpassung der Hyperparameter

Es ist eine gute Idee, alles auszuprobieren, was Sie sich als Lernender vorstellen können. (Weil es später Ensemble sein kann.) Die Hyperparameteranpassung kann auch eine Rastersuche, eine Zufallssuche und in jüngerer Zeit eine Bayes'sche Optimierung mit Optuna sein. Dies schafft einen Zustand, in dem jeder Lernende die höchste Punktzahl erzielen kann. Löschen Sie Lernende, deren Ergebnisse der Leistungsbewertung zu niedrig sind.

Schritt 3: Ensemble

Es fasst die Ergebnisse jedes Lernenden zusammen. Wenn es nur einen Lernenden gibt, kann es kein Ensemble sein, so dass der Lernende das endgültige Modell ist. Sie können einfach abstimmen oder meinen, oder Sie können Mixer stapeln und stapeln. Beim Stapeln müssen auch die Hyperparameter des Lernenden angepasst werden, der zum Mixer wird. Darüber hinaus kann das Bewertungsergebnis ohne Ensemble besser sein. In diesem Fall ist es eine Frage der Überlegung, welches das endgültige Modell sein wird. (Es kann besser sein, beide einzureichen.)

Über Kreuzvalidierung

Die Kreuzvalidierung wird häufig als Methode zur Bewertung der Modellleistung verwendet. Es wird mit K-Fold gemacht, aber im Grunde ist es besser, eine große Anzahl von K zu haben. (Es braucht jedoch Zeit, wenn es viele Ks gibt.) Zusätzlich werden geschichtetes KFold und zufällige Extraktion durchgeführt, damit kein Datenungleichgewicht auftritt. Die Leistungsbewertung berücksichtigt nicht nur die durchschnittliche Punktzahl für jede Falte, sondern auch die Standardabweichung.

Implementierungsbeispiel im Titanic-Wettbewerb

Artikel, auf die verwiesen wird https://www.kaggle.com/ldfreeman3/a-data-science-framework-to-achieve-99-accuracy http://maruo51.com/2019/04/07/titanic-3/ https://yolo-kiyoshi.com/2020/01/22/post-1588/

Feature Quantity Engineering

EDA entfällt. Für RFE wurde zufälliger Wald verwendet.

import pandas as pd 
import numpy as np

data_train = pd.read_csv('./input/train.csv')
data_test  = pd.read_csv('./input/test.csv')
data_train_raw = data_train.copy(deep = True) #Erstellen Sie eine Kopie der Originaldaten
data_test_raw = data_test.copy(deep = True) #Erstellen Sie eine Kopie der Originaldaten
data_cleaner = [data_train, data_test]#Das Kombinieren als Liste ist praktisch, da Sie die Kopierquelle auch zusammen betreiben können.
#Der Join im Datenrahmen sind übrigens Daten_all = pd.concat([data_train, data_test], sort=False)Kann mit gemacht werden

#Nicht verwendete löschen
drop_column = ['PassengerId','Cabin', 'Ticket','Name']
data_train.drop(drop_column, axis=1, inplace = True)
#Fehlender Wertersatz
for dataset in data_cleaner:    
    dataset['Age'].fillna(dataset['Age'].median(), inplace = True)
    dataset['Embarked'].fillna(dataset['Embarked'].mode()[0], inplace = True)
    dataset['Fare'].fillna(dataset['Fare'].median(), inplace = True)
#
for dataset in data_cleaner:    
    dataset['FamilySize'] = dataset ['SibSp'] + dataset['Parch'] + 1
    dataset['IsAlone'] = 1
    dataset['IsAlone'].loc[dataset['FamilySize'] > 1] = 0 
#
from sklearn.preprocessing import LabelEncoder
label = LabelEncoder()
for dataset in data_cleaner:    
    dataset['Sex_Code'] = label.fit_transform(dataset['Sex'])
    dataset['Embarked_Code'] = label.fit_transform(dataset['Embarked'])
drop_column = ['Sex','Embarked']
data_train.drop(drop_column, axis=1, inplace = True)
# x,
lavel_y = "Survived"
lavel_x = data_train.columns.values[1:]

#()
from sklearn.model_selection import StratifiedKFold
from sklearn.feature_selection import RFECV
from sklearn.ensemble import RandomForestClassifier
NFOLD = 20 #
kf = StratifiedKFold(n_splits=NFOLD, shuffle=True, random_state=0)
rfe = RFECV(RandomForestClassifier(random_state = 0), scoring = 'accuracy', cv = kf)
rfe.fit(data_train[lavel_x], data_train[lavel_y])
f_importances = pd.DataFrame({"features":lavel_x,"select":rfe.get_support()})
print(f_importances) #Holen Sie sich ein Etikett mit Etikettencodierung und Eliminierung rekursiver RFE-Merkmale in zufälliger Gesamtstruktur-CV-Aufteilung
#Bestätigen Sie die zu verwendenden Funktionsmengenangaben
X_train = rfe.transform(data_train[lavel_x])
X_test = rfe.transform(data_test[lavel_x])
Y_train = data_train[lavel_y]

Auswahl der Lernenden und Anpassung der Hyperparameter

Mit Random Forest, XGBoost und LightGBM als Lernenden haben wir Hyperparametersuchen in Optuna durchgeführt.

from sklearn.model_selection import cross_validate
from xgboost import XGBClassifier
from lightgbm import LGBMClassifier
import optuna

#Zufälliger Wald
def objective(trial):
    param_grid_rfc = {
        "max_depth": trial.suggest_int("max_depth", 5, 15),
        "min_samples_leaf": trial.suggest_int("min_samples_leaf", 1, 5),
        'min_samples_split': trial.suggest_int("min_samples_split", 7, 15),
        "criterion": trial.suggest_categorical("criterion", ["gini", "entropy"]),
        'max_features': trial.suggest_int("max_features", 3, 10),
        "random_state": 0
    }
    model = RandomForestClassifier(**param_grid_rfc)
    scores = cross_validate(model, X=X_train, y=Y_train, cv=kf)
    return scores['test_score'].mean()
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=100)
print(study.best_params)
print(study.best_value)
rfc_best_param = study.best_params

# XGBoost
def objective(trial):   
    param_grid_xgb = {
        'min_child_weight': trial.suggest_int("min_child_weight", 1, 5),
        'gamma': trial.suggest_discrete_uniform("gamma", 0.1, 1.0, 0.1),
        'subsample': trial.suggest_discrete_uniform("subsample", 0.5, 1.0, 0.1),
        'colsample_bytree': trial.suggest_discrete_uniform("colsample_bytree", 0.5, 1.0, 0.1),
        'max_depth': trial.suggest_int("max_depth", 3, 10),
        "random_state": 0
    }
    model = XGBClassifier(**param_grid_xgb)
    scores = cross_validate(model, X=X_train, y=Y_train, cv=kf)
    return scores['test_score'].mean()
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=100)
print(study.best_params)
print(study.best_value)
xgb_best_param = study.best_params

# LightGBM
def objective(trial):
    param_grid_lgb = {
        'num_leaves': trial.suggest_int("num_leaves", 3, 10),
        'learning_rate': trial.suggest_loguniform("learning_rate", 1e-8, 1.0),
        'max_depth': trial.suggest_int("max_depth", 3, 10),
        "random_state": 0
    }
    model = LGBMClassifier(**param_grid_lgb)
    scores = cross_validate(model, X=X_train, y=Y_train, cv=kf)
    return scores['test_score'].mean()
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=100)
print(study.best_params)
print(study.best_value)
lgb_best_param = study.best_params

Ensemble

Zusammengestellt durch Mehrheitswahl.

from sklearn.ensemble import VotingClassifier
estimators = [
    ('rfc', RandomForestClassifier(**rfc_best_param)),
    ('xgb', XGBClassifier(**xgb_best_param)),
    ('lgb', LGBMClassifier(**lgb_best_param)),
]
voting = VotingClassifier(estimators)
scores = cross_validate(voting, X=X_train, y=Y_train, cv=kf)
print(scores["test_score"].mean())
print(scores["test_score"].std())

Da das Ergebnis des Ensembles das beste zu sein scheint, sage ich es mit diesem Modell voraus und erstelle eine Einreichungsdatei.

voting.fit(X_train, Y_train)
data_test['Survived'] = voting.predict(X_test)
submit = data_test[['PassengerId','Survived']]
submit.to_csv("./submit.csv", index=False)

Schließlich

Der Kreuzvalidierungswert lag bei 0,85, was ziemlich gut aussah, aber mit PLB nicht so gut. Es gibt viele Dinge, die Sie entwickeln können, z. B. das Erstellen von Funktionen, die Auswahl von Lernenden in RFE, die Anzahl der KFolds, die Auswahl von Lernenden, die Auswahl des Hyperparameterbereichs, die Auswahl der Ensemble-Methode usw. Ich denke, sie können es noch weiter verbessern.

Recommended Posts

Datenvorhersagewettbewerb in 3 Schritten (titanisch)
Datenanalyse Titanic 2
Datenanalyse Titanic 1
Datenanalyse Titanic 3
LightGBM, der erste Schritt, um das Denken in Datenanalyse-Wettbewerben zu beenden
OPT Data Science Wettbewerb
Behandeln Sie Umgebungsdaten in Python
Bearbeiten von Daten in Python-try mit Pandas_plyr
Zeigen Sie UTM-30LX-Daten in Python an
Schreiben Sie Daten im HDF-Format
Wahrscheinlichkeitsvorhersage von unausgeglichenen Daten