1. 程式人生 > >如何利用Keras中的權重約束減少深度神經網路中的過擬合

如何利用Keras中的權重約束減少深度神經網路中的過擬合

                                                如何利用Keras中的權重約束減少深度神經網路中的過擬合

       權重約束提供了一種方法,用於減少深度學習神經網路模型對訓練資料的過度擬合,並改善模型對新資料(例如測試集)的效能。有多種型別的權重約束,例如最大和單位向量規範,有些需要必須配置的超引數。

在本教程中,您將發現Keras API,用於向深度學習神經網路模型新增權重約束以減少過度擬合。

完成本教程後,您將瞭解:

如何使用Keras API建立向量範數約束。
如何使用Keras API為MLP,CNN和RNN層新增權重約束。
如何通過向現有模型新增權重約束來減少過度擬合。

 

教程概述
本教程分為三個部分;他們是:

Keras的重量約束
圖層上的權重約束
體重約束案例研究
Keras的重量約束
Keras API支援權重限制。

約束是按層指定的,但是在層中應用和強制執行每個節點。

使用約束通常涉及在圖層上為輸入權重設定kernel_constraint引數,併為偏差權重設定bias_constraint。

通常,權重約束不用於偏差權重。

一組不同的向量規範可以用作約束,作為keras.constraints模組中的類提供。他們是:

最大範數(max_norm),用於強制權重等於或低於給定限制。
非負規範(non_neg),強制權重具有正數。
單位範數(unit_norm),強制權重為1.0。
Min-Max範數(min_max_norm),用於強制權重在一個範圍之間。
例如,一個簡單的約束可以這樣被引入和例項化:

# import norm
from keras.constraints import max_norm
# instantiate norm
norm = max_norm(3.0)
# import norm
from keras.constraints import max_norm
# instantiate norm
norm = max_norm(3.0)

    圖層上的權重約束
    權重規範可用於Keras的大多數層。

    在本節中,我們將看一些常見的例子。

    MLP加權約束
    以下示例在密集完全連線層上設定最大範數權重約束。

# example of max norm on a dense layer
from keras.layers import Dense
from keras.constraints import max_norm
...
model.add(Dense(32, kernel_constraint=max_norm(3), bias_constraint==max_norm(3)))
...
# example of max norm on a dense layer
from keras.layers import Dense
from keras.constraints import max_norm
...
model.add(Dense(32, kernel_constraint=max_norm(3), bias_constraint==max_norm(3)))
...


   CNN加權約束
   下面的示例在卷積層上設定最大範數權重約束。

# example of max norm on a cnn layer
from keras.layers import Conv2D
from keras.constraints import max_norm
...
model.add(Conv2D(32, (3,3), kernel_constraint=max_norm(3), bias_constraint==max_norm(3)))
...

    RNN權重約束
    與其他圖層型別不同,遞迴神經網路允許您對輸入權重和偏差以及迴圈輸入權重設定權重約束。通過圖層的recurrent_constraint引數設定重複權重的約束。以下示例在LSTM圖層上設定最大範數權重約束。

# example of max norm on an lstm layer
from keras.layers import LSTM
from keras.constraints import max_norm
...
model.add(LSTM(32, kernel_constraint=max_norm(3), recurrent_constraint=max_norm(3), bias_constraint==max_norm(3)))
...
# example of max norm on an lstm layer
from keras.layers import LSTM
from keras.constraints import max_norm
...
model.add(LSTM(32, kernel_constraint=max_norm(3), recurrent_constraint=max_norm(3), bias_constraint==max_norm(3)))
...

    現在我們知道如何使用權重約束API,讓我們看一個有效的例子。

    加權約束案例研究
    在本節中,我們將演示如何使用權重約束來減少MLP對簡單二元分類問題的過度擬合。此示例提供了一個模板,用於將權重約束應用於您自己的神經網路以進行分類和迴歸問題。

    二元分類問題
    我們將使用標準二進位制分類問題來定義兩個半圓資料集,每個類一個半圓。每個觀測值都有兩個輸入變數,它們具有相同的比例,類輸出值為0或1.該資料集稱為“月球”資料集,因為繪製時每個類中的觀測值的形狀。我們可以使用make_moons()函式從這個問題中生成觀察結果。 我們將為資料新增噪聲併為隨機數生成器播種,以便每次執行程式碼時生成相同的樣本。

# generate 2d classification dataset
X, y = make_moons(n_samples=100, noise=0.2, random_state=1)

      我們可以繪製兩個變數在圖表上作為x和y座標的資料集,並將類值作為觀察的顏色。下面列出了生成資料集並繪製資料集的完整示例。

# generate two moons dataset
from sklearn.datasets import make_moons
from matplotlib import pyplot
from pandas import DataFrame
# generate 2d classification dataset
X, y = make_moons(n_samples=100, noise=0.2, random_state=1)
# scatter plot, dots colored by class value
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()

# generate two moons dataset
from sklearn.datasets import make_moons
from matplotlib import pyplot
from pandas import DataFrame
# generate 2d classification dataset
X, y = make_moons(n_samples=100, noise=0.2, random_state=1)
# scatter plot, dots colored by class value
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()

       執行該示例會建立一個散點圖,顯示每個類中觀察的半圓形或月亮形狀。 我們可以看到點的分散中的噪音使得衛星不太明顯。

                                      

      這是一個很好的測試問題,因為類不能用一行來分隔,例如不是線性可分的,需要非線性方法,如神經網路來解決。我們只生成了100個樣本,這對於神經網路而言很小,提供了過度擬合訓練資料集的機會,並且在測試資料集上具有更高的誤差:使用正則化的一個好例子。此外,樣本具有噪聲,使模型有機會學習不一致的樣本的各個方面。

    過度多層感知器
   我們可以開發一個MLP模型來解決這個二進位制分類問題。該模型將具有一個隱藏層,其具有比解決該問題所需的節點更多的節點,從而提供過度擬合的機會。我們還將訓練模型的時間超過確保模型過度所需的時間。在我們定義模型之前,我們將資料集拆分為訓練集和測試集,使用30個示例來訓練模型,使用70個示例來評估擬合模型的效能。

 

X, y = make_moons(n_samples=100, noise=0.2, random_state=1)
# split into train and test
n_train = 30
trainX, testX = X[:n_train, :], X[n_train:, :]
trainy, testy = y[:n_train], y[n_train:]

     接下來,我們可以定義模型。隱藏層使用隱藏層中的500個節點和整流的線性啟用函式。 在輸出層中使用S形啟用函式以預測0或1的類值。該模型使用二元交叉熵損失函式進行優化,適用於二元分類問題和梯度下降的有效Adam版本。

    

# define model
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'])

       然後,定義的模型擬合4,000個訓練資料,預設批量大小為32。我們還將使用測試資料集作為驗證資料集。

# fit model
history = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=4000, verbose=0)

          我們可以在測試資料集上評估模型的效能並報告結果。

# evaluate the model
_, 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))

        最後,我們將在每個時期的訓練集和測試集上繪製模型的效能。如果模型確實過度擬合訓練資料集,我們將期望訓練集上的準確度線圖繼續增加並且測試設定上升然後隨著模型在訓練資料集中學習統計噪聲而再次下降。

# plot history
pyplot.plot(history.history['acc'], label='train')
pyplot.plot(history.history['val_acc'], label='test')
pyplot.legend()
pyplot.show()

        我們可以將所有這些部分組合在一起; 下面列出了完整的示例。

# mlp overfit on the moons dataset
from sklearn.datasets import make_moons
from keras.layers import Dense
from keras.models import Sequential
from matplotlib import pyplot
# generate 2d classification dataset
X, y = make_moons(n_samples=100, noise=0.2, random_state=1)
# split into train and test
n_train = 30
trainX, testX = X[:n_train, :], X[n_train:, :]
trainy, testy = y[:n_train], y[n_train:]
# define model
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'])
# fit model
history = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=4000, verbose=0)
# evaluate the model
_, 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))
# plot history
pyplot.plot(history.history['acc'], label='train')
pyplot.plot(history.history['val_acc'], label='test')
pyplot.legend()
pyplot.show()

        執行該示例報告列車和測試資料集上的模型效能。我們可以看到模型在訓練資料集上的效能優於測試資料集,這是過度擬合的一個可能標誌。鑑於神經網路和訓練演算法的隨機性,您的具體結果可能會有所不同。 因為模型是過度擬合的,所以我們通常不會期望在相同資料集上重複執行模型的精度差異(如果有的話)。

Train: 1.000, Test: 0.914

        建立一個圖,顯示訓練集和測試集上模型精度的曲線圖。我們可以看到過度擬合模型的預期形狀,其中測試精度增加到一個點然後再次開始減小。

                                   

     具有加權約束的Overfit MLP
     我們可以更新示例以使用權重約束。有一些不同的加權限制可供選擇。 這個模型的一個很好的簡單約束是簡單地標準化加權,使得範數等於1.0。此約束具有強制所有傳入權重較小的效果。我們可以通過在Keras中使用unit_norm來實現。 可以將此約束新增到第一個隱藏層,如下所示:

	
model.add(Dense(500, input_dim=2, activation='relu', kernel_constraint=unit_norm()))

      我們也可以通過使用min_max_norm並將min和maximum設定為1.0來實現相同的結果,例如:

model.add(Dense(500, input_dim=2, activation='relu', kernel_constraint=min_max_norm(min_value=1.0, max_value=1.0)))

       我們無法通過最大範數約束獲得相同的結果,因為它允許規範等於或低於指定的限制; 例如:

model.add(Dense(500, input_dim=2, activation='relu', kernel_constraint=max_norm(1.0)))

       下面列出了具有單位規範約束的完整更新示例:

# mlp overfit on the moons dataset with a unit norm constraint
from sklearn.datasets import make_moons
from keras.layers import Dense
from keras.models import Sequential
from keras.constraints import unit_norm
from matplotlib import pyplot
# generate 2d classification dataset
X, y = make_moons(n_samples=100, noise=0.2, random_state=1)
# split into train and test
n_train = 30
trainX, testX = X[:n_train, :], X[n_train:, :]
trainy, testy = y[:n_train], y[n_train:]
# define model
model = Sequential()
model.add(Dense(500, input_dim=2, activation='relu', kernel_constraint=unit_norm()))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
# fit model
history = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=4000, verbose=0)
# evaluate the model
_, 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))
# plot history
pyplot.plot(history.history['acc'], label='train')
pyplot.plot(history.history['val_acc'], label='test')
pyplot.legend()
pyplot.show()

        執行該示例報告訓練集和測試資料集上的模型效能。我們可以看到,對權重大小的嚴格限制確實提高了模型在測試集上的效能,而不會影響訓練集的效能。

Train: 1.000, Test: 0.943

      回顧訓練集的曲線和測試精度,我們可以看到模型已經過度擬合訓練資料集了。訓練集和測試集的模型精度繼續提高到穩定水平。

                              

擴充套件
本節列出了一些擴充套件您可能希望探索的教程的想法。

報告加權標準。更新示例以計算網路權重的大小,並證明約束確實使得幅度更小。
約束輸出層。更新示例以將約束新增到模型的輸出層並比較結果。
約束偏差。更新示例以向偏差權重新增約束並比較結果。
反覆評估。更新示例以多次擬合和評估模型,並報告模型效能的均值和標準差。