Dropout是神經網絡和深度學習模型的簡單而有效的正則化技術。
在這篇文章中,你將發現Dropout正則化技術,以及如何使用Keras將其應用於Python中的模型。
看完這篇文章後,你會知道:
Dropout正則化的原理。
如何在輸入層上使用Dropout。
如何在隱藏的層上使用Dropout。
如何根據問題調整Dropout。
讓我們開始吧。
神經網絡的Dropout正則化Dropout是由Srivastava等人在2014年的一篇論文中提出的一種針對神經網絡模型的正則化方法「Dropout: A Simple Way to Prevent Neural Networks from Overfitting」(下載PDF)。
Dropout是在訓練期間隨機選擇的一些神經元忽略的技術。他們隨機「Dropout」。這意味著它們對下遊神經元的激活的貢獻暫時消除,並且在反向過程沒有實施任何權重的更新。
隨著神經網絡學習,神經元的權重會與網絡上下文適應。神經元的權重為特定的特性提供一些專門化的調整。相鄰的神經元變得依賴於這種專業化,如果過度使用,會導致這種過度專業化的模型脆弱不堪,無法訓練數據。神經元在訓練過程中的這種依賴上下文的現象被稱為複雜的協同適應(complex co-adaptations)。
你可以想像,如果神經元在訓練期間被隨機地從網絡中捨棄,那麼其他的神經元將不得不介入並處理對缺失的神經元做出預測所需要的表徵。這被認為可以讓網絡學習到多個獨立的內部表徵。
它的效果是讓網絡對神經元的特定權重變得不那麼敏感。讓網絡能夠更好地泛化,並且很少過擬合訓練數據。
Keras中的Dropout正則化每輪權重更新,以給定的概率(例如20%)從隨機選擇的節點中捨棄,這個過程很容易實現。這就是在Keras中實現Dropout。Dropout僅在訓練模型時使用,在評估模型的技能時不使用。
接下來我們將探討在Keras中使用Dropout的幾種不同方法。
這些例子將使用Sonar數據集。這是二分類問題,其目標是用聲納的回聲正確識別巖石和礦。它是神經網絡的一個很好的測試數據集,因為所有的輸入值都是數字型,並且具有相同的量綱。
數據集可以從UCI Machine Learning庫下載。你可以將聲納數據集放在當前的工作目錄中,文件名為sonar.csv。
我們將使用scikit-learning的10次折交叉驗證來評估開發的模型,以便更好地梳理結果的差異。
有60個輸入值和一個輸出值,輸入值在網絡使用前被歸一化。基準神經網絡模型有兩個隱藏層,第一個為60個節點,第二個為30個。使用隨機梯度下降以較低的學習率和動量對模型進行訓練。
完整的基準模型如下所示。
01# Baseline Model on the Sonar Dataset03from pandasimport read_csv04from keras.modelsimport Sequential05from keras.layersimport Dense06from keras.layersimport Dropout07from keras.wrappers.scikit_learnimport KerasClassifier08from keras.constraintsimport maxnorm09from keras.optimizersimport SGD10from sklearn.model_selectionimport cross_val_score11from sklearn.preprocessingimport LabelEncoder12from sklearn.model_selectionimport StratifiedKFold13from sklearn.preprocessingimport StandardScaler14from sklearn.pipelineimport Pipeline15# fix random seed for reproducibility17numpy.random.seed(seed)19dataframe= read_csv("sonar.csv", header=None)20dataset= dataframe.values21# split into input (X) and output (Y) variables22X= dataset[:,0:60].astype(float)24# encode class values as integers25encoder= LabelEncoder()27encoded_Y= encoder.transform(Y)32 model= Sequential()33 model.add(Dense(60, input_dim=60, kernel_initializer='normal', activation='relu'))34 model.add(Dense(30, kernel_initializer='normal', activation='relu'))35 model.add(Dense(1, kernel_initializer='normal', activation='sigmoid'))37 sgd= SGD(lr=0.01, momentum=0.8, decay=0.0, nesterov=False)38 model.compile(loss='binary_crossentropy', optimizer=sgd, metrics=['accuracy'])41numpy.random.seed(seed)43estimators.append(('standardize', StandardScaler()))44estimators.append(('mlp', KerasClassifier(build_fn=create_baseline, epochs=300, batch_size=16, verbose=0)))45pipeline= Pipeline(estimators)46kfold= StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)47results= cross_val_score(pipeline, X, encoded_Y, cv=kfold)48print("Baseline: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))運行示例,生成的估計分類準確度是86%。
在可見層上使用DropoutDropout應用於輸入的神經元稱為可見層。
在下面的示例中,我們在輸入(或者說可見層)和第一個隱藏層之間添加一個新層Dropout。捨棄率設置為20%,這意味著從每個更新周期中隨機排除5個輸入中的一個。
另外,按照關於Dropout的原始文章中的建議,對每個隱藏層的權重加了限制,確保權重的最大值不超過3。這可以通過在構造層時設置Dense class中的kernel_constraint參數實現。
學習率提升一個數量級,momentum上升到0.9。這些增加的學習率的方法也是在原來的Dropout論文中推薦的。
繼續從上面的基準示例,下面的代碼練習與相同的輸入Dropout網絡。
01# dropout in the input layer with weight constraint04 model= Sequential()05 model.add(Dropout(0.2, input_shape=(60,)))06 model.add(Dense(60, kernel_initializer='normal', activation='relu', kernel_constraint=maxnorm(3)))07 model.add(Dense(30, kernel_initializer='normal', activation='relu', kernel_constraint=maxnorm(3)))08 model.add(Dense(1, kernel_initializer='normal', activation='sigmoid'))10 sgd= SGD(lr=0.1, momentum=0.9, decay=0.0, nesterov=False)11 model.compile(loss='binary_crossentropy', optimizer=sgd, metrics=['accuracy'])14numpy.random.seed(seed)16estimators.append(('standardize', StandardScaler()))17estimators.append(('mlp', KerasClassifier(build_fn=create_model, epochs=300, batch_size=16, verbose=0)))18pipeline= Pipeline(estimators)19kfold= StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)20results= cross_val_score(pipeline, X, encoded_Y, cv=kfold)21print("Visible: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))運行示例,生成的估計分類準確度下降到83.5%。
在隱藏層中使用DropoutDropout也可用於模型內的隱藏層節點
在下面的示例中,Dropout應用於兩個隱藏層之間以及最後一個隱藏層和輸出層之間。再次使用20%的輟學率,就像這些層的權重約束一樣。??????
01# dropout in hidden layers with weight constraint04 model= Sequential()05 model.add(Dense(60, input_dim=60, kernel_initializer='normal', activation='relu', kernel_constraint=maxnorm(3)))06 model.add(Dropout(0.2))07 model.add(Dense(30, kernel_initializer='normal', activation='relu', kernel_constraint=maxnorm(3)))08 model.add(Dropout(0.2))09 model.add(Dense(1, kernel_initializer='normal', activation='sigmoid'))11 sgd= SGD(lr=0.1, momentum=0.9, decay=0.0, nesterov=False)12 model.compile(loss='binary_crossentropy', optimizer=sgd, metrics=['accuracy'])15numpy.random.seed(seed)17estimators.append(('standardize', StandardScaler()))18estimators.append(('mlp', KerasClassifier(build_fn=create_model, epochs=300, batch_size=16, verbose=0)))19pipeline= Pipeline(estimators)20kfold= StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)21results= cross_val_score(pipeline, X, encoded_Y, cv=kfold)22print("Hidden: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))我們可以看到,對於這個問題,以及使用隱藏層中的Dropout網絡配置並沒有提升性能。事實上,表現比基線差。
可能需要額外的訓練次數,或者需要進一步調整學習率。
使用Dropout的提示??關於Dropout的原始論文提供了一套標準機器學習問題的實驗結果。因此,他們在實踐中提供了一些有用的啟發式來考慮使用輟學。
通常,使用20%-50%的捨棄率比較好。一個概率太低,沒什麼效果,概率太高會導致網絡的學習不充分。
Dropout被使用在大型網絡中可能會有更好的表現,有更多機會學習獨立表徵。
在輸入層和隱藏層都使用Dropout已經證明效果不錯。
使用大的學習率與衝量,學習率擴大10~100倍,衝量值調到0.9~0.99。
限制網絡權重的大小。大的學習率可能導致過大的網絡權重。對網絡權重的大小施加約束,可以改善結果。
總結在這篇文章中,你發現了深度學習模型的Dropout正則化技術。你學了:
Dropout的含義和原理。
如何在自己的深度學習模式使用Dropout。
使用Dropout達到最好效果的技巧。