摘要:介紹權重正則化可以減輕深度神經網絡模型的過擬合問題,可以提升對新數據的泛化能力。代碼展示在卷積層中使用正則化。許多正則化方法通過向訓練數據添加噪聲來防止過擬合。模型使用損失函數,優化器。
介紹
權重正則化可以減輕深度神經網絡模型的過擬合問題,可以提升對新數據的泛化能力。有多種正則方法可供選擇,如:L1,L2正則化,每種方法在使用前需要超參數配置。在這篇文章中,你將學習在keras如何使用權重正則化的方法來減輕模型過擬合問題。
讀完本篇文章,你將學習到:
如何在keras中使用權重正則化應用到MLP,CNN,或者LSTM神經網絡任務中
一些常見論文在模型中使用權重正則化的方法和經驗
通過一個案例學習如何使用權重正則化解決過擬合問題
## keras中權重正則化方法 ##
keras提供了權重正則化方法,可以在損失函數中通過添加懲罰系數來使用。keras提供了三種正則化方法:
L1:絕對值權重之和
L2:平方權重之和
L1L2:兩者累加之和
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中,權重正則化可以應用到任意一層,不過,模型默認不使用任何權重正則化。
全連接層使用權重正則化全連接層使用L2權重正則化:
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)) )卷積層使用權重正則化
同全連接層一樣,卷積層也使用kernel_regularizer和bias_regularizer參數添加正則化。代碼展示在卷積層中使用L2正則化。
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網絡中使用L2權重正則化
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)) )權重正則化使用經驗
最常見的權重正則化是L2正則化,數值通常是0-0.1之間,如:0.1,0.001,0.0001。
找到最優的系數并不容易,需要嘗試不同的權重系數,找到模型表現最平穩優秀的系數
L2正則化在CNN網絡中,建議系數設置小一些,如:0.0005
少量的權重正則對模型很重要,可以減少模型訓練誤差
LSTM網絡中L2權重系數通常更小,如:10^-6
權重正則化案例學習我們將使用標準二元分類問題來定義兩個半圓觀察:每個類一個半圓。每個觀測值都有兩個輸入變量,它們具有相同的比例,類輸出值為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。過擬合模型
我們創建一個只有一層隱藏層的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之間的一些數量級進行網格搜索,然后再找到一個級別后進行網格搜索,這是一個很好的做法。
# 待測權重正則化值 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生成新數據;利用機器翻譯生成新數據。
降低模型復雜度:減少網絡層數,神經元個數;
添加正則化項,如:L1,L2
集成學習:神經網絡,dropout
避免過長時間訓練模型,設置提前終止。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/19965.html
摘要:下面介紹一些值得注意的部分,有些簡單解釋原理,具體細節不能面面俱到,請參考專業文章主要來源實戰那我們直接從拿到一個問題決定用神經網絡說起。當你使用時可以適當減小學習率,跑過神經網絡的都知道這個影響還蠻大。 神經網絡構建好,訓練不出好的效果怎么辦?明明說好的擬合任意函數(一般連續)(為什么?可以參考http://neuralnetworksanddeeplearning.com/),說好的足夠...
摘要:以用于檢測垃圾郵件的邏輯回歸模型為例。邏輯回歸的損失函數線性回歸的損失函數是平方損失。正則化在邏輯回歸建模中極其重要。 正則化:簡單性 查看以下泛化曲線,該曲線顯示的是訓練集和驗證集相對于訓練迭代次數的損失。 showImg(https://segmentfault.com/img/bVbahiL?w=750&h=322);上圖顯示的是某個模型的訓練損失逐漸減少,但驗證損失最終增加。換...
閱讀 2618·2021-09-28 09:36
閱讀 2228·2021-09-07 09:58
閱讀 1492·2019-08-26 13:53
閱讀 1275·2019-08-23 17:53
閱讀 3023·2019-08-23 15:34
閱讀 1850·2019-08-23 15:34
閱讀 2864·2019-08-23 12:04
閱讀 3717·2019-08-23 10:56