[PYTHON] SIGNATE [1st _Beginner Limited Competition] Teilnahme am Bankkunden-Targeting

Teilnahme am [1st_Beginner Limited Competition] Bank Customer Targeting von SIGNATE, einer Website für datenwissenschaftliche Analysen.

Da ich erfolgreich zum Intermidiate befördert wurde, schrieb ich einen Artikel, der auf meinen Notizen und Überlegungen basierte, in der Hoffnung, dass mehr Menschen problemlos am Wettbewerb teilnehmen können.

Was ist SIGNATE?

Ein Data-Science-Wettbewerb des japanischen Unternehmens SIGNATE.

Das Ministerium für Wirtschaft, Handel und Industrie, My Navi, NTT, Sansan usw. nehmen ebenfalls teil

Sie können es sich als die japanische Version von kaggle vorstellen.

Da das Forum nicht aktiv ist, scheint es für die Teilnehmer nicht viel Tendenz zu geben, "noch" Meinungen und Informationen auszutauschen. Das Forum hat sich am Ende dieses Anfängerwettbewerbs ein wenig bewegt, daher kann es sich von nun an ändern.

(Übrigens Offizielles Video ), Die korrekte Intonation scheint "Sig (↑) Ney (→) To (↓)" zu sein. Ist es dasselbe wie die Tangente der Dreiecksfunktion?)

Was ist der Beginner Limited Wettbewerb?

Dies ist das erste denkwürdige Ereignis, das jeden Monat nur für Anfänger stattfinden soll Wenn Sie eine bestimmte Punktzahl (AUC beträgt diesmal 0,85) durch absolute Bewertung anstelle von Wettbewerb überschreiten, können Sie zu einem höherstufigen Intermidiate befördert werden.

Weitere Informationen finden Sie unter Offizielle Website.

Wie man vorerst fördert

Betrieben von Benchmark Score Script ) Ist veröffentlicht

Wenn Sie dies 100 Mal mit einer geeigneten Zufallszahl für die Aussage vorhersagen und dann den Durchschnitt nehmen, beträgt die AUC 0,854, sodass Sie sie fördern können.


output_df = pd.DataFrame()
for i in range(100):
    #Testdaten von Trainingsdaten trennen
    X_train , X_valid , y_train , y_valid = train_test_split(X_train_origin,y_train_origin,test_size = 0.3 , random_state = i , stratify=y_train_origin)
    #Das verwendete Modell ist LGB (ohne Parametereinstellung)
    lgb_train = lgb.Dataset(X_train,y_train,categorical_feature = categorical_features)
    lgb_eval = lgb.Dataset(X_valid , y_valid , reference = lgb_train , categorical_feature = categorical_features)
    params = {
        "objective":"binary"
    }

    model = lgb.train(
        params,lgb_train,
        valid_sets=[lgb_train,lgb_eval],
        verbose_eval = 10,
        num_boost_round = 1000,
        early_stopping_rounds=10
    )
    
    y_pred = model.predict(X_test_origin,num_iteration=model.best_iteration)
    output_df[i] = y_pred

submit_df["1"] = output_df.mean(axis = 1)

submit_df.to_csv('submit.csv',index=False,header=None)

__ Es stellt sich heraus, dass die Strategie der "Mittelung mehrerer Vorhersageergebnisse" sehr leistungsfähig ist __

Was ich getan habe, um 0,860 zu überschreiten

Das ist nicht interessant, deshalb habe ich beschlossen, mein Bestes zu geben, um AUC 0,860 zu überschreiten.

Grob wiederholtes Ausprobieren mit dem folgenden Verfahren

Grundlegende Tabellierung

Berechnen Sie Statistiken wie Mittelwert und Medianwert durch Gruppierung nach Zielvariablen Visualisierung mit Histogrammen und Balkendiagrammen Ich habe auch den Korrelationskoeffizienten usw. berechnet.

import pandas as pd
import matplotlib.pyplot as plt
pd.set_option('display.max_rows' ,500)
pd.set_option('display.max_columns', 100)

train_df = pd.read_csv("../../data/train.csv")

#Ich werde Monat mit Tag kombinieren, also habe ich es in eine Zahl geändert
#Dezember existiert in diesen Daten nicht
month_dict = {"jan":1,"feb":2,"mar":3,"apr":4,"may":5,"jun":6,"jul":7,"aug":8,"sep":9,"oct":10,"nov":11,"dec":12}
month_int = [train_df["month"][i] for i in range(len(train_df))]
train_df["month"] = month_int

#Alter
#age
#Ich war besorgt darüber, wie ich mit über 60 Jahren umgehen sollte, also rollte ich es zusammen
#Jeder Teenager bis 59 Jahre alt
age_list = list(train_df["age"])

new_age_list = []

for i in range(len(age_list)):
    if age_list[i] == 60:
        new_age_list.append(60)
    elif age_list[i] > 60:
        new_age_list.append(70)
    else:
        new_age_list.append(int(age_list[i]/10)*10)
train_df["age_round"] = new_age_list

train_df.describe()


numeric_col_list = ["age","balance","duration","campaign","pdays","previous"]

categorical_col_list  = [categorical_feature for categorical_feature in train_df.columns if categorical_feature not in numeric_col_list]
categorical_col_list.remove("id")

#Für numerische Variablen nach Zielvariablen gruppieren, um Statistiken zu berechnen
for target_col in numeric_col_list:
    print("\ntarget_col:",target_col)
    display(train_df.groupby("y")[target_col].describe())

#Für kategoriale Gruppierung nach Zielvariable und Anzahl
for target_col in categorical_col_list:
    print("\ntarget_col:",target_col)
    display(train_df.groupby(["y",target_col])[target_col].count())


#Visualisieren und bestätigen Sie Durchschnitts- und Medianwerte
#Mittelwert und Medianwert um 01 von y
y0_df = train_df.query('y == 0')
y1_df = train_df.query('y == 1')

for target_col in numeric_col_list:
    
    #0,Durchschnittswert um 1
    y0_target_col_mean = y0_df[target_col].mean()
    y1_target_col_mean = y1_df[target_col].mean()

    #0,Median um 1
    y0_target_col_median = y0_df[target_col].median()
    y1_target_col_median = y1_df[target_col].median()

    #Vertikale Achseneinstellung
    #1 des Maximums der Durchschnitts- und Medianwerte.1x ist die vertikale Achse
    #Die Vergrößerung kann beliebig sein, solange sie leicht zu erkennen ist
    graph_y_length = (1.1*max(y0_target_col_mean,y1_target_col_mean,y0_target_col_median,y1_target_col_median))

    plt.title(target_col + ": mean")
    plt.ylabel(target_col)
    plt.ylim([0,graph_y_length],)
    plt.bar(["y0_mean","y1_mean"],[y0_target_col_mean,y1_target_col_mean])
    #plt.annotate(y0_target_col_mean,y0_target_col_mean)
    plt.show()

    plt.title(target_col + ": median")
    plt.ylabel(target_col)
    plt.ylim([0,graph_y_length],)
    plt.bar(["y0_median","y1_median"],[y0_target_col_median,y1_target_col_median],color = "green")
    plt.show()

#Erfassen Sie das gesamte Bild auch mit einem Histogramm
for target_col in numeric_col_list:
    #Achseneinstellungen
    graph_x_length = 1.1*max(train_df[target_col])
    graph_y_length = len(y0_df)
    
    print("y0",target_col)
    plt.xlim([0,graph_x_length],)
    plt.ylim([0,graph_y_length],)
    plt.hist(y0_df[target_col],bins = 20)
    plt.show()
    
    graph_y_length = graph_y_length/10
    print("y1",target_col)
    plt.xlim([0,graph_x_length],)
    plt.ylim([0,graph_y_length],)
    plt.hist(y1_df[target_col],bins = 20)
    plt.show()
    
    
#Berechnung des Korrelationskoeffizienten
train_df.corr()

#Nehmen Sie nur den Korrelationskoeffizienten der Zielvariablen auf
train_df.corr()["y"]

Ich habe auch versucht, ein Faltliniendiagramm in chronologischer Reihenfolge zu zeichnen, aber ich werde es weglassen. Mit dieser Art von Gefühl dachte ich darüber nach, welche Merkmalsmenge wesentlich zur Zielvariablen beitragen würde und ob ich eine Merkmalsmenge erstellen könnte.

Rohdatenbestätigung

Ich habe bestätigt, dass es Daten gibt, die nicht existieren, wie etwa 90 Jahre alt oder der 30. Februar. Ich habe überlegt, ob ich es verarbeiten oder löschen soll, aber ich habe es so verwendet, wie es ist

Feature Quantity Engineering

・ Pdays und Saldo werden gelöscht ・ Erstellen Sie ein Monatsend-Flag -Erstellen Sie eine Datumsspalte, die Monat und Tag kombiniert

Aus der Grundtabelle und Bestätigung der Rohdaten Merkmalsmengen, die wahrscheinlich einen starken Einfluss auf die Zielvariable haben, werden verarbeitet, um neue Merkmalsmengen zu erstellen. Ich habe es gelöscht, wenn ich beschlossen habe, dass es mich nicht betrifft Ich habe auch auf die unten beschriebene Funktionsbedeutung hingewiesen.

Einstellen von lightgbm mit optuna → 100-mal vorhersagen

optuna ist eine Bibliothek, die Hyperparameter mithilfe der Bayes'schen Optimierung optimiert Höher bewertet als Rastersuche und Zufallssuche

Ich habe auf die folgenden zwei Artikel verwiesen

Einführung in optuna

Automatische Optimierung von Hyperparametern durch die Optuna-Erweiterung LightGBM Tuner

Der Punkt ist, optuna für lightgbm zu verwenden Ich hatte einen Fehler mit optuna 2.0, der sich bereits auf meinem Computer befand, also habe ich ihn mit optuna 1.3 ausgeführt

import pandas as pd
import optuna
import functools
import warnings
warnings.simplefilter('ignore')


from sklearn.model_selection import train_test_split

#Dieser Typ ist wirklich fähig
import optuna.integration.lightgbm as lgb

from sklearn import preprocessing
from sklearn.model_selection import cross_val_score

%matplotlib 


#Daten lesen
train_df = pd.read_csv("../../data/train.csv")
test_df = pd.read_csv("../../data/test.csv")
submit_df = pd.read_csv("../../data/submit_sample.csv",header = None)


#Ersetzen Sie Dummy-Zielvariablen, damit Trainingsdaten und Testdaten verstanden werden können
test_df["y"] = -999

#Kombinieren Sie Trainingsdaten und Testdaten
all_df = pd.concat([train_df,test_df])
del train_df , test_df

all_df.reset_index(inplace=True)


#Monatsend-Flagge
month_list = list(all_df["month"])
day_list = list(all_df["day"])

end_of_month_flag = []
for i in range(len(all_df)):
    if day_list[i] in [30,31]:
        end_of_month_flag.append(1)
    elif day_list[i] == 29 and month_list[i] in ["feb","apr","jun","sep","nov"]:
        end_of_month_flag.append(1)
    elif day_list[i] == 28 and month_list[i] == "feb":
        end_of_month_flag.append(1)
    else:
        end_of_month_flag.append(0)
        
all_df["end_of_month_flag"] = end_of_month_flag


#Mond(Monatsspalte)Zu einer Nummer
month_dict = {"jan":1,"feb":2,"mar":3,"apr":4,"may":5,"jun":6,"jul":7,"aug":8,"sep":9,"oct":10,"nov":11,"dec":12}
month_int = [month_dict[all_df["month"][i]] for i in range(len(all_df))]
all_df["month"] = month_int

#month_Tagesspaltenerstellung
#Ich denke, es ist in Ordnung, den Entscheidungsbaum als int zu behandeln, da er nur die Größenbeziehung kennen muss.
month_day = []
month_day = all_df["month"]*100 + all_df["day"]
all_df["month_day"] = month_day

#Löschen Sie nicht benötigte Spalten
del all_df["index"]
del all_df["id"]
del all_df["pdays"]
del all_df["balance"]

#Geben Sie den Spaltennamen der Kategorie an
categorical_features = ["job","marital","education","default","housing","loan","contact","month","poutcome","end_of_month_flag"]


#Etikettencodierung
#Ich habe die Zielcodierung durchgeführt, aber die Punktzahl hat sich nicht geändert

for col in categorical_features:
  lbl = preprocessing.LabelEncoder()
  lbl.fit(all_df[col])
  lbl.transform(all_df[col])
  all_df[col] = lbl.transform(all_df[col])


#Aufteilung der Trainingsdaten und Testdaten
train_df = all_df[all_df["y"] != -999]
test_df = all_df[all_df["y"] == -999]

#Teilen Sie in erklärende Variablen und objektive Variablen
origin_y_train = train_df["y"]
origin_X_train = train_df.drop(["y"],axis = 1)
origin_X_test = test_df.drop(["y"],axis = 1)

output_df = pd.DataFrame()

##Ausführung von hier auf meinem PC(Core i5-Speicher der 10. Generation 8 GB)Dann dauerte es mehr als 10 Stunden

for i in range(100):
    #Testdaten von Trainingsdaten trennen
    X_train , X_valid , y_train , y_valid = train_test_split(origin_X_train,origin_y_train,test_size = 0.3 , random_state = i , stratify=origin_y_train)
    #Datensatzerstellung
    lgb_train = lgb.Dataset(X_train,y_train,categorical_feature = categorical_features,free_raw_data=False)
    lgb_eval = lgb.Dataset(X_valid , y_valid , reference = lgb_train , categorical_feature = categorical_features,free_raw_data=False)
    params ={"objective":"binary",
             "metric":"auc"    
    }

    best_params, tuning_history = dict(), list()
    booster = lgb.train(params, lgb_train, valid_sets=[lgb_train,lgb_eval],
                        verbose_eval=0,
                        best_params=best_params,
                        tuning_history=tuning_history)

    print("Best Params:", best_params)
    print("Tuning history:", tuning_history)

    #Hyperparameter mit der höchsten AUC hinzugefügt
    params.update(best_params)

    #Lernen
    model = lgb.train(
        params,lgb_train,
        valid_sets=[lgb_train,lgb_eval],
        verbose_eval = 10,
        num_boost_round = 1000,
        early_stopping_rounds=10
    )

    #Vorausgesagt durch Wettbewerbsdaten
    y_pred = model.predict(origin_X_test,num_iteration=model.best_iteration)

    output_df[i] = y_pred


submit_df = pd.read_csv("../../data/submit_sample.csv",header = None)
del submit_df[1]
submit_df["1"] = output_df.mean(axis = 1)
submit_df
submit_df.to_csv("../../output/result.csv",header=None,index=False)

#Während des Versuchs und Irrtums bestätigte ich die Wichtigkeit des Merkmals und konstruierte die Merkmalsmenge.
lgb.plot_importance(model, height=0.5, figsize=(8,12))

__ Als ich dies einreichte, betrug die AUC 0,859__

Darüber hinaus betrug das Ergebnis der 100-fachen Vorhersage durch Entfernen der Spalte Tag und des Monatsend-Flags 0,859.

Als ich den Durchschnitt dieser __2 Vorhersagen nahm und einreichte, konnte ich 0,860 __ sicher überschreiten Herzliche Glückwünsche

image.png

Was ich sonst noch getan habe

Ich habe versucht, die Punktzahl durch Optimieren der Hyperparameter eines Modells mit Catboost zu erhöhen, aber die Punktzahl ist nur geringfügig erhöht und die Berechnungszeit nicht wert. Es schien hoffnungsvoll, lightgbm mit einer geeigneten Zufallszahl für die Aussage zu drehen, also gab ich es auf.

Was ich wünschte, ich hätte getan

Modellausgabe

Ich wünschte, ich hätte xgboost und NN zusammen gestapelt Wenn man es betrachtet, scheint es, dass die Kombination mehrerer Methoden eine der königlichen Straßenstrategien des Wettbewerbs ist.

Ich war zufrieden damit, das Ziel von 0,860 zu überschreiten, und betrat das Lagerhaus.

Code-Ausgabe

Ich dachte, es wäre besser, die Verarbeitung von Merkmalsmengen zu einer Funktion zu machen. Ich möchte in der Lage sein, schönen Code auch durch Ausprobieren zu schreiben

Schließlich

Bis zum Ende Danke fürs Lesen Wenn Sie Fragen, Vorschläge oder Verbesserungen haben, die schwer zu verstehen sind, können Sie diese gerne kommentieren.

Recommended Posts

SIGNATE [1st _Beginner Limited Competition] Teilnahme am Bankkunden-Targeting
SIGNATE [1st _Beginner Limited Competition] Lösen von Bankkunden-Targeting
Signate_ Rückblick auf den 1. Beginner Limited Competition
[SIGNATE] Bankkunden-Targeting @ Learning
Signate 2nd _Beginner Limited Competition Review
Ich besuchte die Schule und nahm zum ersten Mal am SIGNATE BEGINNER Limited-Wettbewerb teil.
Ich habe an Kaggles NFL-Wettbewerb teilgenommen