ウェイト正規化を使用してモデルのオーバーフィットを少なくする


紹介する
重み正規化は深さニューラルネットワークモデルのオーバーフィット問題を軽減し,新しいデータの汎化能力を向上させることができる.L 1,L 2を正規化するなど、複数の正規化方法があり、各方法は使用前にスーパーパラメータ構成が必要です.この文章では、kerasで重みを正規化する方法をどのように使用してモデルのオーバーフィット問題を軽減するかを学びます.この文章を読むと、次のことを学びます.
  • は、MLP、CNN、またはLSTMニューラルネットワークタスクの
  • にkerasで重み正規化を使用してどのように適用するか.
  • いくつかの一般的な論文はモデルの中で重みの正規化の方法と経験
  • を使用する
  • は、重み正規化を使用してオーバーフィット問題
  • を解決する方法を一例によって学習する.
    ##kerasにおける重み正規化方法##kerasは、損失関数にペナルティ係数を追加することによって使用できる重み正規化方法を提供する.kerasは3つの正規化方法を提供した.
  • L 1:絶対値重みの和
  • L 2:二乗重みの和
  • L 1 L 2:両者の合計
  • tf.keras.regularizers.l1(l=0.01)
    tf.keras.regularizers.l2(l=0.01)
    tf.keras.regularizers.l1_l2(l1=0.01,l2=0.01)

    kerasでは、ウェイト正規化は任意のレイヤに適用できますが、モデルのデフォルトではウェイト正規化は使用されません.
    全接続レイヤのウェイト正規化(Weight Normalization for Full Connection Layer)
    全接続層はL 2重みを使用して正規化する:
    import tensorflow as tf
    
    model=tf.keras.models.Sequential(
      
    #      ,bias   (    )
    tf.keras.layers.Dense(512,activation=tf.nn.relu,kernel_regularizer=tf.keras.regularizers.l2(l=0.001),bias_regularizer=tf.keras.regularizers.l2(l=0.001))
    )

    ボリュームレイヤのウェイト正規化の使用(Use Weight Normalization)
    フルコネクション層と同様に、ボリューム層もkernel_を使用します.regularizerとbias_regularizerパラメータは正規化を追加します.コードは,L 2正規化を用いた畳み込み層を示している.
    import tensorflow as tf
    
    model=tf.keras.models.Sequential(
      tf.keras.layers.Conv2D(32,3,activation=tf.nn.relu,kernel_regularizer=tf.keras.regularizers.l2(l=0.001),bias_regularizer=tf.keras.regularizers.l2(l=0.001))
    )

    RNNネットワークにおける重み正規化の使用
    コード表示LSTMネットワークにおけるL 2重み正規化の使用
    import tensorflow as tf
    
    model=tf.keras.models.Sequential(
      tf.keras.layers.LSTM(32,activation=tf.nn.tanh,recurrent_regularizer=tf.keras.regularizers.l2(l=0.001),kernel_regularizer=tf.keras.regularizers.l2(l=0.001),bias_regularizer=tf.keras.regularizers.l2(l=0.001))
    )

    ウェイト正規化の使用経験
  • の最も一般的な重み正規化はL 2正規化であり、数値は通常0〜0.1の間であり、例えば、0.1、0.001、0.0001である.
  • 最適係数を見つけるのは容易ではなく、異なる重み係数を試みる必要があり、モデルが最も安定で優れた係数を表現する
  • を見つける必要がある.
  • L 2はCNNネットワークに正規化されており、推奨係数は0.0005
  • のように小さく設定されている.
  • 少量の重み正則はモデルにとって重要であり、モデル訓練誤差
  • を低減することができる.
  • LSTMネットワークにおけるL 2重み係数は、通常、10^-6
  • のように、より小さい.
    ウェイト正規化事例学習
    標準二元分類問題を用いて,2つの半円観察を定義する:各クラスに1つの半円.各観測値には2つの入力変数があり、それらは同じ割合を有し、クラス出力値は0または1である.このデータセットは、ペイント時の各クラスの観測値の形状のため、「月」データセットと呼ばれます.
    #   sklearn     
    from sklearn.datasets import make_moons
    from matplotlib import pyplot
    from pandas import DataFrame
    #   2     
    X, y = make_moons(n_samples=100, noise=0.2, random_state=1)
    
    print(X.shape)
    print(X[:6])
    print(y.shape)
    print(y[:6])
    
    df = DataFrame(dict(x=X[:,0], y=X[:,1], label=y))
    colors = {0:'red', 1:'blue'}
    fig, ax = pyplot.subplots()
    grouped = df.groupby('label')
    for key, group in grouped:
        group.plot(ax=ax, kind='scatter', x='x', y='y', label=key, color=colors[key])
    pyplot.show()

    sklearn共通データセット:
    データセットのフォーマット:
    matplotの結果は次のとおりです.
    図に示すように,この問題は非線形問題であり,ニューラルネットワークを用いて解決できる.我々は100個のサンプルしか生成せず,ニューラルネットワークにとってデータ量が少なく,これはオーバーフィット問題を引き起こしやすい.正規化を用いて,問題を処理するためにノイズデータを追加した.
    コンボリューションニューラルネットワーク(CNN)は強力な機能を持ち、様々なコンピュータビジュアルタスクに広く応用されているが、パラメータが多すぎるために過度なフィッティングを招く[22].ニューラルネットワークの最初の発展は人間の脳機構に啓発された[18].コンピューターほど正確ではありません違いにヒントを得て、トレーニング中に騒音を追加すると、CNNが騒音の影響を相殺するためにより強力な特徴表現を学ぶことを示す可能性があり、過度なフィッティングのリスクを低減すると推定されています.多くの正規化法は,訓練データにノイズを加えることによってオーバーフィットを防止する.ランダムカット,フリップおよびブロッキング[9,21,30]のようなデータ増強入力画像は,CNnsの汎化能力の向上に広く用いられている.Adversarial Training[1]は,画像に勾配に基づく摂動を加えることでネットワークを調整することを提案した.DisturbLabel[26]試料の一部のサブセットのラベルをランダムに不正確な値に変更し,損失層上でCNNを規則化した.
    オーバフィットモデル
    非表示層が1層しかないMLPモデルを作成し,ニューロン数をサンプル数より大きくし,その後モデルを長時間訓練しすぎて,人為的に過フィッティング問題をもたらした.訓練モデルの前に,データセットを分割し,訓練データ30%,検証データ70%を用いてモデル表現を訓練した.
    X, y = make_moons(n_samples=100, noise=0.2, random_state=1)
    #      
    n_train = 30
    trainX, testX = X[:n_train, :], X[n_train:, :]
    trainy, testy = y[:n_train], y[n_train:]

    モデル非表示層には500ニューロンがあり,活性化関数にはreluを用い,出力層にはsigmoid活性化関数を用い,カテゴリを出力した.モデル使用bind_crossentropy損失関数,adamオプティマイザ.
    model = Sequential()
    model.add(Dense(500, input_dim=2, activation='relu'))
    model.add(Dense(1, activation='sigmoid'))
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    

    モデル反復データセット400回、batch_size=32.
    model.fit(trainX, trainy, epochs=4000, verbose=0)

    テストセットでモデルのパフォーマンスを評価します.
    # model.evaluate  :loss value;metrics value
    _, train_acc = model.evaluate(trainX, trainy, verbose=0)
    _, test_acc = model.evaluate(testX, testy, verbose=0)
    print('Train: %.3f, Test: %.3f' % (train_acc, test_acc))

    モデル出力結果:
    訓練表現が試験表現よりはるかに大きいことを見た.これは過フィッティング問題の典型的な標識である.trainとtest訓練精度過程をグラフィックス化して示した.
    from sklearn.datasets import make_moons
    from keras.layers import Dense
    from keras.models import Sequential
    from matplotlib import pyplot
    
    X, y = make_moons(n_samples=100, noise=0.2, random_state=1)
    
    n_train = 30
    trainX, testX = X[:n_train, :], X[n_train:, :]
    trainy, testy = y[:n_train], y[n_train:]
    #     
    model = Sequential()
    model.add(Dense(500, input_dim=2, activation='relu'))
    model.add(Dense(1, activation='sigmoid'))
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    #     ,          
    history = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=4000, verbose=0)
    pyplot.plot(history.history['acc'], label='train')
    pyplot.plot(history.history['val_acc'], label='test')
    pyplot.legend()
    pyplot.show()

    図に示すように、ある点でtrainとtestの精度に分岐点が現れる.
    正規化されたモデルの使用
    非表示レイヤで重みを正規化し、係数を0.001に設定することで、オーバーフィットの問題を軽減します.
    model.add(Dense(500, input_dim=2, activation='relu', kernel_regularizer=l2(0.001)))
    

    完全なコードは次のとおりです.
    from sklearn.datasets import make_moons
    from keras.layers import Dense
    from keras.models import Sequential
    from keras.regularizers import l2
    #      
    X, y = make_moons(n_samples=100, noise=0.2, random_state=1)
    #      
    n_train = 30
    trainX, testX = X[:n_train, :], X[n_train:, :]
    trainy, testy = y[:n_train], y[n_train:]
    #     
    model = Sequential()
    #        
    model.add(Dense(500, input_dim=2, activation='relu', kernel_regularizer=l2(0.001)))
    model.add(Dense(1, activation='sigmoid'))
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    #     
    model.fit(trainX, trainy, epochs=4000, verbose=0)
    #     
    _, train_acc = model.evaluate(trainX, trainy, verbose=0)
    _, test_acc = model.evaluate(testX, testy, verbose=0)
    print('Train: %.3f, Test: %.3f' % (train_acc, test_acc))

    一見、testの精度が下がる以外に何もないようです.trainとtestの訓練過程を絵に描いてみましょう.
    from sklearn.datasets import make_moons
    from keras.layers import Dense
    from keras.models import Sequential
    from keras.regularizers import l2
    from matplotlib import pyplot
    
    X, y = make_moons(n_samples=100, noise=0.2, random_state=1)
    
    n_train = 30
    trainX, testX = X[:n_train, :], X[n_train:, :]
    trainy, testy = y[:n_train], y[n_train:]
    
    model = Sequential()
    model.add(Dense(500, input_dim=2, activation='relu', kernel_regularizer=l2(0.001)))
    model.add(Dense(1, activation='sigmoid'))
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    
    history = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=4000, verbose=0
    pyplot.plot(history.history['acc'], label='train')
    pyplot.plot(history.history['val_acc'], label='test')
    pyplot.legend()
    pyplot.show()

    図に示すように、testはtrainと一致していることが明らかになった.
    メッシュ検索正規化スーパーパラメータ
    ウェイト正規化がモデルを改善できると判断した場合、異なるウェイト係数の数値を試してみることができます.まず0.0~0.1の間のいくつかのレベルのメッシュ検索を行い、次に1つのレベルを見つけてメッシュ検索を行うのが良い方法です.
    #         
    values = [1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6]
    all_train, all_test = list(), list()
    for param in values:
        ...
        model.add(Dense(500, input_dim=2, activation='relu', kernel_regularizer=l2(param)))
        ...
        all_train.append(train_acc)
        all_test.append(test_acc)

    訓練過程をグラフィカルに示すことができます.
    pyplot.semilogx(values, all_train, label='train', marker='o')
    pyplot.semilogx(values, all_test, label='test', marker='o')

    完全なコードは次のとおりです.
    from sklearn.datasets import make_moons
    from keras.layers import Dense
    from keras.models import Sequential
    from keras.regularizers import l2
    from matplotlib import pyplot
    #      
    X, y = make_moons(n_samples=100, noise=0.2, random_state=1)
    #      
    n_train = 30
    trainX, testX = X[:n_train, :], X[n_train:, :]
    trainy, testy = y[:n_train], y[n_train:]
    #        
    values = [1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6]
    all_train, all_test = list(), list()
    for param in values:
        #     
        model = Sequential()
        model.add(Dense(500, input_dim=2, activation='relu', kernel_regularizer=l2(param)))
        model.add(Dense(1, activation='sigmoid'))
        model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
        #     
        model.fit(trainX, trainy, epochs=4000, verbose=0)
        #     
        _, train_acc = model.evaluate(trainX, trainy, verbose=0)
        _, test_acc = model.evaluate(testX, testy, verbose=0)
        print('Param: %f, Train: %.3f, Test: %.3f' % (param, train_acc, test_acc))
        all_train.append(train_acc)
        all_test.append(test_acc)
    # plot train and test means
    pyplot.semilogx(values, all_train, label='train', marker='o')
    pyplot.semilogx(values, all_test, label='test', marker='o')
    pyplot.legend()
    pyplot.show()

    まとめ
    オーバーフィットの問題を低減するには、一般的に「データ」、「モデル構造」、「モデルパラメータ」、「モデルトレーニング方法」などの観点から、以下の方法を採用する必要があります.
  • データ強化:画像の平行移動、回転、剪断など;GANを利用して新しいデータを生成する.機械翻訳を利用して新しいデータを生成する.
  • モデルの複雑さを低減する:ネットワーク層数、ニューロン個数を減少する;
  • 正規化項(L 1,L 2
  • )を追加
  • 統合学習:ニューラルネットワーク、dropout
  • 長時間トレーニングモデルを回避し、早期終了を設定します.