はじめに
本記事では今すぐに一度機械学習モデルを作ってみたいという方に向けて特に単純な機械学習モデルの作成方法を紹介することを目的としています。
本記事では機械学習の中でも教師あり学習についてのみ紹介します。
教師あり学習とはなにか
機械学習は教師あり学習と教師なし学習に大別できます。今回扱う教師あり学習とは問題と解答のセットで構成された教師データによって学習を行わせる方法です。
教師あり学習のより数学的な定義は、既知の問題
$$
\begin{align}
(x_i , y_i)
\end{align}
$$
というデータの組が$i=1,2, \cdots ,n$まで$n$個与えられたとき、未知の$x_{\mathrm{unknown}}$に対して対応する$y_{\mathrm{unknown}}$を予測することだと言えます。ここでは$x$を問題、$y$を解答と思ってみてください。機械学習の世界では$x$を説明変数、$y$を目的変数といいます。また、既知の問題と解答のデータセットのことを教師データといい、これがあるというのが教師あり学習の名前の由来です。
例えば画像を与えると写っているものが猫か犬かを見分けるような教師あり学習を考えてみましょう。この場合、教師データとして猫というラベルの付いた猫の画像(画像が説明変数、ラベルが目的変数)、犬というラベルの付いた犬の画像を十分な数用意する必要があります。そして、それらの教師データをモデルに読み込ませて学習(学習アルゴリズムの詳細はここでは触れません)を行い、最終的に未知の画像を与えたときに「これは猫だ」と識別できるようにさせるのです。
用意するもの
Pythonの実行環境を用意してください。特にノートブックの形式になっているものが扱いやすいと思います。すでに環境を用意してある方はお使いの環境で大丈夫です。
Pythonに触れたことのない方はGoogle Colabが最も手軽だと思います。Google Colabの導入は簡単です。お使いのGoogleアカウントのGoogle Driveから設定を行ってください。
XORを再現する機械学習
機械学習が本領を発揮するのは複雑な説明変数が与えられている際のクラスタリングですが、今回はとにかくモデルを作ることが目的なので、特に単純なXOR回路の結果を予測する機械学習モデルを作成していきます。論理回路の入力は$2 \times 2$の大きさを持つ二次元データ、出力は一次元データです。
①importしておくもの
TensorFlow
と呼ばれるPythonの機械学習でよく使わるライブラリをあらかじめimportしておきます。Modelの作成にはKerasを使います。
import matplotlib.pyplot as plt
import numpy as np
from tensorflow import keras
from keras import layers
②教師データとテストデータ
x_train = x_test = np.array([[0, 0], [1, 0], [0, 1], [1, 1]])
y_train = y_test = np.array([0, 1, 1, 0])
教師データとテストデータ(今回は同じものですが一般には教師データとテストデータは重複していません)を用意します。シンプルなのでベタ書きです。
③Modelの設計
model = keras.models.Sequential()
Modelのオブジェクトの生成はシンプルです。ここからModelの具体的な設計を書いていきます。
# 入力層
model.add(layers.Dense(8, activation="relu", input_dim = 2))
# 全結合層
model.add(layers.Dense(8, activation="relu"))
# 出力層
model.add(layers.Dense(2, activation="softmax"))
入力層、全結合層、出力層を記述しました。入力データは二次元なのでinput_dim=2
となります。全結合層の活性化関数には様々な選択肢があり、どれがいいという話は難しいのですが、計算量が少なく学習効率の高いReLU関数がおすすめです。出力層にはsoftmax関数を使います。
完成したModelの情報を表示したい時は次のように記述します。
model.summary()
今回の場合、Total params: 114
と表示されると思います。これはModelのニューロン(厳密にはPerceptron)とそれらをつなぐ軸索の数の合計に対応しています。モデルの持つ変数(パラメータ)の数とも言いかえることができます。
④学習
作成したモデルに学習をさせます。記述はシンプルです。
model.compile(optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
history = model.fit(x_train, y_train, epochs=500, validation_data=(x_test, y_test))
test_loss, test_acc = model.evaluate(x_test, y_test)
ここでの重要な情報はオプティマイザにAdamを使っていること、500世代の学習を行っていることです。オプティマイザは他にも種類がありますが、現在最も人気があるのはAdamだろうと思います。
⑤テスト
本当に学習がうまく言ったかどうかを見るにはテストをしなければなりません。正答率と損失関数を表示してみましょう。これは厳密な言い方ではありませんが、損失関数とは予測と正解とのいわばズレを数値化したものです。したがって、学習がうまく進めば損失関数は減っていきます。
param =[["Accuracy", "accuracy", "val_accuracy"],["Loss", "loss", "val_loss"]]
plt.figure(figsize=(10, 5))
for i in range(2):
plt.subplot(1, 2, i + 1)
plt.title(f"{param[i][0]}")
plt.xlabel("Epoch")
plt.ylabel(param[i][2])
plt.plot(history.history[param[i][1]], "o-")
plt.plot(history.history[param[i][2]], "o-")
plt.legend(["train", "test"])
if i == 0:
plt.ylim([0, 1])
plt.show()
正答率が1になり、同時に損失関数の値が小さくなっていく様子がわかります。今回はテストデータと教師データが同じなので損失関数のグラフは重なっていますが、一般に重なるわけではありません。むしろこれは重ならないほうが普通です。
まとめ
ここまで機械学習モデルの設計から、検証までをかなり大雑把ではありますが見てきました。XOR回路は機械学習でなくても簡単に作れるので、メリットは見えにくいかもしれません。しかし、ほとんど同じ方法で画像から数字を識別するようなモデルを作ることもできます。
数字を識別するときはモデルの入力を画像の大きさに合わせて増やし、中間層の深さを調整し、出力の種類を増やす必要があります。
機械学習の中でも中間層が深いモデルを使うものは特に深層学習(Deep Learning)と呼ばれています。また、画像認識では中間層で畳み込みと呼ばれる操作を行います。畳み込みを行ったニューラルネットワークを畳み込みニューラルネットワーク(CNN)といいます。
一見、中間層をひたすら大きくしていけば、いくらでもよいモデルを作ることができそうですが、その点は単純ではありません。モデルの設計を色々といじりながら実験を繰り返してみると面白いかも知れません。