[英]Why DNN with Dropout always predict one?
我已經實現了一個非常簡單的深度神經網絡來執行多標簽分類。 該模型的概述是(為了簡化可視化,省略了偏見):
也就是一個以ReLU單元和Sigmoid作為輸出單元的3層深度神經網絡。
損失函數為Sigmoid交叉熵,使用的優化器為Adam。
當我在不使用 Dropout的情況下訓練該NN時,會得到以下結果:
#Placeholders
x = tf.placeholder(tf.float32,[None,num_features],name='x')
y = tf.placeholder(tf.float32,[None,num_classes],name='y')
keep_prob = tf.placeholder(tf.float32,name='keep_prob')
#Layer1
WRelu1 = tf.Variable(tf.truncated_normal([num_features,num_features],stddev=1.0),dtype=tf.float32,name='wrelu1')
bRelu1 = tf.Variable(tf.zeros([num_features]),dtype=tf.float32,name='brelu1')
layer1 = tf.add(tf.matmul(x,WRelu1),bRelu1,name='layer1')
relu1 = tf.nn.relu(layer1,name='relu1')
#Layer2
WRelu2 = tf.Variable(tf.truncated_normal([num_features,num_features],stddev=1.0),dtype=tf.float32,name='wrelu2')
bRelu2 = tf.Variable(tf.zeros([num_features]),dtype=tf.float32,name='brelu2')
layer2 = tf.add(tf.matmul(relu1,WRelu2),bRelu2,name='layer2')
relu2 = tf.nn.relu(layer2,name='relu2')
#Layer3
WRelu3 = tf.Variable(tf.truncated_normal([num_features,num_features],stddev=1.0),dtype=tf.float32,name='wrelu3')
bRelu3 = tf.Variable(tf.zeros([num_features]),dtype=tf.float32,name='brelu3')
layer3 = tf.add(tf.matmul(relu2,WRelu3),bRelu3,name='layer3')
relu3 = tf.nn.relu(tf.matmul(relu2,WRelu3) + bRelu3,name='relu3')
#Out layer
Wout = tf.Variable(tf.truncated_normal([num_features,num_classes],stddev=1.0),dtype=tf.float32,name='wout')
bout = tf.Variable(tf.zeros([num_classes]),dtype=tf.float32,name='bout')
logits = tf.add(tf.matmul(relu3,Wout),bout,name='logits')
#Predictions
logits_sigmoid = tf.nn.sigmoid(logits,name='logits_sigmoid')
#Cost & Optimizer
cost = tf.losses.sigmoid_cross_entropy(y,logits)
optimizer = tf.train.AdamOptimizer(LEARNING_RATE).minimize(cost)
測試數據評估結果:
ROC AUC - micro average: 0.6474180196222774
ROC AUC - macro average: 0.6261438437099212
Precision - micro average: 0.5112489722699753
Precision - macro average: 0.48922193879411413
Precision - weighted average: 0.5131092162035961
Recall - micro average: 0.584640369246549
Recall - macro average: 0.55746897003228
Recall - weighted average: 0.584640369246549
當我訓練此神經網絡添加Dropout層時,我得到以下結果:
#Placeholders
x = tf.placeholder(tf.float32,[None,num_features],name='x')
y = tf.placeholder(tf.float32,[None,num_classes],name='y')
keep_prob = tf.placeholder(tf.float32,name='keep_prob')
#Layer1
WRelu1 = tf.Variable(tf.truncated_normal([num_features,num_features],stddev=1.0),dtype=tf.float32,name='wrelu1')
bRelu1 = tf.Variable(tf.zeros([num_features]),dtype=tf.float32,name='brelu1')
layer1 = tf.add(tf.matmul(x,WRelu1),bRelu1,name='layer1')
relu1 = tf.nn.relu(layer1,name='relu1')
#DROPOUT
relu1 = tf.nn.dropout(relu1,keep_prob=keep_prob,name='relu1drop')
#Layer2
WRelu2 = tf.Variable(tf.truncated_normal([num_features,num_features],stddev=1.0),dtype=tf.float32,name='wrelu2')
bRelu2 = tf.Variable(tf.zeros([num_features]),dtype=tf.float32,name='brelu2')
layer2 = tf.add(tf.matmul(relu1,WRelu2),bRelu2,name='layer2')
relu2 = tf.nn.relu(layer2,name='relu2')
#DROPOUT
relu2 = tf.nn.dropout(relu2,keep_prob=keep_prob,name='relu2drop')
#Layer3
WRelu3 = tf.Variable(tf.truncated_normal([num_features,num_features],stddev=1.0),dtype=tf.float32,name='wrelu3')
bRelu3 = tf.Variable(tf.zeros([num_features]),dtype=tf.float32,name='brelu3')
layer3 = tf.add(tf.matmul(relu2,WRelu3),bRelu3,name='layer3')
relu3 = tf.nn.relu(tf.matmul(relu2,WRelu3) + bRelu3,name='relu3')
#DROPOUT
relu3 = tf.nn.dropout(relu3,keep_prob=keep_prob,name='relu3drop')
#Out layer
Wout = tf.Variable(tf.truncated_normal([num_features,num_classes],stddev=1.0),dtype=tf.float32,name='wout')
bout = tf.Variable(tf.zeros([num_classes]),dtype=tf.float32,name='bout')
logits = tf.add(tf.matmul(relu3,Wout),bout,name='logits')
#Predictions
logits_sigmoid = tf.nn.sigmoid(logits,name='logits_sigmoid')
#Cost & Optimizer
cost = tf.losses.sigmoid_cross_entropy(y,logits)
optimizer = tf.train.AdamOptimizer(LEARNING_RATE).minimize(cost)
測試數據評估結果:
ROC AUC - micro average: 0.5
ROC AUC - macro average: 0.5
Precision - micro average: 0.34146163499985405
Precision - macro average: 0.34146163499985405
Precision - weighted average: 0.3712475781926326
Recall - micro average: 1.0
Recall - macro average: 1.0
Recall - weighted average: 1.0
從Dropout版本的Recall值中可以看到,NN輸出始終為1,對於每個樣本的每個類別始終為正類別。
的確,這不是一個簡單的問題,但是在應用Dropout之后,我至少期望得到與不使用Dropout時相似的結果,結果不會更差,當然也不是飽和輸出。
為什么會這樣呢? 我如何避免這種行為? 您在代碼中看到一些奇怪或不好的事情嗎?
超參數:
輟學率:0.5 @訓練/ 1.0 @推論
時期:500
學習率:0.0001
數據集信息:
實例數:+22.000
班級數量:6
謝謝!
最終,我通過更多的實驗設法解決了自己的問題,所以這就是我的想法。
我導出了Tensorboad圖以及權重,偏差和激活數據,以便在TB上進行探索。
然后我意識到砝碼不能正常工作。
如您所見,權重根本沒有變化。 換句話說,該層“沒有學習”任何東西。
但是眼前的眼神就在眼前。 權重的分布范圍太廣。 查看該直方圖范圍,從[-2,2]起算太大。
然后我意識到我正在用初始化權重矩陣
truncated_normal(mean=0.0, std=1.0)
對於正確的init來說,這是一個很高的std.dev。 一個明顯的技巧是使用更正確的初始化來初始化權重。 然后,我選擇了“ Xavier Glorot初始化” ,然后權重變為:
預測不再是積極的,而是再次變成混合預測。 當然,由於Dropout的緣故,它在測試裝置上的性能更好。
總而言之,沒有Dropout的網絡可以通過過於廣泛的初始化來學習一些東西,但是帶有Dropout的網絡則不能,並且需要更好的初始化以免卡住。
感謝所有閱讀該帖子並發表評論的人們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.