ホーム » Keras » TensorFlow 2.0 : Tutorials : Keras ML 基本 :- overfitting と underfitting を調査する

TensorFlow 2.0 : Tutorials : Keras ML 基本 :- overfitting と underfitting を調査する

TensorFlow 2.0 : Beginner Tutorials : Keras ML 基本 :- overfitting と underfitting を調査する (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 10/04/2019

* 本ページは、TensorFlow org サイトの TF 2.0 – Beginner Tutorials – ML basics with Keras の以下のページを翻訳した上で
適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

無料セミナー開催中 クラスキャット主催 人工知能 & ビジネス Web セミナー

人工知能とビジネスをテーマにウェビナー (WEB セミナー) を定期的に開催しています。スケジュールは弊社 公式 Web サイト でご確認頂けます。
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
  • Windows PC のブラウザからご参加が可能です。スマートデバイスもご利用可能です。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/
Facebook: https://www.facebook.com/ClassCatJP/

 

Keras ML 基本 :- overfitting と underfitting を調査する

いつものように、このサンプルのコードは tf.keras API を使用します、これについては TensorFlow Keras ガイド で更に学習できます。

前の例の両者 — 映画レビューの分類と燃費効率の予測 — では、検証データ上のモデルの精度が幾つかのエポックの訓練後に最大になり、それから減少し始めることを見ました。

換言すれば、モデルは訓練データに overfit しています。overfitting にどのように対処するかを学ぶことは重要です。訓練セット上で高い精度を獲得することはしばしば可能ですが、本当に望むことはテストデータ (あるいは前にまだ見ていないデータ) に上手く一般化されたモデルを開発することです。

overfitting の反対は underfitting です。underfitting は テストデータ上でまだ改善の余地があるときに発生します。これは幾つかの理由で起こります : モデルが十分にパワフルでない場合、過剰に正則化されている、あるいは単に十分に長く訓練されていない場合。これはネットワークが訓練データ内の関連するパターンを学習していないことを意味しています。

けれども長すぎる訓練をする場合、モデルは overfit し始めて訓練データからテストデータに一般化されないパターンを学習するでしょう。上手くバランスを取る必要があります。どのように適切な数のエポックの間訓練するかを理解することは下で探究するように有用なスキルです。

overfitting を回避するためには、最善の解法はより多くの訓練データを使用することです。より多くのデータ上で訓練されたモデルは自然により良く一般化されます。それが最早可能ではないとき、次善の解法は正則化のようなテクニックを使用することです。これらはモデルがストアできる情報の量とタイプに制約を課します。ネットワークが小さい数のパターンを記憶する余裕だけがある場合、最適化プロセスはそれに最も目立つパターンに注目するように強制します、これは上手く一般化するより良い可能性を持ちます。

このノートブックでは、2 つの一般的な正則化テクニックを探究します — 重み正則化と dropout です — そしてそれらを使用して IMDB 映画レビュー分類ノートブックを改良します。

from __future__ import absolute_import, division, print_function, unicode_literals

import tensorflow as tf
from tensorflow import keras

import numpy as np
import matplotlib.pyplot as plt

print(tf.__version__)
2.0.0

 

IMDB データセットをダウンロードする

前のノートブックのように埋め込みを使用するのではなく、ここではセンテンスを multi-hot エンコードします。このモデルは訓練セットに対して素早く overfit します。それは overfitting が発生するとき、それとどのように戦うかを実演するために使用されます。

リストの multi-hot エンコーディングはそれらを 0 と 1 のベクトルに変えることを意味します。具体的には、これは例えばシークエンス [3, 5] を (1 となる) インデックス 3 と 5 を除いて総て 0 の 10,000 次元ベクトルに変えることを意味します。

NUM_WORDS = 10000

(train_data, train_labels), (test_data, test_labels) = keras.datasets.imdb.load_data(num_words=NUM_WORDS)

def multi_hot_sequences(sequences, dimension):
    # Create an all-zero matrix of shape (len(sequences), dimension)
    results = np.zeros((len(sequences), dimension))
    for i, word_indices in enumerate(sequences):
        results[i, word_indices] = 1.0  # set specific indices of results[i] to 1s
    return results


train_data = multi_hot_sequences(train_data, dimension=NUM_WORDS)
test_data = multi_hot_sequences(test_data, dimension=NUM_WORDS)
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/imdb.npz
17465344/17464789 [==============================] - 0s 0us/step

結果としての multi-hot ベクトルの一つを見てみましょう。単語インデックスは頻度でソートされますので、プロットで見て取れるように、インデックス 0 の近くにはより多くの 1-値があることが予想されます :

plt.plot(train_data[0])
[<matplotlib.lines.Line2D at 0x7f3e71290630>]

 

overfitting を実演する

overfitting を回避する最も単純な方法はモデルのサイズ, i.e. モデルの学習可能なパラメータの数 (これは層数と層毎のユニット数により決定されます) を減じることです。深層学習では、モデルの学習可能なパラメータ数はしばしばモデルの “capacity” として参照されます。直感的には、より多くのパラメータを持つモデルはより多くの “記憶 capacity” を持ちそしてそれ故に訓練サンプルとターゲットの間の完全な辞書ライクなマッピング、どのような一般化力もないマッピングを容易に学習可能です、しかしこれは以前に見ていないデータ上で予測を行なうときに役に立ちません。

これを常に念頭に置いてください : 深層学習モデルは訓練データに fit するには良い傾向がありますが、実際の課題は一般化であり、fitting ではありません。

その一方で、ネットワークが制限された記憶リソースを持つ場合には、マッピングを容易には学習することができないでしょう。その損失を最小化するためには、より予測力を持つ圧縮された (= compressed) 表現を学習しなければなりません。同時に、モデルを小さくし過ぎれば、それは訓練データに fit することが困難になるでしょう。これは “too much capacity” と “not enough capacity” の間のバランスです。

不幸なことに、(層の数や各層のための正しいサイズの視点から) モデルの正しいサイズやアーキテクチャを決定するための魔法の公式はありません。異なるアーキテクチャのシリーズを使用して実験しなければなりません。

適切なモデルサイズを見つけるためには、比較的少ない層とパラメータで始めて、それから検証損失上のリターンが減衰し始めるまで層のサイズを増やしたり新しい層を追加し始めます。これを映画レビュー分類ネットワークで試してみましょう。

ベースラインとして Dense 層だけを使用する単純なモデルを作成します、それからより小さいものと大きいバージョンを作成し、それらを比較してみます。

 

ベースライン・モデルを作成する

baseline_model = keras.Sequential([
    # `input_shape` is only required here so that `.summary` works.
    keras.layers.Dense(16, activation='relu', input_shape=(NUM_WORDS,)),
    keras.layers.Dense(16, activation='relu'),
    keras.layers.Dense(1, activation='sigmoid')
])

baseline_model.compile(optimizer='adam',
                       loss='binary_crossentropy',
                       metrics=['accuracy', 'binary_crossentropy'])

baseline_model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 16)                160016    
_________________________________________________________________
dense_1 (Dense)              (None, 16)                272       
_________________________________________________________________
dense_2 (Dense)              (None, 1)                 17        
=================================================================
Total params: 160,305
Trainable params: 160,305
Non-trainable params: 0
_________________________________________________________________
baseline_history = baseline_model.fit(train_data,
                                      train_labels,
                                      epochs=20,
                                      batch_size=512,
                                      validation_data=(test_data, test_labels),
                                      verbose=2)
Train on 25000 samples, validate on 25000 samples
Epoch 1/20
25000/25000 - 3s - loss: 0.4629 - accuracy: 0.8118 - binary_crossentropy: 0.4629 - val_loss: 0.3224 - val_accuracy: 0.8776 - val_binary_crossentropy: 0.3224
Epoch 2/20
25000/25000 - 2s - loss: 0.2377 - accuracy: 0.9143 - binary_crossentropy: 0.2377 - val_loss: 0.2824 - val_accuracy: 0.8877 - val_binary_crossentropy: 0.2824
Epoch 3/20
25000/25000 - 2s - loss: 0.1766 - accuracy: 0.9381 - binary_crossentropy: 0.1766 - val_loss: 0.3035 - val_accuracy: 0.8799 - val_binary_crossentropy: 0.3035
Epoch 4/20
25000/25000 - 2s - loss: 0.1394 - accuracy: 0.9520 - binary_crossentropy: 0.1394 - val_loss: 0.3174 - val_accuracy: 0.8783 - val_binary_crossentropy: 0.3174
Epoch 5/20
25000/25000 - 2s - loss: 0.1129 - accuracy: 0.9637 - binary_crossentropy: 0.1129 - val_loss: 0.3480 - val_accuracy: 0.8734 - val_binary_crossentropy: 0.3480
Epoch 6/20
25000/25000 - 2s - loss: 0.0910 - accuracy: 0.9734 - binary_crossentropy: 0.0910 - val_loss: 0.3837 - val_accuracy: 0.8699 - val_binary_crossentropy: 0.3837
Epoch 7/20
25000/25000 - 2s - loss: 0.0729 - accuracy: 0.9795 - binary_crossentropy: 0.0729 - val_loss: 0.4268 - val_accuracy: 0.8647 - val_binary_crossentropy: 0.4268
Epoch 8/20
25000/25000 - 2s - loss: 0.0576 - accuracy: 0.9854 - binary_crossentropy: 0.0576 - val_loss: 0.4668 - val_accuracy: 0.8619 - val_binary_crossentropy: 0.4668
Epoch 9/20
25000/25000 - 2s - loss: 0.0448 - accuracy: 0.9909 - binary_crossentropy: 0.0448 - val_loss: 0.5207 - val_accuracy: 0.8581 - val_binary_crossentropy: 0.5207
Epoch 10/20
25000/25000 - 2s - loss: 0.0345 - accuracy: 0.9938 - binary_crossentropy: 0.0345 - val_loss: 0.5537 - val_accuracy: 0.8582 - val_binary_crossentropy: 0.5537
Epoch 11/20
25000/25000 - 2s - loss: 0.0260 - accuracy: 0.9962 - binary_crossentropy: 0.0260 - val_loss: 0.6112 - val_accuracy: 0.8553 - val_binary_crossentropy: 0.6112
Epoch 12/20
25000/25000 - 2s - loss: 0.0193 - accuracy: 0.9980 - binary_crossentropy: 0.0193 - val_loss: 0.6450 - val_accuracy: 0.8554 - val_binary_crossentropy: 0.6450
Epoch 13/20
25000/25000 - 2s - loss: 0.0145 - accuracy: 0.9988 - binary_crossentropy: 0.0145 - val_loss: 0.6834 - val_accuracy: 0.8546 - val_binary_crossentropy: 0.6834
Epoch 14/20
25000/25000 - 2s - loss: 0.0109 - accuracy: 0.9995 - binary_crossentropy: 0.0109 - val_loss: 0.7230 - val_accuracy: 0.8531 - val_binary_crossentropy: 0.7230
Epoch 15/20
25000/25000 - 2s - loss: 0.0084 - accuracy: 0.9997 - binary_crossentropy: 0.0084 - val_loss: 0.7577 - val_accuracy: 0.8526 - val_binary_crossentropy: 0.7577
Epoch 16/20
25000/25000 - 2s - loss: 0.0066 - accuracy: 0.9999 - binary_crossentropy: 0.0066 - val_loss: 0.7853 - val_accuracy: 0.8528 - val_binary_crossentropy: 0.7853
Epoch 17/20
25000/25000 - 2s - loss: 0.0052 - accuracy: 1.0000 - binary_crossentropy: 0.0052 - val_loss: 0.8236 - val_accuracy: 0.8521 - val_binary_crossentropy: 0.8236
Epoch 18/20
25000/25000 - 2s - loss: 0.0043 - accuracy: 1.0000 - binary_crossentropy: 0.0043 - val_loss: 0.8500 - val_accuracy: 0.8520 - val_binary_crossentropy: 0.8500
Epoch 19/20
25000/25000 - 2s - loss: 0.0036 - accuracy: 1.0000 - binary_crossentropy: 0.0036 - val_loss: 0.8752 - val_accuracy: 0.8519 - val_binary_crossentropy: 0.8752
Epoch 20/20
25000/25000 - 2s - loss: 0.0031 - accuracy: 1.0000 - binary_crossentropy: 0.0031 - val_loss: 0.8978 - val_accuracy: 0.8521 - val_binary_crossentropy: 0.8978

 

より小さいモデルを作成する

作成したばかりのベースライン・モデルに対して比較するためにより少ない隠れユニットを持つモデルを作成しましょう :

smaller_model = keras.Sequential([
    keras.layers.Dense(4, activation='relu', input_shape=(NUM_WORDS,)),
    keras.layers.Dense(4, activation='relu'),
    keras.layers.Dense(1, activation='sigmoid')
])

smaller_model.compile(optimizer='adam',
                      loss='binary_crossentropy',
                      metrics=['accuracy', 'binary_crossentropy'])

smaller_model.summary()
Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_3 (Dense)              (None, 4)                 40004     
_________________________________________________________________
dense_4 (Dense)              (None, 4)                 20        
_________________________________________________________________
dense_5 (Dense)              (None, 1)                 5         
=================================================================
Total params: 40,029
Trainable params: 40,029
Non-trainable params: 0
_________________________________________________________________

そして同じデータを使用してモデルを訓練します :

smaller_history = smaller_model.fit(train_data,
                                    train_labels,
                                    epochs=20,
                                    batch_size=512,
                                    validation_data=(test_data, test_labels),
                                    verbose=2)
Train on 25000 samples, validate on 25000 samples
Epoch 1/20
25000/25000 - 2s - loss: 0.6136 - accuracy: 0.7166 - binary_crossentropy: 0.6136 - val_loss: 0.5074 - val_accuracy: 0.8207 - val_binary_crossentropy: 0.5074
Epoch 2/20
25000/25000 - 1s - loss: 0.3874 - accuracy: 0.8805 - binary_crossentropy: 0.3874 - val_loss: 0.3464 - val_accuracy: 0.8756 - val_binary_crossentropy: 0.3464
Epoch 3/20
25000/25000 - 2s - loss: 0.2706 - accuracy: 0.9104 - binary_crossentropy: 0.2706 - val_loss: 0.2991 - val_accuracy: 0.8856 - val_binary_crossentropy: 0.2991
Epoch 4/20
25000/25000 - 2s - loss: 0.2177 - accuracy: 0.9271 - binary_crossentropy: 0.2177 - val_loss: 0.2868 - val_accuracy: 0.8867 - val_binary_crossentropy: 0.2868
Epoch 5/20
25000/25000 - 2s - loss: 0.1848 - accuracy: 0.9387 - binary_crossentropy: 0.1848 - val_loss: 0.2858 - val_accuracy: 0.8858 - val_binary_crossentropy: 0.2858
Epoch 6/20
25000/25000 - 2s - loss: 0.1620 - accuracy: 0.9463 - binary_crossentropy: 0.1620 - val_loss: 0.2878 - val_accuracy: 0.8852 - val_binary_crossentropy: 0.2878
Epoch 7/20
25000/25000 - 2s - loss: 0.1425 - accuracy: 0.9554 - binary_crossentropy: 0.1425 - val_loss: 0.2963 - val_accuracy: 0.8831 - val_binary_crossentropy: 0.2963
Epoch 8/20
25000/25000 - 2s - loss: 0.1276 - accuracy: 0.9599 - binary_crossentropy: 0.1276 - val_loss: 0.3082 - val_accuracy: 0.8803 - val_binary_crossentropy: 0.3082
Epoch 9/20
25000/25000 - 2s - loss: 0.1149 - accuracy: 0.9647 - binary_crossentropy: 0.1149 - val_loss: 0.3216 - val_accuracy: 0.8783 - val_binary_crossentropy: 0.3216
Epoch 10/20
25000/25000 - 2s - loss: 0.1037 - accuracy: 0.9694 - binary_crossentropy: 0.1037 - val_loss: 0.3371 - val_accuracy: 0.8757 - val_binary_crossentropy: 0.3371
Epoch 11/20
25000/25000 - 2s - loss: 0.0934 - accuracy: 0.9740 - binary_crossentropy: 0.0934 - val_loss: 0.3543 - val_accuracy: 0.8726 - val_binary_crossentropy: 0.3543
Epoch 12/20
25000/25000 - 2s - loss: 0.0844 - accuracy: 0.9761 - binary_crossentropy: 0.0844 - val_loss: 0.3714 - val_accuracy: 0.8712 - val_binary_crossentropy: 0.3714
Epoch 13/20
25000/25000 - 2s - loss: 0.0766 - accuracy: 0.9795 - binary_crossentropy: 0.0766 - val_loss: 0.3930 - val_accuracy: 0.8680 - val_binary_crossentropy: 0.3930
Epoch 14/20
25000/25000 - 2s - loss: 0.0686 - accuracy: 0.9832 - binary_crossentropy: 0.0686 - val_loss: 0.4103 - val_accuracy: 0.8660 - val_binary_crossentropy: 0.4103
Epoch 15/20
25000/25000 - 2s - loss: 0.0620 - accuracy: 0.9857 - binary_crossentropy: 0.0620 - val_loss: 0.4330 - val_accuracy: 0.8638 - val_binary_crossentropy: 0.4330
Epoch 16/20
25000/25000 - 2s - loss: 0.0558 - accuracy: 0.9886 - binary_crossentropy: 0.0558 - val_loss: 0.4543 - val_accuracy: 0.8626 - val_binary_crossentropy: 0.4543
Epoch 17/20
25000/25000 - 2s - loss: 0.0503 - accuracy: 0.9902 - binary_crossentropy: 0.0503 - val_loss: 0.4837 - val_accuracy: 0.8604 - val_binary_crossentropy: 0.4837
Epoch 18/20
25000/25000 - 2s - loss: 0.0451 - accuracy: 0.9920 - binary_crossentropy: 0.0451 - val_loss: 0.5002 - val_accuracy: 0.8598 - val_binary_crossentropy: 0.5002
Epoch 19/20
25000/25000 - 2s - loss: 0.0403 - accuracy: 0.9932 - binary_crossentropy: 0.0403 - val_loss: 0.5244 - val_accuracy: 0.8582 - val_binary_crossentropy: 0.5244
Epoch 20/20
25000/25000 - 2s - loss: 0.0356 - accuracy: 0.9947 - binary_crossentropy: 0.0356 - val_loss: 0.5418 - val_accuracy: 0.8576 - val_binary_crossentropy: 0.5418

 

より大きいモデルを作成する

エクササイズとして、より大きいモデルさえも作成して、それがどのように素早く overfitting し始めるかを見ることができます。次に、このベンチマークに、問題が必要とするよりも遥かにより大きい capacity を持つネットワークを追加しましょう :

bigger_model = keras.models.Sequential([
    keras.layers.Dense(512, activation='relu', input_shape=(NUM_WORDS,)),
    keras.layers.Dense(512, activation='relu'),
    keras.layers.Dense(1, activation='sigmoid')
])

bigger_model.compile(optimizer='adam',
                     loss='binary_crossentropy',
                     metrics=['accuracy','binary_crossentropy'])

bigger_model.summary()
Model: "sequential_2"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_6 (Dense)              (None, 512)               5120512   
_________________________________________________________________
dense_7 (Dense)              (None, 512)               262656    
_________________________________________________________________
dense_8 (Dense)              (None, 1)                 513       
=================================================================
Total params: 5,383,681
Trainable params: 5,383,681
Non-trainable params: 0
_________________________________________________________________

そして、再度、同じデータを使用してモデルを訓練します :

bibigger_history = bigger_model.fit(train_data, train_labels,
                                  epochs=20,
                                  batch_size=512,
                                  validation_data=(test_data, test_labels),
                                  verbose=2)
Train on 25000 samples, validate on 25000 samples
Epoch 1/20
25000/25000 - 2s - loss: 0.3632 - accuracy: 0.8388 - binary_crossentropy: 0.3632 - val_loss: 0.3111 - val_accuracy: 0.8732 - val_binary_crossentropy: 0.3111
Epoch 2/20
25000/25000 - 2s - loss: 0.1507 - accuracy: 0.9453 - binary_crossentropy: 0.1507 - val_loss: 0.3334 - val_accuracy: 0.8712 - val_binary_crossentropy: 0.3334
Epoch 3/20
25000/25000 - 2s - loss: 0.0520 - accuracy: 0.9848 - binary_crossentropy: 0.0520 - val_loss: 0.4234 - val_accuracy: 0.8711 - val_binary_crossentropy: 0.4234
Epoch 4/20
25000/25000 - 2s - loss: 0.0073 - accuracy: 0.9988 - binary_crossentropy: 0.0073 - val_loss: 0.5934 - val_accuracy: 0.8643 - val_binary_crossentropy: 0.5934
Epoch 5/20
25000/25000 - 2s - loss: 0.0015 - accuracy: 1.0000 - binary_crossentropy: 0.0015 - val_loss: 0.6518 - val_accuracy: 0.8715 - val_binary_crossentropy: 0.6518
Epoch 6/20
25000/25000 - 2s - loss: 2.7016e-04 - accuracy: 1.0000 - binary_crossentropy: 2.7016e-04 - val_loss: 0.6956 - val_accuracy: 0.8729 - val_binary_crossentropy: 0.6956
Epoch 7/20
25000/25000 - 2s - loss: 1.5716e-04 - accuracy: 1.0000 - binary_crossentropy: 1.5716e-04 - val_loss: 0.7263 - val_accuracy: 0.8731 - val_binary_crossentropy: 0.7263
Epoch 8/20
25000/25000 - 2s - loss: 1.1159e-04 - accuracy: 1.0000 - binary_crossentropy: 1.1159e-04 - val_loss: 0.7499 - val_accuracy: 0.8730 - val_binary_crossentropy: 0.7499
Epoch 9/20
25000/25000 - 2s - loss: 8.5236e-05 - accuracy: 1.0000 - binary_crossentropy: 8.5236e-05 - val_loss: 0.7686 - val_accuracy: 0.8728 - val_binary_crossentropy: 0.7686
Epoch 10/20
25000/25000 - 2s - loss: 6.7757e-05 - accuracy: 1.0000 - binary_crossentropy: 6.7757e-05 - val_loss: 0.7851 - val_accuracy: 0.8726 - val_binary_crossentropy: 0.7851
Epoch 11/20
25000/25000 - 2s - loss: 5.5290e-05 - accuracy: 1.0000 - binary_crossentropy: 5.5290e-05 - val_loss: 0.7995 - val_accuracy: 0.8726 - val_binary_crossentropy: 0.7995
Epoch 12/20
25000/25000 - 2s - loss: 4.6074e-05 - accuracy: 1.0000 - binary_crossentropy: 4.6074e-05 - val_loss: 0.8120 - val_accuracy: 0.8725 - val_binary_crossentropy: 0.8120
Epoch 13/20
25000/25000 - 2s - loss: 3.8983e-05 - accuracy: 1.0000 - binary_crossentropy: 3.8983e-05 - val_loss: 0.8241 - val_accuracy: 0.8728 - val_binary_crossentropy: 0.8241
Epoch 14/20
25000/25000 - 2s - loss: 3.3416e-05 - accuracy: 1.0000 - binary_crossentropy: 3.3416e-05 - val_loss: 0.8348 - val_accuracy: 0.8728 - val_binary_crossentropy: 0.8348
Epoch 15/20
25000/25000 - 2s - loss: 2.8980e-05 - accuracy: 1.0000 - binary_crossentropy: 2.8980e-05 - val_loss: 0.8449 - val_accuracy: 0.8728 - val_binary_crossentropy: 0.8449
Epoch 16/20
25000/25000 - 2s - loss: 2.5312e-05 - accuracy: 1.0000 - binary_crossentropy: 2.5312e-05 - val_loss: 0.8543 - val_accuracy: 0.8728 - val_binary_crossentropy: 0.8543
Epoch 17/20
25000/25000 - 2s - loss: 2.2330e-05 - accuracy: 1.0000 - binary_crossentropy: 2.2330e-05 - val_loss: 0.8633 - val_accuracy: 0.8730 - val_binary_crossentropy: 0.8633
Epoch 18/20
25000/25000 - 2s - loss: 1.9788e-05 - accuracy: 1.0000 - binary_crossentropy: 1.9788e-05 - val_loss: 0.8720 - val_accuracy: 0.8730 - val_binary_crossentropy: 0.8720
Epoch 19/20
25000/25000 - 2s - loss: 1.7688e-05 - accuracy: 1.0000 - binary_crossentropy: 1.7688e-05 - val_loss: 0.8800 - val_accuracy: 0.8731 - val_binary_crossentropy: 0.8800
Epoch 20/20
25000/25000 - 2s - loss: 1.5866e-05 - accuracy: 1.0000 - binary_crossentropy: 1.5866e-05 - val_loss: 0.8877 - val_accuracy: 0.8730 - val_binary_crossentropy: 0.8877

 

訓練と検証損失をプロットする

実線は訓練損失を示し、破線は検証損失を表示します (remember: より低い検証損失はより良いモデルを示します)。ここで、より小さいネットワークはベースラインモデルよりも後で overfitting し始めて (4 ではなくて 6 エポック後) そしてそのパフォーマンスはそれがひとたび overfitting し始めれば遥かによりゆっくりと低下します。

def plot_history(histories, key='binary_crossentropy'):
  plt.figure(figsize=(16,10))

  for name, history in histories:
    val = plt.plot(history.epoch, history.history['val_'+key],
                   '--', label=name.title()+' Val')
    plt.plot(history.epoch, history.history[key], color=val[0].get_color(),
             label=name.title()+' Train')

  plt.xlabel('Epochs')
  plt.ylabel(key.replace('_',' ').title())
  plt.legend()

  plt.xlim([0,max(history.epoch)])


plot_history([('baseline', baseline_history),
              ('smaller', smaller_history),
              ('bigger', bigger_history)])

より大きいネットワークは殆ど直ちに、丁度 1 エポック後に overfitting し始めます、そして遥かにより厳しく overfit することが分かるでしょう。ネットワークがより多くの capacity を持つほど、より素早く訓練データをモデル化することが可能です (低い訓練損失という結果になります) が、それはより overfitting しやすいです (訓練と検証損失間の巨大な差異という結果になります) 。

 

overfitting を回避するためのストラテジー

重み正則化を追加する

貴方はオッカムの剃刀の原理に馴染みがあるかもしれません: 何かについて 2 つの説明が与えられたとき、最も正しい可能性がある説明は「最も単純な」もの、最小量の仮定をするものです。これはまたニューラルネットワークにより学習されたモデルにも適用されます : ある訓練データとネットワーク・アーキテクチャが与えられたとき、データを説明できる重み値の複数のセット (複数のモデル) があり、そしてより単純なモデルは複雑なものよりも overfit する可能性が低いです。

このコンテキストでの「単純なモデル」はそこではパラメータ値の分布がより少ないエントロピーを持ちます (あるいはまとめてより少ないパラメータを持つモデルです、上のセクションで見たように)。そのため overfitting を軽減する一般的な方法はその (ネットワークの) 重みを小さい値だけを取るように強制してネットワークの複雑さに制約を置くことです、それは重み値の分布をより「正則 (= regular)」にします。これは「重み正則化」と呼ばれ、それはネットワークの損失関数に巨大な重みを持つことに関するコストを追加することによって成されます。このコストは 2 つのフレーバーに分けられます :

  • L1 正則化, そこでは追加されるコストは重み係数の絶対値に (i.e. 重みの「L1 ノルム」と呼称されるものに) 比例します。
  • L2 正則化, そこでは追加されるコストは重み係数の値の二乗に (i.e. 重みの「L2 ノルム」と呼称されるものに) 比例します。L2 正則化はまたニューラルネットワークのコンテキストでは重み減衰とも呼称されます。異なる名前に混乱してはいけません。重み減衰は数学的には L2 正則化と正確に同じです。

L1 正則化は重みパラメータの幾つかをゼロにするために疎性を導入します。L2 正則化は重みパラメータにそれらを疎にすることなくペナルティを課します – L2 がより一般的である一つの理由です。

tf.keras では、重み正則化は層にキーワード引数として重み regularizer インスタンスを渡すことにより追加されます。今は L2 重み正則化を追加しましょう。

l2_model = keras.models.Sequential([
    keras.layers.Dense(16, kernel_regularizer=keras.regularizers.l2(0.001),
                       activation='relu', input_shape=(NUM_WORDS,)),
    keras.layers.Dense(16, kernel_regularizer=keras.regularizers.l2(0.001),
                       activation='relu'),
    keras.layers.Dense(1, activation='sigmoid')
])

l2_model.compile(optimizer='adam',
                 loss='binary_crossentropy',
                 metrics=['accuracy', 'binary_crossentropy'])

l2_model_history = l2_model.fit(train_data, train_labels,
                                epochs=20,
                                batch_size=512,
                                validation_data=(test_data, test_labels),
                                verbose=2)
Train on 25000 samples, validate on 25000 samples
Epoch 1/20
25000/25000 - 2s - loss: 0.4830 - accuracy: 0.8133 - binary_crossentropy: 0.4422 - val_loss: 0.3531 - val_accuracy: 0.8826 - val_binary_crossentropy: 0.3105
Epoch 2/20
25000/25000 - 1s - loss: 0.2810 - accuracy: 0.9154 - binary_crossentropy: 0.2355 - val_loss: 0.3295 - val_accuracy: 0.8873 - val_binary_crossentropy: 0.2820
Epoch 3/20
25000/25000 - 2s - loss: 0.2358 - accuracy: 0.9354 - binary_crossentropy: 0.1864 - val_loss: 0.3399 - val_accuracy: 0.8825 - val_binary_crossentropy: 0.2889
Epoch 4/20
25000/25000 - 2s - loss: 0.2133 - accuracy: 0.9445 - binary_crossentropy: 0.1609 - val_loss: 0.3569 - val_accuracy: 0.8791 - val_binary_crossentropy: 0.3034
Epoch 5/20
25000/25000 - 2s - loss: 0.2009 - accuracy: 0.9507 - binary_crossentropy: 0.1463 - val_loss: 0.3721 - val_accuracy: 0.8764 - val_binary_crossentropy: 0.3164
Epoch 6/20
25000/25000 - 2s - loss: 0.1911 - accuracy: 0.9558 - binary_crossentropy: 0.1342 - val_loss: 0.3923 - val_accuracy: 0.8722 - val_binary_crossentropy: 0.3348
Epoch 7/20
25000/25000 - 2s - loss: 0.1826 - accuracy: 0.9580 - binary_crossentropy: 0.1242 - val_loss: 0.4081 - val_accuracy: 0.8702 - val_binary_crossentropy: 0.3491
Epoch 8/20
25000/25000 - 2s - loss: 0.1810 - accuracy: 0.9579 - binary_crossentropy: 0.1209 - val_loss: 0.4244 - val_accuracy: 0.8674 - val_binary_crossentropy: 0.3633
Epoch 9/20
25000/25000 - 2s - loss: 0.1751 - accuracy: 0.9609 - binary_crossentropy: 0.1134 - val_loss: 0.4368 - val_accuracy: 0.8640 - val_binary_crossentropy: 0.3745
Epoch 10/20
25000/25000 - 2s - loss: 0.1685 - accuracy: 0.9646 - binary_crossentropy: 0.1056 - val_loss: 0.4534 - val_accuracy: 0.8626 - val_binary_crossentropy: 0.3900
Epoch 11/20
25000/25000 - 2s - loss: 0.1637 - accuracy: 0.9678 - binary_crossentropy: 0.0996 - val_loss: 0.4678 - val_accuracy: 0.8616 - val_binary_crossentropy: 0.4031
Epoch 12/20
25000/25000 - 2s - loss: 0.1593 - accuracy: 0.9706 - binary_crossentropy: 0.0941 - val_loss: 0.4777 - val_accuracy: 0.8622 - val_binary_crossentropy: 0.4119
Epoch 13/20
25000/25000 - 2s - loss: 0.1551 - accuracy: 0.9718 - binary_crossentropy: 0.0887 - val_loss: 0.4929 - val_accuracy: 0.8623 - val_binary_crossentropy: 0.4261
Epoch 14/20
25000/25000 - 2s - loss: 0.1503 - accuracy: 0.9727 - binary_crossentropy: 0.0830 - val_loss: 0.5096 - val_accuracy: 0.8578 - val_binary_crossentropy: 0.4416
Epoch 15/20
25000/25000 - 2s - loss: 0.1462 - accuracy: 0.9777 - binary_crossentropy: 0.0777 - val_loss: 0.5244 - val_accuracy: 0.8558 - val_binary_crossentropy: 0.4558
Epoch 16/20
25000/25000 - 2s - loss: 0.1385 - accuracy: 0.9801 - binary_crossentropy: 0.0699 - val_loss: 0.5409 - val_accuracy: 0.8558 - val_binary_crossentropy: 0.4720
Epoch 17/20
25000/25000 - 2s - loss: 0.1376 - accuracy: 0.9804 - binary_crossentropy: 0.0683 - val_loss: 0.5409 - val_accuracy: 0.8578 - val_binary_crossentropy: 0.4709
Epoch 18/20
25000/25000 - 2s - loss: 0.1326 - accuracy: 0.9818 - binary_crossentropy: 0.0628 - val_loss: 0.5578 - val_accuracy: 0.8551 - val_binary_crossentropy: 0.4880
Epoch 19/20
25000/25000 - 2s - loss: 0.1292 - accuracy: 0.9848 - binary_crossentropy: 0.0591 - val_loss: 0.5672 - val_accuracy: 0.8575 - val_binary_crossentropy: 0.4970
Epoch 20/20
25000/25000 - 2s - loss: 0.1278 - accuracy: 0.9837 - binary_crossentropy: 0.0576 - val_loss: 0.5868 - val_accuracy: 0.8540 - val_binary_crossentropy: 0.5162

l2(0.001) は層の重み行列の総ての係数が 0.001 * weight_coefficient_value**2 をネットワークの総計損失に追加することを意味します。このペナルティは訓練時のみに追加されますので、このネットワークに対する損失はテスト時よりも訓練時に遥かに高くなることに注意してください。

L2 正則化ペナルティのインパクトがここにあります :

plot_history([('baseline', baseline_history),
              ('l2', l2_model_history)])

見て取れるように、両者のモデルが同じパラメータ数を持つ場合でさえも、L2 正則化されたモデルはベースライン・モデルよりも overfitting に大して遥かにより耐性があります。

 

dropout を追加する

Dropout は最も効果的で最も一般に使用されるニューラルネットワークのための正則化テクニックの一つで、University of Toronto の Hinton とその学生により開発されました。Dropout は層に適用され、訓練の間層の幾つかの出力特徴をランダムに “dropping out” (i.e. ゼロに設定) することから成ります。与えられた層は訓練の間に与えられた入力サンプルに対して通常はベクトル [0.2, 0.5, 1.3, 0.8, 1.1] を返したと仮定します ; dropout を適用した後、このベクトルはランダムに分布する幾つかのゼロ要素を持つでしょう、e.g. [0, 0.5, 1.3, 0, 1.1] です。”dropout 率” はゼロにされる特徴の割合です ; それは通常は 0.2 と 0.5 の間に設定されます。テスト時には、ユニットは drop out されず、代わりに層の出力値は dropout 率に等しい因子 (= factor) でスケールダウンされます、これは訓練時よりもより多いユニットが有効であるという事実のためにバランスを取るためです。

tf.keras では Dropout 層を通してネットワークに dropout を導入できます、それはすぐ前の層の出力に適用されます。

IMDB ネットワークに 2 つの Dropout 層をそれらがどのように上手く overfitting を減じるかを見るために追加しましょう :

dpt_model = keras.models.Sequential([
    keras.layers.Dense(16, activation='relu', input_shape=(NUM_WORDS,)),
    keras.layers.Dropout(0.5),
    keras.layers.Dense(16, activation='relu'),
    keras.layers.Dropout(0.5),
    keras.layers.Dense(1, activation='sigmoid')
])

dpt_model.compile(optimizer='adam',
                  loss='binary_crossentropy',
                  metrics=['accuracy','binary_crossentropy'])

dpt_model_history = dpt_model.fit(train_data, train_labels,
                                  epochs=20,
                                  batch_size=512,
                                  validation_data=(test_data, test_labels),
                                  verbose=2)
Train on 25000 samples, validate on 25000 samples
Epoch 1/20
25000/25000 - 2s - loss: 0.6462 - accuracy: 0.6234 - binary_crossentropy: 0.6462 - val_loss: 0.5490 - val_accuracy: 0.8367 - val_binary_crossentropy: 0.5490
Epoch 2/20
25000/25000 - 2s - loss: 0.4980 - accuracy: 0.7862 - binary_crossentropy: 0.4980 - val_loss: 0.3830 - val_accuracy: 0.8785 - val_binary_crossentropy: 0.3830
Epoch 3/20
25000/25000 - 2s - loss: 0.3816 - accuracy: 0.8632 - binary_crossentropy: 0.3816 - val_loss: 0.3146 - val_accuracy: 0.8863 - val_binary_crossentropy: 0.3146
Epoch 4/20
25000/25000 - 2s - loss: 0.3183 - accuracy: 0.8917 - binary_crossentropy: 0.3183 - val_loss: 0.2829 - val_accuracy: 0.8872 - val_binary_crossentropy: 0.2829
Epoch 5/20
25000/25000 - 2s - loss: 0.2693 - accuracy: 0.9120 - binary_crossentropy: 0.2693 - val_loss: 0.2768 - val_accuracy: 0.8886 - val_binary_crossentropy: 0.2768
Epoch 6/20
25000/25000 - 2s - loss: 0.2336 - accuracy: 0.9237 - binary_crossentropy: 0.2336 - val_loss: 0.2817 - val_accuracy: 0.8878 - val_binary_crossentropy: 0.2817
Epoch 7/20
25000/25000 - 2s - loss: 0.2032 - accuracy: 0.9346 - binary_crossentropy: 0.2032 - val_loss: 0.3035 - val_accuracy: 0.8854 - val_binary_crossentropy: 0.3035
Epoch 8/20
25000/25000 - 2s - loss: 0.1819 - accuracy: 0.9403 - binary_crossentropy: 0.1819 - val_loss: 0.3091 - val_accuracy: 0.8848 - val_binary_crossentropy: 0.3091
Epoch 9/20
25000/25000 - 2s - loss: 0.1634 - accuracy: 0.9484 - binary_crossentropy: 0.1634 - val_loss: 0.3387 - val_accuracy: 0.8834 - val_binary_crossentropy: 0.3387
Epoch 10/20
25000/25000 - 2s - loss: 0.1463 - accuracy: 0.9536 - binary_crossentropy: 0.1463 - val_loss: 0.3582 - val_accuracy: 0.8825 - val_binary_crossentropy: 0.3582
Epoch 11/20
25000/25000 - 2s - loss: 0.1325 - accuracy: 0.9590 - binary_crossentropy: 0.1325 - val_loss: 0.3648 - val_accuracy: 0.8814 - val_binary_crossentropy: 0.3648
Epoch 12/20
25000/25000 - 2s - loss: 0.1262 - accuracy: 0.9612 - binary_crossentropy: 0.1262 - val_loss: 0.3971 - val_accuracy: 0.8808 - val_binary_crossentropy: 0.3971
Epoch 13/20
25000/25000 - 2s - loss: 0.1119 - accuracy: 0.9646 - binary_crossentropy: 0.1119 - val_loss: 0.4107 - val_accuracy: 0.8796 - val_binary_crossentropy: 0.4107
Epoch 14/20
25000/25000 - 2s - loss: 0.1084 - accuracy: 0.9659 - binary_crossentropy: 0.1084 - val_loss: 0.4270 - val_accuracy: 0.8787 - val_binary_crossentropy: 0.4270
Epoch 15/20
25000/25000 - 2s - loss: 0.1006 - accuracy: 0.9699 - binary_crossentropy: 0.1006 - val_loss: 0.4258 - val_accuracy: 0.8776 - val_binary_crossentropy: 0.4258
Epoch 16/20
25000/25000 - 2s - loss: 0.0955 - accuracy: 0.9698 - binary_crossentropy: 0.0955 - val_loss: 0.4619 - val_accuracy: 0.8778 - val_binary_crossentropy: 0.4619
Epoch 17/20
25000/25000 - 2s - loss: 0.0878 - accuracy: 0.9730 - binary_crossentropy: 0.0878 - val_loss: 0.4991 - val_accuracy: 0.8771 - val_binary_crossentropy: 0.4991
Epoch 18/20
25000/25000 - 2s - loss: 0.0850 - accuracy: 0.9735 - binary_crossentropy: 0.0850 - val_loss: 0.5159 - val_accuracy: 0.8754 - val_binary_crossentropy: 0.5159
Epoch 19/20
25000/25000 - 2s - loss: 0.0790 - accuracy: 0.9756 - binary_crossentropy: 0.0790 - val_loss: 0.5484 - val_accuracy: 0.8759 - val_binary_crossentropy: 0.5484
Epoch 20/20
25000/25000 - 2s - loss: 0.0785 - accuracy: 0.9754 - binary_crossentropy: 0.0785 - val_loss: 0.5404 - val_accuracy: 0.8752 - val_binary_crossentropy: 0.5404
plot_history([('baseline', baseline_history),
              ('dropout', dpt_model_history)])

dropout の追加はベースライン・モデルを超える明確な改良です。

復習のために: ここにニューラルネットワークで overfitting を回避するための最も一般的な方法があります :

  • より多くの訓練データを得る。
  • ネットワークの capcity を減じる。
  • 重み正則を追加する。
  • dropout を追加する。

そしてこのガイドでカバーされていない 2 つの重要なアプローチはデータ増強とバッチ正規化です。

 

以上



AI導入支援 #2 ウェビナー

スモールスタートを可能としたAI導入支援   Vol.2
[無料 WEB セミナー] [詳細]
「画像認識 AI PoC スターターパック」の紹介
既に AI 技術を実ビジネスで活用し、成果を上げている日本企業も多く存在しており、競争優位なビジネスを展開しております。
しかしながら AI を導入したくとも PoC (概念実証) だけでも高額な費用がかかり取組めていない企業も少なくないようです。A I導入時には欠かせない PoC を手軽にしかも短期間で認知度を確認可能とするサービの紹介と共に、AI 技術の特性と具体的な導入プロセスに加え運用時のポイントについても解説いたします。
日時:2021年10月13日(水)
会場:WEBセミナー
共催:クラスキャット、日本FLOW(株)
後援:働き方改革推進コンソーシアム
参加費: 無料 (事前登録制)
人工知能開発支援
◆ クラスキャットは 人工知能研究開発支援 サービスを提供しています :
  • テクニカルコンサルティングサービス
  • 実証実験 (プロトタイプ構築)
  • アプリケーションへの実装
  • 人工知能研修サービス
◆ お問合せ先 ◆
(株)クラスキャット
セールス・インフォメーション
E-Mail:sales-info@classcat.com