
ニューラルネットワークの学習過程を可視化してみよう
2020.08.13
目次
ニューラルネットワークの学習過程は可視化できるの?
「ニューラルネットワークのモデルを作ってみたけど、本当にうまく機能しているのか分からない…」
「AIはブラックボックスだから、どのように学習が起こっているかイマイチ分からない…」
こんな悩みを抱えていませんか?
この記事では、このような疑問を解決するために「ニューラルネットワークの学習過程を可視化」していきたいと思います。
ニューラルネットワークの学習過程を可視化して、「モデルがどのように訓練されているのか」「モデルの学習で問題が起こっていないか」などを見てみましょう!
こちらの記事もオススメ!
ライブラリとフレームワークのインポート
今回は、「TensorFlow」と「Keras」で構築した画像分類モデルを可視化します。
TensorFlow と Keras の他に、ヘルパーライブラリとして「Numpy」と「matplotlib」も使用するので、まずはインポートしておきましょう!
1 2 3 4 5 6 7 8 9 | from __future__ import absolute_import, division, print_function,unicode_literals # TensorFlow、Keras import tensorflow as tf from tensorflow.keras import datasets, layers, models # ヘルパーライブラリ import numpy as np import matplotlib.pyplot as plt |
使用するデータセット
それでは、使用するデータセットを用意しましょう!
今回使用するのは、おなじみに「MNIST」という手書き数字のデータセットです。

MNISTについて
MNIST には、1枚の画像に「0~9」までの数字がそれぞれ1つ書かれたデータが入っています。
28×28のピクセルの中には「0~255」の整数が格納されています。
「0」は「黒」を、「255」は「白」を表しています。
画像は全部で70,000件あり、そのうちの60,000件が訓練データで、残りの10,000件がテストデータです。
また、すべての画像に「5」「0」「4」などの正解が記されたラベルがつけられています。
今回は、この MNIST を使って、画像に書かれている数字を推測するモデルを構築していきましょう!
データセットのロード
まずは、データセットをロードします。
1 2 3 4 5 6 7 8 | (x_train, y_train), (x_test, y_test) = datasets.mnist.load_data() # モデルを訓練するときのためにサイズを変更する x_train.resize(60000, 28, 28, 1) x_test.resize(10000, 28, 28, 1) print(x_train.shape, y_train.shape) # (60000, 28, 28, 1) (60000,) print(x_test.shape, y_test.shape) # (10000, 28, 28, 1) (10000,) |
x_train と y_train はそれぞれ「訓練データ」の画像とラベルで、 x_test と y_test はそれぞれ「テストデータ」の画像とラベルです。
訓練データには60,000件、テストデータには10,000件のデータがあり、画像は28×28ピクセル、ラベルはそれぞれ1つの値であることが確認できますね。
データの前処理
データセットをロードできたら、モデルの構築をする前に、前処理をしましょう。
画像データのピクセルは「0~255」までの整数をとりますが、これを「0~1」に正規化します。
1 2 3 4 5 | x_train = x_train / 255.0 x_test = x_test / 255.0 print('Max:', x_train.max(), ', Min:', x_train.min()) # Max: 1.0 , Min: 0.0 print('Max:', x_test.max(), ', Min:', x_test.min()) # Max: 1.0 , Min: 0.0 |
訓練データとテストデータともに、最大値が「1」、最小値が「0」のデータに正規化できました。
MNISTを画像分類するモデルを構築する
それでは、MNISTを画像分類するモデルを構築していきましょう!
今回は、4つの層からなる「簡単なモデル」を作成します。
1 2 3 4 5 6 | model = models.Sequential([ layers.Conv2D(16, (3, 3), activation='relu', input_shape=(28, 28, 1)), # 畳み込み layers.MaxPooling2D((2, 2)), # プーリング layers.Flatten(), #ベクトル化 layers.Dense(10, activation='softmax') # 出力 ]) |
ネットワークを定義したらモデルをコンパイルし、構築したモデルを確認します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | model.compile( optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'] ) model.summary() """ _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d_5 (Conv2D) (None, 26, 26, 16) 160 _________________________________________________________________ max_pooling2d_5 (MaxPooling2 (None, 13, 13, 16) 0 _________________________________________________________________ flatten_5 (Flatten) (None, 2704) 0 _________________________________________________________________ dense_6 (Dense) (None, 10) 27050 ================================================================= Total params: 27,210 Trainable params: 27,210 Non-trainable params: 0 _________________________________________________________________ """ |
問題なくモデルを構築することができました!
モデルを訓練する
モデルの構築が完了したら、次はモデルを訓練をしましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 | history = model.fit(x_train, y_train, validation_data=(x_test, y_test), epochs=10) """ Epoch 1/10 1875/1875 [==============================] - 20s 10ms/step - loss: 0.2849 - accuracy: 0.9194 - val_loss: 0.1273 - val_accuracy: 0.9646 Epoch 2/10 1875/1875 [==============================] - 19s 10ms/step - loss: 0.1103 - accuracy: 0.9692 - val_loss: 0.0820 - val_accuracy: 0.9748 Epoch 3/10 1875/1875 [==============================] - 19s 10ms/step - loss: 0.0753 - accuracy: 0.9783 - val_loss: 0.0679 - val_accuracy: 0.9775 (省略) Epoch 10/10 1875/1875 [==============================] - 19s 10ms/step - loss: 0.0089 - accuracy: 0.9976 - val_loss: 0.0679 - val_accuracy: 0.9827 """ |
Keras では、このように訓練の過程がデフォルトで可視化されます。
- 現在どのくらい学習が進んでいるのか
- 損失関数の値はどのくらいか
- 正解率がどのくらいか
これで、学習の様子を知ることができます。
しかし、このように損失値や正解率を数字で眺めても、いまいちピンと来ませんね。
そこで、グラフを描画するライブラリ「matplotlib」を使用して、これらの値の変化を可視化してみましょう!
学習の様子を可視化する
それでは、「matplotlib」を使って学習の様子を可視化しましょう。
実装例コード
学習を可視化するときのコードは、こちらです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | metrics = ['loss', 'accuracy'] # 使用する評価関数を指定 plt.figure(figsize=(10, 5)) # グラフを表示するスペースを用意 for i in range(len(metrics)): metric = metrics[i] plt.subplot(1, 2, i+1) # figureを1×2のスペースに分け、i+1番目のスペースを使う plt.title(metric) # グラフのタイトルを表示 plt_train = history.history[metric] # historyから訓練データの評価を取り出す plt_test = history.history['val_' + metric] # historyからテストデータの評価を取り出す plt.plot(plt_train, label='training') # 訓練データの評価をグラフにプロット plt.plot(plt_test, label='test') # テストデータの評価をグラフにプロット plt.legend() # ラベルの表示 plt.show() # グラフの表示 |
コードを解説するので、1つずつ見ていきましょう!
使用する評価関数を決める
まず最初のコードでは、使用する評価関数をリストとして指定します。
1 | metrics = ['loss', 'accuracy'] |
今回の場合は、損失関数 loss と正解率 accuracy を使用していますね。
なお、損失関数と評価関数は本来異なるものですが、今回は「モデルを評価できる関数」という意味で、「評価関数」として統一して説明します。
グラフを描画するための準備
plt.figure(figsize=(10, 5))は、matplotlib でグラフを表示するときに必要なコードです。
このコードでは、グラフを表示するスペース(この場合は10×5のスペース)を確保しています。
なお、for 文の中にある plt.subplot(2, 2, i+1) と plt.title(metric) はコメントの通り、グラフを描くスペースを決めてタイトルを表示するためのコードです。
評価を取得する
それでは、for 文の中を詳しく見てみましょう。
まずは、for 文を使うことで、 metrics から評価関数を1つずつ取り出し、 metrics に代入しています。
このことから、このループでは「評価関数ごとにグラフを表示していく(ループを繰り返す)」ということが分かりますね。
metric に評価関数を代入したら、次は history.history[metric] と history.history['val_' + metric] で、 history から評価関数の値を取得して plt_train と plt_test にそれぞれ代入します。
ところで、 history にはモデルをコンパイルしたときの返り値が代入されていましたね。
ここで、 history.history とすることで訓練中・テスト中の評価を取得することができます。
なお、テストの評価は val_metric のように、先頭に val_ をつけることで取り出せるため、テストデータの評価は plt_test = istory.history['val_' + metric] として取得しています。
評価をグラフ化する
訓練データとテストデータの評価を取得したら、これらの評価をグラフにプロットしましょう。
plt.plot(plt_train, label='training') では訓練データの評価である plt_train をグラフにプロットし、 plt.plot(plt_test, label='test') ではテストデータの評価である plt_test をグラフにプロットしています。
それぞれのグラフには training ラベルと test ラベルがついていますが、これらのラベルは plt.legend() で表示することが可能です。
コードを実行する
それでは、実際にコードを実行してみましょう。

無事にグラフが表示されました!
損失関数(左のグラフ)
左のグラフは、「損失関数の値をグラフにしたもの」です。
青い線が訓練中の損失値、オレンジの線がテスト中の損失値です。
ニューラルネットワークの学習では損失関数の値を小さくするように学習が進んでいくため、一般には損失値が小さいほど良いモデルであると考えられます。
ところが、可視化したグラフを見てみてみましょう!
4エポック目以降はテスト中の損失値があまり小さくならず、訓練中の損失値との差が徐々に広がっていることが分かりますね。
これは、4エポック目以降に「過学習」が発生していることを表しています。
正解率(右のグラフ)
右のグラフは、「正解率をグラフにしたもの」です。
左のグラフと同様に、青い線が訓練中の正解率、オレンジの線がテスト中の正解率を表しています。
正解率が高いほど良い状態なのですが、損失値と同じように、4エポック目以降はテスト中の正解率が停滞していることが分かりますよね。
こちらも、「過学習」を示すサインです。
このようにグラフを可視化することで、「モデルがどのように学習しているか」「モデルの学習中に問題が起こっていないか」などを簡単に理解することができるようになります。
グラフを可視化するメリットが十分に分かったところで、次は色々な評価関数を使って、モデルの学習過程を可視化してみましょう。
色々な評価関数で可視化してみる
先ほど可視化したのは「損失値」と「正解率」でしたが、他にも様々な評価関数の値を可視化することができます。
こちらは、先ほどモデルのコンパイルをしたときのコードです。
1 2 3 4 5 | model.compile( optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'] ) |
metrics=['accuracy'] と正解率で評価していましたが、この metrics に評価関数を指定することで、様々な種類の評価関数を使うことができます。
色々な評価関数を使った可視化の実装
それでは、他の評価関数を使ってモデルの学習を可視化してみましょう。
Keras では binary_accuracy 、 categorical_accuracy 、 sparse_categorical_accuracy 、 top_k_categorical_accuracy の4つの評価関数に加え、自分で作成した評価関数も使用することができます。
なお、単に accuracy を指定した場合には、4つの評価関数の中から最適な関数が適用されています。
それでは、実際に4つの評価関数をすべて使い、モデルが学習する様子を可視化してみましょう!
実装例コード
コードはこちらになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | # 使用する評価関数を指定 metrics = ['binary_accuracy', 'categorical_accuracy', 'sparse_categorical_accuracy', 'top_k_categorical_accuracy'] # 指定したmetricsでコンパイル model.compile( optimizer='adam', loss='sparse_categorical_crossentropy', metrics=metrics ) # モデルの訓練 history = model.fit(x_train, y_train, validation_data=(x_test, y_test), epochs=10) # グラフを描画 plt.figure(figsize=(10, 10)) # 10×10のスペースを用意 for i in range(len(metrics)): metric = metrics[i] plt.subplot(2, 2, i+1) # figureを2×2のスペースに分ける plt.title(metric) plt_train = history.history[metric] plt_test = history.history['val_' + metric] plt.plot(plt_train, label='training') plt.plot(plt_test, label='test') plt.legend() plt.show() |
ほとんどが先ほどのコードと同じなので、変わった部分について見ていきましょう!
評価関数をリスト指定
まず、 metrics = ['binary_accuracy', 'categorical_accuracy', 'sparse_categorical_accuracy', 'top_k_categorical_accuracy']では、4種類の評価関数をリストで指定しています。
モデルのコンパイルと訓練
上記で、使用する評価関数が変わったため、モデルのコンパイルと訓練をもう一度行います。
1 2 3 4 5 6 7 | model.compile( optimizer='adam', loss='sparse_categorical_crossentropy', metrics=metrics ) history = model.fit(x_train, y_train, validation_data=(x_test, y_test), epochs=10) |
metrics=metrics で左辺の metrics に渡しているのは、最初に指定したリストの metrics です。
グラフを表示
グラフを表示する部分はほとんど変わりません。
plt.figure(figsize=(10, 10)) ではグラフを表示するためのスペースを10×10で指定し、 plt.subplot(2, 2, i+1) では表示するスペースを2×2に分割しているだけです。
Keras は様々な評価関数が使える
このように、Keras では様々な評価関数を使って、モデルが学習する様子を簡単に可視化することもできます。
なお、自分で作成した評価関数についても metrics で指定すれば簡単に使えるので、気になる方はぜひ自作の評価関数で挑戦してみてください!
注意点
モデルをコンパイルする際、 metrics に loss を指定してしまうとエラーが発生してしまいます。
1 2 3 4 5 6 7 8 9 | model.compile( optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['loss'] # metricsにlossを指定している ) history = model.fit(x_train, y_train, validation_data=(x_test, y_test), epochs=10) # ValueError: Unknown metric function:loss |
これは「損失関数」が「評価関数」とは異なり、ディープラーニングに欠かせないものだからです。
ディープラーニングでは学習に「損失関数」を使っているため、 metrics に loss を指定せずとも、 history.history['loss'] のように「損失関数」の値を取得することができます。
さいごに
今回は、「ニューラルネットワークの学習過程を可視化」していきました。
「モデルがどのように訓練されているのか」
「モデルの学習中に問題が起こっていないか」
このような疑問は、実際に「TensorFlow」と「Keras」でモデルを構築し、学習の様子を可視化することで解決できます。
これを機に、ぜひ色々なニューラルネットワークを可視化してみましょう!
(株)ライトコードは、WEB・アプリ・ゲーム開発に強い、「好きを仕事にするエンジニア集団」です。
機械学習でのシステム開発依頼・お見積もりはこちらまでお願いします。
また、機械学習系エンジニアを積極採用中です!詳しくはこちらをご覧ください。
※現在、多数のお問合せを頂いており、返信に、多少お時間を頂く場合がございます。
こちらの記事もオススメ!
ライトコードよりお知らせ






一緒に働いてくれる仲間を募集しております!
ライトコードでは、仲間を募集しております!
当社のモットーは「好きなことを仕事にするエンジニア集団」「エンジニアによるエンジニアのための会社」。エンジニアであるあなたの「やってみたいこと」を全力で応援する会社です。
また、ライトコードは現在、急成長中!だからこそ、あなたにお任せしたいやりがいのあるお仕事は沢山あります。「コアメンバー」として活躍してくれる、あなたからのご応募をお待ちしております!
なお、ご応募の前に、「話しだけ聞いてみたい」「社内の雰囲気を知りたい」という方はこちらをご覧ください。
ライトコードでは一緒に働いていただける方を募集しております!
採用情報はこちら書いた人はこんな人

ITエンタメ2021.01.12【スティーブ・ウォズニアック】アップルコンピューターのもう一人の創業者!
IT技術2021.01.11React Hooks登場でコンポーネントはどう変わった?
IT技術2021.01.05【Unity】Rigidbodyの基本
IT技術2021.01.04【Unity】ARkit3を使ったARアプリを開発する方法を解説(AR foundation,iOS)