【忘備録】Pythonではじめる機械学習


# はじめに
思い立ったが吉日というので、『[Pythonではじめる機械学習 - O'Reilly Japan, Inc.](https://www.oreilly.co.jp/books/9784873117980/)』を読んでいこうと思う。
少しづつ読み進めていき、この記事に学んだことを記していくつもりだ。

ここで、筆者について述べておく。

<dl>
  <dt>pythonの知識</dt>
  <dd><a href="https://www.rutles.net/products/detail.php?product_id=775">12歳からはじめる ゼロからの Pythonゲームプログラミング教室</a>を一通り読んだ。</dd>
  <dt>機械学習の知識</dt>
  <dd>一切ない。</dd>
</dl>

この通り、機械学習は超初心者である。
果たして、最後まで読むことができるのだろうか。
ちなみにMarkdown記法にも初めて触れるので、試行錯誤しながら記載していく所存である。


# 動作環境
* PC - windows10 64bit
* Python - 3.9.5 64bit
* pandas - 1.4.0
* matplotlib - 3.5.1
* NumPy - 1.22.1
* SciPy - 1.7.3
* IPython - 8.0.1
* scikit-learn - 1.0.2
* VS Code - 拡張機能Jupyter


# 1章 アイリスのクラス分類

**目標: 種類がわかっているアイリスの測定値を用いた機械学習モデルで、新しく見つけたアイリスの種類を予測する**


この問題の分類

* 教師あり学習: 種類がわかっているアイリスの測定結果が存在する。
* クラス分類: 複数の選択肢の中から1つを選ぶ。ここで判定するアイリスは3種類あるため、3クラス分類問題となる。


```python:main.ipynb
from sklearn.datasets import load_iris

# irisのデータセットを読み込む
iris_dataset = load_iris()
```

ここで、```iris_dataset```の内容についてまとめる。

|key|説明|
|:-:|:-:|:-:|:-:|:-:|:-:|
|data|個々の花に対して、ガクの長さ、ガクの幅、花弁の長さ、花弁の幅が格納されたNumPy配列|
|target|花の種類を番号にした配列|
|frame|わからないので調査中|
|target_names|予測しようとしている花の種類が格納された配列|
|DESCR|データセットについての説明|
|feature_names|それぞれの特徴量の説明が格納された配列|
|filename|iris.csvが保存されているファイルパス|

<br>
さて、このデータセットを**訓練セット**と**テストセット**に分割しよう。
これをうまく行ってくれるのが、```train_test_split```関数だ。
この関数は以下を順に返すので、その分の変数を用意する。

特徴量 - ガクの長さや幅など
ラベル - アイリスの品種名

* 特徴量の訓練データ - ```X_train ```
* 特徴量のテストデータ - ```X_test```
* ラベルの訓練データ - ```y_train```
* ラベルのテストデータ - ```y_test```

```python:main.ipynb
# train_test_split関数: データセットを並べ替えて分割する。75%を訓練セット、残りをテストセットにする。
X_train, X_test, y_train, y_test = train_test_split(iris_dataset['data'], iris_dataset['target'], random_state=0)
```

<br>
次に、```train_test_split```関数で作成した訓練セットの特徴量を可視化して、データを検査してみよう。
データを検査することは、機械学習に必要な情報が含まれているかを確認するためにもとても重要である。

```python:main.ipynb
# 訓練セットの特徴量のペアプロットを表示する。
import pandas as pd
import mglearn
iris_dataframe = pd.DataFrame(X_train, columns=iris_dataset.feature_names)

grr = pd.plotting.scatter_matrix(iris_dataframe, c=y_train, figsize=(15,15), marker='o', hist_kwds={'bins': 20}, s=60, alpha=.8, cmap=mglearn.cm3)
```

これを実行すると、まあなんときれいなグラフが出力されるので、ぜひ実行してみて欲しい。
クラス(アイリスの品種)が色分けされて表示されるが、それがよく分かれていることがわかるだろう。
このことは、機械学習モデルを訓練できる可能性が高いことを意味している。

:::note warn
scatter_matrixについて
例ではpandas.scatter_matrix()であるが、pandas 1.4.0ではpandas.plotting.scatter_matrix()になっているので、pandasのバージョンを確認して使用すること。
:::
参考サイト - [pandas 1.4.0](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.plotting.scatter_matrix.html)

:::note warn
pandas.plotting.scatter_matrix()を実行する際、以下のエラーが発生した。
importerror: matplotlib is required for plotting when the default backend "matplotlib" is selected.

軽く調べて、import pandas.plotting._matplotlibを追加したがエラーは解消されなかった。
最終的に、pandasとmatplotlibのバージョンを最新にupgradeしたらエラーは解消された。
:::
(2022/1/29)

<br>
準備が整ったところで、機械学習モデルを構築しよう。
使用するアルゴリズムは**k-最近傍法**だ。
詳細は2章に記載されているらしいから、楽しみにとっておこう。まずはモデル構築の雰囲気を知ることが大切だ。

```python:main.ipynb
from sklearn.neighbors import KNeighborsClassifier

# k-最近傍法クラス分類アルゴリズムを用いる
# KNeighborsClassifierクラスのインスタンスを生成してオブジェクトknnを作成する
knn = KNeighborsClassifier(n_neighbors=1)

# knnオブジェクトのfitメソッドを呼び出し、訓練セットからモデルを構築する
knn.fit(X_train, y_train)
```

<br>
作成したモデル```knn```の評価をしよう。
ここで、先ほど作成したデータセットを用いる。
モデルを作成するときにはテストセットを使用していないし、何より正解がわかっている。こんなに嬉しいことはない。<br>

早速、テストデータのアイリスに対して予測を行い、ラベル(既知の品種名)と比較してみよう。
モデルがどの程度うまく機能しているか**精度**(accuracy)も計算しよう。<br>

```python:main.ipynb
y_pred = knn.predict(X_test)
print("テストセットの予測:\n {}".format(y_pred))

# knnオブジェクトのscoreメソッドでテストセットに対する精度を計算する
print("モデルの精度: {:.2f}".format(knn.score(X_test, y_test)))

# 出力
テストセットの予測:
 [2 1 0 2 0 2 0 1 1 1 2 1 1 1 1 0 1 1 0 0 2 1 0 0 2 0 0 1 1 0 2 1 0 2 2 1 0 2]
モデルの精度: 0.97
```

このモデルはテストセットのアイリスに対して97%正解した。
機械学習について全くの無知である筆者には97%という数値が良いのかすらわからないが、ある程度のミスが許される環境下では使用したいと思う。目視確認よりはるかに時間効率が良くなるはずだ。

<br>
# おわり
機械学習はとても難しく手に負えないかと思っていたが、ここまでなら意外と理解できることが多かった。
動くものが作れることは大変楽しい。この調子でどんどん知識を深めたいものだ。
しかし、1章を読むだけでもかなり時間がかかった。体感6時間といったところである。
この際、時間をかけてじっくりと読んでいこう。

今回はここまで。

(2022/1/30)