機械学習の「リーケージ」を防ぐ方法が分かる【Kaggle Course – Intermediate Machine Learning 7】Data Leakage

Kaggle

アメリカのデータ分析コンペKaggleでは、世界中の優秀なデータサイエンティストによって作成された様々なeラーニング教材が無料で公開されています。

その中でも、この記事では以下の講座について解説します。

Intermediate Machine Learning
7.Data Leakage

ただ、全編英語ですし、ところどころ説明を省略しているところもあるので、私なりにかみ砕いて解説していきます。

 

Data Leakage(機械学習のリーケージ)

この講座では、リーケージとは何か、そしてそれを防ぐ方法を学びます。

Introduction(イントロダクション)

リーケージは、訓練データに含まれているデータが、実際にモデルを使って予測するときに使えないときに起こります。

ちなみに、リーケージには大きく分けて、「ターゲットリーク」と「Train-Test Contamination」の2種類があります。

Target leakage(ターゲットリーク)

ターゲットリークは、予測を行う時点では入手できないデータが予測因子に含まれている場合に発生します。

例えば、ある店の売り上げを予測するとき、天気データが訓練データに含まれていることがあるかもしれません。実際に天気は店の売り上げに大きく影響するでしょうが、当日の天気はその日になってみないと分からないので、予測には使用できないデータとなります

実際、Kaggleコンペでも3件のリーケージが報告されています。
(1) https://www.kaggle.com/c/two-sigma-connect-rental-listing-inquiries/discussion/31870
(2) https://www.kaggle.com/c/dato-native/discussion/16485
(3) https://www.kaggle.com/c/seti-breakthrough-listen/discussion/246772

リーケージが露見すると、正当なやり方でスコアを上げているKagglerたちが報われなくなってしまいます…。

Train-Test Contamination(トレーニングとテストの汚染)

トレーニングデータと検証データの区別ができていないと、別のタイプのリークが発生します。

検証とは、モデルが未知のデータにどう作用するかを測定することです。検証データが前処理の動作に影響を与えると、このプロセスが微妙に乱れます。これを「トレーニングとテストの汚染」と呼びます。

例えば、train_test_split()を呼び出す前に前処理を行ってしまうと、検証では良いスコアだったとしても、実際にテストデータで予測すると精度が低下してしまいます

Example(具体例)

ターゲットリークを見つけて除去する方法を具体的に見てみましょう。

ここでは、クレジットカードの申し込みに関するデータセットを使用します。

まず、クレジットカードの申し込みに関するデータをXに格納し、カードの申請が通ったかどうかをyで予測します。

from sklearn.pipeline import make_pipeline
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score

# Since there is no preprocessing, we don't need a pipeline (used anyway as best practice!)
my_pipeline = make_pipeline(RandomForestClassifier(n_estimators=100))
cv_scores = cross_val_score(my_pipeline, X, y, 
                            cv=5,
                            scoring='accuracy')

print("Cross-validation accuracy: %f" % cv_scores.mean())
Cross-validation accuracy: 0.980294

交差検証の結果は98%となりました。

慣れてくると、このような高い精度が出ることは稀だと気づきます。もちろん、ないとはいえませんが、このような場合はターゲットリークが発生していないか注意深く見ていく必要があります。

以下はデータの概要です。

card カードの申請が通っていれば1、そうでなければ0
reports 悪い評価レポート
age 年齢+12分の1年
income 年収(1万で割った値)
share 年収に対する毎月のクレジット決済の割合
expenditure 月間平均クレジットカード支出額
owner 自宅を所有している場合は1、賃貸の場合は0
selfempl 自営業の場合は1、そうでない場合は0
dependents 1+扶養家族の数
months 現在の住所に住んでいる月数
majorcards 主要なクレジットカードの保有枚数
active 有効なクレジットカードの数

疑わしいデータがいくつかあります。例えば、支出expenditureはこのカードでの支出なのか、それとも申請前に使用していたカードでの支出のことなのでしょうか。

データを比較してみましょう。

expenditures_cardholders = X.expenditure[y]
expenditures_noncardholders = X.expenditure[~y]

print('Fraction of those who did not receive a card and had no expenditures: %.2f' \
      %((expenditures_noncardholders == 0).mean()))
print('Fraction of those who received a card and had no expenditures: %.2f' \
      %(( expenditures_cardholders == 0).mean()))
Fraction of those who did not receive a card and had no expenditures: 1.00
Fraction of those who received a card and had no expenditures: 0.02

expenditures_cardholdersにはカードの申請が通っている人の支出を、expenditures_noncardholdersにはカードの申請が通っていない人の支出を格納します。

それぞれの値が0となっている割合を見ると、カードの申請が通っている人は2%、通っていない人は100%でした。つまり、expenditureは申請したカードの支出を見ていたようです。

これでは、予測精度が98%と高くなるのは当然でしたね…。

また、shareも支出expenditureから決まるので、これも除外するべきです。

activemajorcardsも少し怪しいので、ここでは除外します。

# Drop leaky predictors from dataset
potential_leaks = ['expenditure', 'share', 'active', 'majorcards']
X2 = X.drop(potential_leaks, axis=1)

# Evaluate the model with leaky predictors removed
cv_scores = cross_val_score(my_pipeline, X2, y, 
                            cv=5,
                            scoring='accuracy')

print("Cross-val accuracy: %f" % cv_scores.mean())
Cross-val accuracy: 0.836989

精度は98%に対してかなり下がったので、残念に思うかもしれません。しかし、未知のデータにモデルを適用すれば、80%程度の精度が期待できるでしょう

一方、先ほどのリーケージのモデルは、交差検証のスコアは98%と高いにも関わらず、実際は80%よりもはるかに悪い結果になると思われます

Conclusion(結論)

データサイエンスにおいて、データのリーケージは数百万ドル規模の損失となる可能性があります。それは、せっかく苦労して作ったモデルが実運用で使えないことを意味するためです

しかし、トレーニングデータと検証データを注意深く分離することで、トレーニングとテストの汚染を防ぐことができます。

What’s next?

今回の例を参考にして、練習問題を解いてみましょう。

今回はKaggle Courseでリーケージについて学びました。交差検証の結果とテスト結果が大きく異なるときはリーケージも疑った方がいいかもしれません。

今回でCourseを修了したので、修了証がもらえました!

以上、最後までお読みいただきありがとうございました。

コメント

タイトルとURLをコピーしました