如何计算 PyTorch 中所有输入的网络梯度 w.r.t 权重?
How can I calculate the network gradients w.r.t weights for all inputs in PyTorch?
我正在尝试弄清楚如何计算每个输入的网络梯度。我有点迷路了。本质上,我想要的是为输入 x 的所有值计算 d self.output/d weight1 和 d self.output/d weight2。因此,例如,我将有一个大小为 (1000, 5) 的矩阵。其中1000是输入x的大小,5是层中权重的个数。
我在下面包含的示例 returns 权重大小为 (1,5)。这里究竟在计算什么?这个 d self.output/ d weight1 是 x 的 1 个输入,还是所有输入的平均值?
其次,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")
我不确定你到底想达到什么目的,因为通常你只使用(d 输出)/(d 参数)的梯度总和,而不使用介于两者之间的任何其他梯度,因为 autograd 会注意,但让我试着回答一下。
问题一
The example I've included below returns weights as size (1,5). What exactly is being calculated here? Is this d self.output/ d weight1 for 1 input of x, or an average of all inputs?
你得到大小 (1,5) 因为训练是在小批量中完成的,这意味着每个数据点相对于 (5) 权重的梯度是在小批量中计算和求和的。
根据文档:
This attribute is None by default and becomes a Tensor the first time a call to backward() computes gradients for self. The attribute will then contain the gradients computed and future calls to backward() will accumulate (add) gradients into it.
如果您明确想要每个数据点的梯度,则将您的小批量设置为 1。通常我们以小批量进行训练,因为在每个数据点之后进行更新可能不稳定,图像每次都在不同的方向上跳跃,而对于批量来说,这将是平均的。
另一方面,很多数据集实在是太大了,无法一次性计算出梯度。
问题二
一个示例可能会提供更多见解:
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
。
我正在尝试弄清楚如何计算每个输入的网络梯度。我有点迷路了。本质上,我想要的是为输入 x 的所有值计算 d self.output/d weight1 和 d self.output/d weight2。因此,例如,我将有一个大小为 (1000, 5) 的矩阵。其中1000是输入x的大小,5是层中权重的个数。
我在下面包含的示例 returns 权重大小为 (1,5)。这里究竟在计算什么?这个 d self.output/ d weight1 是 x 的 1 个输入,还是所有输入的平均值?
其次,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")
我不确定你到底想达到什么目的,因为通常你只使用(d 输出)/(d 参数)的梯度总和,而不使用介于两者之间的任何其他梯度,因为 autograd 会注意,但让我试着回答一下。
问题一
The example I've included below returns weights as size (1,5). What exactly is being calculated here? Is this d self.output/ d weight1 for 1 input of x, or an average of all inputs?
你得到大小 (1,5) 因为训练是在小批量中完成的,这意味着每个数据点相对于 (5) 权重的梯度是在小批量中计算和求和的。 根据文档:
This attribute is None by default and becomes a Tensor the first time a call to backward() computes gradients for self. The attribute will then contain the gradients computed and future calls to backward() will accumulate (add) gradients into it.
如果您明确想要每个数据点的梯度,则将您的小批量设置为 1。通常我们以小批量进行训练,因为在每个数据点之后进行更新可能不稳定,图像每次都在不同的方向上跳跃,而对于批量来说,这将是平均的。 另一方面,很多数据集实在是太大了,无法一次性计算出梯度。
问题二
一个示例可能会提供更多见解:
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
。