データサイエンスや機械学習の知識を活かして、コンペティションに挑戦してみよう!
クレジットカード会社にとって、支払い不履行になり得る顧客を予測することは、最も重要なタスクの一つです。
このコンペティションでは、default of credit card clientsと呼ばれるデータセットを用いて、顧客の支払いの履行・不履行の予測に挑戦します。
このデータは台湾における顧客のクレジットカード支払いに関するデータです。
1位 100,000円
※ 対象者には、コンペティション終了後 メールにてご連絡いたします。
実践Data Scienceシリーズ PythonではじめるKaggleスタートブック (KS情報科学専門書)
Pythonで動かして学ぶ! Kaggleデータ分析入門 (AI & TECHNOLOGY)
データをダウンロードするにはログインまたはユーザー登録して下さい
データは2つのグループに分けられます:
なお訓練データセットとテストデータセットにはそれぞれ27,000と3,000のサンプルが含まれています。
訓練データセットは、機械学習モデルを構築するために使用してください。訓練データセットについては、不履行か履行かのラベルが振られています。
テストデータセットを使用して、どの程度新しいデータに対してモデルが実行されているかを確認する必要があるので、テストデータセットについては、
顧客ごとのラベルデータは存在しません。
なので、テストデータセットを使用して、各顧客のラベルを予測してください。
また、提出ファイルの例に関しては 評価方法 のタグを参照してください。
データセットのカラムは以下の通りになっています。
カラム名 | 内容 |
---|---|
X1 | 与えられたクレジットの金額(NTドル)個人消費者クレジットと家族(補足)クレジットの両方を含みます |
X2 | 性別(1=男性, 2=女性) |
X3 | 教育(1=大学院, 2=大学, 3=高校, 4=その他) |
X4 | 婚姻状況(1=既婚, 2=単身, 3=その他) |
X5 | 年齢(年) |
X6 | 過去の毎月の支払記録(2005年9月の返済状況) |
X7 | 過去の毎月の支払記録(2005年8月の返済状況) |
X8 | 過去の毎月の支払記録(2005年7月の返済状況) |
X9 | 過去の毎月の支払記録(2005年6月の返済状況) |
X10 | 過去の毎月の支払記録(2005年5月の返済状況) |
X11 | 過去の毎月の支払記録(2005年4月の返済状況) |
X12 | 請求書の金額(NTドル)/2005年9月の請求書明細書 |
X13 | 請求書の金額(NTドル)/2005年8月の請求書明細書 |
X14 | 請求書の金額(NTドル)/2005年7月の請求書明細書 |
X15 | 請求書の金額(NTドル)/2005年6月の請求書明細書 |
X16 | 請求書の金額(NTドル)/2005年5月の請求書明細書 |
X17 | 請求書の金額(NTドル)/2005年4月の請求書明細書 |
X18 | 前払い金額(NTドル)/2005年9月に支払われた金額 |
X19 | 前払い金額(NTドル)/2005年8月に支払われた金額 |
X20 | 前払い金額(NTドル)/2005年7月に支払われた金額 |
X21 | 前払い金額(NTドル)/2005年6月に支払われた金額 |
X22 | 前払い金額(NTドル)/2005年5月に支払われた金額 |
X23 | 前払い金額(NTドル)/2005年4月に支払われた金額 |
※ X6-X11の測定スケールは、-1=正当な支払い, 1=支払い遅延1か月間, 2=2ヶ月間の支払い遅延, ..., 8=8ヶ月間の支払い遅延, 9=9ヶ月以上の支払い遅延 となっています。
ラベル'Y'は以下の通りです
ラベル | 説明 |
---|---|
0 | 支払い履行 |
1 | 支払い不履行 |
目標は、テストデータセットのクレジットカード使用者のデータに基づき、支払い不履行か、履行かを予測することです。それぞれの顧客IDにおいて、変数Y(支払い
不履行 or 履行)を1 or 0で予測してください。
モデルの予測性能は3,000のテストデータセットのうち、予測が正解した割合で与えられます。
$$
\text{accuracy} = \frac{\text{correct prediction}}{\text{total}}
$$
回答用のsubmission.csvを用意する(3,000のエントリーとヘッダー行を含む) 。
提出されたファイルに余分な行や列(IDとY以外)が含まれていた場合はエラーとなります。
提出ファイルは以下の列のみを必ず含んでください:
以下は提出ファイルの例です。
ID,Y
0,1
1,1
2,0
3,1
4,0
複数のアカウントを使ってコンペティションに参加することはできません。
コードやデータを,特定のコンペティション参加者に個人的に共有することはできません。コンペティションの全ての参加者が利用できるような状態であれば、コードを共有することは問題ありません。
1日あたり最大5件の応募が可能です。
審査のために最終提出を5件まで選択することができます。
開始日 | 2019/4/9 0:00 JST |
---|---|
エントリー締め切り | なし |
終了日 | 2019/6/3 0:00 JST |
優勝者は、以下の条件を満たすことで賞金を受け取ることができます。
本コンペティションで公開されているデータのみを用いてチャレンジして下さい。また、学習済みモデルを用いることも外部データを用いているとみなします(FAQより転載)。
公平性の担保、チーティング等の不正防止のため、β版のコンペでは、予告なくルールの追加・変更を行う場合がございます。
ご不便をおかけすることもあるかと思いますが、サービス向上のためご了承ください。
はい。最も精度の高い学習モデルを作成した優勝者には、賞金10万円を贈呈します。ただし、賞金を受け取るにあたっては、学習済みモデルの提出、解説の作成が必要となります。
可能です。現時点ではチームとして参加する機能は未実装のため、参加者ごとに同じ結果を提出いただいて構いません。
※ 同率スコアの場合は提出時間の早いユーザーが上位となりますこと、ご了承ください。
本コンペティションで公開されているデータのみを用いてチャレンジして下さい。また、学習済みモデルを用いることも外部データを用いているとみなします。
[こちら](https://prob.space/users/sign_up)から作っていただけます。
アカウントを作らないと、コンペティションに参加することはできないので気をつけてください。
Seed を固定することが推奨です.ただし,Seed を固定しなくても提出用コードとしては認めていく方針です。
まずはデータを読み込んで見ましょう.csvデータの読み込みは複数のやり方がありえますが,pandas
のread_csv
関数はその中でも機能が豊富で,扱いやすいためこれを使います.
これを使うと,csvデータを読み込み,pandas dataframeにして返してくれます.
また,dataframeには.head()
というメソッドが定義されており,これを使うと先頭の数行を確認できます.
import pandas as pd
path = "./data/train_data.csv"
df = pd.read_csv(path)
# >>> df.head()
# ID X1 X2 X3 X4 X5 X6 ... X18 X19 X20 X21 X22 X23 Y
# 0 0 20000 2 2 1 24 2 ... 0 689 0 0 0 0 1
# 1 1 120000 2 2 2 26 -1 ... 0 1000 1000 1000 0 2000 1
# 2 2 90000 2 2 2 34 0 ... 1518 1500 1000 1000 1000 5000 0
# 3 3 50000 1 2 1 57 -1 ... 2000 36681 10000 9000 689 679 0
# 4 4 50000 1 1 2 37 0 ... 2500 1815 657 1000 1000 800 0
最適化の際に収束性を保証するため,入力データに平均が0で分散が1であるという仮定を置くものがままあります.そこで,連続値のデータに対しては平均が0で分散が1になるように正規化しておきます.(標準化と呼ばれるケースもあります.)
ここでは,離散的な変数(性別や教育などのダミー変数)については除外し,正規化を行います.
from sklearn.preprocessing import StandardScaler
def standardize(df: pd.DataFrame) -> pd.DataFrame:
"""
Parameters
----------
df : pd.DataFrame
Returns
-------
_df : pd.DataFrame
"""
_df = df.copy()
_df_subset = _df.iloc[:, 12:]
if 'Y' in _df_subset.columns:
_df_subset = _df_subset.drop('Y', axis=1)
scaler = StandardScaler()
X_subset_std = scaler.fit_transform(_df_subset)
_df.loc[:, _df_subset.columns] = X_subset_std
return _df
def load_train_data(path: str, standardized: bool=True) -> np.ndarray:
"""
Parameters
----------
path : str
path of train_data.csv
standardized : bool
If True, train_data.csv will be standardized.
Returns
-------
X : np.ndarray
y : np.ndarray
Examples
--------
>>> path = "./data/train_data.csv"
>>> X, y = load_train_data(path, standardized=True)
"""
df = pd.read_csv(path)
if standardized:
df = standardize(df)
X = df.iloc[:, 1:-1].values
y = df.Y.values
return X, y
ここで定義した関数を用いると,以下のようにしてcsvデータを読み込むことができます.
path = "./data/train_data.csv"
X, y = load_train_data(path, standardized=True)
訓練データにおいて,そもそも支払い履行と支払い不履行がどのような割合なのか確認してみましょう.
one_ratio = y.sum() / len(y)
print("ratio of 1 in label: ", one_ratio)
print("ratio of 0 in label: ", 1 - one_ratio)
# ratio of 1 in label: 0.222
# ratio of 0 in label: 0.778
支払い不履行が22%ほど含まれたデータであることがわかります.
pandas dataframeのメソッドには,describe
メソッドという便利なものがあります.
これを使うと,dataframeの各列について,基本的な統計量を確認することができます.
path = "./data/train_data.csv"
df = pd.read_csv(path)
df.describe()
# ID X1 ... X23 Y
# count 27000.00000 27000.000000 ... 27000.000000 27000.000000
# mean 13499.50000 166856.284444 ... 5238.613148 0.222000
# std 7794.37297 129363.239705 ... 17865.467132 0.415599
# min 0.00000 10000.000000 ... 0.000000 0.000000
# 25% 6749.75000 50000.000000 ... 140.000000 0.000000
# 50% 13499.50000 140000.000000 ... 1500.000000 0.000000
# 75% 20249.25000 240000.000000 ... 4002.250000 0.000000
# max 26999.00000 1000000.000000 ... 528666.000000 1.000000
# [8 rows x 25 columns]
ここでは試しに,ロジスティック回帰モデルを作成してみましょう.sklearn
は多くの機械学習モデルが実装されたライブラリであり,これを使って実装してみます.
from sklearn.linear_model import LogisticRegression
path = "./data/train_data.csv"
X, y = load_train_data(path, standardized=True)
lr = LogisticRegression(tol=1e-6, class_weight={0: 0.4, 1: 0.6})
lr = lr.fit(X, y)
先ほどデータを確認した際に,支払い不履行の割合が22%でした.このように,ラベルごとにデータの割合がアンバランスであるようなデータを,不均衡データと言います.このようなデータを用いてモデルの学習を行うと,全て0と答えるモデルができてしまうケースがあります.(今回の場合,全て0と答えるだけで78%の正答率が得られています.しかし,これは我々が望んでいるモデルではありません.)
それを回避するため,class_weight
オプションで,1を間違いなく識別することを,0を間違いなく識別することよりも重要視するように設定しています.
sklearn
の識別モデルには,.predict()
メソッドが定義されており,これを使うと与えられたデータに対して,その0か1かの予測結果を返してくれます.
また,予測結果と実際の結果がどの程度異なるかを評価する関数がsklearn.metrics
に定義されています.ここでは精度を確認してみましょう.
from sklearn.metrics import accuracy_score
y_hat = lr.predict(X)
print(accuracy_score(y, y_hat))
# 0.8162962962962963
このように,81.6%程度となり,全て0と識別するモデルに比べて4%ほど精度が増加しています.
これをベースにして,モデルのパラメータを変える,モデルを変える,有用な特徴量を探るなど試行錯誤して,モデルの性能を上げていきましょう.