繁体   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