[機械学習] 分類問題をサクッと30分程度で試したい人向け。

# 初めに

機械学習にちょっと興味のあるという人向けに、30分程度で実装出来ればと思います。
それぞれのアルゴリズムについては少ししか説明しないので、詳しく知りたい方は、分かりやすくまとまっている記事のリンクを適宜貼っておきますので、そちらを参照してください。
また、今回取り扱うのはスパムフィルタ判定や花の種類を判定する<b>分類問題</b>になります。

曖昧な部分もありますのでご了承ください。誤っている箇所があればご指摘いただけますと幸いですm(__)m
※ 編集リク投げてくださった方、ありがとうございます。


## 機械学習とは。

※何となくわかってる方は読み飛ばして頂いて問題ないです。

<b>機械学習とは、学習データからデータの傾向を読み取り、未知のデータに対応することです。</b>

機械学習は大きく3つに分けることが出来ます。

1,<b>教師あり学習</b>
2,教師なし学習
3,強化学習

教師あり学習とは、データに付随する正解ラベルを用いた学習です。詳しくはこの後説明します。
教師なし学習とは、与えられたデータの隠れた構造を見つけ出す事です。正解ラベルが存在しない故に、正解や不正解が存在せず、人間的な解釈が必要な場面が多いです。レコメンド機能等で用いられます。
強化学習とは、ある環境の中で探索的に行動し、より良い結果(報酬)を得られるように学習することです。赤ちゃんが自分のおかれている環境から試行錯誤して歩けるようになるというイメージです。


ちょっとややこしいですね。
この辺の違いは、はじめの内はわかりにくいですが、やっていくうちに何となくわかってくると思います。
詳しく学びたい方は[Aidemy](https://aidemy.net)の「機械学習概論」(無料)をやると整理出来るかもしれません。

さて、教師あり学習についてですが、更に2つに分かれます。

1,回帰問題
2,<b>分類問題</b>

回帰問題とは、部屋の広さから家賃を予測したり株価を予測したりすることです。予測したい値(目的変数)が連続値である場合がこれに該当します。
分類問題とは、迷惑メールか普通のメールか判定することです。つまりは0か1かラベルを予測することになります(二項分類)。また、3つ以上分類(多項分類)することも可能です。

## すること。

![アヤメ](http://newtechnologylifestyle.net/wp-content/uploads/2018/02/%E3%82%A2%E3%83%A4%E3%83%A1.jpg "アヤメの種類")
参考：[初心者のためのAI人工知能テクノロジーブログ　AI人工知能テクノロジー](http://newtechnologylifestyle.net/tensorflow-keras%E3%81%A7%E3%81%AE%E6%95%99%E5%B8%AB%E3%81%82%E3%82%8A%E5%AD%A6%E7%BF%92%e3%80%80-%E3%82%A2%E3%83%A4%E3%83%A1%E3%81%AE%E5%88%86%E9%A1%9E/)

これらアヤメの3種類にそれぞれ
・がくの長さ (Sepal Length)
・がくの幅 (Sepal Width)
・花びらの長さ (Petal Length)
・花びらの幅 (Petal Width)
の合計4つの特徴量がセットになった150個のデータがあります。

そして未知の4つの特徴量が与えられたときに、それがアヤメの3種類の内どれに該当するのか当てていきましょう。

具体的なイメージが沸きにくいと思いますので↓

|特徴  |cm  |
|---|---|
|がくの長さ (Sepal Length)  |5.2  |
|がくの幅 (Sepal Width) |3.0  |
|花びらの長さ (Petal Length) |1.5  |
|花びらの幅 (Petal Width) |0.6  |

最終的に、この特徴を持ったアヤメがどれに該当するか予測しましょう。

## 必要なモノ
・Googleアカウント

# まずは、実行環境

## Google colabを開く
[Google colab](https://colab.research.google.com/)

「Python３の新しいノートブック」をクリック。

以上です。
Googleアカウントを持っていれば10秒で出来ると思います。

## GPU/TPU
また、今回は大きいデータを扱わないのでGPU/TPUは必要ないですが、
「ランタイム」
↓
「ランタイムのタイプを変更」
↓
「ハードウェア アクセラレータ」からGPU/TPUに切り替えて「保存」で使えます。

此方が参考になります。
[【秒速で無料GPUを使う】TensorfFow/Keras/PyTorch/Chainer環境構築 on Colaboratory](https://qiita.com/tomo_makes/items/f70fe48c428d3a61e131)


## コーディング



前置きが少々長くなってしまいましたが、早速コーディングしていきましょう。

まず以下のモジュールは共通で使いますので、実行しておいてください。

```python
# データ加工・処理・分析モジュール
import numpy as np
import numpy.random as random
import scipy as sp
import pandas as pd
from pandas import Series, DataFrame
```

次にアヤメのデータを読み込んで、データを分割します。

```python
# 学習用データとテストデータに分けるためのモジュール（正解率を出すため）
from sklearn.model_selection import train_test_split
# アヤメの花(学習するデータ)
from sklearn.datasets import load_iris

# アヤメの花データ(150個)
iris = load_iris()
# irisをDataFrameで扱う。
df = pd.DataFrame(iris.data, columns=iris.feature_names)
# アヤメの種別(ラベル)を追加
df["target"] = iris.target_names[iris.target]

# 引数で表示数を変更できます。defaultは5
df.head()
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/0705d19d-953c-cb1c-28d0-ec37a0b0432a.png)

全て実行すると上記のように出力されると思います。

最初でも説明しましたが、

|column  |意味  |
|---|---|
|Sepal Length  |がくの長さ   |
|Sepal Width |がくの幅  |
|Petal Length |花びらの長さ  |
|Petal Width |花びらの幅  |
|target |アヤメの種類  |
を表しています。

ここから更に、学習モデルに通すために特徴量データとラベルデータの2つに分けたいと思います。
また正解率を知るために学習用データとテスト用データに分けています。

```python
# 説明変数X(特徴量4つ×150)と目的変数Y(アヤメの種類×150)に分ける
X = df.drop('target', axis=1)
Y = df['target']

#ここから学習用データとテスト用データに分ける。random_stateは乱数を固定
X_train, X_test, y_train, y_test = train_test_split(X, Y, random_state=0)
```

前準備はこれで終了です。実際のデータを用いると、この前準備に8割近く時間を取られます。
データの準備が出来たので、機械学習していきます。以下がメニューです。

・k-近傍法（k-NN）
・決定木
・サポートベクターマシン（SVM）
・ロジスティック回帰

全ての手法を試さず、どれか1つでも問題ないです。
k-近傍法(k-NN)が理論的に一番理解しやすいかと思われます。


# k-近傍法（k-NN）
k-近傍法（k-NN）とは、新しいデータが入力された時に、それに最も近いk個のデータのラベルで多数決を取り、多い方に分類されます。
下図ですと、赤点が新しいデータになります。そしてそのデータに最も近いデータ３個で多数決を取り、青1:緑2で緑に分類されるわけです。
kの値によって結果も異なります。その例としてkの値を7にした場合、青4:緑:3になり青に分類されます。ですので最適なkをループにかけて求めてあげる必要があるのですが、今回は省略します。

![k-近傍法（k-NN）](http://www.nag-j.co.jp/nagdmc/img/knn.gif "k-近傍法（k-NN）")

[K近傍法(多クラス分類)](https://qiita.com/yshi12/items/26771139672d40a0be32)（もう少し詳しく知りたい方）

```python
# k-近傍法（k-NN）
from sklearn.neighbors import KNeighborsClassifier

#k-NNインスタンス。今回は3個で多数決。3の値を変更して色々試すと〇
model = KNeighborsClassifier(n_neighbors=3)
#学習モデル構築。引数に訓練データの特徴量と、それに対応したラベル
model.fit(X_train, y_train)

# .scoreで正解率を算出。
print("train score:",model.score(X_train,y_train))
print("test score:",model.score(X_test,y_test))
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/62a0c38b-1992-7906-cb4a-87de0e7a0655.png)

実行すると、こんな感じでスコアが出ると思います。テストデータでは97%正解しています。

では、以下のデータがアヤメのどの種類に該当されるか確認しましょう。

|特徴  |cm  |
|---|---|
|がくの長さ (Sepal Length)  |5.2  |
|がくの幅 (Sepal Width) |3.0  |
|花びらの長さ (Petal Length) |1.5  |
|花びらの幅 (Petal Width) |0.6  |

```python
# 上記データ
data = [[5.2, 3.0, 1.5, 0.6]]

# 構築したモデルからアヤメの種類を求める
model.predict(data)
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/3a1ccb05-a435-058a-3f0c-bb0cc035d183.png)

結果がでました。どうやらヒオウギアヤメ(setosa)と予測できたようです。

# 決定木

決定木とは、YES/NOでこたえられる質問で構成された階層的な木構造を学習します。
ですので今回のアヤメの例ですと、がくの長さは6.0cm以上かYES/NOといった具合に質問を繰り返す木を成形し、最終的に葉に辿り着き、どのアヤメの種類か判定することになります。

以下が非常にわかりやすいです。
[[入門]初心者の初心者による初心者のための決定木分析](https://qiita.com/3000manJPY/items/ef7495960f472ec14377)

```python
# 決定木
from sklearn.tree import DecisionTreeClassifier

# 決定木インスタンス(木の深さ3)
model = DecisionTreeClassifier(max_depth=3)
#学習モデル構築。引数に訓練データの特徴量と、それに対応したラベル
model.fit(X_train, y_train)

# .scoreで正解率を算出。
print("train score:",model.score(X_train,y_train))
print("test score:",model.score(X_test,y_test))
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/c07fc190-dff4-3bfb-cd8e-03caf1c66429.png)

こちらも正解率97%です。

データを与えて予想結果も確認してみます。

```python
# 予測したいデータ
data = [[5.2, 3.0, 1.5, 0.6]]

# 構築したモデルからアヤメの種類を求める
model.predict(data)
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/bb1b870a-3b99-f4b3-e7aa-ba7faf7dee04.png)

こちらも同じく、ヒオウギアヤメ(setosa)と予測されました。

決定木を応用した、ランダムフォレストというものもあり、更に勾配ブースティング回帰木（xgboost）といったものもあります。kaggle(データコンペ)で多く使われている手法です。

# サポートベクターマシン（SVM）
サポートベクターマシン（SVM）とは、クラス(ラベル)の集合間の境界に位置する一部のデータ(サポートベクタ)を基準として、距離(マージン)が最も大きくなるように境界線を引くことです。

![サポートベクターマシン（SVM）](http://www.jepoc.or.jp/upload/lib_data/120513120351.jpg "サポートベクターマシン（SVM）")

以下が非常にわかりやすいです。
[SVM（多クラス分類）](https://qiita.com/yshi12/items/668e699ed70906f9868b)

```python
# サポートベクターマシン（SVM）
from sklearn.svm import LinearSVC

# SVMインスタンス
model = LinearSVC()
#学習モデル構築。引数に訓練データの特徴量と、それに対応したラベル
model.fit(X_train, y_train)

# .scoreで正解率を算出。
print("train score:",model.score(X_train,y_train))
print("test score:",model.score(X_test,y_test))
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/32f246f1-5c8e-4e84-cf48-cc54ca1aff87.png)

正解率97%です。

データを与えて予想結果も確認してみます。

```python
# 予測したいデータ
data = [[5.2, 3.0, 1.5, 0.6]]

# 構築したモデルからアヤメの種類を求める
model.predict(data)
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/52bbe248-3b36-aed7-fdee-e787cf464d5a.png)

ヒオウギアヤメ(setosa)と予測されました。

# ロジスティック回帰
ロジスティック回帰とは、どのクラスに属すかの確立を計算するアプローチになります。
回帰という名前ですが、分類問題を考えるときに使うので注意です。また、多重共線性といって同じような特徴量(相関の強い)を与えても、かえってモデルが不安定になります。(キャラ被りは良くないらしい。)
言葉で説明するのが難しいので、参考に丸投げします。m(__)m

↓参考
[ロジスティック回帰分析](http://www.ner.takushoku-u.ac.jp/masano/class_material/waseda/keiryo/15_logit.html)
[ロジスティック回帰](https://qiita.com/yshi12/items/3dbd336bd9ff7a426ce9)

```python
# ロジスティック回帰
from sklearn.linear_model import LogisticRegression

# ロジスティック回帰インスタンス
model = LogisticRegression()
#学習モデル構築。引数に訓練データの特徴量と、それに対応したラベル
model.fit(X_train, y_train)

# .scoreで正解率を算出。
print("train score:",model.score(X_train,y_train))
print("test score:",model.score(X_test,y_test))
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/aaa13967-20b5-11b5-d32a-16476b211661.png)

正解率94%です。

データを与えて予想結果も確認してみます。

```python
# 予測したいデータ
data = [[5.2, 3.0, 1.5, 0.6]]

# 構築したモデルからアヤメの種類を求める
model.predict(data)
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/52bbe248-3b36-aed7-fdee-e787cf464d5a.png)

ヒオウギアヤメ(setosa)と予測されました。

# まとめ

どうやら

|特徴  |cm  |
|---|---|
|がくの長さ (Sepal Length)  |5.2  |
|がくの幅 (Sepal Width) |3.0  |
|花びらの長さ (Petal Length) |1.5  |
|花びらの幅 (Petal Width) |0.6  |

は、ヒオウギアヤメ(setosa)といって間違いないでしょう。
もし余裕があれば値を変えて試してみてください。

このように、機械学習モデルがsklearn(ライブラリ)で提供されているので簡単に実装することができます。
ただ、アルゴリズムを理解できていないと、各手法の選定やハイパーパラメータ(今回はやってない)を上手く設定することができないので注意です。

詳しくやりたい方は以下をおすすめします。
[Cousera Machine Learning](https://www.coursera.org/learn/machine-learning)
[GCIデータサイエンティスト育成講座演習コンテンツ 公開ページ](https://weblab.t.u-tokyo.ac.jp/gci_contents/)
どちらも無料です。


以上になります、ここまで読んで頂きありがとうございましたm(__)m