調整しよう!ランダムフォレストのハイパーパラメータ

前回は、銀行の顧客ターゲティングを機械学習でやってみるにあたり、まずは最低限の前処理で、どれくらいの精度が出るのかを、図ってみました。

今回は、「ハイパーパラメータ」を調整し、精度の向上に挑戦してみたいと、思います。

ハイパーパラメータって何?

ハイパーパラメータと聞くと、なんだかとっても凄そうな名前ですよね。イメージだけで言うと、これを調節すれば、ものすごい精度があがりそうです。が、実際には、そんなに御大層なものでも(?)ありません。

機械学習において、入力データと出力データの関係から、機械が自動的に学習して、値を調節する変数がパラメータ。機械をうまく学習させるために、人間がマニュアルで調節する必要がある変数を、ハイパーパラメータという、みたいです*1

今回はこの「ハイパーパラメータ」の調節に、チャレンジしてみたいと思います。

ランダムフォレストとハイパーパラメータ

一般に、ランダムフォレストは調整すべきハイパーパラメータが少ないと、言われているみたいです。が、scikit-learnのドキュメンテーションを見る限り、素人目には、それなりに数がありるように、見えます。やみくもに調整するのも大変なので、まずは、ランダムフォレストの仕組みに立ち戻って、考えてみたいと思います。

そもそも、ランダムフォレストとは、このあたりこのあたりでも触れましたが、決定木/回帰木を弱学習器として利用した、バギングによる、アンサンブル機械学習のはずです。

ということは、まず重要なハイパーパラメータは、「n_estimators」だと、思われます。これは、ベースとして利用する決定木/回帰木の数で、理論上、数が多ければ多いほど精度は上がりそうです。が、計算時間も、うなぎ上りに、なりそうです。デフォルトは、10みたいです。

次に目に付くのが、「max_depth」です。これは、先のn_estimatorsで指定した決定木/回帰木の深さを、どこまでにするかを、指定します。「木の深さ」については、このあたりのイメージを、ご覧ください。木を深くすればするほど、複雑な関数を近似できるようになります。が、学習データに過剰にフィットしすぎて、肝心かなめの未知のデータに対して精度が悪くなる、いわゆる過学習が起きる可能性が、あります。デフォルトはNone。この場合、=∞つまり、どこまででも木を深くする、みたいです。

続いては、「max_features」。個々の決定木に、どれくらいの特徴量を使用するかを、表します。特徴量とは、=入力データの種類。銀行の顧客ターゲティングにおいては、このあたりでまとめてみましたが、「age」~「poutcom」までの、16項目。経験則的に、入力項目数の平方根、今回の場合は16^(1/2)を指定すると、精度が上がることが多いみたいですが、log2(入力項目数)とかも、慣例的に用いられる、そうです。デフォルトはautoになっているみたいですが、auto=sqrt、即ち、デフォルトだと、入力項目数の平方根が、max_featuresに用いられるそうです。

気配的に、このあたりがランダムフォレストの三大パラメータの気がするので、まずはこの3つを、調節してみたいと、思います。

グリッドサーチによるハイパーパラメータの調整

ハイパーパラメータを調整する方法として、1個1個手動で調整する方法と、組み合わせを総当たりで調整する方法が、あります。正直、総当たりはとても計算時間がかかるし、あらかじめ当たりがついていないと組み合わせ候補も作れないため、個人的には手動であたりをつけたいところなんですが・・・今回はパラメータが3つなので、総当たりやってみたいと思います。

パラメータ 値候補
n_estimators 10, 100, 200, 300
max_depth 5, 10, 50, None
max_features 'sqrt', 'log2', None

n_estimatorsとmax_depthは、とりあえずオーダー感にあたりをつけるため、ざっくり増やしていきます。余裕があれば、もっとも精度がよくなった近辺をもう少し探ってみる、方針です。

続いて、総当たりの方法ですが・・・グリッドサーチという手法で、やってみたいと思います。以下の図を、ご覧ください。

f:id:tatsu_mk2:20190504171824p:plain
図1 グリッドサーチイメージ
 
前回の「ホールドアウト法」では、入力データを「学習データ」と「検証データ」に2分割しましたが、グリッドサーチでは、3以上に分割します。図の場合、3分割したので、学習データと検証データの組み合わせが、3つあります。これに対して、パラメータを総当たりで組み合わせを検証するため・・・4(n_estimators)×4(max_depth)×3(max_features)×3(学習データと検証データの組み合わせ)=144通りになります。うーん、ディープラーニングとかだと、とてもじゃないけどやってられなさそうな数字ですね。図は、簡単なように3分割で書いてみましたが、ここでは5分割でやってみようと、思います。つまり、240通りです。うげっ・・・

GridSearchCVによるグリッドサーチ

Pythonには、グリッドサーチを行うためのライブラリとして、その名もずばりGridSearchCVというライブラリがあるため、今回はこれを使ってやってみたいと、思います。

まずは、前回に倣い、最低限の前処理を行うまでを、一気にやります。

# まずはGoogle Colabのお約束、Googleドライブをマウント
from google.colab import drive
drive.mount('/content/gdrive/')

# 作業フォルダへ移動
%cd ./gdrive/My\ Drive/colab/bank

# pandasをインポート
import pandas as pd

# 銀行の顧客データを読み込み、正しく読み込めていることを確認
train = pd.read_csv("./dataset/train.csv")
train.head()

# ダミーコーディング実行
train_data = pd.get_dummies(data=train, columns=['job', 'marital', 'education', 'default', 'housing', 'loan', 'contact', 'poutcome', 'month'], drop_first=True)
train_data.columns

# 目的変数の定義
target_col = 'y'


# 説明変数に使用しない列の定義
exclude_cols = [target_col, 'id']


# 説明変数の定義
feature_cols = [col for col in train_data.columns if col not in exclude_cols]


# 目的変数と説明変数を分割
y = train_data[target_col]
x = train_data[feature_cols]
x.head()


そしてここからが今日の本題。まずは、ハイパーパラメータの値候補を、ディクショナリ型で、定義します。

# ディクショナリ型でハイパーパラメータの値候補を定義
params = {"n_estimators": [10, 100, 200, 300], "max_depth": [5, 10, 50, None], "max_features": ["sqrt", "log2", None]}

続いて、ランダムフォレストとグリッドサーチ用のライブラリを、インポートします。

# 学習用ライブラリをインポート
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV

GridSearchCVですが、情報によっては「from sklearn.grid_search」となっているものもあるみたいですが、私の環境だと、「from sklearn.model_selection」にいました。場所が変わったようです。

続いて、いよいよランダムフォレストで、GridSearchCVを実行します。基本的に、GridSearchCVをインスタンス化して、fit()関数を実行すれば、グリッドサーチが実行されます。インスタンス化する際の第一引数が、グリッドサーチしたいモデルのインスタンス(この場合ランダムフォレスト)、param_gridに先ほど定義したディクショナリ型の値候補を、cvに分割数(この場合、5)、scoringに評価指標(この場合、AUC)を、指定します。scoringに指定できる指標値は、scikit-learnのドキュメンテーションのこのあたりに、あります。

# グリッドサーチ実行
rf = RandomForestClassifier(random_state=1234)
gscv = GridSearchCV(rf, param_grid=params, cv=5, scoring="roc_auc", verbose=1)
gscv.fit(x, y)


案の定めっちゃ時間かかりました

優に2,30分はかかりましたでしょうか・・・終わってよかったです。では、ベストな組み合わせの確認。

# ベストパラメータの確認
gscv.best_params_

{'max_depth': 50, 'max_features': 'sqrt', 'n_estimators': 300}

n_estimatorsは最大の300がベストになっているので、まだまだ増やせる余地があるかもしれません。一方、max_depthは、Noneよりも50の方がベストになっているので、もう少しは増やせるかもしれませんが、無限にするのはやりすぎみたいです。そして、max_featuresは、ちまたの噂通り、sqrtでした。指標確認してみたいと思います。

# scoring(今回の場合、roc_auc)で指定した指標の確認
gscv.best_score_

0.9275434071386318

だいぶスコアがあがりました!

前回が0.889くらいだったのに対し、0.928くらいでしょうか。SIGNATEのランキングで言うと、370/5115位(2019年5月6日現在)くらいになりました。

改めてホールドアウト法で確認

グリッドサーチで求めたパラメータをベースに、もう少しパラメータを調整しつつ、改めてホールドアウト法で、他の指標の値も確認してみたいと、思います。

# データ分割用の関数をインポート
from sklearn.model_selection import train_test_split

# 分割実行
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.1, random_state=1234)

# 学習を実行
rcf = RandomForestClassifier(n_estimators=1000, max_depth=50, max_features="sqrt", random_state=1234)
rcf.fit(x_train, y_train)

# 分類結果を取得
y_pred = rcf.predict(x_test)

# 確率を取得
y_pred_proba = rcf.predict_proba(x_test)[:, 1]

# 精度測定用関数のインポート
from sklearn.metrics import roc_auc_score
from sklearn.metrics import accuracy_score
from sklearn.metrics import recall_score
from sklearn.metrics import precision_score

# 精度測定
auc = roc_auc_score(y_test, y_pred_proba)
print('AUC: ', auc)
acy = accuracy_score(y_test, y_pred)
print('Accuracy: ', acy)
rc = recall_score(y_test, y_pred)
print('Recall: ', rc)
pr = precision_score(y_test, y_pred)
print('Precision: ', pr)

AUC: 0.9315272819303317
Accuracy: 0.9100626612605971
Recall: 0.3948220064724919
Precision: 0.6815642458100558

max_depthの値は、50のほかに、改めて60, 70, 80も試してみましたが、小数点のかなり下の方の値がちょっぴり上がるだけだったので、計算時間も考慮し、50に据え置きました。n_estimatorsは、250, 350, 400を試してみたところ、逆にAUCが下がりましたが、1000を試してみたところ、0.0005くらいは上がったので、採用してみました。

グリッドサーチに比べて少し精度が上がっているように見えますが・・・これをどう見るかは、少し難しいところです。先のグリッドサーチは、データを5分割し、4つを学習データ・1つを検証データに使用しました。つまり、学習データ:検証データの割合は、8:2です。一方、ホールドアウト法は9:1で分割したため、学習データが多い分、精度が上がった可能性も、あります。

一方、グリッドサーチは、学習データと検証データの組み合わせを5つ作成し、その平均を取ったのに対し、ホールドアウト法は1回しか実行していません。たまたまホールドアウト法の組み合わせにうまくフィットし、精度が上がった可能性もありますが、それが実データ(未知のデータ)の分布と近いのか離れているのかは、分からないので、いいことか悪いことかは、なかなか判別しかねるところです。

ちなみに、0.932ですと・・・330位/5115位くらいでしょうか。

終わりに

いかがだったでしょうか。上の方では、「ハイパーパラメータは名前は御大層でも、名前ほど御大層なものではない」なんて書いてしまいましたが・・・初心者でも、モデルとハイパーパラメータの選択を誤らなければ、そこそこの精度は出せそうなことが、分かりました。このあたりが、「ランダムフォレストは安定した精度が出る」なんて言われる所以かな、なんて気が、します。深い業務知識と職人芸的なテクニックが必要そうな、特徴量設計*2に比べると、誰でもある程度精度をあげることが、出来そうです。

というわけで、今回はこのあたりにして、次回は、ランダムフォレストの残りのハイパーパラメータについても、掘り下げてみたいと思います。最後まで読んでいただいて、ありがとうございました。

参考資料

フリーライブラリで学ぶ機械学習入門

フリーライブラリで学ぶ機械学習入門

*1:ベイズ最適化という、ハイパーパラメータ含め最適化する手法も、あるみたいですが。

*2:ざっくり言えば、入力データをそのまま機械学習に使うのではなく、より精度が上がりそうな加工を施して、取捨選択して機械学習に使用する手法とでも、言えましょうか?

いざ機械学習!そのための最低限の前処理とは?

前回までで、ようやく、銀行の顧客ターゲティングに機械学習を活用するにあたって、そのビジネス的な目的と、性能を図るに適した指標の整理が、出来ました。

今回からいよいよ、実際に機械学習していってみたいと、思います。

はじめに:前処理ってなに?

機械学習するためには、データの前処理が必要だと、言われています。一口に「前処理」といいますが、私が思うに、実際には二つあるような、気がします。一つ目が、「それをしないと、そもそも機械学習を実行出来ない」前処理で、二つ目が、「それをすることにより、精度が上がる」前処理です。

前者は、最低限必須な前処理です。一方後者は、コンペなどで勝利するためにはある意味、必須な前処理かもしれません。が、ビジネス的には、必ずしも必須ではない可能性も、ありえます。ビジネス上必要な精度に達していなければ、やる必要がありますし、達していれば、あえてやる必要も、ないかもしれません。

本エントリーではまず、最低限必要な前者の前処理のみを行って、銀行の顧客ターゲティングを機械学習してみたいと、思います。

ほんとはよくない?いきなり機械学習

どこかで見ました。「いきなり機械学習するのは、よくない」と。あくまでもデータと向き合い、そのデータがどういうデータであるかを理解するのが、重要だと。確かに、その通りかもしれません。いきなり機械学習して、「〇〇な精度が出ました。」となっても、「で、どうしよ?」で終わるのが、オチかもしれません。

大体の本やサイトだと、データを読み込んで、とりあえずhead()*1して、describe()*2して、相関を調べて・・・なんて、やっているような気が、します。相関とは、超ざっくりいうと、比例関係でしょうか。一方の値が変化すれば、それに連動してもう一方の値も変わる、あれです。

相関を調べ、予測したい値*3と強い相関を持つデータを、入力値として使い、機械学習を実行する・・・それが、王道な気がします。

しかし、です。

基準値が欲しいと、思いませんか?

もしかしたら私だけかもしれませんが、初心者が無い知恵を絞って、入力データを選りすぐる*4より、何も考えずに全量ぶち込んで機械学習した方が、ましな可能性が、あります。初心者が初心者なりに工夫したつもりになって、「やあ、いい精度が出たぞ」と思っても、何もしない方が精度が高いことも、ありうるのです。

・・・というわけで、本エントリーでは、今後、何か工夫してみた時に、効果があった/なかったを判断するための基準値として、まずは最低限の前処理で、機械学習してみることに、しました。

最低限の前処理で機械学習する流れ

当然と言えば当然ですが、まずは「どんな前処理が必要か」を、確認する必要が、あります。それを踏まえ、以下のような流れで、やってみたいと、思います。

  1. 必要な前処理を確認する
  2. 必要な前処理を実施する
  3. モデルを選択する
  4. 機械学習を実行する
  5. 精度を測定する

ではやってみよう!

必要な前処理を確認する

まずそもそも、機械学習は入力データとして、数値しかとることが出来ません。つまり、「最低限必要な前処理」とは具体的に、以下と考えます。

  • 数値項目の非数値データを、処理する。
  • 文字列項目を数値データに、変換する。

前者はいわゆる、「NaN」(Not a Number)というやつでしょうか。間違えて数値項目に文字列が入っていることもありえますが、いわゆるnull(欠損値)が、代表的です。処理の仕方は様々で、NaNのある行を除去したり、代表値(平均値や最頻値など)で埋めたり、高度なものになると、前処理用の機械学習で欠損値を埋めることなども、あるようです。

後者は、カテゴリ項目などが代表的で、「性別」などがあります。例えば、男性⇒1、女性⇒2などに置き換えることもあれば、以下のように、「性別」項目を「男性フラグ」「女性フラグ」に分割することなども、あります。前者の手法を「マッピング」、後者の手法を「one-hot-encoding」という、みたいです。

性別 男性フラグ 女性フラグ
男性 1 0
女性 0 1

これを踏まえ、Google版Jupyter NotebookであるGoogle Colabを使って、実際に必要な前処理を確認していってみたいと、思います。銀行の顧客ターゲティング用のGoogle Colabの環境については、このあたりのエントリーをご確認いただければと、思います。

それでは早速、Google Colabのお約束からやっていきます。一個一個が、Jupyter(Colab)のセルの、イメージになります。

# まずはGoogle Colabのお約束、Googleドライブをマウント
from google.colab import drive
drive.mount('/content/gdrive/')

# 作業フォルダへ移動
%cd ./gdrive/My\ Drive/colab/bank

続いて、構造化データを扱うためのPythonのライブラリである、pandasをインポート。pandasを使って、銀行の顧客データを、読み込みます。

# pandasをインポート
import pandas as pd

# 銀行の顧客データを読み込み、正しく読み込めていることを確認(head()の実行結果は省略)
train = pd.read_csv("./dataset/train.csv")
train.head()


さて、ここからが本題。先に挙げた二つの前処理(①数値項目の非数値データを、処理する。②文字列項目を数値データに、変換する)を実施するには、どの項目が数値項目で、どの項目が文字項目かを、確認する必要があります。pandasのinfo()関数を、使います。

# 各項目のデータ型を確認
train.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 27128 entries, 0 to 27127
Data columns (total 18 columns):
id 27128 non-null int64
age 27128 non-null int64
job 27128 non-null object
marital 27128 non-null object
education 27128 non-null object
default 27128 non-null object
balance 27128 non-null int64
housing 27128 non-null object
loan 27128 non-null object
contact 27128 non-null object
day 27128 non-null int64
month 27128 non-null object
duration 27128 non-null int64
campaign 27128 non-null int64
pdays 27128 non-null int64
previous 27128 non-null int64
poutcome 27128 non-null object
y 27128 non-null int64
dtypes: int64(9), object(9)
memory usage: 3.7+ MB


結果、「age、balance、day、duration、campaign、pdays、previous」が数値。「job、marital、education、default、housing、loan、contact、month、poutcom」が文字項目*5であることが、分かりました。ちなみに、idは単なるキー項目、yは予測対象の項目(入力データでは、ない)なので、ここでは除きます。

続いて、実際にNaN項目があるかないかを、確認します。isnull()関数とsum()関数を、使います。

train.isnull().sum()

id 0
age 0
job 0
marital 0
education 0
default 0
balance 0
housing 0
loan 0
contact 0
day 0
month 0
duration 0
campaign 0
pdays 0
previous 0
poutcome 0
y 0
dtype: int64

どうやら、NaNはないらしいことが分かりました。素晴らしい!というわけで、最低限の前処理として、今回は、以下のみが必要であることになります。

  • 文字列項目を数値データに、変換する。

必要な前処理を実施する

さて、実際に

  • 文字列項目を数値データに、変換する。

これを行うにあたり、まずはマッピングかone-hot-encodingかを切り分ける必要があります。一般的に、サイズの「S」「M」「L」みたいに、序列関係がありそうなものは「1」「2」「3」みたいにマッピングして、先の性別みたいに序列関係のないものは、各フラグ項目に分けてone-hot-encodingするのが、良いそうです。ざっと見た限り、今回怪しげなのは、monthです。まずは、monthの値を、value_counts()関数で、確認してみます。

train["month"].value_counts()

may 8317
jul 4136
aug 3718
jun 3204
nov 2342
apr 1755
feb 1586
jan 846
oct 439
sep 356
mar 299
dec 130
Name: month, dtype: int64

「may」や「jul」など、英単語の各月の略称が、入っているみたいです。時系列データを考えるなら、「jun」→「1」、「feb」→「2」のように、マッピングするのがよさそうな気がしますが・・・今回の銀行の顧客ターゲティングでいうと、特に1月よりも2月の方が序列が上とか、そういう関係は、直感的に、なさそうな気がします。今回は、精度の基準値を図るのが目的ですし、pythonの場合、マッピングよりone-hot-encodingの方がちょっぴり手間がかからないので、一旦月も一緒くたにone-hot-encodingしたいと、思います。

続いて、以下をご覧ください。先にご紹介したone-hot-encodingを、結婚状態(marital)に対して、やってみたイメージです。

結婚状態 未婚フラグ 既婚フラグ 離婚フラグ
未婚 1 0 0
既婚 0 1 0
離婚 0 0 1

実はこれ、下記のようにフラグ列を一個減らしても、情報量は同じです。

結婚状態 既婚フラグ 離婚フラグ
未婚 0 0
既婚 1 0
離婚 0 1

既婚フラグも離婚フラグも立っていなければ、未婚と判断できます。「機械学習のための特徴量エンジニアリング ―その原理とPythonによる実践 (オライリー・ジャパン)」によると、この手法は、「ダミーコーディング」というようです。人によっては、「one-hot-encoding」「ダミー変数」「ダミーコーディング」とごっちゃになっていることがあったりなかったりするようなしないような気がしますが・・・別物みたいです*6

情報量が同じなので結果はさして変わらないような気もしてきますが、実際のところ、one-hot-encoding/ダミーコーディングで精度が変わることが、ままあります。one-hot-encodingのやり方は有名なので、ここではダミーコーディングでいってみます。

最後に、カテゴリ量が膨大すぎて、one-hot-encodingすると膨大なフラグ列が生まれるケースがありえますが・・・先のvalue_counts()関数で確認したところ、今回に関してはそのような項目はなさそうなので、割愛します。

というわけで、いざ、ダミーコーディングです。

# ダミーコーディング実行
train_data = pd.get_dummies(data=train, columns=['job', 'marital', 'education', 'default', 'housing', 'loan', 'contact', 'poutcome', 'month'], drop_first=True)
train_data.columns

Index(['id', 'age', 'balance', 'day', 'duration', 'campaign', 'pdays',
'previous', 'y', 'job_blue-collar', 'job_entrepreneur', 'job_housemaid',
'job_management', 'job_retired', 'job_self-employed', 'job_services',
'job_student', 'job_technician', 'job_unemployed', 'job_unknown',
'marital_married', 'marital_single', 'education_secondary',
'education_tertiary', 'education_unknown', 'default_yes', 'housing_yes',
'loan_yes', 'contact_telephone', 'contact_unknown', 'poutcome_other',
'poutcome_success', 'poutcome_unknown', 'month_aug', 'month_dec',
'month_feb', 'month_jan', 'month_jul', 'month_jun', 'month_mar',
'month_may', 'month_nov', 'month_oct', 'month_sep'],
dtype='object')

pandasのget_dummies()関数を使えば、簡単にダミーコーディングできます。dataにpandasのデータフレームを、columnsにダミーコーディングしたい列の列名を、指定します。また、同じ関数で、「drop_first=True」の指定をなくせば、one-hot-encodingになります

参考までに、もし月をマッピングしてみたい場合は、以下のようなコードで、マッピングできます。当然ながら、一個一個マッピング変数を定義して変換しないといけないので、一気に出来るone-hot-encoding/ダミーコーディングに比べ、数が増えると面倒です。

# 月を数字に変換
month_mapping = {'jan': 1, 'feb': 2, 'mar': 3, 'apr': 4, 'may': 5, 'jun': 6, 'jul': 7, 'aug':8, 'sep': 9, 'oct': 10, 'nov': 11, 'dec': 12}
train['month'] = train['month'].map(month_mapping)

最低限必要な前処理は、以上になります。

モデルを選択する

続いて、モデルを選択します。一般的には、いくつかのモデルで実際に機械学習してみて、よさそうなものを選んでさらなるチューニングをしていくのが、セオリーみたいですが・・・ここでは、決め打ちでランダムフォレストでやってみます。ランダムフォレストには、以下の特徴が、あります。

  • 安定してそこそこの精度が出る。
  • チューニングするパラメータもそんなに多くなく、初心者に優しい。

これより簡単なモデル、例えば決定木やロジスティック回帰などですと、解釈可能性*7は高いですが、精度はそんなに出ません。一方、これよりも複雑なモデル、例えば勾配ブースティングやディープラーニングですと、ちゃんとチューニングすると精度は出ますが、初心者が適当に使うと、あまり精度が出たりでなかったり。

というわけで、初心者がとりあえず基準値を図るには、ランダムフォレストが最適かと、考えてみました。

機械学習を実行する

いよいよ機械学習です。ここでは、ホールドアウト法でやってみたいと、思います。ホールドアウト法とは、以下の図1のイメージのように、入力データを2分割し、一方を訓練用、他方を検証用にする手法です。

f:id:tatsu_mk2:20190429120939p:plain
図1 ホールドアウト法イメージ

機械学習では、未知のデータに対して、可能な限り正確な予測をしたいわけですが、未知のデータは文字通り未知、手にはいりません。そこで、手元のデータを2分割し、片方のみで学習。もう片方は学習せずにとっておくことにより、仮想の未知のデータとします。仮想の未知のデータで精度を図ることにより、本物の未知のデータに対して、どれくらい精度が出そうかを推測するのが、ホールドアウト法の基本コンセプトと、なります。

pythonでは、train_test_sprit()という関数を使えば、簡単にホールドアウト法を実現できるので、やってみたいと思います。まずは、入力データを、予測対象の項目である「y」と、予測に使用するデータx(yとid以外)に、分割します。

# 予測対象列の定義
target_col = 'y'


# 予測に使用しない列の定義
exclude_cols = [target_col, 'id']


# 予測に使用する列の定義
feature_cols = [col for col in train_data.columns if col not in exclude_cols]


# 予測対象列と予測に使用する列を分割
y = train_data[target_col]
x = train_data[feature_cols]
x.head()

「予測に使用する列の定義」のところ、Pythonになじみがないと(私もないですが)分かりにくいですが、「リスト内法表記」という、やつです。「train_data.columns」という変数に、train_dataが持っている列の列名が、リストで定義されています。その列定義のリストから、「exclude_cols」で定義した、予測に使用しない列に合致しない列のみを、取り出しています。

続いて、ホールド法を実行するために、xとyを2分割します。

# データ分割用の関数をインポート
from sklearn.model_selection import train_test_split

# 分割実行
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.1, random_state=1234)


「test_size」を指定することにより、どれくらいを学習に使用し、どれくらいを仮想の未知のデータとして使用するか、指定できます。所説あるみたいですが・・・事前に色々やってみたところ、今回の銀行の顧客ターゲティングに関しては、9割を学習に使用するのが、よさそうでした。random_stateは、乱数のシードです。設定しておくことにおり、再現性のある分割結果を得られるため、精度を図る際は、固定しておく方が、望ましいです。

では、学習を実行してみます。

# ランダムフォレストをインポート
from sklearn.ensemble import RandomForestClassifier

# 学習を実行
rcf = RandomForestClassifier(random_state=1234)
rcf.fit(x_train, y_train)

# 分類結果を取得
y_pred = rcf.predict(x_test)


# 確率を取得
y_pred_proba = rcf.predict_proba(x_test)[:, 1]

今回は、予測をしたい数値が離散値の、分類問題*8なので、ランダムフォレストのうち、「RandomForestClassifier」を使います。同じく、再現性を持たせるため、random_stateには何かしらの値を設定しておきますが、それ以外のチューニングパラメータは、今回は指定しません(まずは、素でやります)。

そして学習を実行し、予測結果を取得します。pythonの機械学習ライブラリであるscikit-learnを使用すれば、どのモデルを使用しても、関数は以下のように統一されています。

  • 学習を実行する場合は、fit()
  • 分類結果を得る場合は、predict()
  • 各分類項の確率(予測値が0である確率/1である確率)を得る場合は、predict_proba()

最後のところの[:, 1]の部分ですが、predict_proba()の実行結果(リスト)から、サブリスト(特定の行/列)を、切り出しています。まず行ですが、全行切り出すので「:」(特定の行だけ切り出すには、0:10とか指定します)、列は、0番目の列にFalseの確率、1番目の列にはTrueの確率が入っているので、今回は1番目の列のみを、取り出しています。

精度を測定する

それでは最後に、精度を測定してみたいと思います。前回整理した通り、コンペにおける指標値はAUCですが、ここでは参考までに、正解率・Recall・Presicionも、出してみたいと思います。

# 精度測定用関数のインポート
from sklearn.metrics import roc_auc_score
from sklearn.metrics import accuracy_score
from sklearn.metrics import recall_score
from sklearn.metrics import precision_score

# AUC測定
auc = roc_auc_score(y_test, y_pred_proba)
print('AUC: ', auc)


# 正解率測定
acy = accuracy_score(y_test, y_pred)
print('Accuracy: ', acy)


# Recall測定
rc = recall_score(y_test, y_pred)
print('Recall: ', rc)


# Presicion
pr = precision_score(y_test, y_pred)
print('Precision: ', pr)

AUC: 0.8896970529161214
Accuracy: 0.903059343899742
Recall: 0.34951456310679613
Precision: 0.6352941176470588

注意点として、AUCの測定には、predict_proba()の実行結果を使用する必要があります。正解率/Recall/Precisionは、基本的に、「一致する率」を見るので、predict_proba()を閾値で0/1に切り上げた、predict()の値を使用します。こちらでも整理した通り、AUCは、閾値を変化させつつ確率を0/1に切り上げ/切り下げし、真陽性率・偽陽性率を図るものです。なので、閾値で切り上げ/切り下げ済みのpredict()の値を使用すると・・・ちょっと変なことになります。最初は私、間違ってpredict()の値でAUCを測定し、あまりの低さに愕然としました

それはさておき、結果ですが・・・AUC0.889だと、SIGNATEのコンペ上は、大体1062/5034位くらいです(2019年4月29日現在)。上位2割くらいには、入っていますね。

一方、仮にこのモデルに沿って、ビジネスを行ったとすると・・・Recallは大体0.35くらい。顧客データは、全部で4万人くらいあったので、およそ1.4万人くらいの優良顧客を、発掘できる計算になります。一方、Precisionは、0.64くらい。モデルが「True」と予測した顧客に絞って営業した場合、成約率は65%とみることが、出来ます。何も考えずにテレマーケティングした場合、よほど魅力的でタイムリーな商品でもない限り、成約率は30%もあればいいところのような気がするので・・・悪くない数字だと、思います。

終わりに

というわけで、何もせずに機械学習をした場合の基準値は、大体AUC0.889くらいであることが、分かりました。次回は、ランダムフォレストのパラメータをチューニングして、精度を上げていってみたいと、思います。

最後まで読んでいただいて、ありがとうございました。「とりあえず機械学習をやってみたいけど、どうやればいいか分からない」と言う方の、何かしらの参考にでもなれば、幸いでございます。

参考資料一覧

機械学習のための特徴量エンジニアリング ―その原理とPythonによる実践 (オライリー・ジャパン)

機械学習のための特徴量エンジニアリング ―その原理とPythonによる実践 (オライリー・ジャパン)

  • 作者: Alice Zheng,Amanda Casari,株式会社ホクソエム
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2019/02/23
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログを見る
フリーライブラリで学ぶ機械学習入門

フリーライブラリで学ぶ機械学習入門

*1: 読み込んだデータの先頭5行を表示する、pythonの関数です。

*2: 読み込んだデータの平均や標準偏差といった、基礎統計を表示する。pythonの関数です。

*3: 今回の銀行の顧客ターゲティングの場合、その顧客が優良顧客(True)か否(False)か。もっと言えば、優良顧客である確率(%)。

*4: 専門用語で言えば、特長量選択でしょうか?

*5:info()関数の場合、文字項目はStringじゃなく、Objectと出るみたいです。

*6:one-hot-encoding/ダミーコーディング総称して、ダミー変数と呼んでいるのかも、しれません。後述しますが、関数がget_dummies()ですし。

*7: 「何故そのような予測結果になったのか」を、人が理解しやすいかどうか。

*8: 今回のケースは、True/Falseや0/1などの、2項分類問題にあたります。

謎指標?AUCの銀行顧客ターゲティングにおける意味とは

前回は、銀行の顧客ターゲティングにおいて機械学習を用いるにあたり、ビジネスのゴール・分析のゴールについて、自分なりに考えてみました。

今回は、実際のSIGNATEの評価指標である「AUC」について、それが高いとビジネス上どういう意味を持つのか、自分なりに考えてみたいと、思います。

そもそもAUCとは何なのか

AUCとは、「Area Under the Curve」の略、あるグラフ(曲線=Curve)の、曲線の下の部分の面積、という意味になります。

機械学習で、特に何も断りもせずに「AUC」とだけ言った場合、「ROC曲線の」AUC(ROC AUC)になるみたいです。イメージ的には、以下の図1における、グラフ(黒い太線)の下の、青い部分の面積のことになります。

f:id:tatsu_mk2:20190420140147p:plain
図1 AUCのイメージ

横軸が偽陽性率(確率なので、0~1)で、縦軸が真陽性率(同じく、0~1)。故に、AUCの最大値は1になります。

じゃあ、真陽性とか偽陽性とかって何なのかというと、こちらをご覧ください。

AIがTrueと予測 AIがFalseと予測
実際にTrueだった顧客 True Positive(TP) False Negative(FN)
実際にFalseだった顧客 False Positive(FP) True Negative(TN)


前回ご紹介させていただいた、二項分類問題における正解・不正解のマトリックスになります。「陽性」というのはつまり「True」のことで、「陰性」というのは「False」のことになります。

即ち、真陽性率とは、「実際に陽性(True)だったもののうち、AIが正しく陽性(True)と判定出来た割合」=TP/(TP+FN)、要するにRecallと同じです。

偽陽性率とは、「実際は陰性(False)だったのに、AIが誤って陽性(True)と判定してしまった割合」、つまり「FP/(FP + TN)」になります。

この、真陽性率を縦軸に、偽陽性率を横軸にグラフを描くとは、一体どういうことなのでしょう?

閾値と真陽性率・偽陽性率の変化

本、銀行の顧客ターゲティングのような二項分類問題は、Trueか/Falseかを予測する問題です。が、より正確には、まず確率を予測することになります。どういうことかといいますと、

顧客 優良顧客である確率(0~1) 優良顧客であるか否か(True/False)
顧客A 0.51 True
顧客B 0.41 False
顧客C 0.9 True
顧客D 0.1 False

まず顧客が優良顧客である確率を予測し、一定確率を超えていたら、優良顧客であると判断するような、アルゴリズムになります。この境界となる一定の値のことを、閾値といい、上記の表は0.5を閾値として、True/Falseに振り分けています。

この、閾値を変えてみると、どうなりますでしょうか?例えば、上記の表で、閾値を0.4に変えると、以下のようになります。

顧客 優良顧客である確率(0~1) 優良顧客であるか否か(閾値0.4)
顧客A 0.51 True
顧客B 0.41 True ←←← 注目!!
顧客C 0.9 True
顧客D 0.1 False


優良顧客が増えました!このように、閾値を変えればTrue/Falseの判定が変ります。Trueに判定が変わった顧客が、本当にTrueと限りませんので、当然、真陽性率・偽陽性率も、変わります。

真陽性率を縦軸に、偽陽性率を横軸にグラフを描くとは即ち、閾値を0~1の間で変化させつつ、そのときの真陽性率・偽陽性率をグラフにプロットすることに、なります。

AUCが1に近いことの意味

AIが完璧に予測できる場合

仮に、あるAIが、ある閾値において、完璧にTrueを予測できるとします。このAIのROC曲線を描くにあたり、まず、閾値を1に設定すると、Trueと予測されるものはゼロになりますので、真陽性率・偽陽性率ともに、ゼロになります。この点を、グラフにプロットしてみます。

f:id:tatsu_mk2:20190420150532p:plain
図2 閾値1の場合の真陽性率・偽陽性率(共に0)

ここから少しずつ閾値を下げていきます。例えば、閾値を0.9にすると、AIが「優良顧客である確率が90%」と判定したものが、True(陽性)になり、90%未満は、False(陰性)になります。このAIは、「ある閾値において、完璧にTrueを予測できる」としているので、その「ある閾値に到達するまで」は、AIがTrueと予測した顧客は、実際にTrueです。すなわち、閾値を下げていってしばらくは、真陽性率は上がり続けるものの、偽陽性率は上がらない状態が、続きます。このイメージを、プロットしてみます。

f:id:tatsu_mk2:20190420152147p:plain
図3 閾値を徐々に下げていった場合のAUC

ここで、「ある閾値」に到達して、実際にTrueである顧客を、AIがTrueと検出しつくしたとします。図3でいうところの、一番左上のプロット点ですね。ここに達してもなお閾値を下げると、検出されるTrueは増えますが、それは全て偽陽性になります。なので、ここにきてようやく、偽陽性率が上がり始めます。

f:id:tatsu_mk2:20190420153743p:plain
図4 なお閾値を下げ続ける

真陽性率は既に1に到達していますので、そこから偽陽性率が上がり続け、最終的に、真陽性率・偽陽性率とも、1に到達します。ということで、AIが完璧にTrueを予測できるなら、AUCは1になることが、分かりました。

AIが完璧に予測でない場合

完璧にTrueを予測できないAIの場合、閾値を徐々に下げていくと、真陽性率が1に到達する前に、本当ならば陰性のものを、間違えて陽性と判定してしまうことになります。仮に、真陽性率が1に到達する直前で、惜しくも判定を間違ってしまった場合、以下のようなグラフに、なります。

f:id:tatsu_mk2:20190420154759p:plain
図5 おしくも偽陽性が出てしまった場合のAUC

曲線下の面積(AUC)が、わずかに1より下がったことが、分かるかと思います。一方、閾値を下げ始めた早い段階で、偽陽性が出てしまうと・・・

f:id:tatsu_mk2:20190420155532p:plain
図6 早い段階で偽陽性が出た場合

先ほどより、AUCの面積が、小さくなることが、分かるかと思います。

AUCの意味を考える

というわけで、AUCが高いほど、真陽性と偽陽性を綺麗に分けられるということに、なるかと思います。もう少し言うと、閾値を1から徐々に下げていったときに、なるべく偽陽性を出さずに、真陽性を検出出来るということに、なるかと思います。つまり・・・1偽陽性当たりの真陽性の数が多いということになって、即ちPrecisionが高いということに、なるような気がしました。

単純にPrecisionだけを指標にすると、真陽性が1個、偽陽性が0個でも、Precisionは1(100%)に、なります。銀行の顧客ターゲティングに例えると、確かに無駄な営業は省けますが、その代わり優良顧客も、ほぼ検出出来ていません。一方、AUCが高いと、無駄な営業を省きつつ(Precisionが高い)、なるべくたくさんの優良顧客(真陽性)を検出できるということが、出来そうな気がしました。

即ち、F-scoreが、Recall(優良顧客をたくさん検出するが無駄打ちもあるかもしれない)と、Precision(なるべく無駄打ちをしないがあまり優良顧客を検出出来ないかもしれない)を、同じ比重でバランスを取った指標であるのに対して、AUCは、Precision寄りでバランスが取れる指標なのではないか、という気がしてきました。つまり、ビジネス的には、AUCを指標にすると、なるべく費用対効果の高い顧客ターゲティングが、出来るように思います。

それでも分かりづらいAUC

それでもAUCがなんか分かりづらい気がするのは・・・確率ではないからのような、気がします。AUCが1なら、真陽性と偽陽性を、100%分離できることは、分かりました。しかし、AUCが0.9だと、90%分離できるというわけでは、ありません。ビジネス的に目標を立てるには、やっぱり確率じゃないと分かりづらい気がします。

というわけで、AIを調整する際には、AUCを指標にして調整したとしても、最終的にユーザーにお話しする際には、いくつかの具体的な閾値を元に、いくつかのPrecision/Recallのバリエーションを提示して、ビジネス目標に合致する閾値/Recall/Precisionを決める方が、分かりやすい気がしました。

おまけ:もう一つのAUC

ここまで、AUC=ROC AUCということで、自分なりの考えをまとめてきましたが・・・機械学習におけるAUCにはもう一つ、PR AUCというものが、あるかと思います。横軸に真陽性=Recall、縦軸にPrecisionをプロットするので、Precision-Recall曲線というわけみたいです。なんですが・・・Pythonのscikit-learnだと、標準でPR-AUCを計算できる関数が、ない?ROC-AUCは、「sklearn.metrics.roc_auc_score()」という関数で、簡単に計算できますが、「pr_auc_score()」という関数は、ないみたいです。

体感的に、PR-AUCの方が、上げるのが難しく、指標として信頼できる気がするのですが・・・一旦、考察はまたの機会にしたいと、思います。

終わりに

というわけで、実際のSIGNATEの評価指標である「AUC」についても、なんとなく理解できました。次回こそはいよいよ、機械学習していって、予測AIを作ってみたいと、思います。最後まで読んでいただいて、ありがとうございました。

「AUCって何が嬉しいのか良くわかんねぇ」という方の、何かしらの参考にでもなりましたら、幸いでございます。混乱になりましたら、すみません。

我試考・銀行の顧客ターゲティング、その目的とは?

前回までで、ようやく機械学習を行う環境が整いました。今回から、ようやく銀行の顧客ターゲティングに入っていきたいと、思います。

まず初めに、そもそも何のために機械学習して、予測AIを作るのか?について、ビジネス的な意味と、機械学習を使ったデータ分析のゴールを、自分なりに考えてみたいと、思います。

ある意味、ようやく前置きが終わったと思ったらまた前置きですが・・・よろしくお願いいたします。

はじめに

私が読んだ、ある機械学習の本に、ありました*1

ビジネスのゴールと、分析のゴールには、大きな隔たりがある

と。どういうことかと申しますと、

  • ビジネスのゴールとは、経済的なインパクト。
    • 売り上げが増加する、コストが削減される、リスクが低減される*2など。
  • 分析のゴールとは、データを分析した結果。
    • 不動産スペックから不動産価格を予測する、顧客属性から優良顧客と通常顧客に分類する、など。
  • よって、分析結果が、どのように経済インパクトに繋がるのか、連動ロジックを考えておくことが、重要。
  • それこそが、分析の課題設定

では、この銀行の顧客ターゲティングの、ゴールはと言いますと・・・元のUCIのサイトには、こうあります。

  • The data is related with direct marketing campaigns (phone calls) of a Portuguese banking institution. The classification goal is to predict if the client will subscribe a term deposit.

日本語に訳すと、こんな感じでしょうか。

  • これは、ポルトガルの銀行の、ダイレクトマーケティング(電話営業)キャンペーンに関する、データです。
  • 分類のゴールは、顧客が、定期預金口座を開設するかどうかを、予測することです。

日本語のサイトを見ると、「(単なる)口座を開設するかどうか」と書かれていることがありますが、「term deposit」なので、多分「定期預金口座」が正しいと、思います。

「口座開設」だと、口座も持っていない見込み顧客に、いきなり電話をかけることになってしまい、ちょっと変ですよね。まだ顧客じゃない人は、通常は顧客データベースに、登録されていないはずです。口座を開設してくれた既存顧客が、優良顧客(定期預金口座を、開設してくれる可能性がある)か、通常顧客かを分類する方が、しっくりきます。

ということで、分析のゴールは、既存顧客を優良顧客(定期預金口座を、開設してくれる可能性がある)と、通常顧客に、分類することと、考えます。

では、ビジネス上の目的は、何なのでしょう?実務ではない仮想問題では、そこは推測するしかありません。が、古今東西、ビジネス上の目的と言うと、大体、利益・売り上げの増加か、コスト削減と、相場は決まっています。繰り返しになりますが。そこで、その二つの立場に立ってみますと・・・

立場 目的 キャンペーンの目的
A 利益・売り上げの向上 一人でも多くの優良顧客を、発掘したい。
B コスト削減 なるべく無駄打ちを避けたい。可能な限り、100発100中の電話営業を、したい。

こうなるかと、思います。精度100%の予測AIが作れれば、上記は両立できるかもしれませんが、現状の機械学習技術だと、そうはいかないかと思います。

精度を指標にする場合の問題点

それでも、「可能な限り精度を高くすれば、一人でも多くの優良顧客を、可能な限り少ない無駄打ちで、発掘できるはずだ」と、一見思ってしまいませんか?

必ずしも間違いではないのですが、以下を、ご覧ください。

from google.colab import drive
drive.mount('/content/gdrive/')
%cd ./gdrive/My\ Drive/colab/bank
import pandas as pd
train = pd.read_csv("./dataset/train.csv")
train["y"].value_counts()


0 23954
1 3174
Name: y, dtype: int64


3174 / (23954 + 3174) * 100
11.70008846947803

前回構築したGoogle Colabの環境で、打ってみたコマンドです。このあたりでも触れましたが、優良顧客は全体の1割程度です。たまたまこのサンプルが偏っているのか、全体も同じような偏りをしているのかは、判断が分かれるところです。が、私は後者ではないかと、予測します。1銀行で3万人近くの顧客と言えば、それなりの数のサンプリングだと思いますし、電話営業の成約率ならまぁ、こんなものかなという、感覚があるからです。

つまり、全て非優良顧客と予測すれば、精度は90%近くになってしまいます。確かに、無駄な営業は一切なくなりますが、その代わり優良顧客は一人も発掘されません。「電話営業は非効率なんでそんなキャンペーンは止めましょう」なんていうのも、提案の一つではありますが、それを言うと話が終わってしまいます。

単純に精度を見るだけでは駄目だとするならば、一体何を見れば、良い予測AIが作れるのでしょうか。

RecallとPrecision

突然ですが、本問題は、「二項分類」になります。現状、AIが予測できる回帰*3・分類*4のうちの分類問題の一つ、True(この場合、優良顧客)/False(この場合、通常顧客)を予測する、問題です。二項分類問題の場合、「精度」は正解か不正解の簡単な二択に見えて、実はそうでもないのです。以下をご覧ください。

AIがTrueと予測 AIがFalseと予測
実際にTrueだった顧客 True Positive(TP) False Negative(FN)
実際にFalseだった顧客 False Positive(FP) True Negative(TN)

正解・不正解にも、二つずつあることが、分かります。

  • 正解
    • AIがTrueと予測して、実際にもTrueなもの(TP)
    • AIがFalseと予測して、実際にもFalseなもの(TN)
  • 不正解
    • AIがTrueと予測したけど、実際にはFalseなもの(FP)
    • AIがFalseと予測したけど、実際にはTrueなもの(FN)

ここで、以下のビジネスの目的に、立ち返ってみたいと思います。

立場 目的 キャンペーンの目的
A 利益・売り上げの向上 一人でも多くの優良顧客を、発掘したい。
B コスト削減 なるべく無駄打ちを避けたい。可能な限り、100発100中の電話営業を、したい。

立場Bに立ってみた場合、AIが「優良顧客」と予測したのに、実際は「通常顧客」だと、困ります。無駄打ち営業になってしまうからです。なので、Bの立場だと、なるべくFP(False Positive)を減らしつつ、精度を高めていけば、良いAIが作れるのではないかと、考えられます。

立場Aに立ってみた場合、本当は「優良顧客」なのに、AIが「通常顧客」と予測してしまうと、困ります。一人でも多くの優良顧客を発掘したいのに、取りこぼしてしまう可能性が、あるからです。なので、Aの立場だと、なるべくFN(False Negative)を減らしつつ、精度を高めていけば、良いAIが作れるのではないかと、考えられます。

結論としては、前者の場合、TP/(TP+FP)を見ればよいことに、なります。この値が1に近ければ近いほど、AIが優良顧客と予測した顧客は、本当に優良顧客である確率が高いと、言えます。この指標のことを、Precision/適合率と言います。

また、後者の場合は、TP/(TP+FN)を見ればよいことに、なります。この値が1に近ければ近いほど、本当の優良顧客を、AIがちゃんと優良顧客と予測してくれる確率が高いと、言えます。この指標のことを、Recall/検出率と言います。

トレードオフとF-score

ちょっと難しい話ではありますが・・・RecallとPrecisionは、トレードオフの関係に、あります。すなわち、Recallを上げればPrecisionは下がり、Precisionを上げれば、Recallが下がります。

このケースで想像してみますに・・・とにかく電話をかけまくれば、一人でも優良顧客を発掘できる確率は、高まります。つまり、Recallはあがります。でも、外れを引く確率も高まるので、Precisionは下がりそうです。

逆に、確度の高そうな人に絞って電話をかければ、電話一本当たりの勝率は高まりそうです。つまり、Precisionは上がります。ただ、「低確率ではあるものの、もしかしたら定期預金口座開設してくれるかもしれない」人は取りこぼすので、Recallは下がります。

こんな感じでしょうか。よって、極端にRecallを重視すれば、成果は上がる代わりに無駄打ちは多くなりますし、極端にPrecisionを重視すれば、無駄な営業コストは削減出来る代わりに、成果も少ないキャンペーンに、なりそうです。

そうなってくると、そんな極端な指標ではなく、もっとバランスの取れた指標はないのかと思うのが、人情ですよね。そんな人情派のあなたにぴったりの指標が、F-scoreです。計算式上は以下で表され、まさしく、RecallとPrecisionのバランスを取った指標になります。

F-score = 2×Recall×Precision/(Recall + Presision)

まとめと次回予告

というわけで、ビジネスの目的から分析のゴールを考えると、良い予測AIを作るためには、以下のようになるかと、考えました。

ビジネスの目的 分析のゴール
金に糸目はつけず、とにかく一人でも多く優良顧客を発掘 Recallの高い予測AIを、作る
あまりお金をかけず、効率的に優良顧客を発掘したい Precisionの高い予測AIを、作る
ほどほどにお金をかけ、ほどほどに優良顧客を発掘する、バランスの取れたキャンペーンを打ちたい F-scoreの高い予測AIを、作る

で、実際に、SIGNATEのコンペで、何の指標を元にランキングされているかというと・・・「ROC AUC」という指標です。

個人的になんですが、Recall・Precision・F-scoreまでは、ビジネス上の目的とも結びつけやすく、理解しやすい気がします。一方、AUCが高いと、ビジネス的にどういう意味があるのか?って、理解が難しい。そう思ったこと、ありませんか?

ちょっと長くなってきたので、今回はここらへんまでにして、次回、その意味を自分なりに考えてみたいと、思います。最後まで読んでいただいて、ありがとうございました。

参考資料

Watson Studioで始める機械学習・深層学習ーーノンプログラミングでやさしく体験

Watson Studioで始める機械学習・深層学習ーーノンプログラミングでやさしく体験

フリーライブラリで学ぶ機械学習入門

フリーライブラリで学ぶ機械学習入門

*1:Amazonアフィリエイト設定したら、リンク貼ろうと思います。

*2:リスク対策コストが減ると考えれば、これも広義にはコスト削減ですね。

*3:予測結果が、連続値。売り上げなど。

*4:予測結果が、離散値。True/Flaseの二項分類や、上/中/下の多項分類など。

やってみよう!Google Colabで機械学習の準備

前回は、機械学習を学習するための*1環境として、Google Colabをセットアップしてみました。

今回は、そこで実際に機械学習を実行するための、作業環境を作っていってみたいと、思います。

はじめに

機械学習をするためには、基本的に、CSVファイルを読み込んで、入力データをモデルに読み込ませる必要が、あります。そして、SIGNATEなどのコンペサイトに投稿するためには、学習結果をCSVファイルに出力する必要が、あります。ローカルのJupyter Notebookでやる分には何の問題もないですが、Google Colabでやる分には、ファイルをGoogle ドライブにアップロードしなければならず、また読み込みにも、一仕掛けいります。

今回は、そんなGoogle ドライブを通したPythonのファイル入出力と、ついでに今後必要になってくるであろう以下のやり方について、実際の機械学習に入る前に、整理してみたいと思います。

  • GPUの使い方
  • 追加パッケージのインストール
  • キーボードショートカット
    • とりあえず、Jupyterでよく使っていた、セルの追加・削除、セルの種類の変換あたり。
    • ついで、コード補完のやり方

作業環境の作成

作業ディレクトリの作成

まずは、マイドライブの直下にファイルを置くのもあれなので、作業ディレクトリを作っていきたいと思います。Google ドライブへのアクセスについては、前回の投稿をご参照ください。

なんと、Google ドライブでは、Webアプリであるにも関わらず、右クリックが使えます*2。マイドライブのフォルダ一覧の適当なところで右クリックして、「新しいフォルダ」を選択します*3

f:id:tatsu_mk2:20190407183121p:plain
図1 新しいフォルダの追加

以下のような画面が出てくるので、「colab」と入力し、Google Colab用のルートフォルダにしたいと思います。

f:id:tatsu_mk2:20190407183856p:plain
図2 ルートフォルダの作成

すると、以下のようにフォルダが出来上がるので、出来上がったフォルダをダブルクリックします。Webでダブルクリックとは、斬新・・・

f:id:tatsu_mk2:20190407184240p:plain
図3 作成したフォルダをダブルクリック

colabフォルダを開いたら、同様の手順で、銀行の顧客ターゲティングをする用の「bank」フォルダを、作ります。

f:id:tatsu_mk2:20190407184924p:plain
図4 bankフォルダの追加

最後に、同様の手順で、bankフォルダの下に、CSVファイルを置くための「dataset」フォルダを置きます。また、好み次第ではありますが、図中の赤四角の場所をクリックすれば、以下のような詳細表示に、変わります。

f:id:tatsu_mk2:20190407185511p:plain
図5 datasetフォルダの追加

データファイルの準備

データは、以下の場所から、「学習用データ (train.csv)」「検証用データ (test.csv)」「応募用サンプル (submit_sample.csv)」の三つを、ダウンロードします。

【練習問題】銀行の顧客ターゲティング

ダウンロードするためには、SIGNATEにアカウントを作って、コンペに参加するための参加規約に同意する必要がありますが、ここでは手順は割愛します。一点、独自のアカウントを作らずとも、TwitterやFacebook、Googleアカウントなどでもログインできますが、ランキングサイト等に投稿者名が載ってしまうため、本名でこれらのアカウントを作っているものの、ここでは本名を出したくない人などは、注意が必要です。

データファイルのアップロード

まずは、図5で作った「dataset」フォルダに、移動します。フォルダ名をダブルクリックすれば、移動可能です。

f:id:tatsu_mk2:20190408200037p:plain
図6 datasetフォルダに移動

「ここにファイルをドロップ」とか書いてある適当なあたりで右クリックし、「ファイルをアップロード」を選びます。

f:id:tatsu_mk2:20190408200416p:plain
図7 ファイルアップロードを選択

SIGNATEからダウンロードされた3ファイルを、選択します。

f:id:tatsu_mk2:20190408200753p:plain
図8 ファイル選択

アップロードされました。

f:id:tatsu_mk2:20190408200959p:plain
図9 アップロード完了

早くも容量が0.1GB増えることに・・・
容量対策についてはまた考えよう。

ノートブックの作成

それでは早速、ノートブックを作っていきたいと思います。まずは、赤枠の部分をクリックし、作業ディレクトリに戻ります。ここはクリックなんですね・・・まぁ、Windowsのエクスプローラでも、そうですけど。

f:id:tatsu_mk2:20190408201548p:plain
図10 作業ディレクトリに戻る

戻った先の「dataset」フォルダの下あたりで右クリックし、その他⇒Colaboratoryで新規に追加します。

f:id:tatsu_mk2:20190408201920p:plain
図11 新規Colabolatory追加

開いたら、ファイル⇒名前の変更から、とりあえず「Test」とでも名前を変えておきたいと思います。

f:id:tatsu_mk2:20190408202318p:plain
図12 名前変更

名前欄にカーソルが当たって編集可能状態になり、ここで直接入力して、エーターキーを押すと、名前変更が確定するようです。

f:id:tatsu_mk2:20190408202531p:plain
図13 名前変更後

これでようやく、準備が整いました。

検証してみる

基本的な使い方

基本的には、通常のJupyter Notebook同様、「セル」と呼ばれる箱にPythonコードを入力して、Shift+Enterを押すことにより、プログラムを実行出来ます。ただ、通常のJupyter Notebookと違って、「編集モード」「選択モード」はないみたいで、これのおかげかショートカットキーの設定がちょっと違うみたいです。これは後でまとめたいと思います。

f:id:tatsu_mk2:20190410221905p:plain
図14 基本的な使い方

ファイルを読み込んでみる

それでは、早速やっていってみたいと、思います。Google Colabでは、pandasでpd.read_csv()としてCSVを読み込む前にまず、以下のように、Google ドライブをマウントする必要が、あるみたいです。

from google.colab import drive
drive.mount('/content/gdrive/')

f:id:tatsu_mk2:20190408220004p:plain
図15 gdriveのマウント

マウントを実行すると、以下のように、「/content」というディレクトリがカレントディレクトリになっているみたいです。

!pwd
!ls
%cd ./gdrive
!pwd
!ls

f:id:tatsu_mk2:20190408221600p:plain
図16 ディレクトリの確認

なので、図4で作った「bank」フォルダに、移動してみたいと思います。

%cd ./My\ Drive/colab/bank
!pwd
!ls

f:id:tatsu_mk2:20190408222429p:plain
図17 作業ディレクトリに移動

移動できたみたいなので、直下のdatasetディレクトリから、train.csvを読み込んで、head()してみたいと思います。

import pandas as pd
train = pd.read_csv("./dataset/train.csv")
train.head()

f:id:tatsu_mk2:20190408223017p:plain
図18 CSV読み込み

出来ました!!!

ファイルを書き出してみる

ここまでいけば特に問題ないかと思いますが、一応、to_csvでCSV出力してみたいと思います。

train.to_csv("./test_out.csv")

f:id:tatsu_mk2:20190408223408p:plain
図19 CSV書き出し

Google ドライブの方を見てみると、問題なく出力できていました*4

f:id:tatsu_mk2:20190408223711p:plain
図20 CSV出力確認

GPUの使い方

Google Colabの目玉と言えば無料でGPUが使えることですが、具体的な使い方としてはまず、ランタイム⇒ランタイムタイプの変更を、選びます。

f:id:tatsu_mk2:20190410222647p:plain
図21 GPUの利用その1

その後、ハードウェアアクセラレータから、GPUを選びます。

f:id:tatsu_mk2:20190410222958p:plain
図22 GPUの利用その2

・・・TPU?

GPUだけじゃなく、TPUも使えるみたいです。Googleが開発した、Tensor Processing Unitの略のあれですね。ぱっとぐぐった感じ、その名の通り、TensorFlow使って畳み込みニューラルネットワーク(CNN)やるときは、早くなるみたいです。

追加パッケージのインストール

上の方でも書きましたが、Google Colabの場合、!に続けてUnixコマンドを打つことができます。なので、以下のように、!に続けてpipコマンドを打つことで、任意のパッケージを、追加インストールすることが出来ます。以下は試しに、LightGBMを追加インストールしてみたところです。

!pip install lightgbm
import lightgbm as lgb
model = lgb.LGBMClassifier(random_state=1234)

f:id:tatsu_mk2:20190410224326p:plain
図23 パッケージの追加インストール

なんか、ローカルでインストールするよりは早い感はありますが、問題は、毎回コレをやらなければならない点です。インストール済みの環境を取っておくことは、出来ないようなので、ちょっとめんどくさいかも、しれません。

キーボードショートカット

上の方でも書きましたが、Google Colabではセルの選択モードが無い代わりに、Ctrl+Mを押すことにより、セル操作のキーボードショートカットが出来ます。例えば、上にセルを挿入するには以下のように、Ctrl+M Aを押します。

f:id:tatsu_mk2:20190411220949p:plain
図24 セルの挿入

同様に、Ctrl+M Bで下にセルが挿入され、Ctrl+M Dでセルを削除することが出来ます。また、「ツール⇒コマンド パレット」からキーボードショートカットを確認でき、例えばプログラムを入力するためのコードセルから、メモを入力するためのテキストセルに変換するには、Ctrl+M Mを押せば良いことが、分かります。ちなみに、テキストセルをコードセルに変換するには、Ctrl+M Yを押します。

f:id:tatsu_mk2:20190411222211p:plain
図25 セルの形式を変換

コード補完のやり方

最後に、コード補完についてです。通常のJupyter Notebookだと、nbextentionsを入れることによりコード補完が有効になりますが、Google Colabど最初から有効なようです。TabキーまたはCtrl+スペースを押すことにより、補完が表示されます。ただ、ネットワークを介しているためか、ローカルのJupyter Notebookと比べると、Tabキーを押して候補ウィンドウが出るまで、少しもっさりしています。

f:id:tatsu_mk2:20190411223301p:plain
図26 コード補完例

おわりに

いかがだったでしょうか。今回やってみて分かりましたが、一見デメリットが無いように思えたGoogl Colab、以下などは使うにあたり、注意が必要かなと思いました。

  • ネットワークを介しているためか、ちょっとしたコマンドを実行して帰ってくるまでが、ローカルよりちょっと遅い。
  • 環境を取っておけない。LightGBMなど、デフォルトでインストールされていないパッケージは、毎回インストールする必要がある。
  • ファイルI/Oは基本的にGoogle ドライブ経由。毎度マウントして、認証コードを貼らないといけない。
  • 同じく、Google ドライブの容量を消費するため、データセットの容量管理には注意が必要。

というわけで、ようやく環境の整理も出来たので、次回からようやく、銀行の顧客ターゲティングについて考えていってみたいと、思います。最後まで読んでいただいて、ありがとうございました。

*1:ややこしい・・・

*2:スプレッドシートなどに比べれば、驚くべきことではないかもしれませんが・・・

*3:iPadだと、長押しかマルチタップで出てくるのかな・・・新規ボタン押せば、確実に出てきますが。

*4:とりあえず出力できましたし、2MBもったいないので、このファイルはすぐに消しときます。

構築しよう!機械学習に最適な環境を

前回は、機械学習について学んだ知識を試してみるにあたって、データをどうやって入手し、学んだ成果をどうやって図るのかについて、考えてみました。

今回は、入手したデータを実際に処理するための、開発環境について、自分なりに学んだことを、アップしていきたいと思います。

結論から言うと、Python+Google Colaboratory(Google Colab)を使ってみたいと、思います。

得意の言語?いやいや、そこはあの言語で

あなたには、得意なプログラミング言語が、ありますか?Javaでしょうか。.NET(C#)でしょうか。「TIOBE Index」*1によると、この何年かずーっと1位な言語は、Javaです。もしかしたらあなたは、機械学習を始めるにあたって、こんな風に考えたことは、ないでしょうか?

プログラミング言語なんて所詮どれも同じ、とりあえず得意な言語で、仕組みから理解しよう

と。とても真面目なアプローチですが、これは大いに危険な可能性があります。あなたが学生時代から数学を学んでおり、高度な数式をプログラミング言語のアルゴリズムに落とし込めるほど数学・プログラミングに長けているならば、これは良いアプローチかもしれません。しかし、そうでないならば、難しすぎて挫折する可能性が、あります。まぁ、

全部私のことなんですが

例えて言えば、車を運転するにあたって、まずは車の仕組みから理解して、車の組み立てからやってみようとしているようなもの。初心者がいきなりやるには、だいぶハードルが高すぎます。一般人は、大体の車の概要を理解して、後は実際に運転できれば十分でしょう。同様に、機械学習も、大まかに仕組みを理解して、後はやってみる方が、挫折せずに身につけれるのではないかと、個人的な結論に至りました。

ここで、組み立て済みの車にあたるのが、ライブラリになります。一般人は、組み立て済みの車を運転できれば、自分で組み立てれる必要がないように、機械学習も、まずはライブラリを使いこなせれば、初級者としては、それで十分なのではないでしょうか。つまり、自分の得意な言語ではなく、ライブラリが充実している言語を選ぶことが、機械学習を身に着けるための第一歩だと、思いました。

機械学習のライブラリが充実している言語というと・・・そう、Pythonですね。月並みですが、やはりそういう結論に至りました。

一時期は、Javaで自力で機械学習のアルゴリズムを組むのに挫折して、Watson StudioやNeural Network Consoleのような、ノンプログラミング系のものにしようかと思いましたが・・・これはこれで、簡単にそれなりの精度は出るものの、その後どうすればいいのか、路頭に迷ってしまいました。

ライブラリを使ってプログラミングするのが、ほどほどに簡単で、工夫も出来てスキルが向上している感も持て、バランスが取れているのかな、なんて思いました。

IDEは一択。に見えて・・・

Pythonで機械学習をするならば、やっぱりAnnacondaとJupyter Notebookです。Java屋さんに分かるように表現すると(?)、Annacondaはmavenがもっと便利になったもの(つまり、ライブラリ管理ツール)で、Jupyter Notebookは、EclipseがWebになったもの「のようなもの」(つまり、IDE)と言えば、当たらずとも遠からずな感じでしょうか・・・

基本的には、Annacondaをダウンロードしてインストールして、Annaconda経由で、機械学習に必要なライブラリやJupyter Notebookをインストールすれば、学習環境は出来ます。書籍やネットにも手順はたくさん書いてあるので、特に問題はありません。ありませんが・・・

機械学習には、それなりのマシンパワーが、必要になります。昨今、「ネットが見れればまぁ十分」と、ご自宅のPCには、そこまでハイスペックのものを用意していない人も、多いのではないでしょうか。あるいは、会社PCだと、会社特有のプロキシ設定にひっかかって、やっぱり環境の構築に色々と面倒だったりも、するかもしれません。

そこで、本ブログで試してみたいのが、Google Colaboratory略して、Google Colab。クラウド版のJupyter Notebookになります。クラウド版のJupyter Notebookというと、AWSやAzure、Watson Studioなど、各社主要クラウドベンダーも出していますが・・・無料で、しかもGPUまで使えるというのは、今のところ、Google Colabだけではないでしょうか。90分ルール*2や12時間ルール*3など、注意すべき制限はいくつかあるみたいですが、それを差し引いても魅力的なツールです。なんだったら、

iPad Proで機械学習を行う

なんてシャレオツなことも、出来てしまいます。ということで早速、セットアップしてみました。

Google Colabをセットアップしよう!

Googleアカウントの作成

まずは、Googleアカウントを作成する必要があります。以下のURLから、Googleアカウントを作成しましょう。・・・とはいえ、今のご時世、大半の人がgmail使ってると思いますし、既に持っている人が多いのではと、思いますが。
accounts.google.com

Google ドライブへアクセス

基本的に、Google Colabは、Google ドライブから使うみたいです。以下のURLからGoogle ドライブにアクセスし、「Google ドライブへアクセス」というボタンを押しましょう。
www.google.com

f:id:tatsu_mk2:20190407110442p:plain
Google Driveへアクセス

Google Colabを追加

Google ドライブにアクセスしたら、新規ボタンをクリックします。

f:id:tatsu_mk2:20190407120021p:plain
図2 新規ボタンをクリック

すると、以下のようなポップアップメニューが表示されるので、その他⇒アプリを追加を、クリックします。

f:id:tatsu_mk2:20190407122101p:plain
図3 アプリを追加

続いて、以下のような画面がポップアップされるので、Colabを検索し、「+ 接続」ボタンをクリックします。

f:id:tatsu_mk2:20190407121838p:plain
図4 ドライブにアプリを追加

追加が完了したら、以下の画面が表示されるので、OKボタン及び×ボタンを押して、画面を閉じます。

f:id:tatsu_mk2:20190407121459p:plain
図5 追加完了

これで、Google Colabを使う準備が、出来ました。

ノートブックの追加

試しに、ノートブックを追加してみたいと、思います。図2~図3の手順で、新規⇒その他を選択すると、今度はその中に「Colabolatory」というものがあると思うので、それをクリックします。

f:id:tatsu_mk2:20190407122539p:plain
図6 ノートブックの追加

すると、ノートブックが開きます。

f:id:tatsu_mk2:20190407122807p:plain
図7 追加されたノートブック

Jupyter Notebookっぽくはありますが、若干アレンジされていることが分かるかと思います。試しになんか実行してみると・・・

f:id:tatsu_mk2:20190407123224p:plain
図8 試しにPythonコードを実行

実行できました。とてもセットアップが簡単だと、思いませんか?

ノートブックが追加された場所の確認

既にご想像されているかもしれませんが、Google ドライブの「マイドライブ」上で新規追加したため・・・

f:id:tatsu_mk2:20190407123940p:plain
図9 ノートブックが新規追加された場所

マイドライブ直下に、新しいノートブックが、追加されています。追加直後なのでUntitledとなっていますが、通常のJupyterと同じように、名前を変更することが出来ます。標準でメニューが日本語になっているのは、嬉しいですね!

f:id:tatsu_mk2:20190407130300p:plain
図10 追加したノートブックの名前変更


・・・というわけで、Google Colabは基本、Google ドライブをファイルシステムとして、使用します。なので、無料ではありますが・・・Google ドライブの容量には、要注意です。

次回予告:Google ColabのちょっとしたTIPS

ちょっと長くなってきたので、今回はここらへんで一旦、終了にしようと思います。前述したとおり、Google Colabは、ローカルのディレクトリではなく、Google ドライブを使用することを前提としています。ですので、ファイルの読み書きで、通常のJupyterとはちょっとした違いが、あります。次回は、実際の機械学習に入る前に、一旦以下当たりの「Google Colabの癖」について、整理してみたいと思います。

  • 追加のライブラリの導入方法
  • ファイルの読み書き
  • コード補完のやり方*4
  • GPUの使い方
  • キーボードショートカット
    • とりあえず、Jupyterでよく使っていた、セルの追加・削除、セルの種類の変換あたり。

最後まで読んでいただいて、ありがとうございました。

*1:TIOBE Software社が公開する、複数の検索エンジンの検索結果から、各言語がどれだけ話題になっているのかを評価したランキング。

*2: 放置しておくと、90分で強制シャットダウンします。

*3: 実行中でも、12時間立てば、強制シャットダウンします。

*4: 通常のJupyterの場合、nbextensionsという拡張機能を、入れます。

分からない?機械学習はどう試せばいいのか

あなたは、こんなことを考えたことは、ありませんか?機械学習の本を見て、なんとなく分かったので試しにやってみたいが、一体どうやって試せばいいのだろう?と。どうやって、スキルを伸ばしていけば、いいのだろうと。

Webアプリの場合、なんか思いついたものを適当に作ることもできますが、機械学習の場合は、そうもいきませんよね。適当なデータがない限り、試すことができません。テキトウにデータを作る訳にもいきませんし、仮にやってみたとして、作ってみたモデルがすごいのかすごくないのかも、一人だとよくわかりません。

今回のエントリーでは、初心者がそんな学びたての機械学習を試す方法について、情報を収集して考えてみました。

データを収集するには

機械学習の本を買うと、だいたい出てくる例題が、アヤメの品種の分類とか、手書き文字の画像の分類とかだと、思います。あれの元ネタがどこにあるかといいますと・・・

ここです。:カリフォルニア大学アーバイン校

351個のデータセットがあるそうで、金融っぽいものや医療データっぽいものも、あります。とりあえずやってみる分には良いですが、問題点として、

  • 英語なので、入力データの意味がいまいちよくわからないことも、ある
  • なんか予測するモデルを作ってみたとして、そのデキがよいのか悪いのか、自分がどれくらいの実力なのか、いまいちよくわからない

という点があります。現代のエンジニアたるもの、英語くらい出来るべきだというのは、それはそうでしょうが・・・だからといって、一朝一夕で英語が出来るようになるわけでは、ありません。日本語のサイトがあれば、それに越したことはないと、思います。

そこで、活用してみたいのが・・・

コンペサイトの練習問題に挑戦しよう!

これです。AI/機械学習のコンペサイトとして、世界的に有名なのはKaggleというサイトですが、それの日本版とでも言うべきサイトが、あります。それが、こちら

signate.jp

元々、DeepAnaliticsという名前だったのが、2018年4月に、SIGNATEという名前に変わったみたいです。安心と信頼の(?)日本語サイト、入力データの説明も日本語でされており、コンペに投稿すれば、自分が大体どれくらいの実力なのかも、分かります。しかも、練習問題は、期間無制限で挑戦できるという、初心者には優しい(?)親切設計つき。初心者がまず力試しをしてみるには、うってつけのように思います。

そこで、実際にピックアップしてみた、練習問題が・・・

銀行の顧客ターゲティングをしてみよう!

これです。以下のような顧客データを元に、その顧客が、定期預金口座を開設するか否かを、機械学習により予測してみよう、という問題に、なります。

項目名 意味
id 通し番号
age 年齢
job 職種
marital 未婚/既婚
education 教育水準
default 債務不履行があるか
balance 年間平均残高(€)
housing 住宅ローン(yes, no)
loan 個人ローン(yes, no)
contact 連絡方法
day 最終接触日
month 最終接触月
duration 最終接触時間(秒)
compaign 現キャンペーンにおける接触回数
pdays 経過日数:前キャンペーン接触後の日数
previous 接触実績:現キャンペーン以前までに顧客に接触した回数
poutcome 前回のキャンペーンの成果
y 定額預金申し込み有無(1:有り, 0:無し)

実はこのデータ、先の「カリフォルニア大学アーバイン校」のサイトにもあるのですが、少しデータが簡易化されています。具体的には、「欧州銀行間取引金利」とか、「消費者物価指数」などの、いくつかの項目(指標)が、省略されています。難しそうな項目が省略されて、初心者がまず力試ししてみるに、分かりやすそうな項目構成に、なっています。

なっているのですが・・・

このデータセットのいいところ

このデータセット、先のアヤメや手書き文字と違って、なかなかに趣のあるデータセットになっています。まず、アヤメとかと違って、そうそう簡単に精度が出ません。というのも、最後のこの項目、

項目名 意味
y 定額預金申し込み有無(1:有り, 0:無し)

0:無しがほぼ9割を占めるという、偏りがあるというか現実そんなもんなんだろうという、にくらしい構成になっています。よって、全部Noと答えてしまえば、見かけ上精度90%のモデルになるのですが、それで「良いモデル」かというと、当然そうではありません。肝心かなめの、定額預金を申し込んでくれそうな優良顧客を、一人も発掘できていないからです。じゃあ、多少精度を落としてもいいので、1:有りを多めに出すモデルにした方がいいのかというと・・・そうとも、言いきれません。可能性の低い人にあまり営業をかけても、この労働力不足のご時世、色々無駄の多いキャンペーンになってしまうからです。

・・・などなど、ビジネス的に考えて、どういうモデルを作れば、費用対効果の高いキャンペーンが打てるだろう?なんて、機械学習をお仕事に使う際の思考トレーニングなんかにも、なったりします。

そしてもう一つ、分かりやすく精度を上げる工夫が、見えづらい点です。機械学習の場合、入力データと入力データを掛け合わせて、もっと精度が上がりそうな新たな入力データを作る、いわゆる特徴量設計が重要かと思いますが・・・

このデータ、分かりやすく掛け合わせれそうな項目が、あまりありません。例えば、同じく有名な練習問題の「不動産の成約価格を予測する」問題だと、なんとなく、「周辺物件と比較できそうな指標を入れれば、精度があがるかな?」なんて発想が、比較的簡単に出てきます。なので、「その物件の面積が、周辺物件の面積の平均値よりどのくらい大きいか?」なんて指標を、作ってみようかな?なんて、発想したりできます。

しかしこの問題の場合・・・例えば、ローン持ってない人の方が、定額預金しそうかな??なんて、想像は沸きますが、じゃあこの項目と何を掛け合わせれば、どんな入力データが作れるかというと、???と、なりませんか?

そんなわけで、分かりやすい特徴量設計が思い浮かびづらく、精度もそう簡単に上がりづらい分、逆に特徴量設計を始めとした精度の上げ方について、いろいろ調べてみたりする、いいきっかけになります。

というわけで、次回以降、本データを活用して、具体的に機械学習していってみたことを、アップしていきたいと、思います。最後まで読んでいただいて、ありがとうございました。