LoginSignup
0
1

More than 3 years have passed since last update.

Tensorfrowで画像分類など学習してみる(手書き文字認識編3)

Last updated at Posted at 2020-07-10

前回の記事「Tensorfrowで画像分類など学習してみる(手書き文字認識編2)」の続きになります。
前回は、データの前処理(スケール変換・1hotベクトル変換と、3層の順伝播型ニューラルネットワークをkerasを用いて構築しました。今回はその続きとしてモデルの学習を進めていきます。

前提/環境

前提となる環境とバージョンは下記となります。
・Anaconda3
・Python3.7.7
・pip 20.0
・TensorFlow 2.0.0

この記事ではJupyter Notebookでプログラムを進めていきます。コードの部分をJupyter Notebookにコピー&ペーストし実行することで同様の結果が得られると思います。前回分のコードは前回の記事を参照してもらえるとありがたいです。

モデルの学習

機械学習では大まかにモデル構築⇒モデルを用いて訓練⇒未知のデータの分類または予測 という流れで進めます。モデルの訓練は次のコードで行います。keras ではfit関数を利用します。fitは固定のエポック数でモデルを訓練するものになります。

code
model.fit(
    x_train,
    y_train,
    batch_size=32,
    epochs=20,
    validation_split=0.2
)

訓練ではデータすべてを使うわけではありません、手書き文字のデータセットの内60000枚を利用します。残りの10000枚のデータは未知のデータへの検証や予測のために利用します。

fit関数を用いるにあたり引数を指定しています。それぞれは下記の意味合いとなります。

x_train
訓練データの画像に手書き文字セットの画像の行列に対応します。
y_train
訓練データのラベルに対応する行列に対応します。
batch_size
整数またはNoneを指定します。動作としては設定したサンプル数ごとに勾配の更新を行います。指定しなければデフォルトで32で更新します。機械学習の原理として与えられた関数の傾き(勾配)を計算して、勾配の傾きが大きいほうへパラメーターをずらしていきます。この動きに対する指定となります。
epochs
整数で,モデルを訓練するエポック数を指定します。
validation_sprit
訓練データ全体を訓練にのみ利用するのではなく、一部を訓練中の検証用データとして用いる場合に設定します。kerasでは0から1までの浮動小数点数で指定します。この設定値は訓練データの中で検証データとして使う割合を示します。この記事では0.2を定していますが、訓練に使われるのは全体の8割、残りの2割は検証用データとして利用するということになります。ここで設定した検証データは訓練には利用されません。

モデルの訓練の実行

fitを実行すると下記のような結果が得られます。(一部抜粋)注:結果中のaccuracyなどの値は全く同じにならない場合があります

Train on 48000 samples, validate on 12000 samples
Epoch 1/20
48000/48000 [==============================] - 230s 5ms/sample - loss: 0.1753 - accuracy: 0.9567 - val_loss: 0.3396 - val_accuracy: 0.9468
Epoch 2/20
48000/48000 [==============================] - 246s 5ms/sample - loss: 0.1696 - accuracy: 0.9575 - val_loss: 0.3084 - val_accuracy: 0.9444



Epoch 20/20
48000/48000 [==============================] - 317s 7ms/sample - loss: 0.1477 - accuracy: 0.9636 - val_loss: 0.4187 - val_accuracy: 0.9446

得られる結果としてデータセット数、loss、accuracy、val_loss、val_accuracyというものが得られます。手書き文字セットの訓練データは60000枚でしたがその8割を利用するので48000枚を利用して訓練をしています。残りの2割データで検証を行っています。
loss、accuracy、val_loss、val_accuracyそれぞれの意味合いは下記になります。

loss
訓練データを用いた場合の損失関数の値。損失関数の値が減少することが望ましい
accuracy
訓練データに対しての分類精度(正解率)この値が高くなることが望ましい。
val_loss
訓練データの一部を検証用データとして利用した場合に得られる。検証用データ(未知のデータ)に対する損失関数の値
val_accuracy
訓練データの一部を検証用データとして利用した場合に得られる。検証用データ(未知のデータ)に対する正解率

基本的にエポックを重ねるごとにlossが減少し、accuracyが増加します。またval_loss,val_accuracyの値に比べ正解率が高く、損失値が小さくなります。訓練用データでのエポックを過剰に進めると、未知のデータに対する正解率が上がらず損失値が減少しない場合があります。これを過学習といいます。

モデルの正解率の評価

code
test_loss, test_acc = model.evaluate(x_test, y_test, verbose=0)
print('\nTest accuracy:', test_acc)

結果
Test accuracy: 0.9414

手書き文字セットの内、10000枚のデータで評価しました。値は訓練データでの正解率に比べ現象しています。

モデルを使い予測してみる。

predict関数を用いて、手書き文字セットの評価用データを用いて予測してみます。

code
predictions = model.predict(x_test)
predictions[0]

結果
array([0.0000000e+00, 1.4220487e-26, 1.4102146e-16, 1.2095399e-13,
5.7181305e-13, 1.5182375e-28, 0.0000000e+00, 1.0000000e+00,
0.0000000e+00, 3.0219263e-18], dtype=float32)

この結果として予測した結果の値が得られます。いくつかの候補に値があります。

code
np.argmax(predictions[0])

結果
7

予測したもので最も可能性が高いと思われるものが7であるという結果が得られました。
ラベルを確認しましょう。

code
y_test[0]

結果
array([0., 0., 0., 0., 0., 0., 0., 1., 0., 0.], dtype=float32)

正解を示すラベルでは7番目の要素が1となっています。この結果から正しいことがわかりました。念のため画像を見ましょう

code
x_test_image = x_test[0].reshape(28, 28) 

plt.figure()
plt.imshow(x_test_image)
plt.colorbar()
plt.grid(False)
plt.show()

ここでは一度784に画像を変更しているので、28×28に再度reshapeしなおして画像として表示しています。
そうすると7という文字の手書き画像が表示されます。

まとめ

ここまで、MNISTの手書きデータセットを用いて順伝播型ニューラルネットワークによる訓練と予測をしてみました。
tensorflowとkerasを用いると簡便にいろいろな機械学習が行えます。
初歩的な内容でしたが、次回以降はCNNによる画像分類を書いていきたいと思います。

2020年7月12日追記
CNNの実装をしてみようということで下記の記事も書き始めました。
Tensorflow・kerasでCNNを構築して画像分類してみる(概要編)

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1