0から始める機械学習プログラミング

## 0.前提
機械学習のプログラミングについて環境構築から実際に動くものを作るまでの作業を纏めていきます。
### 対象読者
- 機械学習の概要は知っているので実践してみたい人。(主に教師あり学習の話がメインです。)  
そもそも機械学習って何？？って人は一旦他の方の記事や書籍で概要だけでも掴んでから読んでもらえるといいかなと思います。
- Pythonをある程度知っている人
作者はPython初心者ですが、Pythonの書き方を細かく解説する予定はないのでPythonを全然知らないという方は他のサイトや本で基本を学んだ上で読んでもらえればと思います。
ただ、そんなに難しい処理を書くわけではないのでPython触ったことなくても他のプログラミング言語を触ったことがあるなら感覚的に理解できると思います。  

### このページでやること
機械学習は大きく分けると以下のステップがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162114/2227261a-4122-e05b-4734-00d8a3c632ec.png)
今回紹介するのは上の図の青色の部分です。

## 1.環境構築
では早速環境構築から始めていきましょう。
今回作成する開発環境は以下の構成です。
- 言語：Python
- 開発・実行環境：Jupyter Notebook

### 1-1.Pythonの導入
PowerShellを立ち上げて以下のコマンドを入力してください。

```PowerShell:
python -m pip install -U pip
```
### 1-2.各ライブラリのインストール
複数のライブラリをインストールする。
それぞれのライブラリの役割は下で説明します。

```powershell
pip install pandas numpy matplotlib scikit-learn
```

##### Pandas
Pandasはデータを変換したり解析したりする機能が入ったライブラリ。
インストールコマンドはコレ

##### NumPy
Pythonで専門的な数学処理を行うためのライブラリ。
タ次元配列の計算や線形代数、フーリエ変換などの計算が可能になる。

##### matplotlib
グラフ描画用のライブラリ。
機械学習では学習に使用しようとしているデータが正常な値なのかを確かめる際に
グラフ化して目で確認することが多い。

##### scikit-learn
機械学習のプログラミングをするうえでよく使うライブラリ。
学習用のデータの取得もこのライブラリから可能。

### 1-3.Jupyter Notebookの導入
PowerShellを立ち上げて以下のコマンドを入力してください。

```PowerShell:
 python -m pip install -U jupyter
```
次にこのコマンドでJupyter Notebookを立ち上げます。

```PowerShell:
 jupyter notebook
```
しばらく待つとブラウザでこんな画面が立ち上がります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162114/a49d80f4-b820-c516-a927-108b972ace76.png)
これが表示されたら準備OK.
c:\Users\ユーザ名がホームディレクトリとなって画面に表示されています。
散らかってて恥ずかしいので隠させてください。。。
今回はこのホームディレクトリの下に「Python」というフォルダを作って
c:\Users\ユーザ名\Python
で作業していきます。
ファイルエクスプローラでフォルダ作成後に画面右上の更新ボタンを押せば一覧に表示されるので選択してPythonフォルダに移動します。
こんな状態。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162114/0b582fee-8f8a-aedb-e472-c
62bacc3d8f0.png)
以上で環境構築終了とします。

ちなみに手順1-1は1回やれば完了ですが、手順1-2はPCを再起動などするたびに必要です。
開けていたJupyterNotebookのページが開けなくなったら再度コマンドを実行すればよい。
と覚えておけば大丈夫です。

## 2.開発準備
特に準備するものもないのですが、この記事を読んでいる方の中にはJupyter Notebookを初めて触るという人も多いと思うので定番のHelloWorldをやっておきます。
画面右上の「New」ボタンを押して「Python3」を選択してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162114/d57006f7-f6c8-4c39-a48e-954327d89b1d.png)
こんな画面が別タブで表示されましたか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162114/86ddd2f7-3742-4206-5508-35f5e03f7ae8.png)
これがエディタです。今後Jupyter Notebookで開発する際によく見る画面になると思います。

ここにHello Worldを出力するようにPythonのコードを記載します。
書けたら入力スペースの左にある実行ボタンを選択すればプログラムが実行されてHello Worldが実行されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162114/49416be6-c005-906a-f12e-462ef75f002c.png)

以上で開発の準備は整いました。

## 3.学習する前にやるべきこと

##### 3-1.機械学習用データの取得と確認
それでは準備も整ったので機械学習のうちの教師あり学習のためのプログラミングを初めて行きましょう！
と言いたいのですが、その前に学習用のデータがないと何もできませんね。。。
このデータを集めるのは本来すごく大変な作業なのですが、事前にインストールした
sicit-learnのライブラリにはこのデータを取得する機能が備わっています！
このソースをJupyterNotebookに入力して実行してみてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162114/715d7bff-0dbb-b31b-823b-7a2e4ff1a5ea.png)

```python:samols.ipynb
from sklearn.datasets import load_iris
import pandas as pd
iris_dataset = load_iris()
display(pd.DataFrame(iris_dataset.data, columns=iris_dataset.feature_names))
```

上2行はライブラリのインストールなので飛ばします。
3行目の```load_iris()```はscikit-learnの機能でこのメソッドを呼び出すだけで機械学習の勉強でよく使われるアヤメの花の情報が取得できます。
4行目はPandasの機能を使用して取得したアヤメのデータをデータフレームという型に変換し、表形式で表示しています。
列名が英語なのでちょっとわかりづらいですが、左から「ガクの長さ」「ガクの幅」「花弁の長さ」「花弁の幅」を表しています。これらが機械学習でいう「特徴量」に当たるものです。
この情報を機械に学ばせていくわけですね。
教師あり学習について知っている人なら特徴量と一緒に政界(その特徴量をもつアヤメの種類)も欲しくなりますよね。
先ほどのプログラムでは```iris_dataset.data```で値を取得しています。iris_datasetのdataには特徴量が入っていますが、targetには対応する正解が入っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162114/f035e086-c5d3-fec4-4262-1739195dfef3.png)

```python:samols.ipynb
display(pd.DataFrame(iris_dataset.target))
```
150行あるデータそれぞれが0か1か2のどれかに対応するのかを表しています。
ここで、0, 1, 2の意味は

- 0：ヒオウギアヤメ(setosa)
- 1：ブルーフラッグ(versicolor)
- 2：バージニカ(virginica)

を表すそうです。
以上でデータの取得と確認は終了です。

##### 3-2. 学習用データの分割

それではいよいよ学習・・・の前にもうちょっと待ってください。
これから機械学習をしてアヤメの花の種類を判断するモデルを作成しようとしていますが、
出来上がったモデルはどうやって評価しましょう？
勿論テスト用のデータを手で作って確認してもいいですが、わざわざテスト用のデータを作成するのも大変ですよね。
そこで学習用に取得したデータを分割して一部はそのまま学習用、残った部分は学習には使用せずにテスト用に残しておきましょう。
ちなみに学習に使ったデータをテストに使うと結果はすごくよくなりますが、実運用時に学習に使ったデータ以外を入力したときにどうなるのかわからなくなるのでよろしくないです。
一般論ですが、収集したデータは75%をそのまま学習に使用し。残りの25%のデータでテストを行えばテスト量としては十分と言われています。
ではデータを分割してみましょう。分割する機能もscikit-learnが提供してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162114/6f938c09-2883-aa26-701a-903b48ab016e.png)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
```python:sample.ipynb
from sklearn.model_selection import train_test_split

Training_Data, Test_Data, Training_Target, Test_Target=train_test_split(iris_dataset.data,iris_dataset.target,random_state=0)

display(pd.DataFrame(Test_Target))

display(pd.DataFrame(Training_Data))
```
train_test_split()はscikit-learnの関数です。
これに引数として特徴量と正解データを渡すと3：1に分割してくれます。
分割した結果、
学習に使う特徴量=>Training_Data
学習に使う正解データ=>Traning_Target
テストに使う特徴量=>test_data
テストに使う正解データ=>test_target
にそれぞれ格納します。
一番後ろの引数のrandom_state=0はiris_datasetの中からランダムにデータを取得するための設定です。

##4 機械学習

##### モデル生成

それでは用意したデータを使用して実際に機械学習していきましょう。
今回は最も単純なk-最近傍法を使用します。
この機械学習のアルゴリズムももちろん用意されているのでプログラムを書く人は関数を呼び出すだけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162114/b91c7266-55df-fceb-1e1c-0a38a8576447.png)


```python:Sample.ipynb
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=1)

knn.fit(Training_Data, Training_Target)
```

1行目はScikit-learnからk-最近傍法を実行するための関数をインポートしているだけです。
2行目で最近傍法を実行するためのオブジェクトを生成しています。
生成時の引数(n_neighbors=1)はk-最近傍法のkに該当する数値です。
この数値によって未知のデータの判定にk個の点を扱えるようになります。
詳しくは最近傍法でググってみてください。
3行目でfitという関数を呼び出していますが、ここでモデルを生成しています。
これで機械学習は一旦完了です。
意外なくらいあっさりと終わってしまいますね。
実際にはこれで終わりではなくて評価を行い、その結果を元にモデルの調整が必要になることがほとんどだと思いますが。。。
次はこのモデルの評価を行っていきます。

##### モデルの評価

分割したテスト用のデータの先頭のレコードをテストに使用してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162114/c6dbec26-b811-8857-38ae-bbe4926f1bc2.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162114/232087b1-bbb6-2a6d-0bbf-f0e5c3322c61.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162114/2736dcaa-95b6-c786-d126-e534c84b54bc.png)

```python:Sample.jpynb
import numpy as np
input=np.array([[5.8, 2.8, 5.1, 2.4]])

result=knn.predict(input)
print(result)
```
scikit-learnの関数への入力はどれも2次元配列形式なのでまず上記のデータを2次元配列形式で作成します。

次に、k-最近傍法のモデルを持つオブジェクトknnに入力情報を渡し、結果を推定します。
最後に結果を出力すると「2」が出ました。
これはテスト用データの先頭の結果と一致しているので学習したモデルを使って未知のデータに対しても結果を出すことができました。

上記ではわかりやすくするためにテスト用のデータを1つだけ使って検証しましたが、実際には複数のデータを使用して正解率〇〇%という結果を出す必要があります。
分割したテスト用データ全てを渡して正答率を見てみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162114/7be5ea4c-f0e3-76ea-0caa-f34a8e5d612b.png)

```python:sample.lpynb
input=np.array(Test_Data)
result=knn.predict(input)

print(np.mean(result==Test_Target))
```

3行目のnp.mean()は引数の率を出してくれるNumPyの関数です。
今回はresult==Test_Targetを引数にしているので両者が一致する率を出してくれます。
検証の結果、正答率は97%となりました。
つまり、今回扱わなかったアイリスの花のデータで検証をおこなっても97%の確率で正解を出す
モデルの作成に成功したわけです。
以上でモデルの生成とその検証を終了します。

#まとめ

最後に纏めです。
今回は細かいところは説明を省いてとりあえず機械学習プログラミングのサイクルを1周回す
というところに重点を置いて記載してみました。
機械学習の知識はなんとなくあって、中で複雑な計算をしていることは知っていた
という人からすればこんな簡単にできるんだ！と思えたのではないかと思います。
実際、機械学習を実装する人にとっては複雑な計算の知識も必要だとは思いますが、
それ以上に複数ある推定方式と入力データの特徴を抑えて最適な方法でモデルの生成を行う経験と知識のほうが大切な気がしています。
Pythonでは複雑な計算はライブラリに任せて開発者が他の部分に注力できる環境が整っているので機械学習によく使われる理由がよくわかります。

自分自身がまだまだ勉強中の身ですが、今回のような簡単な例出ななくてもっと複雑なデータを使ったモデル生成とその正答率を上げる方法について今後学び、また別の記事で纏められたらと思っています。
ここまで読んでいただき、ありがとうございました。