MNISTのニューラルネットワークでの学習の隠れ層のニューロン数と精度の関係

前回の記事に続いて、今回は隠れ層のニューロンの数と精度の関係を見てみました。

size hidden_size process_time train_loss train_accuracy test_loss test_accuracy
60000 [8] 29.06 0.2370 0.9328 0.2473 0.9296
60000 [64] 44.79 0.0208 0.9942 0.0928 0.9740
60000 [512] 103.64 0.0047 0.9985 0.0797 0.9830
60000 [64, 64] 41.83 0.0159 0.9947 0.1170 0.9722
60000 [64, 64, 64] 44.94 0.0199 0.9934 0.1090 0.9757

左から、訓練用データサイズ、隠れ層のニューロン数、処理時間(秒)、訓練データでの損失関数値、訓練データでの精度、テストデータでの損失関数値、テストデータでの精度です。

隠れ層を2層、3層にしたときも試したので、隠れ層のニューロン数を配列で表現しています。

層を増やしてもあまり精度は変わらなかったです。

Pythonコード

Pythonコードを残しておきます。前回の記事とほとんど同じです。Google Colaboratoryで実行しました。

import time
import numpy as np
from matplotlib import pyplot as plt
import tensorflow as tf
from tensorflow.keras.datasets import mnist

plt.rcParams['figure.figsize'] = (16.0, 7.0)

(x_train, y_train), (x_test, y_test) = mnist.load_data()

# 入力と出力サイズ
in_size = 28 * 28
out_size = 10

# モデル構造を定義
def createModel(hidden_size):
  model = tf.keras.models.Sequential()
  if len(hidden_size) == 1:
    model.add(tf.keras.layers.Dense(hidden_size[0], activation='relu', input_shape=(in_size,)))
    model.add(tf.keras.layers.Dense(out_size, activation='softmax'))
  else:
    model.add(tf.keras.layers.Dense(hidden_size[0], activation='relu', input_shape=(in_size,)))
    for i in range(1, len(hidden_size)):
      model.add(tf.keras.layers.Dense(hidden_size[i], activation='relu'))
    model.add(tf.keras.layers.Dense(out_size, activation='softmax'))
  return model

# 学習の様子をグラフへ描画
def plotLearning(result):
  fig = plt.figure()

  xs = range(1, len(result.history['loss']) + 1)

  # ロスの推移をプロット
  ax1 = fig.add_subplot(1, 1, 1)
  ax1.set_ylim(0, 2.5)
  ax1.set_ylabel('Loss')
  ax1.plot(xs, result.history['loss'])
  ax1.plot(xs, result.history['val_loss'])

  # 正解率の推移をプロット
  ax2 = ax1.twinx()
  ax2.set_ylim(0.75, 1.0)
  ax2.set_ylabel('Accuracy')
  ax2.plot(xs, result.history['accuracy'])
  ax2.plot(xs, result.history['val_accuracy'])

  plt.title('Loss & Accuracy')
  plt.legend(['train', 'test'], loc='upper left')
  plt.show()

def calc(train_size, epochs, hidden_size):
  model = createModel(hidden_size)

  # モデルを図で表示
  display(tf.keras.utils.plot_model(model, show_shapes=True))

  # モデルを構築
  model.compile(
      loss = "categorical_crossentropy",
      optimizer = "adam",
      metrics=["accuracy"])

  start = time.time()
  print("train_size: %d, epochs: %d" % (train_size, epochs))
  x_train_reshape = x_train.reshape(-1, in_size).astype('float32') / 255
  x_test_reshape = x_test.reshape(-1, in_size).astype('float32') / 255
  y_train_onehot = tf.keras.backend.one_hot(y_train, out_size)
  y_test_onehot = tf.keras.backend.one_hot(y_test, out_size)

  x_train_reshape = x_train_reshape[:train_size]
  y_train_onehot = y_train_onehot[:train_size]

  # 学習を実行
  result = model.fit(x_train_reshape, y_train_onehot,
      batch_size=50,
      epochs=epochs,
      verbose=1,
      validation_data=(x_test_reshape, y_test_onehot))

  processTime = time.time() - start
  print("train_size: %d, epochs: %d, processTime: %f" % (train_size, epochs, processTime))
  plotLearning(result)

  return "| %d | %s | %5.2f | %6.4f | %6.4f | %6.4f | %6.4f |" % (train_size, str(hidden_size), processTime,
    result.history['loss'][-1], result.history['accuracy'][-1],
    result.history['val_loss'][-1], result.history['val_accuracy'][-1])

table = []
table.append(calc(60000, 15, [8]))
table.append(calc(60000, 15, [64]))
table.append(calc(60000, 15, [512]))
table.append(calc(60000, 15, [64, 64]))
table.append(calc(60000, 15, [64, 64, 64]))
for s in table:
  print(s)