アメリカの大学で奮闘中

アメリカの大学でプログラミングを学ぶべくコンピューターサイエンス学部に留学したものの挫折し数学科に転部した著者が、自分の挫折ポイントを踏まえて数学、プログラミング、アルゴリズムついてできる限り分かりやすく解説してみるブログ。*できる限り記事の内容は技術的な間違いをしないように気をつけていますが、もし間違いがあれば教えていただけると助かります。

MNISTのデーターセットを使ってニューラルネットワークを実装しよう

 

この記事は以下の記事の続きになり、実際にPythonのKerasというライブラリーを用いてニューラルネットワーク(深層学習より層が少ない)を実装していきたいと思います。

 

astrostory.hatenablog.com

 

Kerasとは

Kerasは、ディープラーニングモデルを作成するための高レベルのプログラミングインターフェースを提供するPythonライブラリです。複雑なディープラーニングモデルを比較的簡単に構築できます。

層、目的関数、最適化手法などを追加するのが簡単で、どう簡単なのかは実際にコードを見ながら理解して頂ければと思います。

 

MNISTとは

MNIST(Mixed National Institute of Standards and Technology database)は、手書き数字の大規模なデータセットで、データセットの簡単さとクリーンさにより、初心者が基本的なディープラーニングを学び、経験を積むのに役立ちます。

 

60,000の訓練画像と10,000のテスト画像から成り、手書きの数字(0から9)がグレースケール画像として表現されています。各画像は28x28ピクセルで、各ピクセルは0から255までの値を取り、画像内の特定の位置の強度を表します。

 

ja.wikipedia.org

 

データセットの構造

データセットは上述の通り60,000の訓練画像と10,000のテスト画像が入っています。

ですが6万個.pngや.jpegの画像が入っているわけではなく、各ピクセルの白黒の強さが0から255の数字で表されていた6万個の28×28の配列が入っています。

 

まとめると、データセットは以下の構図になっています。

data_set = ( (A,B) , (C,D) )

 

A ... 訓練用データセット、6万個、白黒の強さが0から255の数字が入った28×28の配列

B ... 訓練用データセットのラベル、6万個、手書きの数字(0から9)の訓練用データセットの正解

C ... 検証用データセット、1万個、白黒の強さが0から255の数字が入った28×28の配列

B ... 検証用データセットのラベル、1万個、手書きの数字(0から9)検証用データセットの正解

 

実際にモデルを作成

ライブラリーのインストール

import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import RMSprop

必要なライブラリーをインポートしていきます。大前提のKeras、MNISTのデーターセット(Kerasからダウンロードできます)、ニューラルネットワークを作る上で必要な機能をimportしてきます。

 

 

データセットの用意

 


#1 データセットを代入
(x_train, y_train), (x_test, y_test) = mnist.load_data() #2  データを調整
x_train = x_train.reshape(60000, 784) x_test = x_test.reshape(10000, 784) x_train = x_train.astype('float32') x_test = x_test.astype('float32') x_train /= 255 x_test /= 255

 

 

#1 データセットを代入

上のデータセットの構造のまま以下のように代入されます。

A → x_train

B → y_train

C → x_test

D → y_train

 

#2 データを正規化

.reshapeは配列の形を変えるのに使われます。28×28の正方形のピクセル([1,2,3 ...28]が28個ある配列)を一時配列(リストの中にリストがない状態、[1,2,3,4]みたいな感じ)に直します。

 

理由は後で分かるのですが、今回のモデルは入力層を728個(28×28)用意したので、28個目の次が別の配列でなく、29個目につながって728まで続くように配列を変形します。

 

データを"正規化"というものをしていきます。

今回は0~255の数字を0~1の間に収めます。

 

ニューラルネットワークでは、入力データが0近辺で中心化されている(平均が0)と、または小さな範囲に収まっている(例えば-1から1、または0から1)と学習がうまく進むことが一般的に知られています。

 

自分の感覚的なイメージは、最後0~9のラベルに確率で出るので入力が158, 230などの大きな数字になると収束されるのが大変でモデルの精度が上がらないものと捉えています。

 

モデルの構造を実装

 

model = Sequential()
model.add(Dense(512, activation='relu', input_shape=(784,)))
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(10, activation='softmax'))

 

最初にどんなmodelにするかを決定します。

今回はadd()で追加した層を順番に実行していくSequentialを採用します。

 

model.add()で層(レイヤー)を追加していきます。

層は入力層、中間層を入れていきます。

 

層の情報はadd()の()の中の情報です。

 

意味はこんな感じです。

Dense ... その層に属する全てのニューロンが前の層の全てのニューロンと接続されている層

activation ... 活性化関数

input_shape ... 入力層

 

活性化関数についてはまた後日ブログを書ければと思います。

 

モデルを実行
model.compile(loss='categorical_crossentropy',
              optimizer=RMSprop(),
              metrics=['accuracy'])

model.fit(x_train, y_train,
          batch_size=128,
          epochs=10,
          verbose=1,
          validation_data=(x_test, y_test))

 

.compileは先ほどのコードをPCが実行できるようにする感じです。

 

.fitで実際に学習が始まります。

 

 

スコアの確認

 

score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

このコードでモデルの結果を確認できます。

自分の実行したときはこんな数字でした。

 

Test loss: 0.09119302034378052

Test accuracy: 0.9825999736785889