【SIGNATE】初心者が銀行の顧客ターゲティングやってみる

  • このエントリーをはてなブックマークに追加

データ分析に挑戦してみます!

SIGNATEの練習問題にある銀行の定期預金予測です。

https://signate.jp/competitions/1

データのダウンロードを行ってからスタートします。

データの読み込み

まずは、よく使うライブラリをimportするところから。もうこれ今後のテンプレートとして使っていこうかな・・・?

# データ操作系
import pandas as pd
import numpy as np
import collections
# グラフ描画系
import matplotlib.pyplot as plt
import seaborn as sns; sns.set()
# 前処理
import sklearn.preprocessing as sp
# データ分割
from sklearn.model_selection import KFold
from sklearn.model_selection import StratifiedKFold
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_validate
# 機械学習モデル
from sklearn.linear_model import LogisticRegression # ロジスティック回帰
from sklearn.ensemble import RandomForestClassifier # ランダムフォレスト
from sklearn.svm import SVC # SVM
import lightgbm as lgb #LightGBM
import xgboost as xgb  
from catboost import CatBoost
from catboost import CatBoostClassifier
from catboost import Pool
# チューニング
from sklearn import metrics
import optuna
# 制御系
import warnings
warnings.simplefilter('ignore')
import gc

そして、データを読み込んでデータを把握するところをやってみます。

!ls

# submit_sample.csv test.csv train.csv
train = pd.read_csv("train.csv")
test = pd.read_csv("test.csv")
sample = pd.read_csv("submit_sample.csv")

読み込んだらすかさずデータの把握をしに行きましょう。

# 先頭5行の表示
train.head()
test.head()
sample.head()

# データの大きさチェック
train.shape
test.shape
sample.shape

# 欠損値の確認
train.isnull().sum()
test.isnull().sum()
sample.isnull().sum()

実際に上記で確認すると、カラムは以下のようになっていました。

変数内容
idインデックス
age年齢
job職業
material結婚しているか?
education学歴
default債務不履行があるか?
balance年間平均残高
housing住宅ローン
loan個人ローン
contact連絡方法
day最終接触日
month最終接触月
duration最終接触時間
campaign現キャンペーンの接触回数
pdays前キャンペーン接触からの日数
previous現キャンペーン前に顧客に接触した回数
poutcome前回キャンペーンの成果
y(目的変数)定額預金申し込みするか?

目的変数であるyはtrainには存在していて、testには存在していません。今回はこのyを予測することになります。

特徴量エンジニアリング

データの結合

trainとtestを同時に処理するために一時的に結合します。

data = pd.concat([train, test], sort=False)

print(len(train), len(test), len(data))
data.isnull().sum()

長さの検算と欠損の検算も忘れずにやっておいたほうが良いみたいです。

まずはデータの全体像を確認します。

train.describe()
train.describe(include='O')

今回は、年齢が60歳かどうか?のカラムだけ追加してやってみます。

data['isRetire'] = 0
data.loc[data['age'] == 60, 'isRetire'] = 1

あとは、LabelEncoder()というものを使って、文字列を数値に変換しておきます。

categorical_features = ['job', 'marital', 'education','default','housing','loan','contact','month','poutcome']
for i in categorical_features:
    label_encoder = sp.LabelEncoder()
    label_encoder.fit(data[i])
    label_encoder.transform(data[i])
    data[i]=label_encoder.transform(data[i])

相関の確認

相関はここら辺で確認します。

data.corr()
sns.heatmap(data.corr(),cmap="Reds")
sns.clustermap(data.corr())

採用するカラムの決定

相関からblanceとpdaysとidとdefaultはあまりyに関係なさそうだったので、採用しないことにしました。

同時にカテゴリ変数だけ集めてcategorical_featuresに入れておきます。

adopt_columns = ['age', 'job', 'marital', 'education',
       'housing', 'loan', 'contact', 'day', 'month', 'duration', 'campaign',
       'previous', 'poutcome', 'y',"isRetire"]
categorical_features = ['job', 'marital', 'education','housing','loan','contact','month','poutcome',"isRetire"]
adopt_data = data[adopt_columns]
adopt_data.head()

機械学習モデルの作成

データ分割

まずは、データを元に戻しておきます。

train = adopt_data[:len(train)]
test = adopt_data[len(train):]

次に、データに名前をつけます。

y_train = train['y']
X_train = train.drop('y', axis=1)
X_test = test.drop('y', axis=1)

評価関数

def get_evaluate(y_test, predict):

    fpr, tpr, thr_arr = metrics.roc_curve(y_test, predict)

    accuracy = metrics.auc(fpr, tpr)
    roc = metrics.roc_auc_score(y_test, predict)      
    
    return roc

評価関数を定義しています。詳しくは次のブログで紹介しています。

LightGBT

今回はLightGBTとXGboostとCatboostという3つの勾配ブースティングを用い、最後にアンサンブルします。

cv = StratifiedKFold(n_splits=4, shuffle=True, random_state=0)

roc_list = []

for train_index, test_index in cv.split(X_train, y_train):
    X_tr = X_train.iloc[train_index]
    y_tr = y_train.iloc[train_index]
    X_va = X_train.iloc[test_index]
    y_va = y_train.iloc[test_index]
    lgb_train = lgb.Dataset(X_tr, y_tr, categorical_feature=categorical_features)
    lgb_test = lgb.Dataset(X_test)
    params = {
        'metric' :'auc',
        'objective': 'binary'
    }

    clf = lgb.train(params, lgb_train,100)

    y_predict = clf.predict(X_va, num_iteration=clf.best_iteration)
    roc= get_evaluate(y_va, y_predict)
    print('roc:{}'.format(roc))

    roc_list.append(roc)
print('Kfold平均 roc:{}'.format(np.mean(roc_list)))
y_predict

xgboost

cv = StratifiedKFold(n_splits=4, shuffle=True, random_state=0)

roc_list = []

for train_index, test_index in cv.split(X_train, y_train):
    X_tr = X_train.iloc[train_index]
    y_tr = y_train.iloc[train_index]
    X_va = X_train.iloc[test_index]
    y_va = y_train.iloc[test_index]
    dtrain = xgb.DMatrix(X_tr, label=y_tr)  
    dvalid = xgb.DMatrix(X_va, label=y_va) 
    param = {'objective': 'binary:logistic'}  
    clf = xgb.train(param, dtrain, 100)  

    y_predict = clf.predict(dvalid)
    print(y_predict[:20])
    print(y_predict.__class__)
    print(y_predict.shape)
    print(y_va.shape)
    roc= get_evaluate(y_va, y_predict)
    print('roc:{}'.format(roc))

    roc_list.append(roc)
print('Kfold平均 roc:{}'.format(np.mean(roc_list)))
y_predict

Catboost

cv = StratifiedKFold(n_splits=4, shuffle=True, random_state=0)

roc_list = []

for train_index, test_index in cv.split(X_train, y_train):
    X_tr = X_train.iloc[train_index]
    y_tr = y_train.iloc[train_index]
    X_va = X_train.iloc[test_index]
    y_va = y_train.iloc[test_index]
    ctrain = Pool(X_tr, label=y_tr)  
    cvalid = Pool(X_va, label=y_va)   
    clf = CatBoost()
    clf.fit(ctrain)
    y_predict = clf.predict(cvalid,prediction_type='RawFormulaVal')

    roc= get_evaluate(y_va, y_predict)
    print('roc:{}'.format(roc))

    roc_list.append(roc)
print('Kfold平均 roc:{}'.format(np.mean(roc_list)))
    

catboostについてはこちら

アンサンブル

# emsanble
## datas
lgb_train = lgb.Dataset(X_train, y_train, categorical_feature=categorical_features)
dtrain = xgb.DMatrix(X_train, label=y_train)
ctrain = Pool(X_train, label=y_train)  
lgb_test = lgb.Dataset(X_test)
d_test = xgb.DMatrix(X_test)
c_test = Pool(X_test)
## params
lgb_params = {'objective': 'binary'}
xgb_params = {'objective': 'binary:logitraw'}  
cat_params = {'iterations' : 100}

## train fit
lgb_clf= lgb.train(best_params, lgb_train)
xgb_clf = xgb.train(xgb_params, dtrain, 100) 
cat_clf = CatBoost(cat_params)
cat_clf.fit(ctrain)

## predict
y_p1 = lgb_clf.predict(X_test, num_iteration=lgb_clf.best_iteration)
y_p2 = xgb_clf.predict(d_test)
y_p3 = cat_clf.predict(c_test,prediction_type='RawFormulaVal')

## emsamble
def get_one(bin):
    return np.max(bin)

emsamble = [get_one([y_p1[i],y_p2[i],y_p3[i]]) for i in range(len(y_p1))]

今回は検出率が高い方が良い成績になるようなので、一番高い評価をしたモデルの結果を採用しました。

提出準備

test["y"] = emsamble
test["y"].to_csv("sub.csv", index=True, header=False)
!cat sub.csv

ここで内容に問題なければ提出です。

上記のコードで、スコアは0.8537626でした!

SNSでもご購読できます。

スポンサードリンク

コメント

コメントを残す

*