(1).やったこと
【7】.Matplotlibを使ったデータ可視化
【7-1】データの可視化
①.データの可視化について
データの可視化によって、様々な示唆を得ることができる。
単に数字を見ているだけよりも、図にすることで理解がより深まることもある。
②.この章で使うライブラリのインポート
6章と同じ、
【7-2】.データの可視化の基礎
(1).棒グラフ
カテゴリーごと(地域別、部門別など)に数値を比較したい時に使う。
pyplotモジュールのbar関数を使う。
また、棒にラベルを表示したい時は、xtick関数を使って指定する。
また、そのまま実行するとグラフが左に寄って見にくいので、グラフ中央に寄せる
ために、align = 'center'パラメータを指定する。
――――
#表示するデータ
x = [1, 2, 3]
y = [10, 1, 4]
#グラフの大きさ指定
plt.figure(figsize = (10, 6))
plt.bar(x, y, align='center', width = 0.5)
#棒グラフそれぞれのラベル
plt.xticks(x, ['A Class', 'B Class', 'C Class'])
#xとyのラベルを設定
plt.xlabel('Class')
plt.ylabel('Score')
#グリッドを表示
plt.grid(True)
#ここまでのコードで描いた図を表示
plt.show()
――――
plt.bar()が棒グラフを呼び出すコード。()が棒グラフの内容の設定。
plt.xticks()が棒グラフのラベル付けするコード。()内はどうラベル付けするか
の設定。
①.横の棒グラフ
上記は縦の棒グラフだが、横にしたい時はbarh関数を使う。
xとyの軸が入れ替わるので、ラベルを再設定する。
――――
#表示するデータ
x = [1, 2, 3]
y = [10, 1, 4]
#グラフの大きさ指定
plt.figure(figsize = (10, 6))
#横の棒グラフの描画
plt.barh(x, y, align='center')
#棒グラフそれぞれのラベル
plt.yticks(x, ['A Class', 'B Class', 'C Class'])
#xとyのラベルを設定
plt.xlabel('Class')
plt.ylabel('Score')
#グリッドを表示
plt.grid(True)
#ここまでのコードで描いた図を表示
plt.show()
――――
②.複数のグラフを描く
複数のグラフを描き、それぞれ比較してみる。
以下はクラスごとに数学の一期目の成績を、最終成績をそれぞれグラフ化し、
比較できるようにしたもの。
――――
#データの準備
y1 = np.array([30, 10, 40])
y2 = np.array([10, 50, 90])
#X軸のデータ
x = np.arange(len(y1))
#グラフの幅(の変数設定)
w = 0.4
#グラフの大きさ指定
plt.figure(figsize = (10, 6))
#グラフの描画。y2の方はグラフの幅の分、右にずらして描画する。
plt.bar(x, y1, color = 'blue', width = w, label = 'Math first', align='center')
plt.bar(x + w, y2, color = 'green', width = w, label = 'Math final', align='center')
#凡例を最適な位置に配置
plt.legend(loc = 'best')
#棒グラフそれぞれのラベル
plt.xticks(x, ['A Class', 'B Class', 'C Class'])
#グリッドを表示
plt.grid(True)
#ここまでのコードで描いた図を表示
plt.show()
――――
③.積み上げ棒グラフ
積み上げ棒グラフでは、同じくbar関数を使っているが、bottomパラメータの設定
に注目。
上に積む方のグラフで、barのパラメータとしてbottom=<下に積むグラフ>を指定
する。
――――
#データの準備
height1 = np.array([100, 200, 300, 400, 500])
height2 = np.array([1000, 800, 600, 400, 200])
#X軸
x = np.array([1, 2, 3, 4, 5])
#グラフの大きさ指定
plt.figure(figsize = (10, 6))
#グラフの描画
p1 = plt.bar(x, height1, color = 'blue')
p2 = plt.bar(x, height2, bottom = height1, color='lightblue')
#凡例を表示
plt.legend((p1[0], p2[0]), ('Class 1', 'Class 2'))
plt.show()
――――
要するに、詰む土台側のグラフがどれかを指定することで、積み上げ型にできる。
#3つ以上のを積み上げる場合ってどうやるんだろう?
(2).円グラフ
全体的な割合を見るときに見やすいグラフである。
①.一般的な円グラフ
円グラフを描くにはpie関数を使い、それぞれのサイズやラベル等を設定する。
axis関数で円グラフを丸く表示するように調整する。
autopctパラメータでそれぞれの割合を表示する書式を指定する。
また、explodeパラメータを指定すると。特定のカテゴリーだけ、円グラフの全
体から離す調整ができる。
startangleパラメータは、各要素の出力を開始する角度を表す。
このパラメータを指定することで、出力開始位置を変更できる。
90と指定すると上部中央が開始位置になり、反時計回りの方向に変更したい時
は正の値、時計回りに変更したい時は負の値を指定する。
出力する向きはcounterclockパラメータで指定する。
Trueか指定しないと時計周り、Falseと指定すると反時計周りに出力される。
※コードはテキストを参照
②.バブルチャート
scatter関数を使う。
※コードはテキストを参照
また、Pandasにも可視化機能は備わっている。
plotメソッドでグラフ化できる。
例えば、「.plot(kind='bar'」と記すと、縦の棒グラフが描ける。
「kind='barth'」で横の棒グラフ。
「kind='pie'」にすれば円グラフになる。
【7-3】応用:金融データの可視化
これは応用的な使い方なので、詳細はテキスト参照
【7-4】分析結果の見せ方を考えよう。
(1).資料作成のポイントについて
・何のためにデータ分析をして、何を見せたいのかをはっきりさせる。
・そもそもの分析結果をだれに伝えるのか? を考える。
・いきなり資料の作成を開始しない,PowerPointを開かない、その前に考える。
・その結果を見せることで、具体的なアクションを促したいか?
・それをやることでどれだけ儲かるのか? コストが下がるのか?
・何を話すのか、目次(アジェンダ)をはっきりさせる(全体像を見せる)
・基本的に結論が先
・情報を入れすぎない。無駄なものは削除。
・言いたいことを一言で+下にその根拠となるデータ(表)の可視化
・ストーリーを考える。
あくまでもざっくりとした要点。
【8-1】機械学習の全体像
(1).機械学習とは
教師あり学習、教師なし学習、強化学習の3つの種類がある。
①.教師あり学習と教師なし学習
(a).教師あり学習
説明変数から、目的変数を予測するモデルを求める手法。
#私が持っている機械学習のイメージはたぶんこれ
訓練データの説明変数を入力し、目的変数に近づくようにモデルのパラメータ
調整することで学習する。
使う例は、メールのタイトルや内容から、スパムかどうかを判別する、とか。
(b).教師なし学習
入力データそのものに着目し、データに潜むパターンや示唆を見出す手法。
訓練データに目的変数はない。
#なんか、教師あり学習は、真理からは必ずズレる気がする。まぁ
全データではない限り当たり前か。
②.強化学習
プログラムの一連の行動の結果に対して報酬を与えることで、機会に実現させた
い行動ルールを獲得させようとする手法。
③.機械学習を適用するにあたって
機械学習はあくまで手段の一つ。
実際のデータ分析の現場では、データの基本的な観察と理解が、機械学習のアウト
プットの品質に大きく影響を与える。
また、一連の確認から有益な気づきを得られることもある。
また、1冊の専門書で機械学習のモデルや実装に関することを網羅することはできな
い。
困ったときは、公式ドキュメントに戻るとよい。量はあるが、細かな説明があるの
で、確実である。
(2).教師あり学習
訓練データを与えて、そこに含まれるある変数を予測するためのモデルを構築する
手法。
y = f(x)という関数があるとすると、yが目的変数、xが説明変数、関数f(x)がモデ
ル。
①.教師あり学習の手法
目的変数のデータ形式によって、2つの種類に分類できる。
目的変数が、株価など、数値を取る場合を回帰、目的変数がカテゴリになる場合を
分類という。(例えば、購入するかしないか、など(〇or×)
アルゴリズムの一例:重回帰、ロジスティック回帰、k近傍法、決定木、サポートベ
クターマシン、ランダムフォレスト、勾配ブ―スティングなど
(3).教師なし学習
データに潜むパターンや示唆を見つけ出そうとするもの。
①.教師なし学習の手法
クラスタリング、主成分分析、マーケットバスケット分析などがある。
パターンや示唆を見つけて終わりではなく、ビジネスの現場感覚とズレてないかを
確認することも重要。
(4).強化学習
ある報酬を最大化させるために何をすべきかの行動ルールを、機会に学習させるた
めの技術。
望ましい行動には高い報酬を、そうでないものには低い報酬を設定し、どのような
行動が最終的により大きな報酬を得られるのかを見つけ出そうとする。
①.強化学習の手法
探索と知識利用のジレンマをどう扱うかが重要なテーマになる。
(過去から学んだ一番いい行動をしてるだけでは、新しい行動が見つけられないが
新しい行動ばかりしてると過去の経験を生かせない)
アプローチには、モンテカルロ法やTD学習などがある。
【8-2】重回帰
重回帰は、複数のaaaa説明変数をつって目的変数を予測する。
(1).自動車価格のデータの取り込み。
自動車の価格と属性のデータから、属性から自動車価格を予測するモデルを重回帰を
使って構築する。
まずは公開されているURLからデータを取り込む。
コードは下記
――――
#インポート
import requests, zipfile
import io
#自動車価格データを取得
url = 'http://archive.ics.uci.edu/ml/machine-learning-databases/autos/imports-85.data'
res = requests.get(url).content
#取得したデータをDataFrameオブジェクトとして読み込み
auto = pd.read_csv(io.StringIO(res.decode('utf-8')), header=None)
#データの列にラベルを設定
auto.columns =['symboling', 'normalized-losses','make','fuel-type' ,'aspiration','num-oh-doors',
'body-styles','drive-wheels','engine-location','wheel-base','length','width','height',
'curb-weight','engine-type','num-of-cylinders','engine-size','fuel-system','bore',
'stroke','compression-ratio','horsepower','peak-rpm','city-mpg','highway-mpg','price']
――――
この時、URLが間違ってたりすると、エラーメッセージでデータの列が1列しかない、な
ど出る。
まずは、参照するURLが間違ってないか、試しにwebで打ち込んでみると良い。
間違っていると「not found」が返ってくる。
あとは、データと書いてある列数が違うとそれもエラーで出てくるので、その時はラベ
ルの設定がおかしい可能性があるので、よく確認すること。
(2).データの整理
入力データには不適切なものが含まれていることがあるので、まずはデータ内容を確
認して適切なデータとして整理する。
①.不適切なデータの除去
(1)で取り込んだデータをauto.head()で確認すると、中に?が含まれていることがわ
かる。
多くの機械学習のアルゴリズムは、数値型データしか扱えないため、このような?などの非数値
データを含む変数に対しては、それを取り除く前処理が必要。
今回は、horsepower,width,heightからpriceを予測しようとしてるので、これらの変数に?が
あれば削除する。
まず、?データが、上記の4つの変数にどれだけ含まれているかを確認する。
――――
#それぞれのカラムに?が何個あるかカウントする
auto = auto[['price','horsepower','width','height']]
auto.isin(['?']).sum()
――――
price 4
horsepower 2
width 0
height 0
dtype: int64
――――
結果を見ると、priceに4つ、horsepowerに2つ、?があることがわかる。
次に、?がある行を削除する。(リストワイズ削除)
――――
#?をNanに置換して、Nanがある行を削除
auto = auto.replace('?', np.nan).dropna()
print('自動車データの形式:{}'.format(auto.shape))
――――
(3).型の確認
ここでデータの型を確認しておく。
※データがこれから使おうとしているモデルで扱えるものかを確認している。
例えば、見た目数字に見えてもオブジェクトのままだったりすると、floatしか
扱えないモデルだとエラーの原因になる。
――――
print('データ型の確認(型変換前)\n{}\n'.format(auto.dtypes))
――――
データ型の確認(型変換前)
price object
horsepower object
width float64
height float64
dtype: object
――――
#「\n{}\n」って何の効果があるんだろう?
全然想像できない。ゲームとかだと改行だけど……
確認した結果、priceとhorsepowerが数値型ではないことがわかる。
そこで、to_numericを使って数値型に変換する。
――――
auto = auto.assign(price=pd.to_numeric(auto.price))
auto = auto.assign(horsepower=pd.to_numeric(auto.horsepower))
print('データ型の確認(型変換後)\n{}'.format(auto.dtypes))
――――
ここまでがデータの前処理
(3).モデル構築と評価
重回帰のモデルを作り、その性能を調べるプログラムを作る。
説明変数をx、目的変数をyとする。
機械学習のモデル構築では「モデル構築に使用する訓練データ」を使って学習さ
せてモデルを構築し、そのモデルに訓練データとは別の「テストデータ」を入れて
、テストデータに対して、どの程度の精度が得られるのかを確認することで性能を
調べるのが一般的なやり方となる、
そこで、下記ではscikit-learnのmodel_selectionモジュールの
train_test_split関数を使い、訓練データとテストデータに分けている。
train_test_split関数はデータをランダムに2つに分ける関数である。どのよう
な割合で分類するのかは、test_sizeで決める。
ここではtest_sizeを0.5にしているので、半分に分かれる。
(例えば、0.4なら4:6に分かれる)
random_stateは乱数の生成を制御するもの。
ここではrandom_stateを0に設定している。
このようにrandom_stateを固定すると、何度実行しても同じように分離される。
もし、任意の値を指定しないと、実行のたびにある行が訓練データに分類された
りテストデータに分類されたりをまちまちになるので、結果が一定とならない。
モデル性能の実証段階では、再現性が必要なので、randdom_stateを固定する。
重回帰のモデル構築は、LineaRegressionクラスを使って行う。
「model = LineaRegression()」でインスタンスを作成して、訓練データを
「model.fit(X_train,y_train)」のように読み込ませると学習が完了する。
学習したら、決定係数や回帰係数、切片を確認できる。
機械学習の目的は、高い汎用化性能の獲得(構築したモデルによって、未知のデータ
でも適切に予測できること)なので、訓練データへの当てはまりを追求すれば良いモデ
ルになりそうだが、実際はそうではなく、訓練データに対する制度は良くてもテスト
データに対する制度が低くなるということがしばしば起こる。
このことを「過学習」もしくは「過剰学習」と呼び、モデル構築の段階において
もっとも注意を要する検証事項になる。
決定係数はscoreメソッドで取得できる。
――――
#データ分割(訓練データとテストデータ)のためのインポート
from sklearn.model_selection import train_test_split
#重回帰のモデル構築のためのインポート
from sklearn.linear_model import LinearRegression
#目的変数にpriceを指定、説明変数にそれ以外を指定。
X = auto.drop('price', axis=1)
y = auto['price']
#訓練データとテストデータに分ける
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0)
#重回帰クラスの初期化と学習
model = LinearRegression()
model.fit(X_train,y_train)
#決定係数を表示
print('決定係数(train):{:.3f}'.format(model.score(X_train,y_train)))
print('決定係数(test):{:.3f}'.format(model.score(X_test,y_test)))
#回帰係数と切片を表示
print('\n回帰係数\n{}'.format(pd.Series(model.coef_, index=X.columns)))
print('\n切片\n{:.3f}'.format(model.intercept_))
――――
(4).モデル構築とモデル評価の流れのまとめ
基本的にモデル構築とモデル評価の流れはだいたい一緒。
step1:各種モデル構築のためのクラスのインスタンス化
model = LinearRefresson()
step2:データを説明変数と目的変数に分ける
Xとy
step3:訓練データとテストデータに分ける。
train_test_split(X, y, test_size=0.5, random_state=0)
step4:訓練データによるあてはめ。
model.fit(X_train,y_train)
step5:モデルの汎化性能をテストデータで確かめる。
model.score(X_test,y_test)
また、今回は恣意的に説明変数をhorsepower、width、heightの3つを恣意的に
選択したが、統計的に選択する方法もいくつかある。
変数増加法(前進的選択法)、変数減少法(後退的選択法)、スワップワイズ法な
どで、選択する基準もRMSE(Root Mean Squared Error)、赤池情報量機銃ん(AIC)、
ベイズ情報量基準(BIC)などがある。
どれが絶対に有効というものはない。モデルの汎化性能やビジネスドメイン知識
なども考慮され選択される。
【8-3】ロジスティック回帰
ロジスティック回帰は、目的変数が数値ではなく、例えばある商品を買うか買わない
かなどの「カテゴリのデータ」を扱うアルゴリズムである。
このようにカテゴリの形になっている変数を「カテゴリ変数」という。
データサンプルがあるカテゴリに属するかどうかの確率を計算するタスクを「分類
(classfication)といい、そのためのアルゴリズムの一つがロジスティック回帰。
回帰という名前がついているものの、分類を扱うアルゴリズムである。
(2分類だけでなく、3分類以上にも使える)
目的変数が数値の時と違い、分類タスクでは、以下の目的関数が最小になるように
学習する。
この目的関数を「交差エントロピー誤差関数」と言い、正解カテゴリを予測できる
確率が高くなるほど値が小さくなる。
(1).ロジスティック回帰の例
まずはデータを用意する。
今回は年齢や性別、職業などの個人に関するデータからその人の収入が50K(50万
ドル)を超えるかどうかを予測するためのモデルを構築してみる。
※詳細はテキスト参照(ここではコード割愛)
データを取得し、カラム名を設定。
データを確認すると、カテゴリ変数と、数値変数が混在したデータセットである。
(2).データの整理
収入が50Kを超えるかどうかを表す目的変数のflg-50Kのデータの値がわかりにくい
(「<=50K」と「>50K」)ので、0または1のフラグが入った変数に変換する。
やり方は「fin_fig」というカラムを追加し、「>50K」である行には1、それ以外は
0とフラグ立てをする。
フラグ立てにはlambdaやmapを使う。
※詳細はテキスト参照(ここではコード割愛)
(3).モデル構築と評価
説明変数として、数値変数のage、fnlwggt1、education-num、capital-gain、
capital-lossを使う。目的変数は上記の通り。
ロジスティック回帰のモデル構築にはLogisticRegressionクラスを使う。
訓練データとテストデータに分けたりscoreメソッドで評価したりする方法は
重回帰と一緒。
※詳細はテキスト参照(ここではコード割愛)
結果から、訓練データとテストデータともに79%の正解率であり、過学習は起きて
いないと判断できる。
学習済みの各変数の係数を、coef_属性を取得することで確認してみる。
※詳細はテキスト参照(ここではコード割愛)
また、それぞれのオッズ比も算出できる。
オッズ比はそれぞれの係数が1増加したとき、正解率にどの程度影響があるかを
示す指標である。
※詳細はテキスト参照(ここではコード割愛)
(4).スケーリングによる予測精度の向上
ここで、予測精度を上げるためのアプローチの1つであるスケーリングについて
紹介する。
このモデルでは、5つの説明変数を使っているが、それぞれの単位や大きさは
異なっている。
このままだとモデルの学習が、値の大きな変数に引っ張られ、値の小さな変数の
影響が小さくなる懸念がある。
そこで、そうならないようにするため、説明変数の標準化を実施する。
標準化とは、変数列の平均で引き、標準偏差で割ること。
こうすることで、スケールの違いをそろえ、標準偏差1に対してどの程度データが
離れているかというZ値という一つの基準にデータをそろえることができる。
データの標準化には、StandardScallerクラスを使う。
※詳細はテキスト参照(ここではコード割愛)
実行すると、標準化しない場合に比べて正解率が上昇している。
このように、説明変数の尺度をそろえることで、機械学習のアルゴリズムをより
うまく動作させることができる。
標準化処理で留意しておきたいポイントは、訓練データの平均値と標準偏差を使用
している点。テスト用データは将来手に入るであろう未知のデータという位置づけな
ので、そのデータを使って標準化することはできません。
#これ、結構大切な気がする。
【8-4】正則化項のある回帰:ラッソ回帰、リッジ回帰
これらは入力が少し動いたときに、出力が大きく変化する場面において、重回帰の
モデルに比べて過学習が起こりにくいという特徴がある。
(1).ラッソ回帰、リッジ回帰の特徴
重回帰では予測値と目的変数の二乗誤差を最小にするように回帰係数を推定する。
これに対置、ラッソ回帰やリッジ回帰には、二乗誤差を小さくしようとする以外に、
回帰係数自体が大きくなることを避ける仕掛けがある。
一般的に、回帰係数が大きいモデルはインプットの少しの動きでアウトプットが大き
く動くようになる。つまり、入出力関係が敏感、または複雑なモデルになる。
このようなモデルは、訓練データには当てはまるが未知のデータには当てはまらない
、過学習を引き起こすリスクが高まる。
そこで回帰係数を推定する際、モデルの複雑さを表す項を損失関数に追加し、それを
含め誤差を最小化するように回帰係数を推定しようとしたものが、ラッソ回帰、リッジ
回帰である。
具体的にラッソ回帰やリッジ回帰では、回帰係数を推定する際の損失関数を下記の
ように定義する。
Σ(i=1→n)(y_i-f(x_i))^2 + λΣ(j=1→M)|w_j|^q
正則化項はモデルの複雑さを抑える役割を持った項である。(λΣ(j=1→M)|w_j|^q)
「正則化(regularization)とは、一般的にモデルの複雑さを低減するための工夫全般
を指す。
要するに、変数の数Mを増やせば増やすほど、重みも増やせば増やすほど損失関数の
第二の項が大きくなり、それがペナルティになる。
重回帰が投入する説明変数の数を分析者側で調整することによってモデルの複雑性
を調整するのに対し、ラッソ回帰・リッジ回帰はパラメータ自体の大きさをモデル
自身が小さく抑えることによって、モデルの複雑性を調整してくれる。
訓練スコアとテストスコアに乖離がある場合、正則化項のあるアルゴリズムを使用
することで汎化性能を改善できる可能性がある。
(2).重回帰とリッジ回帰の比較
※詳細はテキスト参照(ここではコード割愛)
訓練データにおいては重回帰の正解率が高く、テストデータにおいてはそれが逆転
していることから、正則化項による効果が推察できる。
#つまり、あんまりにも訓練データとテストデータが乖離するなら、これらを使う
ことで新たなヒントが得られるかもよ、ということ?
【8-5】決定木
決定木(Decion Tree)は、ある目的に到達するためにデータの各属性の条件分岐を
繰り返してクラス分けする方法である。
目的変数がカテゴリの場合は「分類木」、数値の場合は「回帰木」と呼ぶ。
(1).キノコデータセット
決定木の例として、キノコのデータセットを使う。
キノコには毒キノコとそうでないものがある。
※詳細はテキスト参照(ここではコード割愛)
ここでの目的は、与えられたキノコが毒キノコか否かを見分けること。
キノコの説明変数はカサの形、匂い、ヒダの大きさや色など計20種類以上ある。
これらの説明変数を用いて、例えばかさの形が円錐形かそうでんかいあ、ヒダの色
が黒色なのか赤色なのか、その大きさは大きいのか小さいのかというように条件分岐
をしていき、最終的にそのキノコが毒キノコなのか否かを見分けようと試みる。
(今回は目的変数がカテゴリ変数なので分類木)
このように、ある目的に到達するために、データの各属性の条件分岐を繰り返して
カテゴリ分けするというのが決定木の手法。
目的にたどり着く様々なルートがあり、それがツリー形式で表現されるため決定木
という名前がついている。
まずはデータを確認する。
※詳細はテキスト参照(ここではコード割愛)
目的変数はclasses。これがpなら毒キノコ、eの場合は食用であることを示す。
1つの行が1つのキノコの情報で、属性がそれぞれついている。
また、データの形式と欠損値を確認すると、データは8123行、23列で欠損値は
ないことがわかる。
※詳細はテキスト参照(ここではコード割愛)
(2).データの整理
たくさんの説明変数があるので、ここでは話を簡略にするため、説明変数を
gill_color(ひだの色)、gill_attachment(ひだの付き方)、odor(匂い)、
cap_color(かさの色)の4つに限定する。
これらのデータは、例えばgill_colorはblackの時はnといったカテゴリ変数に
なっている。
しかし、決定木で扱う変数は、説明変数、目的変数、数値型でなければいけない。
そのため、このようなカテゴリ変数は数値変数に変換しなければいけない。
#順序型の質的変数でもないのにどうやって?
そこで、カテゴリ変数をダミー変数にする。
ダミー変数とは、ある値が入ってるかどうか2列に分けて表現すること。(1or0)
Pandasのget_dummies関数を使うとダミー変数化できる。
※詳細はテキスト参照(ここではコード割愛)
返還後のデータは、元の変数メイト値の組み合わせになる。
例えば、色なら色のの項目のカラムがあって、その色であるカラムにだけ1、そ
れ以外のカラムには0が入ってる、というようなデータになる。
次に、目的変数であるclassesについても新しい変数flgに変換しておく。
カテゴリ変数を表す目的変数であっても、入力データ形式が数値である必要が
あるため。
行う処理は、classes変数の値がpの場合は1、そうでない場合は0として、新しい
変数flgを追加している。
そして、map関数を使うことで、その処理をすべての要素(セル)に適用している。
ここまでで、目的変数を0と1の数値型で表現し直し、カテゴリ変数の特徴量も
ダミー変数化したので、決定木(アルゴリズム)に入力することができるようになった。
※詳細はテキスト参照(ここではコード割愛)
(3).エントロピー:不純度の指標
決定木のモデル構築の前に、決定木の作られ方をカテゴリ識別の不純度(impurity)
という視点から見る。
不純度とは、毒キノコか否かの識別の状態を表す指標で、不純度が高いとはカテゴ
リ識別できていない状態を意味する。
例えば、cap_colorがcであるかそうでないのかのTRUE(1)orFALSE(0)でデータで分け
るとして、その時のそれぞれ毒キノコがどれくらいあるのかをクロス集計してみる。
下記は行がcap_colorがcかどうか、列が毒フラグが立ってるかそうでないかのクロ
ス集計表です。
※詳細はテキスト参照(ここではコード割愛)
結果、cであれば、毒が12個、どうでないが32個
cでなければ毒が3904個、毒でないが4176個であることがわかる。
この結果を見ると、cであるかどうかはあまり関係ないことがわかる。
(どちらにも似た割合で毒キノコが含まれているから)
一方、gill_colorがbであるかどうかに着目すると
※詳細はテキスト参照(ここではコード割愛)
bなら毒が1728、毒でないが0。
b意外だと、毒が2188で、毒でないが4208とわかる。
つまり、bであるかどうかの分岐条件が、識別能力の高い(不純度の低い識別状態
を導く)有益な条件だとわかる。
このように決定木とは、多数の変数の中でどの変数から尤有益な条件分岐を見分
けてくれるアルゴリズムで、その分岐条件の優劣を決める際に不純度が使われてい
る。
その不純度の指標としてよく使われるものに「エントロピー(entropy)」がある。
エントロピーの定義は以下の式で与えられる。
(Sはデータの数、nはカテゴリの数、pは各カテゴリーに属するデータサンプルの
割合。
H(S) = -Σ(i=1→n)(p_i・log_2・p_i)
今回の例では、カテゴリは2つ、毒キノコでない割合がp1、毒キノコである割合が
p2となる。ここで1つ目の例として、ある分岐条件について、毒キノコも食用キノコ
も等しい割合で入っている状態を考える。
p1=p2=0.5となるので、エントロピーは下記のように計算できる。
※詳細はテキスト参照(ここではコード割愛)
計算結果、エントロピーは1.0となることが確認できる。
毒キノコもそうでないキノコも等しい割合(0.5)で含まれているので、全く識別が
できていない状態ということです。
次に、毒キノコでない割合p1=0.001、毒キノコである割合がp2=0.999の場合を考え
る。
※詳細はテキスト参照(ここではコード割愛)
結果、エントロピーは0に近い値になっている、
この状態はほぼデータは毒キノコを特定できているので、エントロピーが小さくな
っている。
#つまり、不純度とは、判断のエラー具合を示す指標?
まとめると、エントロピーは1に近と識別ができてない状態、0に近いと識別がよく
できている状態と言える。
今回の例では、カテゴリは2分類のため、p1=1-p2という関係式ができるため、
エントロピーの式は下記のようにコードで表せる。
※詳細はテキスト参照(ここではコード割愛)
pは確率で0から1までの値をとるので、このpとエントロピーの式をグラフで表すと
以下のようになる。
※詳細はテキスト参照(ここではコード割愛)
エントロピーは最大で1、最小で0となることが確認できる。
ここまでのエントロピーの説明で、エントロピーが識別の不純度を表すということ
がわかった。
先ほどのキノコのデータでエントロピーを計算してみる。
目撃変数flgについてカウントする。
※詳細はテキスト参照(ここではコード割愛)
すると、毒でないキノコが4208個、毒キノコが3916個だとわかる。
これらを確率にすると、毒キノコでない確率は0.518、毒キノコである確率は0.482
なので、エントロピーを計算すると
※詳細はテキスト参照(ここではコード割愛)
毒キノコデータのエントロピーの初期値は0.999であることがわかる。
(2).気づいたこと・学んだこと・疑問
・重回帰の強み。
過学習を抑えることができるラッソ回帰や、リッジ回帰があるなら、重回帰は不要な
のではないかという気はしたが、そもそもラッソ回帰やリッジ回帰は回帰係数を小さく
する仕組みがあるので、それはそれでバイアスになってしまう。
ノイズの少ないデータがそろっているような環境なら、重回帰の方が優れている。
ということらしい。
・恐らく、アルゴリズム毎にデータ前処理のパターンがある。
フローというか、やることはだいたい決まってるんじゃないだろうか?
本番(Kaggle)では、それをまずは探すことから始めたらいい気がする。
(3).簡単な復習
・「フラグ立て」とは?
無明関数とmap関数を使って、簡易に新しい1と0に分けられたカラムを作っている。
やってることは、小さな処理と一括適用を最短で実現している、ということ。
『lamba 変数:関数の内容』でその場限りで使う関数を作れる。
mapはリスト(などの反復可能なもの)に対して、同じ処理を一括で適用するための道具
余計な関数を定義する手間を省いてくれているのがlambba
for文などのループ処理を書かなくていいようにしてくれているのがmap