Neural network Pytorch,梯度参数是什么
我正在阅读PyTorch的文档,发现了一个他们编写的示例Neural network Pytorch,梯度参数是什么,neural-network,gradient,pytorch,torch,gradient-descent,Neural Network,Gradient,Pytorch,Torch,Gradient Descent,我正在阅读PyTorch的文档,发现了一个他们编写的示例 gradients = torch.FloatTensor([0.1, 1.0, 0.0001]) y.backward(gradients) print(x.grad) 其中x是一个初始变量,从中构造y(一个3向量)。问题是,梯度张量的0.1、1.0和0.0001参数是什么?文档对此不是很清楚。这里,forward()的输出,即y是一个3向量 这三个值是网络输出处的渐变。如果y是最终输出,它们通常设置为1.0,但也可以有其他值,特别是
gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients)
print(x.grad)
其中x是一个初始变量,从中构造y(一个3向量)。问题是,梯度张量的0.1、1.0和0.0001参数是什么?文档对此不是很清楚。这里,forward()的输出,即y是一个3向量 这三个值是网络输出处的渐变。如果y是最终输出,它们通常设置为1.0,但也可以有其他值,特别是如果y是更大网络的一部分 例如,如果x是输入,y=[y1,y2,y3]是用于计算最终输出z的中间输出 那么 在这里,向后的三个值是
[dz/dy1, dz/dy2, dz/dy3]
然后backward()计算dz/dx通常,您的计算图形有一个标量输出,表示
损失
。然后您可以通过loss.backward()
计算损耗的梯度w.r.t.。权重(w
)。其中backward()
的默认参数为1.0
如果您的输出有多个值(例如,loss=[loss1,loss2,loss3]
),您可以通过loss.backward(torch.FloatTensor([1.0,1.0,1.0])计算权重w.r.t.的损失梯度。
此外,如果要为不同的损失添加权重或重要性,可以使用loss.backward(torch.FloatTensor([-0.1,1.0,0.0001])
这意味着同时计算-0.1*d(loss1)/dw,d(loss2)/dw,0.0001*d(loss3)/dw
。解释
对于神经网络,我们通常使用loss
来评估网络对输入图像(或其他任务)进行分类的能力。损失
项通常是一个标量值。为了更新网络的参数,我们需要计算loss
w.r.t对参数的梯度,这实际上是计算图中的leaf node
(顺便说一下,这些参数主要是卷积、线性等各层的权重和偏差)
根据链式规则,为了计算loss
w.r.t到一个叶节点的梯度,我们可以计算loss
w.r.t一些中间变量的导数,以及中间变量w.r.t到叶变量的梯度,做一个点积,并将所有这些求和
变量
方法的梯度
参数用于计算变量w.r.t的每个元素的加权和。这些权重只是最终损失
w.r.t中间变量的每个元素的导数
一个具体的例子
让我们举一个具体而简单的例子来理解这一点
来自torch.autograd导入变量的
进口火炬
x=变量(torch.FloatTensor([[1,2,3,4]]),需要_grad=True)
z=2*x
损失=z.总和(dim=1)
#对z的第一个元素向后执行
z、 向后(torch.FloatTensor([[1,0,0,0]]),retain\u graph=True)
打印(x级数据)
x、 grad.data.zero#删除x.grad中的梯度,否则它将累积
#对z的第二个元素进行反向运算
z、 向后(torch.FloatTensor([[0,1,0,0]]),retain_graph=True)
打印(x级数据)
x、 grad.data.zero_uz()
#对z的所有元素进行反向计算,权重等于
#损失w.r.t z_1、z_2、z_3和z_4
z、 向后(torch.FloatTensor([[1,1,1,1]]),retain_graph=True)
打印(x级数据)
x、 grad.data.zero_uz()
#或者我们可以直接用损失来支持
loss.backward()#相当于loss.backward(torch.FloatTensor([1.0]))
打印(x级数据)
在上面的示例中,第一次打印的结果是
200
[torch.FLOTTENSOR,尺寸为1x4]
这就是z_1 w.r.t对x的导数
第二次打印的结果是:
0200
[torch.FLOTTENSOR,尺寸为1x4]
这是z_2 w.r.t对x的导数
现在,如果使用[1,1,1,1]的权重来计算z w.r.t对x的导数,结果是1*dz_1/dx+1*dz_2/dx+1*dz_3/dx+1*dz_4/dx
。因此,第三次print
的输出是:
2
[torch.FLOTTENSOR,尺寸为1x4]
应该注意的是,权重向量[1,1,1,1]正好是损耗w.r.t对z_1、z_2、z_3和z_4的导数。损失
w.r.t到x
的导数计算如下:
d(loss)/dx = d(loss)/dz_1 * dz_1/dx + d(loss)/dz_2 * dz_2/dx + d(loss)/dz_3 * dz_3/dx + d(loss)/dz_4 * dz_4/dx
因此,第四次打印
的输出与第三次打印
的输出相同:
2
[torch.FLOTTENSOR,尺寸为1x4]
我在PyTorch网站上再也找不到原始代码了
上面代码的问题是没有基于什么计算梯度的函数。这意味着我们不知道有多少参数(函数采用的参数)和参数的维数
为了充分理解这一点,我创建了一个与原文相近的示例:
例1:
我假设我们的函数是y=3*a+2*b*b+torch.log(c)
,参数是张量,里面有三个元素
你可以想象梯度=torch.FloatTensor([0.1,1.0,0.0001])
就像这是累加器一样
正如您可能听说的,Pyrotch autograd系统计算相当于雅可比积
如果你有一个函数,就像我们做的那样:
y=3*a + 2*b*b + torch.log(c)
雅可比将是[3,4*b,1/c]
。然而,Pytork并不是这样计算某个点的梯度的
PyTorch使用向前传球和(AD)串联
不涉及符号数学,也不涉及数值微分
数值微分是计算δy/δb
,对于b=1
和b=1+ε
,其中ε很小
如果在y.backward()中不使用渐变,请执行以下操作:
例2
您将在某一点上获得结果,具体取决于您如何设置
gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients)
print(x.grad)
a = torch.tensor([1.0, 2.0, 3.0], requires_grad = True)
b = torch.tensor([3.0, 4.0, 5.0], requires_grad = True)
c = torch.tensor([6.0, 7.0, 8.0], requires_grad = True)
y=3*a + 2*b*b + torch.log(c)
gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients,retain_graph=True)
print(a.grad) # tensor([3.0000e-01, 3.0000e+00, 3.0000e-04])
print(b.grad) # tensor([1.2000e+00, 1.6000e+01, 2.0000e-03])
print(c.grad) # tensor([1.6667e-02, 1.4286e-01, 1.2500e-05])
y=3*a + 2*b*b + torch.log(c)
a = torch.tensor(0.1, requires_grad = True)
b = torch.tensor(1.0, requires_grad = True)
c = torch.tensor(0.1, requires_grad = True)
y=3*a + 2*b*b + torch.log(c)
y.backward()
print(a.grad) # tensor(3.)
print(b.grad) # tensor(4.)
print(c.grad) # tensor(10.)
a = torch.empty(1, requires_grad = True, pin_memory=True)
b = torch.empty(1, requires_grad = True, pin_memory=True)
c = torch.empty(1, requires_grad = True, pin_memory=True)
y=3*a + 2*b*b + torch.log(c)
gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients)
print(a.grad) # tensor([3.3003])
print(b.grad) # tensor([0.])
print(c.grad) # tensor([inf])
a = torch.tensor(1.0, requires_grad = True)
b = torch.tensor(1.0, requires_grad = True)
c = torch.tensor(1.0, requires_grad = True)
y=3*a + 2*b*b + torch.log(c)
y.backward(retain_graph=True)
y.backward()
print(a.grad) # tensor(6.)
print(b.grad) # tensor(8.)
print(c.grad) # tensor(2.)