1 训练阶段

原理:训练阶段dropout启动。在前向传播过程,dropout模块对于输入的每个数,都会以概率p将该数置0,如果该数被置0则输出0,如果该数未被置0则把该数乘上11−p\frac{1}{1-p}1p1作为输出。反向传播阶段,即求导数阶段,如下图所示。
dropout
下面通过代码验证一下。

前向过程

首先,我创建一个dropout层,如下所示,p=0.3p=0.3p=0.3

dp = torch.nn.Dropout(0.3)

创建变量

torch.manual_seed(10)
x = torch.randn(3, requires_grad=True)  # 创建3个随机数
x

tensor([-1.2277, 0.9198, -0.3485], requires_grad=True)

y = dp(x)
y

tensor([-1.7538, 1.3140, -0.0000], grad_fn=<MulBackward0>)可以看出第三个数经过dropout层以概率p被置0

那么以第一个数为例,它未被以概率p置0,那么输出是输入的11−p\frac{1}{1-p}1p1倍吗?

-1.2277*(1/(1-0.3))

-1.753857142857143符合-1.7538

再次总结:
前向过程要么以概率p被置0,输出0;要么未被以概率p置0,输入乘11−p\frac{1}{1-p}1p1作为输出。

反向传播,即求导

因为前向过程分2种情况,那么反向传播也分两种情况:
1 若前向输出以概率p被置为0,那么输出y对输入x求导->导数0
2 否则,输出y对输入x求导->导数11−p\frac{1}{1-p}1p1

y.sum().backward()  # 求导
x.grad

tensor([1.4286, 1.4286, 0.0000])第三个数经过dropout层以概率p被置0,其导数0,第一个数未被置0,其导数是11−p=11−0.3=1.4285714285714286\frac{1}{1-p}=\frac{1}{1-0.3}=1.42857142857142861p1=10.31=1.4285714285714286

另一种验证方式

y = dp(x)  # y三维向量
y.backward(torch.tensor([1.0,1.0,1.0]))
x.grad

tensor([1.4286, 1.4286, 0.0000])

2 测试阶段

原理:dropout相当于被关闭,经过dropout层得到的输出等于输入。

x为tensor([-1.2277, 0.9198, -0.3485], requires_grad=True)

dp.eval()  # 测试阶段
y = dp(x)
y

tensor([-1.2277, 0.9198, -0.3485], requires_grad=True)

y==x

tensor([True, True, True])数值相等,所以全为True

3 训练阶段和测试阶段的切换

一个模块被创建,默认是训练模式。
model.train()->训练模式;model.eval()->测试模式。

dp = torch.nn.Dropout(0.3)
dp.training  # 是否是训练模式

True

dp.eval()
dp.training

False

dp.train()
dp.training

True

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐