我试图弄清楚如何为每个输入计算网络的梯度。我有点迷路了。本质上,我想要的是为输入x的所有值计算d self.output / d weight1和d self.output / d weight2。因此,例如,我将有一个大小为(1000,5)的矩阵。其中1000是输入x的大小,5是图层中权重的数量。
我在下面提供的示例将权重作为大小(1,5)返回。这里到底要计算什么?这是x的1个输入的d self.output / d weight1还是所有输入的平均值?
第二,features.grad和weight1.grad的数量是否与我要的相同?所有x值的weight1的所有梯度的矩阵。
class Network(torch.nn.Module):
def __init__(self, iNode, hNode, oNode):
super(Network, self).__init__()
print("Building Model...")
iNode = int(iNode) ; self.iNode = iNode
hNode = int(hNode) ; self.hNode = hNode
oNode = int(oNode) ; self.oNode = oNode
self.fc1 = nn.Linear(iNode, hNode, bias=False)
self.fc2 = nn.Linear(hNode, oNode, bias=False)
def forward(self, x):
self.hidden_probs = self.fc1(x)
self.hidden = self.actFunc1(self.hidden_probs)
self.output_probs = self.fc2(self.hidden)
self.output = self.actFunc2(self.output_probs)
return self.output
def actFunc1(self, x):
return 1.0/(1.0+torch.exp(-x))
def actFunc2(self, x):
return x
def trainData(self, features, labels, epochs, alpha, optimisation, verbose=False):
for epoch in range(0,epochs):
net_pred = self.forward(features)
net_pred.backward(gradient=torch.ones(features.size())) #calc. dout/dw for all w
print(features.grad.size()) #returns (1000,1)
with torch.no_grad():
for name, param in self.named_parameters():
if(param.requires_grad):
param -= alpha*param.grad
for name, param in self.named_parameters():
if(param.requires_grad):
param.grad.zero_()
sys.stdout.write("Epoch: %06i\r" % (epoch))
sys.stdout.flush()
sys.stdout.write("\n")
答案 0 :(得分:1)
我不确定您要实现的目标是什么,因为通常您只能使用(d输出)/(d参数)的梯度之和,而不能使用两者之间的任何其他梯度,因为autograd会注意这一点,但是让我尝试回答。
问题1
我在下面提供的示例将权重作为大小(1,5)返回。这里到底要计算什么?是x的1个输入的d self.output / d weight1还是所有输入的平均值?
您得到的大小为(1,5),因为训练是在小批量中完成的,这意味着每个数据点相对于(5)权重的梯度都是在小批量中计算并求和的。 根据文档:
此属性默认情况下为None,并且在第一次调用Backward()来计算self的渐变时成为Tensor。然后,该属性将包含计算出的渐变,并且将来对backward()的调用会将渐变累积(添加)到其中。
如果您明确想要每个数据点的梯度,则将您的迷你批次大小设为1。通常,我们会进行小批量训练,因为每个数据点之后的更新可能会不稳定,每次图像都朝不同的方向跳动,而对于一个批次,这将平均化。 另一方面,许多数据集太大而无法一次性计算出梯度。
问题2
一个示例可能会提供更多见解:
import torch
x = torch.tensor([1.5], requires_grad=True)
a = torch.nn.Parameter(torch.tensor([2.]))
b = torch.nn.Parameter(torch.tensor([10.]))
y = x*a
z = y+0.5*b
temp = z.backward()
print('gradients of a: %0.2f and b: %0.2f' % (a.grad.item(), b.grad.item()))
我从两个参数a
和b
开始,然后计算z=a*x+0.5*b
。
尚未计算梯度,pytorch仅跟踪操作历史,因此所有.grad
属性均为空。
调用z.backward()
时,将计算输出相对于参数的梯度,您可以通过对参数调用grad来查看。
然后就可以像更新a -= alpha*a.grad
一样完成参数的更新。