初心者挑戦　まずirisでデータ分類やってみた

***
![見出し１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2400825/3a60b7d7-8444-59b7-3687-1a111f5ed6d2.png)

#はじめに

今回成果物を提出にするにあたりscikit-learnライブラリにあるモデルの評価用データセットIrisを使いロジスティック回帰を用いて分類してみます。

##実行環境
・Python ver3
・Google Colaboratory

##使用するデータセットIrisについて
irisデータとは150個のアヤメ(花の一種)のサンプルの「がく片の長さ」「がく片の幅」「花びらの長さ」「花びらの幅」の４つの特徴量(単位はcm)と、3種の品種(0~2)が格納されています。今回は、データの可視化のために特徴量を「がくの長さ」「花びらの長さ」の２つを使用します。

実際にデータをダウンロードし一部を表示してみます。

```python
from sklearn import datasets
iris = datasets.load_iris()
print(iris)
```

from sklearn import datasetsでsklearnライブラリをインポートし
iris = datasets.load_iris()
print(iris)　でirisデータを打ち出してみます。


![iris.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2400825/cb21c896-941e-44ae-5e53-870f932435f4.png)
4つの特徴データが入っていることがわかります。

##使用する分類モデル【ロジスティック回帰】
今回使用するロジスティック回帰は、線形分離可能なデータの境界線を学習によって見つけて、データの分類を行うモデルです。特徴としては、境界線が直線になります。そのため、二項分類などクラスの少ないデータに使われます。

欠点としては、以下があげられます。
・データが線形分離可能でないと分類ができない点
・⾼次元の疎なデータ(0が多いデータ)には適さない点
・訓練データから学習した境界線がデータの近くを通るため、汎化能力が低い点

今回は３品種、２データと種類の少ないデータになりますのでデータの分布状況を俯瞰、把握するのには適したモデルといえます。実際にデータの分布・分類を行ったグラフが以下のもです。![資料１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2400825/e5fc1490-b828-7cbc-ebfd-575d91480580.png)

今回はハイパーパラメータがデフォルト値のものを作成し、そのあと調整を行い違いを見てみたいと思います。
※**ハイパーパラメータ**
　機械学習のモデルが持つパラメーターの中で人が調整をしないといけないパラメーター

##実際にコードを書く
下記のように計算ライブラリ（numpy)、データを可視化するためライブラリ（matlotlib）そして人工知能ライブラリ（sklearn）をインポートします。

```python
import numpy as np
from sklearn import datasets
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import f1_score
import matplotlib
import matplotlib.pyplot as plt
```

次にirisのデータを取得し、得たデータから「がくの長さ」「花びらの長さ」の特徴量を変数Xに格納します。また変数Yにはirisのクラスラベルを格納します。

```python
iris = datasets.load_iris()
X = iris.data[:, [0, 2]]
y = iris.target
```
モデルで学習さるため格納したデータを学習用７０％、学習後モデルテスト用３０％に分けます。

```python
# trainデータ、testデータの分割
train_X, test_X, train_y, test_y = train_test_split(
    X, y, test_size=0.3, random_state=42)
```

学習モデルロジスティック回帰を定義します。

```python
model = LogisticRegression()
```

モデルにデータを学習させます。

```python
model.fit(train_X, train_y)
```
出来たモデルにテスト用データで分類予測させ出力してみます。

```python
Y = model.predict(test_X)
print(Y)
```
【テスト結果】
判定された品種が[0,1,2]で表現されます。

[1 0 2 1 1 0 1 2 1 1 2 0 0 0 0 1 2 1 1 2 0 2 0 2 2 2 2 2 0 0 0 0 1 0 0 2 1
 0 0 0 2 1 1 0 0]

ここで作製したモデルを精度評価指標であるF値で計測してみます。
結果は後述で紹介します。

```python
A  = f1_score(test_y, Y, average="micro")
```
※F値は次のように定義されます。
ざっくりとした意味で再現率と適合率のバランスを表現しています。



```math

\
F=\frac{2Recall・Precision}{Recall+Precision}\

```


Recall（再現率）とPrecision（適合率）については、以下のような考え方です。
・再現率 (recall, 感度, sensitivity)：実際に正であるもののうち，正であると予測されたものの割合
・適合率 (precision)：正と予測したデータのうち，実際に正であるものの割合

***
次にハイパーパラメータをグリッドサーチを使い調整してみます。





グリッドサーチ用にモデルとパラメーターセットをまとめた辞書を用意し辞書のkeyにはオブジェクトのインスタンスを指定します。

```python
model_param_set_grid = {LogisticRegression(): { "C": [10 ** i for i in range(-5, 5)],
        "random_state": [42] }}
```

スコア比較用に変数を用意します。

```python
max_score = 0
best_model = None
best_param = None
```

 グリッドサーチでパラメーターサーチを行います。

```python
for model, param in model_param_set_grid.items():
    clf = GridSearchCV(model, param)
    clf.fit(train_X, train_y)
    pred_y = clf.predict(test_X)
    score = f1_score(test_y, pred_y, average="micro")
```

最高評価更新時にパラメーターを更新します

```python
    if max_score < score:
        max_score = score
        best_model = model.__class__.__name__
        best_param = clf.best_params_
```
最後に結果を出力します。

```python
print(" ")
print("【調整後】")
print("学習モデル:{},\nパラメーター:{}".format(best_model, best_param))
# 最も成績のいいスコアを出力
print("調整済みF値:",max_score)
```

結果は以下のよう出力が得られます。
![資料３.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2400825/cd2771cf-0759-bbdc-4f55-f5d04a946ad8.png)
最適化されたハイパーパラメータが{'C': 100, 'random_state': 42}となりF値が調整前１から0.97に代わっていることがわかります。

F値はトレードオフ関係にある適合率と再現率を調整しており適合率が高まれば、再現率は低くなり…逆もまた然りです。そのためこの値以上ならOK！という明確な目安はありませんが、値の範囲としては0から1の間に収まります。ですので今回のこの数字の変化意味は実際のデータと見比べて再度考える必要があると考えます。


結局モデルやライブラリーは計算を行い目安を提示してくれますが最後の判断は人間が目的にあわせて変数・式を調整・決めていくのだなと感じた結果でした。

今後はさらにモデルの比較等を行ってみたいと思います。
***