簡體   English   中英

為什么帶有Dropout的DNN總是能預測一個?

[英]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上進行探索。

然后我意識到砝碼不能正常工作。

具有TruncatedNormal初始化的第一層的權重

如您所見,權重根本沒有變化。 換句話說,該層“沒有學習”任何東西。

但是眼前的眼神就在眼前。 權重的分布范圍太廣。 查看該直方圖范圍,從[-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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM