100日後にエンジニアになるキミ - 80日目 - プログラミング - 機械学習について5

昨日までのはこちら

[100日後にエンジニアになるキミ - 76日目 - プログラミング - 機械学習について](https://qiita.com/otupy/items/6a4f960ba4df06e27050)

[100日後にエンジニアになるキミ - 70日目 - プログラミング - スクレイピングについて](https://qiita.com/otupy/items/f53e2e7d16adf80b5acf)

[100日後にエンジニアになるキミ - 66日目 - プログラミング - 自然言語処理について](https://qiita.com/otupy/items/5828ac7450c5ba8d6931)

[100日後にエンジニアになるキミ - 63日目 - プログラミング - 確率について1](https://qiita.com/otupy/items/0196897ae4d2134794fa)

[100日後にエンジニアになるキミ - 59日目 - プログラミング - アルゴリズムについて](https://qiita.com/otupy/items/f1a5e81633b868f3b5ed)

[100日後にエンジニアになるキミ - 53日目 - Git - Gitについて](https://qiita.com/otupy/items/0abaad82a7f3fea73f1f)

[100日後にエンジニアになるキミ - 42日目 - クラウド - クラウドサービスについて](https://qiita.com/otupy/items/d1765f1541a104ed6133)

[100日後にエンジニアになるキミ - 36日目 - データベース - データベースについて](https://qiita.com/otupy/items/7af17635d576677606dc)

[100日後にエンジニアになるキミ - 24日目 - Python - Python言語の基礎1](https://qiita.com/otupy/items/6d1e5453f530e07b7aec)

[100日後にエンジニアになるキミ - 18日目 - Javascript - JavaScriptの基礎1](https://qiita.com/otupy/items/2f71d5f9c754b29d9555)

[100日後にエンジニアになるキミ - 14日目 - CSS - CSSの基礎1](https://qiita.com/otupy/items/61a97863f6df14171994)

[100日後にエンジニアになるキミ - 6日目 - HTML - HTMLの基礎1](https://qiita.com/otupy/items/cd2315dcb38671cfded0)

今回は機械学習についてのお話の続きです。

## 機械学習のデータ加工流れについて

機械学習を取り入れる際の業務としては次のような流れになっていきます。

0.目的を決める
1.データ取得
2.データ理解・選択・加工
3.データマート(データセット)作成
4.モデル作成
5.精度検証
6.システム実装

このうち2-3の部分をデータの前処理などと言っています。

今回はこの前処理のうちのデータマート作成やっていきたいと思います。

### 昨日までの前処理

言語はPython
機械学習用のライブラリは`Pandas`や`Numpy`
可視化用のライブラリは`seaborn`,`matplotlib`を用います。


**ライブラリの読み込み**

```python
# ライブラリの読み込み
import pandas as pd 
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')

%matplotlib inline
```

ここからデータマートを作成しました。

[昨日の講義はこちら](https://qiita.com/otupy/items/3d1037093cfcbbb27048)

ここからはデータマートを用いてモデル作成に入ります。

## モデル作成について

ここからは作成したデータを用いて機械学習を行います。

まず最初に機械学習用のライブラリを読み込みします。

**機械学習ライブラリの読み込み**

scikit-learn : 機械学習用のライブラリ

```python
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split

from sklearn.metrics import recall_score,precision_score,f1_score,accuracy_score
from sklearn.metrics import confusion_matrix
```

ざっくりとライブラリの説明をすると`scikit-learn`自体はものすごく巨大なライブラリなので
必要なものだけを読み込みしていきます。1つ1つの項目については後ほど。

### モデル作りの流れ

モデル作りにはいくつかの工程があります。

まずは`学習データ`と`テストデータ`に分ける作業です。
入試のテストを受ける事を思い浮かべてみてください。

何のテストか、事前に答えをしっていたら、満点に近い点数取れると思います。
なので、機械学習でもあらかじめ学習しているデータで検証をするのはあまり意味がありません。

事前に学習させるデータには検証用のデータが含まれないようにして学習させ、学習モデルが出来上がった後、改めて残ったテストデータで検証を行います。

検証した上で、満足のいくものができなかった場合は、手法を変えてみたり、パラメーターの調整をしたり、データの取捨選択から前処理をし直したりしてモデルを作っていきます。

**データの分割**

ここでは`ホールド・アウト法`で単純分割を行います。
テストデータへの分割は`train_test_split`を用いて行います。

X = 正解ラベル以外のデータ(複数列)
Y = 正解ラベルのデータ(1列)

`x_train, x_test, y_train, y_test = train_test_split(X,Y, test_size=テストサイズ)`
※テストサイズは小数点で記入し、テストデータのサイズを入れます。例:0.2

ここで言う`X`と`Y`は昨日作成したデータフレームの列を指定します。

```python
X = data_df.drop(['Survived'],axis=1)
Y = data_df['Survived']
x_train, x_test, y_train, y_test = train_test_split(X,Y, test_size=0.2)
print(len(x_train))
print(len(y_train))
print(len(x_test))
print(len(x_test))
```
712
712
179
179

これで`訓練用の説明変数のデータ`、`訓練用の目的変数のデータ`、`テスト用の説明変数のデータ`、`テスト用の目的変数のデータ`の4つのデータが出来上がります。

**モデルの呼び出し**

次にモデルの呼び出しです。どんな手法を用いるのか決めて、ライブラリから呼び出します。

ここでは
`ロジスティック回帰モデル`を呼び出します。
`ロジスティック回帰`は2値の判別に良く用いられています。
`LogisticRegression`が`ロジスティック回帰`モデルになります。


```python
clf = LogisticRegression()
```

**モデルの学習**

モデルを呼び出したら次は学習です。
学習は`訓練用の説明変数のデータ`、`訓練用の目的変数のデータ`を用いて学習を行います。
基本的に学習は1行で書けてしまいます。

```python
clf.fit(x_train, y_train)
```
LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
                   intercept_scaling=1, l1_ratio=None, max_iter=100,
                   multi_class='warn', n_jobs=None, penalty='l2',
                   random_state=None, solver='warn', tol=0.0001, verbose=0,
                   warm_start=False)

これで学習は終わりです。

**予測を行う**

次に`テストデータ`で検証を行います。
検証では分割した`テストデータ`を用いて、テストの`ラベル`を予測(判別)します。


```python
y_predict = clf.predict(x_test)
```

これで予測した結果が`y_predict`に格納されました。
中身は正解を予測した配列が格納されています。

```python
y_predict[0:5]
```
array([0, 0, 1, 0, 0])

予測は`0`か`1`の値を出力しています。
`正解ラベル`も`0`か`1`の値のデータになっているので、これと比較する事で精度検証が行えます。

**モデルの精度検証を行う**

次はモデルの精度検証です。モデルの精度がどれくらい出ているのかを算出します。
ライブラリから精度検証用のライブラリを読み込みしていますので紹介すると

confusion_matrix : 2x2の正誤表を出力する
accuracy_score : 正答率を算出する
precision_score : 適合率を算出する
recall_score : 再現率を算出する
f1_score : precision x recall の調和平均を算出する

となっています。

早速精度検証をしてみると

```python
print(pd.DataFrame(confusion_matrix(y_predict, y_test), index=['predict 0', 'predict 1'], columns=['real 0', 'real 1']))
print()
print('accuracy  : ',accuracy_score(y_test, y_predict))
print('precision : ',precision_score(y_test, y_predict))
print('recall    : ',recall_score(y_test, y_predict))
print('f1_score  : ',f1_score(y_test, y_predict))
```
  real 0  real 1
predict 0     100      25
predict 1      15      39

accuracy  :  0.776536312849162
precision :  0.7222222222222222
recall    :  0.609375
f1_score  :  0.6610169491525424

こんな結果になりました。
このデータでモデル作成をした場合は`正答率(accuracy)`でみると77.6%ほどの精度が出ています。

検証時の数値の見方ですが

まずは予測の結果は`0`と`1`に分かれます。
あらかじめ正解ラベルのデータも`0`と`1`に分かれているため、正誤表としては2x2のパターンがあります。

予測と実測の関係は次のようになります。

||実測0|実測1|
|:--:|:--:|:--:|
|予測0|100|25|
|予測1|15|39|

ここから正解率(accuracy)を出していきます。正解率は
`(実測0予測0の値 + 実測1予測1の値) / 全部の合計値`
となります。

`(100 + 39)/(100 + 25 + 15 + 39) = 139/179 = 0.7765`

次に適合率(precision)です。適合率は
`実測1予測1の値 / 予測1の値`
となります。

`39/(15 + 39) = 39/54 = 0.7222`

次に再現率(recall)です。再現率は
`実測1予測1の値 / 実測1の値`
となります。

`39/(25 + 39) = 39/64 = 0.609`

最後にf1_scoreです。f1_scoreは
適合率と再現率の調和平均になります。

`2 * 適合率 * 再現率 / (適合率 + 再現率)`

`2 * 0.7222 * 0.609 / (0.7222 + 0.609) =  0.8802 / 1.3316 = 0.6610`

検証でどの数値に重きを置くかは機械学習の目的によって変わります。
今回は2値での判別をおこなっていますが、正解ラベルが満遍なく同じくらいの量分かれているなら正解率で良いでしょう。
どちらか一方のデータが少ないか多くて偏っている場合は正解率で出すと望ましくない場合があります。

例えば99:1の割合のデータだとしたら、多い方のラベルに全部合わせてしまえば正解率99%を取れることになります。
病気の診断をすることなどを考えてみてください。

全員病気でないというモデルを作れば、正解率だと99%ですが、残りの1%は見逃す結果になり、病気の人は困ります。
この場合だと多少間違ってもいいから病気の人を検出できるようにしたモデルでないと少数派を見逃すことになります。

適合率(precision)は陽性と予測されたデータのうち、実際に陽性であるものの割合であり、 再現率(recall)は、実際の陽性のデータのうち、陽性と予測できたものの割合を表しています。

機械学習の目的が少数派をきちんと当てに行けることを見るのであれば再現率(recall)を重視してきちんと検出できるようなモデルを選ぶことがあります。

ただそうすると、引っかかりすぎも出てきます。
その場合は適合率(precision)と再現率(recall)を双方加味したf1_scoreを指標にしたりします。


**他のモデル**

他のモデルも見てみましょう。ここではモデルの紹介だけで詳細については触れません。
まずは決定木です。

```python

# 決定木
clf = DecisionTreeClassifier()
clf.fit(x_train, y_train)
y_predict = clf.predict(x_test)
print(pd.DataFrame(confusion_matrix(y_predict, y_test), index=['predict 0', 'predict 1'], columns=['real 0', 'real 1']))
print()
print('accuracy  : ',accuracy_score(y_test, y_predict))
print('precision : ',precision_score(y_test, y_predict))
print('recall    : ',recall_score(y_test, y_predict))
print('f1_score  : ',f1_score(y_test, y_predict))
```

  real 0  real 1
predict 0      95      26
predict 1      20      38

accuracy  :  0.7430167597765364
precision :  0.6551724137931034
recall    :  0.59375
f1_score  :  0.6229508196721311

次はRandomForestです

```python

# RandomForest
clf = RandomForestClassifier()
clf.fit(x_train, y_train)
y_predict = clf.predict(x_test)
print(pd.DataFrame(confusion_matrix(y_predict, y_test), index=['predict 0', 'predict 1'], columns=['real 0', 'real 1']))
print()
print('accuracy  : ',accuracy_score(y_test, y_predict))
print('precision : ',precision_score(y_test, y_predict))
print('recall    : ',recall_score(y_test, y_predict))
print('f1_score  : ',f1_score(y_test, y_predict))

```
  real 0  real 1
predict 0      98      26
predict 1      17      38

accuracy  :  0.7597765363128491
precision :  0.6909090909090909
recall    :  0.59375
f1_score  :  0.6386554621848739

​
**寄与率の算出**

機械学習のモデルではどのデータが寄与したのか、寄与率を出すことが出来るモノもあります。

`clf.featureimportances`

```python

for i,v in zip(x_train.columns,clf.feature_importances_):
    print(i,'\t',v)
```

SibSp 	 0.08181730881501241
Parch 	 0.053030544663722166
Fare 	 0.40243782816341556
Sex2 	 0.28228147632317596
Pe_0.0 	 0.03352832009152742
Pe_1.0 	 0.014542002215684312
Pe_2.0 	 0.02212292439144309
Pe_3.0 	 0.022599544658725688
Pe_4.0 	 0.013099652111940165
Pe_5.0 	 0.013494114387414768
Pe_6.0 	 0.005599733163595443
Pe_7.0 	 0.002340597855733169
Pe_8.0 	 0.0030199997376331917
Em_C 	 0.012248329962351154
Em_N 	 0.0010747396045908525
Em_Q 	 0.010808812977944686
Em_S 	 0.025954070876089957


## まとめ

昨日はデータを加工して機械学習用のデータマートを作成しました。
本日はそのデータを用いての予測モデルの作成と精度検証となります。
モデルの作成自体はかなり簡単にできるようになっていて、コードを書く量もかなり少なくなっています。

そのため、モデルの作成ではどのモデルを選択するかと言う点が重要になります。
コードを書く総量は少ないので、様々なモデルを作って検証し、一番精度の良いものを選んでいくという作業になります。

精度が低ければ、他のモデルも試し、それでも低ければデータの前処理に戻ってやり直すと言うサイクルになります。
納得のいくモデルができるまでこのサイクルを繰り返し、最悪データの取得からやりなおすと言うことになります。

まずは全体の流れを覚ましょう。

君がエンジニアになるまであと20日

## 作者の情報
乙pyのHP：
http://www.otupy.net/

Youtube：
https://www.youtube.com/channel/UCaT7xpeq8n1G_HcJKKSOXMw

Twitter：
https://twitter.com/otupython