PythonによるAI・機械学習・深層学習アプリのつくり方【2章】：読書メモ

# はじめに
書籍：[すぐに使える! 業務で実践できる! Pythonによる AI・機械学習・深層学習アプリのつくり方](https://www.amazon.co.jp/%E3%81%99%E3%81%90%E3%81%AB%E4%BD%BF%E3%81%88%E3%82%8B-%E6%A5%AD%E5%8B%99%E3%81%A7%E5%AE%9F%E8%B7%B5%E3%81%A7%E3%81%8D%E3%82%8B-Python%E3%81%AB%E3%82%88%E3%82%8B-AI%E3%83%BB%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E3%83%BB%E6%B7%B1%E5%B1%A4%E5%AD%A6%E7%BF%92%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AE%E3%81%A4%E3%81%8F%E3%82%8A%E6%96%B9-%E3%82%AF%E3%82%B8%E3%83%A9%E9%A3%9B%E8%A1%8C%E6%9C%BA/dp/4802611641) について
章ごとのポイントをまとめていきます。また、サンプルの実行と+αのサンプルを最後に載せています。
今回は2章で、ライブラリ部分を中心に触っていきます。

# 2-1　一番簡単な機械学習を実践しよう
## scikit-learnについて
Python:snake:向けの機械学習フレームワーク

### 特徴
- **様々なアルゴリズム**に対応
- すぐに機械学習を試せる**サンプルデータ**を含んでいる
- PandasやNumpyMatplotlib:bar_chart:等の**親和性**が高い
- **無料**で**商用利用可能**:free:

## AND演算

|入力 X|入力 Y|出力 Z (X and Y) |
|:---:|:---:|:---:|
|0  |0  |0  |
|0  |1  |0  |
|1  |0  |0  |
|1  |1  |1  |


### ゴールの決定
はじめに、どのような機械学習プログラムを作成するか**ゴール**を決める。
今回は次のような、**教師あり学習**の機械学習プログラムを作成する。

- 入力と出力のすべてのパターンを学習させる（上記表より４パターン）
- ４パターンいずれかの入力で正しい出力が返ってくるか評価する

## アルゴリズムの選択
ゴールが決まったので、アルゴリズムを選択していく。
そこで、**「どんなアルゴリズムがあるの？」** :confused:、 **「どんなときに、どのアルゴリズムが最適解なの？」** :astonished:といった ~~（越えられない）~~ 壁が存在する。
そのような場合には、**アルゴリズムチートシート**を参考に決定することができる。

[【機械学習初心者向け】scikit-learn「アルゴリズム・チートシート」の全手法を実装・解説してみた](https://qiita.com/sugulu/items/e3fc39f2e552f2355209)

今回のパターンは・・・
- **カテゴリ**の予測
- **ラベル**を持っている
- データが**１０万より少ない**

以上より、**LinearSVC**というアルゴリズムに決定。


## 実装
以下のコードをJupyter Notebookで実装する。


```python:and_KNeighborsClassifier.ipynb
from sklearn.svm import LinearSVC
from sklearn.metrics import accuracy_score

# input data X,Y
learn_data = [[0,0],[0,1],[1,0],[1,1]]

#Result Label
learn_label = [0, 0, 0, 1]

#Specified algorism（ LinearSVC ）
clf = LinearSVC()

#Learning ( input, label )
clf.fit(learn_data, learn_label)

#test
test_data  = [[0,0],[0,1],[1,0],[1,1]]
test_label = clf.predict(test_data)

#Result

print(test_data , "の予測結果：", test_label)
print("正解率 = " , accuracy_score([0, 0, 0, 1], test_label))
```

Runボタンで結果を確認してみる。

```
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-2-36fc46ae7200> in <module>()
----> 1 from sklearn.svm import LinearSVC
      2 from sklearn.metrics import accuracy_score
      3 
      4 # input data X,Y
      5 learn_data = [[0,0],[0,1],[1,0],[1,1]]

ImportError: No module named 'sklearn'

```
anacondaの仮想環境を作り、そこですぐ実行したため、モジュールがなかったみたい。

そのため、モジュールをインストール

```
pip install scikit-learn
```

そして実行してみる。

```
[[0, 0], [0, 1], [1, 0], [1, 1]] の予測結果： [0 0 0 1]
正解率 =  1.0
```

正解率が1.0のため、LinearSVCアルゴリズムによってAND演算の機械学習を実装できた。

## 改良する

ここで正解率が0.3や0.42などで**優れなかった場合**はどうするか。
その場合は、以下のどちらかのアプローチをとることになる。

- アルゴリズムはそのままで、アルゴリズムに指定する**パラメーターを調整する**
- **アルゴリズムを変更**する

ここでは、アルゴリズムを変更するを選択してみる。
チートシート:scroll:から、LinearSVCがうまくいかない場合に、
いくつか選択肢があり、その中から、**KneighborsClassifier**を試してみる。
変更箇所は上記のプログラムのインポートとアルゴリズムの指定部分のみ。

```python
from sklearn.neighbors import KNeighborsClassifier

#Specified algorism（ KNeighborsClassifier ）
clf = KNeighborsClassifier(n_neighbors = 1)
```

#### 実行結果
```
[[0, 0], [0, 1], [1, 0], [1, 1]] の予測結果： [0 0 0 1]
正解率 =  1.0
```

テストの結果が優れない場合は、**アルゴリズムやパラメーターを調整**していく。
それらは**インポートするパッケージ**や**オブジェクトの生成部分を変更**するだけで、
手軽にアルゴリズムを変更できる。

# 2-2　アヤメの分類に挑戦してみよう

「Fisherのアヤメデータ」と呼ばれる有名な品種分類データを利用して、機械学習に挑戦します。

これから分類するものが、何かというくらいは最低限知っておきましょう。~~（どんな花かぼくはまったく知らなry）~~

[アヤメ](https://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%A4%E3%83%A1)


## アヤメデータのダウンロードと確認
以下URLよりアヤメデータをダウンロードする。

[アヤメデータ（csv）](https://github.com/pandas-dev/pandas/tree/master/pandas/tests/data)

ヘッダー（がく片の長さや花びらの幅）とそれに対するデータがずらっと入っているみたいです。
JupyterNotebook上で確認してみます。

```python:iris.ipynb

import urllib.request as req
import pandas as pd

#　Download File
url = "https://github.com/pandas-dev/pandas/raw/master/pandas/tests/data/iris.csv"
save_file = "iris.csv"
req.urlretrieve(url, save_file)
print("Save successful")

#Open File
csv = pd.read_csv(save_file, encoding="utf-8")
csv

```

このデータを使って教師あり学習を行っていきます。

## アヤメデータを使って機械学習してみる

- 手順
    - データ取り込み
    - **データ部**と**ラベル部**に分離
    - 全データのうち、80％を学習用に、20％をテスト用に**分離**
    - 学習データで学習後、テスト用データを与えた時に、正しく分類するか**評価**

## アルゴリズムの選択

#### SVCアルゴリズム
理由：1回も使ってないから、試しにね。

### 実装

~~~python:and_LinearSVC.ipynb
import urllib.request as req
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score

# Open File
iris_csv = pd.read_csv( "iris.csv" , encoding="utf-8")


# Separation into label and input
y = iris_csv.loc[:,"Name"]
x = iris_csv.loc[:,["SepalLength","SepalWidth","PetalLength","PetalWidth"]]

# Separation into Learning and Test
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, train_size = 0.8, shuffle = True)

# Learning
clf = SVC()
clf.fit(x_train, y_train)

# Evaluation
y_pred = clf.predict(x_test)
print("正解率　= ", accuracy_score(y_test, y_pred))

~~~

#### 実行結果

```
正解率　=  0.9666666666666667
```

## これまでに使用したメソッドの整理
上記ソースコードで使用したメソッドたちを整理しときます。

|分類|ライブラリ|メソッド名|
|:---:|:---:|:---:|
|データ読み込み  |Pandas  |read_csv()  |
|データ分離（列）  |Pandas  |loc()  |
|データ分離（行）  |scikit-learn  |train_test_split()  |
|学習  |scikit-learn  |fit()  |
|予測  |scikit-learn  |predict()  |
|正解率の計算  |scikit-learn  |accuracy_score()  |


# 2-3　AIで美味しいワイン:wine_glass:を判定しよう
ワインの美味しさは、成分を調べるおとで判別できるといわれているそうです。
そこで、ワインの成分からランクを判定するプログラムを作ってみます。:wine_glass:

## ワインデータのダウンロードと確認
機械学習の練習で使えるデータは、「UCI Machine Learning Repository」で多く公開されており、
そこにワインデータもあります。

~~~python:count_wine_data.ipynb
from urllib.request import urlretrieve
import pandas as pd
url = "https://archive.ics.uci.edu"+ \
"/ml/machine-learning-databases/wine-quality" + \
"/winequality-white.csv"
save_file = "winequality-white.csv"
urlretrieve(url, save_file)

df = pd.read_csv(save_file, sep = ";", encoding ="utf-8")
df
~~~

11種類の成分表と、ワイン専門家によるワインの品質データからなっています。
qualityは0~10で10に近いほど品質がいいことを示しています。

## アルゴリズムの決定
#### ランダムフォレスト
理由：1回も使ってないから、試しにね。

### 実装

~~~python:wine_random_forest.ipynb
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
from sklearn.metrics import classification_report

# Read Data
wine = pd.read_csv("winequality-white.csv", sep = ";", encoding = "utf-8")

# Separation into label and input
y = wine["quality"]
x = wine.drop("quality", axis=1)

# Separation into Learning and Test
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2)

# Learning
model = RandomForestClassifier()
model.fit(x_train, y_train)

# Evaluation
y_pred = model.predict(x_test)
print(classification_report(y_test, y_pred))
print("正解率　= ", accuracy_score(y_test, y_pred))

~~~

#### 実行結果

```
precision    recall  f1-score   support

           3       0.00      0.00      0.00         3
           4       0.67      0.29      0.41        34
           5       0.66      0.67      0.66       291
           6       0.63      0.74      0.68       435
           7       0.64      0.50      0.56       174
           8       0.74      0.33      0.46        42
           9       0.00      0.00      0.00         1

   micro avg       0.64      0.64      0.64       980
   macro avg       0.48      0.36      0.40       980
weighted avg       0.64      0.64      0.63       980

正解率　=  0.6408163265306123
```

この値は実行するたびに、**多少変動**する。
それは、データを学習用とテスト用に分割するため、**どのデータを学習したか**によって、**多少の誤差**が生じるから。

プログラムでデータをラベルとデータに分離しているとこがありますが、
ラベル部分は**目的変数**、データ部分は**説明変数**といいます。この用語はよく出てくるので、覚えておきましょう。

## 精度向上に向けて
ワインデータ（入力データ）を可視化し、確認してみます。

### 実装

```python
import matplotlib.pyplot as plt
import pandas as pd

# Read Data
wine = pd.read_csv("winequality-white.csv", sep=";", encoding ="utf-8")

# Count Data
count_data = wine.groupby('quality')["quality"].count()
print(count_data)

# Draw Graph
count_data.plot()
plt.savefig("wine-count-plt.png")
plt.show()
```
![wine-count-plt.png](https://qiita-image-store.s3.amazonaws.com/0/295868/c6fe7864-1537-e328-2783-e3802b9b3a57.png)


このような感じで、簡単にデータをグラフ:chart_with_upwards_trend:にプロットすることができます。

このデータは3～9の範囲で値をとっており、**2以下と10**は存在しません。
このような、データ数の分布数の差があるデータを**不均衡データ**といいます。

そのため、ラベルを3段階に振り直してみます。

- ラベルの振り直し
    - 4以下
    - 5～7
    - 8以上


## 再実装

```python
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
from sklearn.metrics import classification_report

# Read Data
wine = pd.read_csv("winequality-white.csv", sep = ";", encoding = "utf-8")

# Separation into label and input
y = wine["quality"]
x = wine.drop("quality", axis=1)

# Renumber the label
newlist = []
for i in list(y):
    if i <= 4:
        newlist += [0]
    elif i <=7:
        newlist += [1]
    else:
        newlist += [2]
        
y = newlist

# Separation into Learning and Test
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2)

# Learning
model = RandomForestClassifier()

model.fit(x_train, y_train)

# Evaluation
y_pred = model.predict(x_test)
print(classification_report(y_test, y_pred))
print("正解率　= ", accuracy_score(y_test, y_pred))

```

#### 実行結果

```
 precision    recall  f1-score   support

           0       0.64      0.25      0.36        36
           1       0.95      0.99      0.97       907
           2       0.94      0.41      0.57        37

   micro avg       0.94      0.94      0.94       980
   macro avg       0.84      0.55      0.63       980
weighted avg       0.94      0.94      0.93       980

正解率　=  0.9438775510204082
```
ラベルの分類を減らすことで精度を向上させることができました。

## MEMO
**どんなデータ**を**どのように分類しようと**しているのか調べて、ちょっとデータを**変形・整形**することで
精度を向上させることができることがわかりました。

## COLUMN
**ランダムフォレストについて:deciduous_tree:**

ランダムフォレストは**複数の分類器**を用いて性能を向上させる**アンサンブル学習法**の一つです。
学習用のデータをサンプリングして**多数の決定木**を作成し、作成した決定木をもとに
多数決で結果を決める手法から、「ランダムフォレスト」と呼ばれています。

# 2-4　過去10年間の気象データを解析してみよう
気象庁のアメダスデータから、データの解析と明日の気温予測に挑戦します。:sunny::umbrella::cloud:

### データの取得
> 過去の気象データ
> 
> https://www.data.jma.go.jp/gmd/risk/obsdl/index.php

ここから、大阪の10年分の平均気温を取得します。
**取得期間：2007/1/1～2017/12/31**

不要なヘッダーを削除し、（1,2,3,5行）
日付を、年・月・日に分解し、新たなcsvファイルを作ります。

```python:csv_trim_header.ipynb
input_file = "osaka_data.csv"
output_file = "temperature_10years.csv"

# Read line
with open(input_file, "rt", encoding="Shift_JIS") as fr:
    lines = fr.readlines()
# New header
lines = ["年,月,日,気温,品質,均質\n"] + lines[5:]
lines = map(lambda v: v.replace('/', ','), lines)
result = "".join(lines).strip()
print(result)

# Output
with open(output_file, "wt", encoding="utf-8") as fw:
    fw.write(result)
    print("saved.")
```

## 各月の平均気温を調べてみる
まずは、データを見ることからはじめます。

### 実装

```python:ave_10years.ipynb
import matplotlib.pyplot as plt
#import matplotlib
import pandas as pd

# Read file
df = pd.read_csv("temperature_10years.csv", encoding ="utf-8")

# Average of Month
group = df.groupby(['月'])["気温"]
ave_group =group.sum() / group.count()

#Output Result
print(ave_group)
ave_group.plot()
plt.savefig("average_month_temperature.png")
plt.show()
#print(matplotlib.rcParams['font.family'])
#print(matplotlib.matplotlib_fname())
#print(matplotlib.get_configdir())
```

コメントアウトしている行はグラフの軸ラベルが文字化けしたため（□←こんなやつに）
解決するために、使用したコードです。

文字化けの解決に参考にしたサイト
[matplotlib出力画像の文字化け解消法](https://qiita.com/dodo5522/items/7f9b390698f0322bf224)

#### 実行結果

```
月
1      5.996736
2      6.708682
3      9.837537
4     15.024848
5     20.090323
6     23.526364
7     27.775953
8     29.103226
9     25.138485
10    19.594135
11    13.619394
12     8.375660
Name: 気温, dtype: float64

```

![average_month_temperature.png](https://qiita-image-store.s3.amazonaws.com/0/295868/0ba62884-606e-9e81-0c3c-5ea2f566ec5c.png)


## 真夏日の日数を調べてみる　-Pandasでフィルタリング-

同様の手法を用いて、真夏日（平均気温が30度以上）の日が、各年に何回あったのか調べてみます。

### 実装

```python:hot_day.ipynb
import matplotlib.pyplot as plt
import pandas as pd

# Read File
df =pd.read_csv("temperature_10years.csv", encoding = "utf-8")

#Research Data over 30
is_hot = (df["気温"]  > 30)

#Fill Data
hot_data = df[is_hot]

# Count
count_data = hot_data.groupby(["年"])["年"].count()
#Output
print(count_data)
count_data.plot()
plt.savefig("over30.png")
plt.show()
```
#### 実行結果

```
年
2007    14
2008    17
2009     1
2010    38
2011    13
2012     9
2013    21
2014     7
2015    13
2016    14
2017    16
Name: 年, dtype: int64

```
![over30.png](https://qiita-image-store.s3.amazonaws.com/0/295868/74968e8b-d892-6929-a331-1dfee373156f.png)


## 回帰分析による明日の気温予測

本題の予測に入っていきます。
2016年までのデータを学習データとし、2017年をテストデータとします。

**7日間の過去データ**を入れると、**翌日の気温を予測する**プログラムです。

### 実装

```python:temperature_regression_analysis.ipynb
from sklearn.linear_model import LinearRegression
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# Read File
df =pd.read_csv("temperature_10years.csv", encoding = "utf-8")

# Split Data
train_years = (df["年"] <= 2016)
test_year = (df["年"]>=2017)
interval = 7

#Learning Data
def make_data(data):
    x = [] #Learning Data
    y = [] # Result
    temps = list(data["気温"])
    for i in range(len(temps)):
        if i <= interval: continue
        y.append(temps[i])
        xa = []
        for j in range(interval):
            d = ( i + j ) - interval
            xa.append(temps[d])
        x.append(xa)
    return (x, y)

train_x, train_y = make_data(df[train_years])
test_x, test_y = make_data(df[test_year])

#Linear regression analysis
lr = LinearRegression(normalize=True)
lr.fit(train_x, train_y)
pre_y = lr.predict(test_x)

#Output
plt.figure(figsize=(10, 6), dpi=100)
plt.plot(test_y)
plt.plot(pre_y,linestyle="dashed")
plt.savefig("LinearRegression.png")
plt.show()
```

#### 実行結果

![LinearRegression.png](https://qiita-image-store.s3.amazonaws.com/0/295868/473dddb2-4843-dda0-b9bd-234621cce8f3.png)
**青色が実測**のデータで、**オレンジの破線が予測値**です。
いい感じに重なっているので、誤差の確認をしてみます。


## 結果の評価

下記コードを新規セルに入力し、全体の誤差と最大誤差を確認する。

```python
diff_y = abs(pre_y - test_y)
print("average = ", sum(diff_y) / len(diff_y))
print("max = ",max(diff_y))
```

```
average =  1.2037169855638823
max =  5.204742626546912
```

### Points
ここで、**過去7日間のデータを説明変数x**とし、
**翌日の気温を目的変数y**としました。
ここの目的変数を、**別の要素**に指定するなら、**様々な予測プログラムに応用**することができます。

# 2-5　最適なアルゴリズムやパラメーターを見つけよう
2-2のアヤメデータの分類では、SVCアルゴリズムを用いたが、**「①他にもっと高い正解率を出せるアルゴリズムがあるんじゃないの？」:open_mouth:**
**「②データの学習方法をいろんなパターンでやっても安定した結果を得られるの？」:open_mouth:**といったことが気になるところ。
そこで、この2つについては次のような解決策があります。

- **解決策**
    - ①について・・・各アルゴリズムの正解率を比較する
    - ②について・・・クロスバリデーション


## ① 最適なアルゴリズムを見つける -各アルゴリズムの正解率を比較-

```python:all_algorithm.ipynb
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import warnings
from sklearn.utils.testing import all_estimators
# Open File
iris_csv = pd.read_csv( "iris.csv" , encoding="utf-8")

# Separation into label and input
y = iris_csv.loc[:,"Name"]
x = iris_csv.loc[:,["SepalLength","SepalWidth","PetalLength","PetalWidth"]]

# Separation into Learning and Test
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, train_size = 0.8, shuffle = True)

# Get All Algorith
warnings.filterwarnings('ignore')
allAlgorithms = all_estimators(type_filter ="classifier")

for(name, algorithm) in allAlgorithms:
    #Create Object
    clf = algorithm()   
    #Learning and Evaluation
    clf.fit(x_train, y_train)
    y_pred = clf.predict(x_test)
    print(name,"の正解率 = ", accuracy_score(y_test, y_pred))
```

実行時にFutureWarning（将来変更される予定であることを示す警告）などの警告が表示されるため、
結果を見やすくするために、**非表示**にしています。

```
AdaBoostClassifier の正解率 =  1.0
BaggingClassifier の正解率 =  1.0
BernoulliNB の正解率 =  0.3
CalibratedClassifierCV の正解率 =  0.9666666666666667
ComplementNB の正解率 =  0.6666666666666666
DecisionTreeClassifier の正解率 =  0.9666666666666667
ExtraTreeClassifier の正解率 =  1.0
ExtraTreesClassifier の正解率 =  1.0
GaussianNB の正解率 =  1.0
GaussianProcessClassifier の正解率 =  0.9666666666666667
GradientBoostingClassifier の正解率 =  1.0
KNeighborsClassifier の正解率 =  1.0
LabelPropagation の正解率 =  1.0
LabelSpreading の正解率 =  1.0
LinearDiscriminantAnalysis の正解率 =  1.0
LinearSVC の正解率 =  1.0
LogisticRegression の正解率 =  1.0
LogisticRegressionCV の正解率 =  0.9666666666666667
MLPClassifier の正解率 =  1.0
MultinomialNB の正解率 =  1.0
NearestCentroid の正解率 =  0.9666666666666667
NuSVC の正解率 =  0.9666666666666667
PassiveAggressiveClassifier の正解率 =  0.7666666666666667
Perceptron の正解率 =  0.3333333333333333
QuadraticDiscriminantAnalysis の正解率 =  1.0
RadiusNeighborsClassifier の正解率 =  0.9666666666666667
RandomForestClassifier の正解率 =  1.0
RidgeClassifier の正解率 =  0.9666666666666667
RidgeClassifierCV の正解率 =  0.9666666666666667
SGDClassifier の正解率 =  0.6666666666666666
SVC の正解率 =  1.0
```

## クロスバリデーションについて
複数のデータパターンで評価した場合でも、**安定した結果**を得られるにはどうすればいいか。
という時に**クロスバリデーション（cross-validation）**を利用することができる。
クロスバリデーションはアルゴリズムの妥当性を評価する手法の一つで、**「交差検証」**とも呼ばれています。
クロスバリデーションにもいくつか手法があるが、ここでは
**k分割クロスバリデーション**により、評価してみる。

> K-分割交差検証
> K-分割交差検証では、標本群をK個に分割する。そして、そのうちの1つをテスト事例とし、残る K − 1 個を訓練事例とするのが一般的である。
> https://ja.wikipedia.org/wiki/%E4%BA%A4%E5%B7%AE%E6%A4%9C%E8%A8%BC

- **k分割クロスバリデーションの手順例**
    - データをA・B・Cの3グループに分割する
    - AとBを学習用データ、Cを評価用データとして、正解率を求める
    - BとCを学習用データ、Aを評価用データとして、正解率を求める
    - CとAを学習用データ、Bを評価用データとして、正解率を求める

### 実装

```python:k-fold_cross_validation.ipynb
import pandas as pd
from sklearn.utils.testing import all_estimators
from sklearn.model_selection import KFold
import warnings
from sklearn.model_selection import cross_val_score

# Open File
iris_csv = pd.read_csv( "iris.csv" , encoding="utf-8")

# Separation into label and input
y = iris_csv.loc[:,"Name"]
x = iris_csv.loc[:,["SepalLength","SepalWidth","PetalLength","PetalWidth"]]

# Get All Algorith
warnings.filterwarnings('ignore')
allAlgorithms = all_estimators(type_filter ="classifier")

#K-fold cross validation
kfold_cv = KFold(n_splits=5, shuffle=True)

for(name, algorithm) in allAlgorithms:
    # Create Object
    clf = algorithm()   
    # score method only
    if hasattr(clf,"score"):
        #cross validation
        scores = cross_val_score(clf, x, y, cv=kfold_cv)
        print(name, "の正解率= ")
        print(scores)
```

#### 実行結果

```
AdaBoostClassifier の正解率= 
[0.96666667 0.9        0.93333333 0.93333333 1.        ]
BaggingClassifier の正解率= 
[0.9        1.         1.         0.86666667 1.        ]
BernoulliNB の正解率= 
[0.2        0.23333333 0.26666667 0.23333333 0.3       ]
CalibratedClassifierCV の正解率= 
[0.93333333 0.83333333 0.96666667 0.93333333 0.96666667]
ComplementNB の正解率= 
[0.7        0.73333333 0.56666667 0.66666667 0.66666667]
・・・
```
クロスバリデーションを行うには、**score()メソッドを持っていることが前提**のため、
その確認が必須となる。

## 最適なパラメータを見つける
これまでは、アルゴリズムのパラメータをデフォルトにしてきたが、
それぞれ設定することができる。
そのようなパラメータは**ハイパーパラメータ**と呼ばれ、
**グリッドサーチ**という手法により、最適なパラメータを探してみる。

### グリッドサーチについて

グリッドサーチは、ハイパーパラメータのチューニング手法の一つで、**指定したパラメータの全パターン**について、正解率を比較する手法です。

### 実装

```python:grid_search.ipynb
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score
from sklearn.model_selection import KFold
from sklearn.model_selection import GridSearchCV

# Open File
iris_csv = pd.read_csv( "iris.csv" , encoding="utf-8")

# Separation into label and input
y = iris_csv.loc[:,"Name"]
x = iris_csv.loc[:,["SepalLength","SepalWidth","PetalLength","PetalWidth"]]


# Separation into Learning and Test
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, 
                                                    train_size = 0.8, shuffle = True)

# Specified Parameter
parameters = [
    {"C":[1, 10, 100, 1000], "kernel":["linear"]},
    {"C":[1, 10, 100, 1000], "kernel":["rbf"], "gamma":[0.001, 0.0001]},
    {"C":[1, 10, 100, 1000], "kernel":["sigmoid"], "gamma":[0.001, 0.0001]}
]

#Grid Search
kfold_cv = KFold(n_splits=5, shuffle=True)
clf = GridSearchCV(SVC(), parameters, cv = kfold_cv)
clf.fit(x_train, y_train)
print("最適なパラメータ = ", clf.best_estimator_)

# Elevation
y_pred = clf.predict(x_test)
print("評価時の正解率 = ", accuracy_score(y_test, y_pred))
```

#### 実行結果

```
最適なパラメータ =  SVC(C=1, cache_size=200, class_weight=None, coef0=0.0,
  decision_function_shape='ovr', degree=3, gamma='auto_deprecated',
  kernel='linear', max_iter=-1, probability=False, random_state=None,
  shrinking=True, tol=0.001, verbose=False)
評価時の正解率 =  1.0
```
何回か実行すると　1.0　になりました。
これにより、**最適なパラメータ**と、**そのパラメータを用いた場合の結果**が表示されました。

これのほか、ハイパーパラメータのチューニングには、**ランダムサーチ**という手法がある。
scikit-learnでは、GridSearchCVを**RandomizedSearchCV**オブジェクトに変えることで、ランダムサーチになる。


# まとめ
この章では**アルゴリズムの選択に、チートシートを使うこと**を学んだ。
また、分類したいといった目的があった時に、**様々なアルゴリズム**を使用して予測できることがわかった。
そして、**グラフの描画方法**や**最適なアルゴリズムの選択方法**も学んだ。

**Next:running:**

次章は、OpenCVを用いた**画像や動画の分析**に入っていきます。

# +α

全章投稿後に、復習をかねて実装予定