我正在从Theano转向Torch,请多包涵。在Theano中,计算损失函数相对于特定权重的梯度是相当直接的。我想知道,在Torch中如何做到这一点?
假设我们有以下代码,用于生成一些数据/标签并定义模型:
t = require 'torch'require 'nn'require 'cunn'require 'cutorch'-- 生成随机标签function randLabels(nExamples, nClasses) -- nClasses: 类别数量 -- nExamples: 样本数量 label = {} for i=1, nExamples do label[i] = t.random(1, nClasses) end return t.FloatTensor(label)endinputs = t.rand(1000, 3, 32, 32) -- 1000个样本,3个颜色通道inputs = inputs:cuda()labels = randLabels(inputs:size()[1], 10)labels = labels:cuda()net = nn.Sequential()net:add(nn.SpatialConvolution(3, 6, 5, 5))net:add(nn.ReLU())net:add(nn.SpatialMaxPooling(2, 2, 2, 2))net:add(nn.View(6*14*14))net:add(nn.Linear(6*14*14, 300))net:add(nn.ReLU())net:add(nn.Linear(300, 10))net = net:cuda()-- 损失criterion = nn.CrossEntropyCriterion()criterion = criterion:cuda()forwardPass = net:forward(inputs)net:zeroGradParameters()dEd_WeightsOfLayer1 -- 如何计算这个?forwardPass = nilnet = nilcriterion = nilinputs = nillabels = nilcollectgarbage()
我如何计算卷积层权重的梯度?
回答:
好的,我找到了答案(感谢Torch7 Google小组的alban desmaison)。问题中的代码有错误,无法工作。所以我重写了代码。以下是如何获取每个节点/参数的梯度的方法:
t = require 'torch'require 'cunn'require 'nn'require 'cutorch'-- 生成一些随机标签的函数function randLabels(nExamples, nClasses) -- nClasses: 类别数量 -- nExamples: 样本数量 label = {} for i=1, nExamples do label[i] = t.random(1, nClasses) end return t.FloatTensor(label)end-- 声明一些变量nClass = 10kernelSize = 5stride = 2poolKernelSize = 2nData = 100nChannel = 3imageSize = 32-- 生成一些[随机]数据data = t.rand(nData, nChannel, imageSize, imageSize) -- 100个随机图像,3个通道data = data:cuda() -- 传输到GPU(如果你不使用GPU,请删除此行)label = randLabels(data:size()[1], nClass)label = label:cuda() -- 传输到GPU(如果你不使用GPU,请删除此行)-- 定义模型net = nn.Sequential()net:add(nn.SpatialConvolution(3, 6, 5, 5))net:add(nn.ReLU())net:add(nn.SpatialMaxPooling(poolKernelSize, poolKernelSize, stride, stride))net:add(nn.View(6*14*14))net:add(nn.Linear(6*14*14, 350))net:add(nn.ReLU())net:add(nn.Linear(350, 10))net = net:cuda() -- 传输到GPU(如果你不使用GPU,请删除此行)criterion = nn.CrossEntropyCriterion()criterion = criterion:cuda() -- 传输到GPU(如果你不使用GPU,请删除此行)-- 进行前向传播并获取每个节点/参数的梯度:net:forward(data) -- 进行前向传播criterion:forward(net.output, label) -- 计算总体负对数似然误差criterion:backward(net.output, label); -- 不要忘记加';'。否则你会看到屏幕上打印所有内容net:backward(data, criterion.gradInput); -- 不要忘记加';'。否则你会看到屏幕上打印所有内容-- 现在你可以访问梯度值layer1InputGrad = net:get(1).gradInputlayer1WeightGrads = net:get(1).gradWeightnet = nildata = nillabel = nilcriterion = nil
复制并粘贴代码,它会像魔法一样工作