tf.keras入門(4)Explore over-fitting and under-fitting


フィッティングと不フィッティングの探索


一般的な2つの正規化技術(重みの正規化と破棄)を探求し、IMDB映画評価分類ノートパソコンを改善します.
前回のように埋め込みを用いるのではなく,文を独熱符号化する.このモデルはすぐにフィットトレーニングセットを通過します.フィッティングがいつ発生したか、およびフィッティングを防止する方法を示すために使用されます.
深さ学習モデルは訓練データとフィットするのが上手であることが多いが、本当の挑戦はフィットではなく汎化であることを忘れないでください.

データプリプロセッシングとネットワーク構造


以前の埋め込み法とは異なり,ここではonehot符号化を直接用い,このモデルはすぐに訓練セットにフィットするであろう.
上から5つのモデルがあり、validationでの結果を比較します.
  • baseline_model
  • smaller_model
  • bigger_model
  • baseline_model_l2
  • baseline_model_dropout

  • インタフェースの説明

  • はデータを2次元マトリクスに変換し、enumerateの動作に注意し、インデックスと値
  • を同時に得ることができる.
    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
        return results
    

    オーバーフィットを緩和するには、ネットワークの複雑さを制限する一般的な方法があります.具体的には、ウェイト値が小さい値だけを強制し、ウェイト値の分布をより「規則」にすることです.これを「重み正規化」と呼び、ネットワークの損失関数に重みが大きいことに関連する代価を追加することで実現します.この代価は2つのタイプに分けられます.
  • L 1が正規化され、付加された対価は、重み係数の絶対値(いわゆる重み"L 1ノルム")に比例する.
  • L 2が正規化され、加えられた対価は重み係数値の二乗(いわゆる重み「L 2ノルム」)に比例する.L 2正規化はニューラルネットワークの分野で重み減衰とも呼ばれる.名前の違いに戸惑わないでください:数学的に言えば、重みの減衰はL 2の正規化と全く同じです.
  • L2正規化表現層を追加する重み行列の各係数は、0.001 * weight_coefficient_value**2をネットワークの総損失に追加する.この罰は、トレーニング時にのみ追加されるため、このネットワークのトレーニング時の損失はテスト時よりはるかに高いことに注意してください.
  •   keras.layers.Dense(16,activation=tf.nn.relu,kernel_regularizer=keras.regularizers.l2(0.001),input_shape=(NUM_WORDS, )),
    
  • dropout層(現在最も有効で最もよく用いられているニューラルネットワーク正規化技術の1つ)を追加する.指定されたレイヤは、通常、トレーニング中に所定の入力サンプルに対してベクトル[0.2, 0.5, 1.3, 0.8, 1.1]を返すと仮定する.破棄が適用されると、このベクトルは、[0, 0.5, 1.3, 0, 1.1]のようないくつかの0エントリをランダムに分布する.「廃棄率」は、通常0.2〜0.5の間に設定される0になる特徴の割合を意味する.テスト時、ネットワークはセルを破棄するのではなく、レイヤの出力値を破棄率に等しい割合で削減し、テスト時のアクティブセル数がトレーニング時のアクティブセル数より大きいという事実をバランスさせる.
  • keras.layers.Dense(16, activation=tf.nn.relu, input_shape=(NUM_WORDS,)),
       				 keras.layers.Dropout(0.5),
        ...
        ...
    
  • 作図関数
  • 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)])
    

    まとめ

  • 3種類の異なる容量のネットワークの訓練効果:
  • 実線は訓練損失を表し、破線は検証損失を表す(検証損失が低いほどモデルが良いことを注意).この例では、小さなネットワークがオーバーフィットを開始する時間は、基準モデルよりも遅く(前者は6サイクル後、後者は4サイクル後)、オーバーフィットを開始すると、その効果の低下速度もはるかに遅い.
  • L 2正規化モデルを追加:
  • 2つのモデルのパラメータ数は同じであるが、L 2正規化モデルのオーバーフィット抵抗力は基準モデルよりもずっと強いことがわかる.
  • dropoutレイヤを追加すると、ベンチマークモデルが著しく改善されます:
  • ニューラルネットワークのオーバーフィットを防ぐ最も一般的な方法をまとめます.
  • より多くのトレーニングデータを取得
  • ネットワーク容量を低減する
  • 重み正規化
  • を追加
  • dropoutレイヤ
  • を追加
    このガイドでは、データの強化とロットの標準化という2つの重要な方法について説明していません.

    Code

    import tensorflow as tf 
    from tensorflow import keras
    import numpy as np
    import matplotlib.pyplot as plt
    
    
    '''
     
    '''
    NUM_WORDS = 10000
    (train_data, train_labels), (test_data, test_labels) = keras.datasets.imdb.load_data(num_words=NUM_WORDS)
    print(train_data.shape)
    
    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
        return results
    
    train_data = multi_hot_sequences(train_data, NUM_WORDS)
    test_data  = multi_hot_sequences(test_data, NUM_WORDS)
    # plt.plot(train_data[0])
    # plt.show()
    
    
    '''
     
    '''
    baseline_model = keras.Sequential([
        # 'input_shape' is only required here so that '.summary' works
        keras.layers.Dense(16, activation=tf.nn.relu, input_shape=(NUM_WORDS, )),
        keras.layers.Dense(16, activation=tf.nn.relu),
        keras.layers.Dense(1, activation=tf.nn.sigmoid)
    ])
    baseline_model.compile( optimizer = 'adam',
                            loss='binary_crossentropy',
                            metrics=['accuracy','binary_crossentropy'])
    baseline_model.summary()
    
    
    
    smaller_model = keras.Sequential([
        keras.layers.Dense(4,activation=tf.nn.relu, input_shape=(NUM_WORDS,)),
        keras.layers.Dense(4,activation=tf.nn.relu),
        keras.layers.Dense(1,activation=tf.nn.sigmoid)
    ])
    smaller_model.compile(optimizer='adam',
                          loss='binary_crossentropy',
                          metrics=['accuracy','binary_crossentropy'])
    smaller_model.summary()
    
    
    
    bigger_model =  keras.Sequential([
        keras.layers.Dense(512, activation=tf.nn.relu, input_shape=(NUM_WORDS,)),
        keras.layers.Dense(512, activation=tf.nn.relu),
        keras.layers.Dense(1,   activation=tf.nn.sigmoid)
    ])
    bigger_model.compile(optimizer='adam',
                         loss='binary_crossentropy',
                         metrics=['accuracy','binary_crossentropy'])
    bigger_model.summary()
    
    
    
    baseline_model_l2 = keras.Sequential([
        keras.layers.Dense(16, activation=tf.nn.relu, kernel_regularizer=keras.regularizers.l2(0.001),
                            input_shape=(NUM_WORDS, )),
        keras.layers.Dense(16, activation=tf.nn.relu, kernel_regularizer=keras.regularizers.l2(0.001)),
        keras.layers.Dense(1, activation=tf.nn.sigmoid)
    ])
    baseline_model_l2.compile(optimizer='adam',
                                loss='binary_crossentropy',
                                metrics=['accuracy','binary_crossentropy'])
    baseline_model_l2.summary()
    
    
    
    baseline_model_dropout = keras.Sequential([
        keras.layers.Dense(16, activation=tf.nn.relu, input_shape=(NUM_WORDS, )),
        keras.layers.Dropout(0.5),
        keras.layers.Dense(16, activation=tf.nn.relu),
        keras.layers.Dropout(0.5),
        keras.layers.Dense(1, activation=tf.nn.sigmoid)
    ])
    baseline_model_dropout.compile(optimizer='adam',
                                    loss='binary_crossentropy',
                                    metrics=['accuracy','binary_crossentropy'])
    baseline_model_dropout.summary()                                
    
    
    
    '''
     
    '''
    def train_model(model):
        history = model.fit(train_data,
                            train_labels,
                            epochs=20,
                            batch_size=512,
                            validation_data=(test_data, test_labels),
                            verbose=2) 
        return history
    
    a= train_model(baseline_model)
    # b= train_model(smaller_model)
    # c= train_model(bigger_model)
    # d = train_model(baseline_model_l2)
    e = train_model(baseline_model_dropout)
    
    
    '''
       
    '''
    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',a),
                  #('smaller_model',b),
                  #('bigger_model',c),
                  #('baseline_l2',d),
                  ('baseline_dropout',e)])
    plt.show()