PyTorch: 动态控制流程 + 权重共享
校对者:@bringtree
为了展示PyTorch的动态图的强大, 我们实现了一个非常奇异的模型: 一个全连接的ReLU激活的神经网络, 每次前向计算时都随机选一个1到4之间的数字n, 然后接下来就有n层隐藏层, 每个隐藏层的连接权重共享.
import randomimport torchfrom torch.autograd import Variableclass DynamicNet(torch.nn.Module):def __init__(self, D_in, H, D_out):"""在构造函数中,我们构造了三个nn.Linear实例,我们将在正向传递中使用它们."""super(DynamicNet, self).__init__()self.input_linear = torch.nn.Linear(D_in, H)self.middle_linear = torch.nn.Linear(H, H)self.output_linear = torch.nn.Linear(H, D_out)def forward(self, x):"""对于模型的正向通道,我们随机选择0,1,2或3,并重复使用多次计算隐藏层表示的middle_linear模块.由于每个正向通道都会生成一个动态计算图,因此在定义模型的正向通道时,我们可以使用普通的Python控制流操作符(如循环或条件语句).在这里我们也看到,定义计算图时多次重复使用相同模块是完全安全的.这是Lua Torch的一大改进,每个模块只能使用一次."""h_relu = self.input_linear(x).clamp(min=0)for _ in range(random.randint(0, 3)):h_relu = self.middle_linear(h_relu).clamp(min=0)y_pred = self.output_linear(h_relu)return y_pred# N 批量大小; D_in是输入尺寸;# H是隐藏尺寸; D_out是输出尺寸.N, D_in, H, D_out = 64, 1000, 100, 10# 创建随机张量来保存输入和输出,并将它们包装在变量中.x = Variable(torch.randn(N, D_in))y = Variable(torch.randn(N, D_out), requires_grad=False)# 通过实例化上面定义的类来构建我们的模型model = DynamicNet(D_in, H, D_out)# 构建我们的损失函数和优化器.# 用随机梯度下降训练这个奇怪的模型非常困难,所以我们使用动量criterion = torch.nn.MSELoss(size_average=False)optimizer = torch.optim.SGD(model.parameters(), lr=1e-4, momentum=0.9)for t in range(500):# 正向传递:通过将x传递给模型来计算预测的yy_pred = model(x)# 计算和打印损失loss = criterion(y_pred, y)print(t, loss.data[0])# 零梯度执行反向传递并更新权重.optimizer.zero_grad()loss.backward()optimizer.step()
