KerasMOME

MNISTを一般的な機械学習で学習させる方法

# MNISTのライブラリをインポートする。
from keras.datasets import mnist
from keras import models
from keras import layers
from keras import optimizers
from keras import regularizers
from keras import utils

# 訓練データ(50000個)とテストデータ(10000個)を用意する。
# 今回は評価として、ホールドアウト法を用いるが、
# データが少ない場合は、k分割交差検証や、ランダムなk分割交差検証も考える必要がある。
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
print(train_images.shape)
print(len(train_labels))
print(train_labels)
print(test_images.shape)
print(len(test_labels))
print(test_labels)

# 線形スタックのモデルを作成する。
network = models.Sequential()
# Denseとは、密に結合された層のことを表す。
# add()でレイヤーを追加できる。
# unitsはセル数。
# kernel_regularizerはネットワークの重みの値を正則化することによって、過学習を防いでいる。
# kernel_regularizerにはL1正則化、L2正則化の両方を適用しているが、片方でも良いし、無くても良い。
# activitationは活性化関数の種類
# input_shapeはarrays of shape (*, 28*28)。形式的にわかりにくい。
# Dropoutは直前の層から直後の層に伝搬するデータの一部を強制的に0にするというもの。
# わざとノイズを入れることで、過学習を防ぐことができる。中間層に入れるのが基本だが無くても良い。
network.add(layers.Dense(units=512,
                        kernel_regularizer=regularizers.l1_l2(l1=0.001, l2=0.001),
                        activation='relu',
                        input_shape=(28 * 28, ))) # 全結合層
network.add(layers.Dropout(0.25)) # ドロップアウト層
network.add(layers.Dense(units=10,
                        activation='softmax')) # ソフトマックス層

# ネットワークを訓練するための準備を整えるために、コンパイルをする必要がある。
# lossで目的関数を設定でき、今回は交差エントロピー誤差。
# optimizerで学習方法を設定でき、SGD、モーメンタムSGD、AdaGrad、RMSpropなどある。
# metrics=['accuracy']は、正答率を計算するという意味です。
network.compile(optimizer='rmsprop',
               loss='categorical_crossentropy',
               metrics=['accuracy'])

# 訓練の前にMNISTデータの前処理を行います。
# 計算量が多くなるので、テンソルの値は0~1の間に収めるなど、工夫する必要がある。
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255
test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255
print(train_images.shape)
print(train_images)
print(test_images.shape)
print(test_images)

# 出力(ラベル)は数字の「0,1,2,3,~,9」と分かれているので、カテゴリ値でエンコードする必要がある。
# [1, 0, 0, 0, 0, 0, 0, 0, 0]…0
# [0, 0, 1, 0, 0, 0, 0, 0, 0]…2
# [0, 0, 0, 0, 0, 1, 0, 0, 0]…6
# のように0,1で数字を表す。
train_labels = utils.to_categorical(train_labels)
test_labels = utils.to_categorical(test_labels)

# ネットワークの訓練を行う準備が整ったので、fitメソッドを呼び出し、モデルを訓練データに適合させます。
# 引数に訓練データの入力、出力のデータを入れます。
# epochsはデータ全体を使用する回数。同じ全データを何回使用するかを表し、使用しすぎると過学習になる。
# batch_sizeは学習に使用する入力データを何分割するかを示している。
# 今回は5万データなので、50000÷100=500で、"1"epochあたり500データ100回文で学習を行う。本官は詳しい理由はわかっていない。
network.fit(train_images, train_labels, epochs=10, batch_size=100)

# 直前で訓練されたネットワーク(network)を用いて、
# テストデータでの損失値(loss)と正答率(accuracy)を求める。
# 引数にテストデータの入力、出力のデータを入れます。
test_loss, test_acc = network.evaluate(test_images, test_labels)
print('test_acc:', test_acc)
# 結果は、「# test_acc: 0.9795」と出たが、これは環境によって値は異なる。
# 理由は、ネットワークの初期化を行う時のシード値を、Kerasがランダムに選ぶからである。


この記事が気に入ったらサポートをしてみませんか?