丢弃法 讨论区


#1

http://zh.diveintodeeplearning.org/chapter_deep-learning-basics/dropout.html


于置顶 #2

#3

关于rescale:

scale =  1 / keep_probability

注释为保证 E[dropout(X)] == X

也查阅了一些资料,初步印象为了计算网络的平均水平,scale可以抵消网络中p。想问下,有没有大神有更严谨的解释说明一下?


#4

CS231n课程笔记翻译:神经网络笔记 2 这里的dropout部分大致解释了这一问题,主要还是为了保证训练和测试的预期是一致的。


#5

可以直观的认为方便改 drop_prob的时候调参数(学习率)提样比较一致。类似说梯度要除batch_size


#6

hi,我看到一种说法是:在做training的时候用dropout;在做testing的估计的时候,不能用dropout,要用完整的structure,但是代码里没有看出这一点,在testing的时候还是用了dropout后的网络。
我直觉上感觉这样比较奇怪,因为最后训练出来的net就变成随机的了,因为dropout是随机的(即使w和b已经训练成一个固定值了)。


#7

内部是个黑箱吧,可以控制的,有个is_train什么的参数,可以查一下。


#8

有同样的疑问


#9

查看了一下文档,autograd.record里默认是train_mod。又可能是这里起作用了。


#10

你说的有道理,这个教程没有完全写对。应该是dropout需要根据autograd.is_training判断下当前是训练还是测试


#11

谢谢,确实


#12

不使用drop的时候准确率似乎更高?


#13

有没有这个GPU版本的?


#14

我也是这样,使用了dropout精度和拟合都没有不使用dropout的高


#15

@astonzhang 我们应该mark下在0.7应该fix这个,(如果还没有的话)


#16

感谢提醒!dropout-scratch 教程里的实现就有这个问题。提供一个workaround:

  1. 先修改net的定义,区分is_training
def net(X, is_training=False):
    X = X.reshape((-1, num_inputs))
    # 第一层全连接。
    h1 = nd.relu(nd.dot(X, W1) + b1)
    # 在第一层全连接后添加丢弃层。
    if is_training: h1 = dropout(h1, drop_prob1)
    # 第二层全连接。
    h2 = nd.relu(nd.dot(h1, W2) + b2)
    # 在第二层全连接后添加丢弃层。
    if is_training: h2 = dropout(h2, drop_prob2)
    return nd.dot(h2, W3) + b3
  1. 然后在训练的时候,传入is_training=True
for epoch in range(5):
    train_loss = 0.
    train_acc = 0.
    for data, label in train_data:
        with autograd.record():
            output = net(data, is_training=True)
            loss = softmax_cross_entropy(output, label)
    # 省略...

因为test_acc = utils.evaluate_accuracy(test_data, net)这里是传的函数句柄,所以is_training的默认值只能设为False,不然要改的东西会更多…


#17

随机初始化会造成一定影响,可以多运行几次,取平均值比较。

我的发现是不使用dropout时,训练集的准确度略有上升,而测试集的准确度略有下降。


#18

丢弃法实质上是对每一个这样的数据集分别训练一个原神经网络子集的分类器。与一般的集成学习不同,这里每个原神经网络子集的分类器用的是同一套参数。因此丢弃法只是在模拟集成学习。

我们刚刚强调了,原神经网络子集的分类器在不同的训练数据批量上训练并使用同一套参数

没有明白,共享同一套参数,有点笼统,具体是啥情况下共享同一套参数了?

for epoch in range(5):
    train_loss = 0.
    train_acc = 0.
    for data, label in train_data:
        with autograd.record():
            output = net(data)
            loss = softmax_cross_entropy(output, label)
        loss.backward()
        utils.SGD(params, learning_rate/batch_size)

    train_loss += nd.mean(loss).asscalar()
    train_acc += utils.accuracy(output, label)

在这里的两层for循环里,net的参数params是在每输入一个不同的batch data后,都会用SGD更新params的。不知道 如何理解这句话: 原神经网络子集的分类器在不同的训练数据批量上训练并使用同一套参数. 感觉net这个原网络子集的分类器的params会一直在update啊。


#19

训练时,各个网络子集分类器迭代的是同一套模型参数


#20

train with dropout, test wihtout dropout
Epoch 0. Loss: 1.132798, Train acc 0.562884, Test acc 0.721254
Epoch 1. Loss: 0.577049, Train acc 0.786108, Test acc 0.808093
Epoch 2. Loss: 0.498431, Train acc 0.818510, Test acc 0.851763
Epoch 3. Loss: 0.448510, Train acc 0.836155, Test acc 0.848958
Epoch 4. Loss: 0.418710, Train acc 0.847456, Test acc 0.844251

test and train without dropout:

Epoch 0. Loss: 1.131452, Train acc 0.565104, Test acc 0.739784
Epoch 1. Loss: 0.551753, Train acc 0.794087, Test acc 0.753305
Epoch 2. Loss: 0.456252, Train acc 0.830278, Test acc 0.853766
Epoch 3. Loss: 0.416722, Train acc 0.844418, Test acc 0.855569
Epoch 4. Loss: 641.115225, Train acc 0.763839, Test acc 0.100060

exchanged the dropout rate
Epoch 0. Loss: 1.155707, Train acc 0.550047, Test acc 0.773538
Epoch 1. Loss: 0.608322, Train acc 0.772920, Test acc 0.800381
Epoch 2. Loss: 0.515801, Train acc 0.810246, Test acc 0.821514
Epoch 3. Loss: 0.471708, Train acc 0.825454, Test acc 0.837340
Epoch 4. Loss: 0.447062, Train acc 0.835320, Test acc 0.848458