機械学習のコードを動かしてみよう(scikit-learn)

概要

昨今、ブームとなっているAI・機械学習の技術は、ハードルが高くて敬遠されている方も多いのではないでしょうか。
たしかに、実際にエンジニアとして開発や研究を行うためには、相応のスキルが必要です。
しかしながら、ソースコードを少し実行するくらいであれば、たった10行のコードで機械学習を体験することができます。

コード

先ずは、今回動かすコードを見てみましょう。このコードを1行ずつ紹介していきます。

1
2
3
4
5
6
7
8
9
10
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier
iris = load_iris()
X = iris.data
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
clf = MLPClassifier()
clf.fit(X_train, y_train)
print (clf.score(X_test, y_test))

1行目

1
from sklearn.datasets import load_iris

scikit-learnはPythonの機械学習ライブラリです。
Deep Learningなどの最先端のアルゴリズムはほとんど実装されていませんですが、
クラシカルで実用的なアルゴリズムやそれらを扱うためのツールが数多く実装されています。

scikit-learnにはサンプルとして、いくつかのデータセットをダウンロードすることができます。その一つがフィッシャーのアヤメと呼ばれるデータで、1行目ではアヤメのデータをダウンロードするための関数load_irisをインポートしています。
データの詳細はこちらを参照いただきたい

2行目

1
from sklearn.model_selection import train_test_split

データ(サンプルの集合)を学習用データとテストデータに分割する関数train_test_splitをインポートしています。データを分割する理由については、やや本題からずれますので記事の最後に補足します。

3行目

1
from sklearn.neural_network import MLPClassifier

クラスMLPClassifierは多層パーセプトロン[1]を用いた分類[2]モデルのクラスです。

[1]多層パーセプトロン・・・ 多層パーセプトロンニューラルネットワーク(Deep Learning)の最もプレーンなネットワーク

[2]分類・・・機械学習のタスクには「回帰」や「分類」といったタスクがあります。分類タスクとは文字通りデータを分類するタスクのことで、例えば、画像に写っている動物が猫か犬かを判定する問題などが考えられます。

4行目

1
iris = load_iris()

先ほど説明したアヤメのデータを変数irisに代入する。

5行目

1
X = iris.data

オブジェクトirisは属性dataを持っており、その中にはアヤメの「がくの長さ」「がくの幅」「花弁の長さ」「花弁の幅」が保持されています。こういった予測に用いるための情報を説明変数特徴量と呼びます。 9行目から説明変数を使って、アヤメの分類を行うことになります。

1
2
>>> X.shape
(150, 4)

データの数(サンプル数)が150で説明変数の種類(次元)が4であることが確認できます。
さて、試しに1つ目のサンプルを確認してみましょう。

1
2
>>> X[0]
array([5.1, 3.5, 1.4, 0.2])

小数で4つの説明変数が格納されていることが確認できます。
ちなみに説明変数の名前はは属性feature_namesで確認できます。

1
2
3
4
5
>>> iris.feature_names
['sepal length (cm)',
'sepal width (cm)',
'petal length (cm)',
'petal width (cm)']

6行目

1
y = iris.target

オブジェクトirisは属性targetを持っており、その中には「アヤメの種類」が保持されています。こういった予測対象となる情報を目的変数ラベルと呼びます。説明変数を使って、目的変数を出来るだけ高い精度で予測することが機械学習の目的の一つです。

1
2
>>> y.shape
(150, )

yについてもデータの数(サンプル数)が150であり、Xの場合とサンプル数が一致していることが確認できます。
さて、試しに1つ目のサンプルを確認してみましょう。

1
2
>>> y[0]
0

今回のtargetは0,1,2のいずれかの数字が保持されています。これらの数字はそれぞれsetona, versicolor, virginicaという種類に対応しています。これは属性target_namesで確認できます。

1
2
>>> list(data.target_names)
['setosa', 'versicolor', 'virginica']

7行目

1
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)

train_test_splitを使ってデータを学習用データとテストデータに分割しています。それぞれに目的変数と説明変数があるため、返却されるオブジェクトは4つとなります。test_sizeは分割の比率を決めるパラメータで、ここでは30%をテストデータに、残りの70%を学習用データとしています。データの形状を確認してみましょう。

1
2
3
4
5
6
7
8
>>> X_train.shape
(105, 4)
>>> X_test.shape
(45, 4)
>>> y_train.shape
(105,)
>>> y_test.shape
(45,)

random_stateはデータを分割する際に利用する乱数を、プログラムの実行ごとに固定するための値です。

8行目

1
clf = MLPClassifier()

多層パーセプトロンを用いた分類モデルのクラスであるMLPClassifierからインスタンスclfを作成しています。

9行目

1
clf.fit(X_train, y_train)

clfの学習を行います。引数として、学習用のデータの説明変数X_trainと目的変数y_trainを渡します。

10行目

1
print (clf.score(X_test, y_test))

ここではメソッドscoreで、clfX_testを入力し予測値を計算したのち、答えであるy_testと比較を行い、平均正解率を求めています。もちろん正解率まで求めず、予測だけを行うこともできます。その際にはメソッドpredictを使用します。

1
2
3
4
clf.predict(X_test)
array([0, 2, 1, 1, 1, 2, 1, 1, 2, 0, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 2, 0,
0, 2, 1, 0, 2, 2, 2, 0, 0, 2, 0, 2, 1, 0, 1, 2, 2, 0, 2, 0, 2, 1,
2])

MLPClassifierで用いる乱数の関係で、ここに記載した結果と異なる結果が出る可能性があります)

先ほど平均正解率を求めましたが、目視でも答えy_testと比較してみましょう。

1
2
3
4
y_test
array([0, 2, 1, 1, 1, 2, 1, 1, 2, 0, 2, 2, 0, 0, 0, 0, 2, 1, 1, 1, 2, 0,
0, 1, 1, 0, 2, 2, 2, 0, 0, 2, 0, 2, 1, 0, 1, 2, 2, 0, 1, 0, 2, 1,
2])

概ね一致しているのではないでしょうか。

まとめ

解説自体は少々長くなりましたが、コード自体はたった10行と非常に短く、機械学習のハードルは思ったより低く感じられた方もいらっしゃるのではないでしょうか。

より詳しくscikit-learnの勉強をしたい方は

連載「scikit-learnで学ぶ機械学習」を始めます

csvデータの学習方法を知りたい方は

CSVファイルをpandasで読み込み、scikit-learnで学習させる

機械学習の入門〜NumPyによるロジスティック回帰の実装を勉強したい方は

連載「ゼロから始める機械学習」

データ分析と機械学習の関係については以下の記事でまとめています。

データ分析とは何か?機械学習との関係について

補足:train_test_splitでデータを分割する理由

以下の2行の値を比較してみて下さい。おそらく、1行目の方が値が高いのではないでしょうか。

1
2
>>> clf.score(X_train, y_train)
>>> clf.score(X_test y_test)

これは、機械学習モデルに学習してほしいと期待しているアヤメのがく・花弁と種類の関係だけではなく、本質的ではない丸暗記のようなものを学習してしまっているためです。これを過学習と呼びます。私たちが機械学習に期待しているのは学習データの丸暗記ではなく、機械学習モデルにとって未知のデータ(ここではテストデータ)に対する高い正解率での予測です。そのため、機械学習モデルを評価する際は、学習用データに対する正解率ではなくテストデータに対する正解率を優先的に見るべきです。(ただし、前者も使い道はあります。)

人間の試験と一緒

人間が受ける入学試験や資格試験では、本番ではすでに公開されている問題(過去問や模試)と全く同じ問題は基本的には出ませんよね。なぜなら、同じ問題を出してしまうとなると暗記をしてしまえばよい、となるからです。逆にいえば、公開されている問題と同じ問題を出してしまうと、その試験では受験者を適切に評価することができなくなってしまいます。

記事情報

  • 投稿日:2020年2月3日
  • 最終更新日:2020年3月31日