Python でニューラルネットワークを実装してみましょう。何回かに分けて作っていきます。
第一弾の今回は、行列データを受け取って、0から9までの10種類のラベルを出力する、3層のモデルを作ります。行列パラメーターの更新機能は無く、手動で成分を設定してラベルを出力します。
Python の環境が無い人は、google colab を使えるようにしましょう。Pythonファイルに色々まとめて置くのが便利ですが、最悪一つのnotebook にまとめても良いです。
Google Colabolatory とニューラルネットワークの話はこちらの記事でどうぞ。
ニューラルネットワークのモデルの実装は、以下の本を参考にしています。管理人はこの本でpythonがなんとなく書けるようになりました。
記事で使っているソースコードはgithub に置いてあります。
https://github.com/msamunetogetoge
使用するデータ
使うデータは Fashion MNIST という画像データです。10種類の衣類が\( 28 \times 28 \)の行列で表現されています。以下のような感じのデータです。
実際のデータでは画像に対して、0~9の数字が割り振られています。単純に考えると、\(28 \times 28\)の数字から、0~9どのクラスに属しているのか当てる問題です。データを読み込むコードを以下に記します。
ただし、ちょっとした細工をしておきます。精度が上がるように画像は白黒に加工します。 また、画像データは\( 28 \times 28 \)の行列ですが、1つのデータが行列として与えられるのは、普段考える問題と違っています。いつも通りが一番なので、行列を1列のベクトルだと思いましょう。numpyのflatten 関数を使えばよいです。
import tensorflow as tf
from tensorflow import keras
fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
train_images = train_images / 255.0
test_images = test_images / 255.0
train_images.flatten().reshape(-1,784) #28*28=784
test_images.flatten().reshape(-1,784)
今回実装するニューラルネットワークモデルの部分
作ろうとしているモデルは、入力層1層、隠れ層1層、出力層1層のモデルです。隠れ層では、relu関数で活性化し、出力層ではsoftmax関数で10個の値を得て最も大きい値を出すクラスを予測値とします。
パラメーターの更新は単純な勾配法で行い、誤差関数は交差エントロピーを使用します。
今回は、データを受け取って予測ラベルを出力し、正解率を計算する関数を作ります。具体的には、以下の機能が必要です。
- 活性化関数(relu)の計算
- 出力関数(softmax)の計算
- 行列同士の積
- 正解率の計算
ニューラルネットワークモデルの予測部分の実装
以下のグラフが示すモデルで予測値を得られるように、コードを書きます。
最終的には一つのクラスにまとめたいので、初めにクラスを作っておいて機能を増やしていきましょう。ニューラルネットワークのクラスとは別に、活性化関数や出力関数を作っておく必要があります。今のところは、reluとsoftmaxがあれば良いので、以下のように定義しておきましょう。
def relu(x):
return np.maximum(0, x)
def softmax(x):
if x.ndim == 2:
x = x.T
x = x - np.max(x, axis=0)
y = np.exp(x) / np.sum(np.exp(x), axis=0)
return y.T
x = x - np.max(x) # オーバーフロー対策
return np.exp(x) / np.sum(np.exp(x))
今回の目玉である、行列の計算と活性化関数の計算、そして出力関数の定義をしましょう。行列の行や列に気を付ければ簡単です。クラスにまとめたいので、TwoLayerNet というクラスの中に、行列の生成や ニューラルネットワークでの予測、正答率の表示を組み込みました。
class TwoLayerNet:
def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.1):
self.params = {}
self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size)
self.params['b1'] = np.zeros(hidden_size)
self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size)
self.params['b2'] = np.zeros(output_size)
def predict(self, x):
W1, W2 = self.params['W1'], self.params['W2']
b1, b2 = self.params['b1'], self.params['b2']
a1 = np.dot(x, W1) + b1
z1 = relu(a1)
a2 = np.dot(z1, W2) + b2
y = softmax(a2)
return y
def accuracy(self, x, t):
y = self.predict(x)
y = np.argmax(y, axis=1)
accuracy = np.sum(y == t) / float(x.shape[0])
return accuracy
この状態で、トレーニング画像からラベルを予測させてみましょう。全く訓練していないパラメーターなので、正答率は10%前後が妥当です。
network=TwoLayerNet(input_size=len(train_images[0]),hidden_size=64, output_size=10)
np.argmax(network.predict(train_images[0])) #1番目の画像の予測
#管理人の環境での出力 1
network.accuracy(train_images , train_labels ) #トレーニング用画像全体の正答率の算出
#管理人の環境での出力 0.05976666666666667
正答率 5 %でした。パラメーターは適当なので正答率は何%でも良いのですが、無事にデータから予測値を得る関数を作ることが出来ました。次回からはpython上で作ったクラスに色々な関数を追加して、パラメーターの更新を自動で行ってくれるようにしていきます。
まとめ
・ Fashion MNIST という\(28 \times 28 \)の画像データがあり、10種類の分類問題に使える。
・計3層のニューラルネットワークモデルを作るために、クラスTwolayernet を作った。
・データに予測値を与える関数を作成した。
・pythonによるニューラルネットワークの実装➁はこちら
https://masamunetogetoge.com/make-neuralnetwork2