摘要:介紹權(quán)重正則化可以減輕深度神經(jīng)網(wǎng)絡(luò)模型的過擬合問題,可以提升對新數(shù)據(jù)的泛化能力。代碼展示在卷積層中使用正則化。許多正則化方法通過向訓(xùn)練數(shù)據(jù)添加噪聲來防止過擬合。模型使用損失函數(shù),優(yōu)化器。
介紹
權(quán)重正則化可以減輕深度神經(jīng)網(wǎng)絡(luò)模型的過擬合問題,可以提升對新數(shù)據(jù)的泛化能力。有多種正則方法可供選擇,如:L1,L2正則化,每種方法在使用前需要超參數(shù)配置。在這篇文章中,你將學(xué)習在keras如何使用權(quán)重正則化的方法來減輕模型過擬合問題。
讀完本篇文章,你將學(xué)習到:
如何在keras中使用權(quán)重正則化應(yīng)用到MLP,CNN,或者LSTM神經(jīng)網(wǎng)絡(luò)任務(wù)中
一些常見論文在模型中使用權(quán)重正則化的方法和經(jīng)驗
通過一個案例學(xué)習如何使用權(quán)重正則化解決過擬合問題
## keras中權(quán)重正則化方法 ##
keras提供了權(quán)重正則化方法,可以在損失函數(shù)中通過添加懲罰系數(shù)來使用。keras提供了三種正則化方法:
L1:絕對值權(quán)重之和
L2:平方權(quán)重之和
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中,權(quán)重正則化可以應(yīng)用到任意一層,不過,模型默認不使用任何權(quán)重正則化。
全連接層使用權(quán)重正則化全連接層使用L2權(quán)重正則化:
import tensorflow as tf model=tf.keras.models.Sequential( # 權(quán)重正則化,bias正則化(應(yīng)用較少) 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)) )卷積層使用權(quán)重正則化
同全連接層一樣,卷積層也使用kernel_regularizer和bias_regularizer參數(shù)添加正則化。代碼展示在卷積層中使用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網(wǎng)絡(luò)中使用權(quán)重正則化
代碼展示在LSTM網(wǎng)絡(luò)中使用L2權(quán)重正則化
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)) )權(quán)重正則化使用經(jīng)驗
最常見的權(quán)重正則化是L2正則化,數(shù)值通常是0-0.1之間,如:0.1,0.001,0.0001。
找到最優(yōu)的系數(shù)并不容易,需要嘗試不同的權(quán)重系數(shù),找到模型表現(xiàn)最平穩(wěn)優(yōu)秀的系數(shù)
L2正則化在CNN網(wǎng)絡(luò)中,建議系數(shù)設(shè)置小一些,如:0.0005
少量的權(quán)重正則對模型很重要,可以減少模型訓(xùn)練誤差
LSTM網(wǎng)絡(luò)中L2權(quán)重系數(shù)通常更小,如:10^-6
權(quán)重正則化案例學(xué)習我們將使用標準二元分類問題來定義兩個半圓觀察:每個類一個半圓。每個觀測值都有兩個輸入變量,它們具有相同的比例,類輸出值為0或1.該數(shù)據(jù)集稱為“月亮”數(shù)據(jù)集,因為繪制時每個類中的觀測值的形狀。
# 導(dǎo)入sklearn中的數(shù)據(jù)集 from sklearn.datasets import make_moons from matplotlib import pyplot from pandas import DataFrame # 生成2分類數(shù)據(jù)集 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常用數(shù)據(jù)集:
數(shù)據(jù)集格式:
matplot結(jié)果顯示:
如圖所示,該問題是非線性問題,可以使用神經(jīng)網(wǎng)絡(luò)來解決。我們只生成了100個樣本,對神經(jīng)網(wǎng)絡(luò)來說數(shù)據(jù)量很少,這很容易造成過擬合問題。我們使用正則化,添加噪聲數(shù)據(jù)來處理問題。
雖然卷積神經(jīng)網(wǎng)絡(luò)(CNN)功能強大,并廣泛應(yīng)用于各種計算機視覺任務(wù)中,但由于參數(shù)過多而導(dǎo)致過度擬合[22]。神經(jīng)網(wǎng)絡(luò)的最初發(fā)展受到人腦機制的啟發(fā)[18],它不像計算機那樣精確。受到差異的啟發(fā),我們推斷在訓(xùn)練過程中添加噪音可能會指示CNN學(xué)習更強大的特征表示以抵消噪音的影響,從而降低過度擬合的風險。許多正則化方法通過向訓(xùn)練數(shù)據(jù)添加噪聲來防止過擬合。數(shù)據(jù)增強的輸入圖像,如隨機裁剪,翻轉(zhuǎn)和阻塞[9,21,30]已廣泛用于提高CNNs的泛化能力。 Adversarial Training [1]被提出來通過在圖像中添加基于梯度的擾動來調(diào)整網(wǎng)絡(luò)。 DisturbLabel [26]隨機地將樣本的一小部分子集的標簽改變?yōu)椴徽_的值,從而在損失層上規(guī)則化CNN。過擬合模型
我們創(chuàng)建一個只有一層隱藏層的MLP模型,并讓神經(jīng)元數(shù)量大于樣本數(shù)量,然后過長時間訓(xùn)練模型,以此來人為造成過擬合問題。訓(xùn)練模型之前,我們拆分下數(shù)據(jù)集,訓(xùn)練數(shù)據(jù)30%,驗證數(shù)據(jù)70%,來訓(xùn)練模型表現(xiàn)。
X, y = make_moons(n_samples=100, noise=0.2, random_state=1) # 拆分數(shù)據(jù)集 n_train = 30 trainX, testX = X[:n_train, :], X[n_train:, :] trainy, testy = y[:n_train], y[n_train:]
模型隱藏層有500個神經(jīng)元,激活函數(shù)使用relu,輸出層使用sigmoid激活函數(shù),輸出一項類別。模型使用bind_crossentropy損失函數(shù),adam優(yōu)化器。
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"])
模型迭代數(shù)據(jù)集400次,batch_size=32。
model.fit(trainX, trainy, epochs=4000, verbose=0)
在測試集上評估模型表現(xiàn):
# 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))
模型輸出結(jié)果:
我們看到訓(xùn)練表現(xiàn)遠大于測試表現(xiàn),這是過擬合問題的典型標志。我們將train和test訓(xùn)練精度過程圖形化展示出來。
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:] # 創(chuàng)建模型 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"]) # 返回訓(xùn)練,驗證集的損失和準確率 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的準確率出現(xiàn)分叉口。
使用正則化的模型我們將在隱藏層中使用權(quán)重正則化,并設(shè)置系數(shù)為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 # 創(chuàng)建數(shù)據(jù)集 X, y = make_moons(n_samples=100, noise=0.2, random_state=1) # 拆分數(shù)據(jù)集 n_train = 30 trainX, testX = X[:n_train, :], X[n_train:, :] trainy, testy = y[:n_train], y[n_train:] # 創(chuàng)建模型 model = Sequential() # 設(shè)置權(quán)重正則化 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"]) # 訓(xùn)練模型 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的訓(xùn)練過程。
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()
如圖所示,現(xiàn)在就很清楚了,test與train一致。
網(wǎng)格搜索正則化超參數(shù)當確定權(quán)重正則化可以改善模型的時候,這時你可以嘗試不同的權(quán)重系數(shù)值。首先對0.0到0.1之間的一些數(shù)量級進行網(wǎng)格搜索,然后再找到一個級別后進行網(wǎng)格搜索,這是一個很好的做法。
# 待測權(quán)重正則化值 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)
我們依然可以圖形化展示訓(xùn)練過程:
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 # 創(chuàng)建數(shù)據(jù)集 X, y = make_moons(n_samples=100, noise=0.2, random_state=1) # 拆分數(shù)據(jù)集 n_train = 30 trainX, testX = X[:n_train, :], X[n_train:, :] trainy, testy = y[:n_train], y[n_train:] # 待測權(quán)重系數(shù)值 values = [1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6] all_train, all_test = list(), list() for param in values: # 創(chuàng)建模型 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"]) # 訓(xùn)練模型 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()總結(jié)
降低過擬合問題,我們一般需要從“數(shù)據(jù)”,“模型結(jié)構(gòu)”,“模型參數(shù)”,“模型訓(xùn)練方法”等角度,采用的方法如下:
數(shù)據(jù)增強:圖像的平移,旋轉(zhuǎn),裁剪等;利用GAN生成新數(shù)據(jù);利用機器翻譯生成新數(shù)據(jù)。
降低模型復(fù)雜度:減少網(wǎng)絡(luò)層數(shù),神經(jīng)元個數(shù);
添加正則化項,如:L1,L2
集成學(xué)習:神經(jīng)網(wǎng)絡(luò),dropout
避免過長時間訓(xùn)練模型,設(shè)置提前終止。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/19965.html
摘要:下面介紹一些值得注意的部分,有些簡單解釋原理,具體細節(jié)不能面面俱到,請參考專業(yè)文章主要來源實戰(zhàn)那我們直接從拿到一個問題決定用神經(jīng)網(wǎng)絡(luò)說起。當你使用時可以適當減小學(xué)習率,跑過神經(jīng)網(wǎng)絡(luò)的都知道這個影響還蠻大。 神經(jīng)網(wǎng)絡(luò)構(gòu)建好,訓(xùn)練不出好的效果怎么辦?明明說好的擬合任意函數(shù)(一般連續(xù))(為什么?可以參考http://neuralnetworksanddeeplearning.com/),說好的足夠...
摘要:以用于檢測垃圾郵件的邏輯回歸模型為例。邏輯回歸的損失函數(shù)線性回歸的損失函數(shù)是平方損失。正則化在邏輯回歸建模中極其重要。 正則化:簡單性 查看以下泛化曲線,該曲線顯示的是訓(xùn)練集和驗證集相對于訓(xùn)練迭代次數(shù)的損失。 showImg(https://segmentfault.com/img/bVbahiL?w=750&h=322);上圖顯示的是某個模型的訓(xùn)練損失逐漸減少,但驗證損失最終增加。換...
閱讀 2631·2021-09-28 09:36
閱讀 2251·2021-09-07 09:58
閱讀 1505·2019-08-26 13:53
閱讀 1290·2019-08-23 17:53
閱讀 3036·2019-08-23 15:34
閱讀 1860·2019-08-23 15:34
閱讀 2878·2019-08-23 12:04
閱讀 3729·2019-08-23 10:56