はじめて機械学習をやってみたので解説する【一日目】


はじめに

機械学習の実装はやったことがないので触ってみることにした。
かなりのボリュームがありそうなので、何回かに分けて学んだことをかみ砕いてアプトプットしていきたいと思う。
もし自分と同じように興味はあるけど、まだ詳しくは知らないっていう方は参考にして頂ければと思います。

もともと持っている知識

IBMのWATSONで画像を使った機械学習や分類器の設定などはやったことがあるので、GUIで学習させるのはこんな感じだよ、というイメージはもっている。
また教師あり・なしの説明できる程度知識はあるが、数学的な知識はなし。
微積分とかシグマとか完全に忘れてる。

何から勉強するか

pythonではじめる機械学習」という本で勉強した。
ということでアマゾンでポチッたら当日に届いた。ほんと便利な世の中になりました。

本記事は1章「はじめに」の内容で学んだことをアウトプットしている。
※記載されていることをそのまま記載はしていません。かみ砕いています。

環境構築

機械学習ではデータをグラフ化したりテーブルで表示することがある。
そこで「Jupyter Notobook」というpythonのコードを実行でき、その値を使ってグラフ化して出力できるライブラリがある。
ただコード補完がないので、ベースはpycharmで実装する。
グラフなど可視化したいときはjupyter notebookを使っていく。
ちなみにanacondaを使っている人はもともと入っているようなので、インストール不要。
jupyter notebookは以下のコマンドでインストールできる。

実行環境のインストール

pip install jupyter notebook

# ちなみにjupyter notebookを使いたいときは下記を実行すればブラウザが自動で開く
jupyter notebook

ライブラリのインストール

色々なライブラリを使うのでインストールする。
まとめたコマンド用意したので下記を実行して貰えればOK。
こちらはAnacondaもやっておいた方がいい。

pip install scikit-learn numpy scipy matplotlib ipython pandas pillow mglearn

機械学習ってどんな感じ?

例を使って説明していく。
例えば、irisという花の種類を判定するモデルを作るとする。
irisには見た目が似ているsetosa、versicolor、virginicaの三種の花があり、花弁とガクのサイズで分類できないかを試みる。
判定するためにはそれぞれの花のサンプルが必要なので、

①花弁の長さ ②花弁の横幅
③ガクの長さ ④ガクの横幅

のサイズを測り、一種あたり50(三種あるので総計150のサンプル)のサンプルのデータを用意する。
流れ的には①~④の値を入力値とし、150サンプルを学習したモデルが判断し、花の種類が出力されるというモデルだ。

で、本来なら150件分のデータを用意する必要があるが、データはscikit-learnに用意されている
irisを使ったモデル作成はチュートリアルで使われることが多いらしいので、このデータを使って解説していく。

モデルの実装と実行

用意されているデータを登録し、判定方法の設定を行うだけでモデルは完成する。
あとは入力値を入れると結果を出してくれる。
一応こんなにシンプルにできるよって思いを込めてソースを載せる。

iris.py
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
import numpy

# 1、用意されているirisのデータを抽出
iris_dataset = load_iris()

# 2、データを訓練用とテスト用に分割する
X_train, X_test, y_train, y_test = train_test_split(
    iris_dataset['data'], iris_dataset['target'], random_state=0
)

# 3、最近傍法(k近傍法)のインスタンスを生成 n_neighborsで近傍点の数を設定できる
knn = KNeighborsClassifier(n_neighbors=1)
knn.fit(X_train, y_train)

# 4、サンプルの測定値をセット
X_new =numpy.array([[5, 2.9, 1, 0.2]])

# 5、予測を実行。返り値に結果が入る
result = knn.predict(X_new)
print("Predicted target name: {}".format(
    iris_dataset['target_names'][result]))

プログラムを実行すると以下の値が表示される。

Predicted target name: ['setosa']

なんじゃこれ ソースを見てもわからん

ちゃんと解説していく。
理解していくには、以下の二点を抑えるとよい。

  • データの中身がどういう構成になっているか
  • どんな方法で分類をしているか

ということでデータの中身から見ていく。

1、もともと用意されているirisのデータを抽出

from sklearn.datasets import load_iris
iris_dataset = load_iris()

# データの中身を見る
# print("Keys of iris_dataset: \n{}".format(iris_dataset.keys()))

こうするとirisのデータを取得できる。
データの中身を見てみると、以下のようになっている。

Keys of iris_dataset: 
dict_keys(['data', 'target', 'frame', 'target_names', 'DESCR', 'feature_names', 'filename'])

要素がいくつがあり、それぞれ役割がある。
ほんとうなら全部確認した方が理解が深まるが、最低限必要なところだけピックアップしていく。

dataとfeature_namesとtargetを見てみる。
print("Type of data: \n{}".format(iris_dataset['data']))

# 以下は実行結果。計150件分のデータが入っている。
Type of data: 
[[5.1 3.5 1.4 0.2]
 [4.9 3.  1.4 0.2]
 ・・・
 [6.2 3.4 5.4 2.3]
 [5.9 3.  5.1 1.8]]
print("Feature names:\n{}".format(iris_dataset['feature_names']))

# 以下は実行結果
# [がくの長さ, がくの幅, 花弁の長さ, 花弁の幅]と表示されている。
Feature names:
['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
print("Type of target: \n{}".format(iris_dataset['target'])) 

# 以下は実行結果
# 0,1,2が総計150ある
# target_nameの中身を見ていると['setosa' 'versicolor' 'virginica']という配列になっている。
Type of target: 
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 2 2]

dataには学習用のサンプルデータが150件入っている。
また半角スペースで区切られていることに注目してほしい。
feature_namesには区切られたデータが何の数値かを説明している。
そしてdataの中には三種のデータが50件ずつ用意されているはずだが、dataのみではどの種類かまでわからない。
targetを見ると「0 1 2」で構成された150のデータがあり、種類を表している。意味は以下の通り。
0 : setosa
1 : versicolor
2 : virginica
つまりdataの最初の50件がsetosa、次の50件がversicolor、最後の50件がvirginicaに対応している。

データの理解はこれでOK。

2、データを訓練用とテスト用に分割する

X_train, X_test, y_train, y_test = train_test_split(
    iris_dataset['data'], iris_dataset['target'], random_state=0
)

モデルができた後はきちんと判定できているかテストする必要がある。
よく用いられる方法として、用意したデータを学習用とテスト用に分割するらしい。
分割するにはtrain_test_splitメソッドを使うとよい。
ちなみにXはデータ(今回でいうと[5.1 3.5 1.4 0.2]みたいなやつ)を示し、yはラベル(今回でいうと種類を表す0,1,2)を示す。

3、最近傍法(k近傍法)のインスタンスを生成 n_neighborsで近傍点の数を設定できる

knn = KNeighborsClassifier(n_neighbors=1)
knn.fit(X_train, y_train)

入力値に対してどんな方法で分類させるかというと色々な方法がある。
今回は「最近傍法(k近傍法)」を用いており、KNeighborsClassifierというメソッドを使えばよいだけ。
そのあとfitメソッドで学習用のデータをセットする。

最近傍法(k近傍法)って何?

ざっくりと説明。
入力値から分類する際に、用意した150件のサンプルに最も近似した値を抽出し、「このサンプルと値が一番近いからこの種類だよね」と分類する方法。

4、サンプルの測定値をセット

X_new =numpy.array([[5, 2.9, 1, 0.2]])

調べたい花の値をセットしている。つまりこれがインプットの値になる。

5、予測を実行。返り値に結果が入る

result = knn.predict(X_new)
print("Predicted target name: {}".format(
    iris_dataset['target_names'][result]))

predictで実行。resultには0が入る。つまりはsetosaという品種を表している。

まとめ

なるべくシンプルに書こうとしたが、複雑になってしまった・・・
そしてここに記載されている内容はhello worldの次にやるレベルの内容っぽいが結構覚えること多い。
AIの実装ができるエンジニアへの道は険しそうだが、その分価値が高くなるはずなので、同じ志の方がいたら一緒に頑張りましょう。