Numpy 这是神经网络的例子I';我在看一个错误,还是我不理解backprop?

Numpy 这是神经网络的例子I';我在看一个错误,还是我不理解backprop?,numpy,machine-learning,pytorch,Numpy,Machine Learning,Pytorch,该模型是在两个位置使用一个relu,还是通过在一个层的两侧进行层的矩阵乘法来计算梯度 在这个简单的神经网络的最后一层(如下)中,在back prop期间,它通过对y prediction-y和h_relu进行矩阵乘法来计算最后一层的梯度w2,我认为这只是在w1和w2层之间,而不是w2和y\u pred 这条线在底部附近。它是grad\u w2=h\u relu.t().mm(grad\u y\u pred) 我很困惑,因为我认为一切都应该按顺序前进和后退。这个relu在两个地方使用吗 下面是模型

该模型是在两个位置使用一个relu,还是通过在一个层的两侧进行层的矩阵乘法来计算梯度

在这个简单的神经网络的最后一层(如下)中,在back prop期间,它通过对y prediction-y和
h_relu进行矩阵乘法来计算最后一层的梯度
w2
,我认为这只是
w1
w2
层之间,而不是
w2
y\u pred

这条线在底部附近。它是
grad\u w2=h\u relu.t().mm(grad\u y\u pred)

我很困惑,因为我认为一切都应该按顺序前进和后退。这个relu在两个地方使用吗

下面是模型的一个直观说明

此示例来自。这是页面上的第二块代码

grad_w2 = h_relu.t().mm(grad_y_pred)


import torch

dtype = torch.float
device = torch.device("cpu")
# device = torch.device("cuda:0") # Uncomment this to run on GPU

# N is batch size; D_in is input dimension;
# H is hidden dimension; D_out is output dimension.
N, D_in, H, D_out = 64, 1000, 100, 10

# Create random input and output data
x = torch.randn(N, D_in, device=device, dtype=dtype)
y = torch.randn(N, D_out, device=device, dtype=dtype)

# Randomly initialize weights
w1 = torch.randn(D_in, H, device=device, dtype=dtype)
w2 = torch.randn(H, D_out, device=device, dtype=dtype)

learning_rate = 1e-6
for t in range(500):
    # Forward pass: compute predicted y
    h = x.mm(w1)
    h_relu = h.clamp(min=0)
    y_pred = h_relu.mm(w2)

    # Compute and print loss
    loss = (y_pred - y).pow(2).sum().item()
    if t % 100 == 99:
        print(t, loss)

    # Backprop to compute gradients of w1 and w2 with respect to loss
    grad_y_pred = 2.0 * (y_pred - y)
    grad_w2 = h_relu.t().mm(grad_y_pred)
    grad_h_relu = grad_y_pred.mm(w2.t())
    grad_h = grad_h_relu.clone()
    grad_h[h < 0] = 0
    grad_w1 = x.t().mm(grad_h)

    # Update weights using gradient descent
    w1 -= learning_rate * grad_w1
    w2 -= learning_rate * grad_w2
grad_w2=h_relu.t().mm(grad_y_pred)
进口火炬
dtype=torch.float
设备=火炬。设备(“cpu”)
#device=torch.device(“cuda:0”)#取消对其的注释以在GPU上运行
#N为批量大小;D_in为输入维;
#H为隐维;D_out是输出维度。
N、 D_in,H,D_out=64100010010
#创建随机输入和输出数据
x=torch.randn(N,D_in,device=device,dtype=dtype)
y=torch.randn(N,D_out,device=device,dtype=dtype)
#随机初始化权重
w1=火炬。随机数(D_in,H,装置=装置,数据类型=数据类型)
w2=火炬.randn(H,D_out,device=device,dtype=dtype)
学习率=1e-6
对于范围(500)内的t:
#向前传球:计算预测y
h=x.mm(w1)
h_relu=h.夹具(最小值=0)
y_pred=h_relu.mm(w2)
#计算和打印损耗
损失=(y_pred-y).pow(2).sum().item()
如果t%100==99:
打印(t,损耗)
#Backprop计算w1和w2相对于损失的梯度
grad_y_pred=2.0*(y_pred-y)
grad_w2=h_relu.t().mm(grad_y_pred)
grad_h_relu=grad_y_pred.mm(w2.t())
grad_h=grad_h_relu.clone()
梯度h[h<0]=0
梯度w1=x.t().mm(梯度h)
#使用梯度下降更新权重
w1-=学习率*年级w1
w2-=学习率*年级w2
我感谢您耐心地看着这件事,并试图为我澄清这件事。

如果你可以试着在中间加上另一层WHEGHT,可以帮助我理解。这就是我试图做的。

考虑下面的图表,它代表了所讨论的网络。反向传播的概念只是一种快速直观地将链式规则应用于复杂操作序列的方法,以计算输出w.r.t.张量的梯度。通常我们感兴趣的是计算叶张量(不是从其他张量导出的张量)相对于损失或目标的梯度。在下图中,所有叶张量表示为圆,损失表示为带有L标签的矩形

使用反向图,我们可以沿着从L到w1和w2的路径,以确定我们需要哪些偏导数来计算Lw.r.t.w1和w2的梯度。为了简单起见,我们假设所有叶张量都是标量,以避免向量和矩阵相乘的复杂性

使用这种方法,Lw.r.t.w1和w2的梯度为


需要注意的是,由于w2是叶张量,我们在计算dL/dw2时只使用dy/dw2(也称为“grad_w2”),因为它不是从L到w1的路径的一部分。

对于相同的网络(查看numpy版本),这是一个类似的问题,但数学是相同的。如果有帮助的话,请告诉我:我不明白的是,当你倒退时,
w2
出现在
h\u relu
之前时,为什么使用
h\u relu
来获得“损失梯度w.r.t.w2”。我想我关于背道具到底是什么的假设是错误的,因为事情似乎发生了混乱。谢谢。这是超越一切的。你能解释一下为什么这里有一个“叶张量”吗?如果我没弄错的话,神经网络是从线性到非线性交替的函数中的函数。为什么“简单示例”nn的其中一个线性层与模型略微相邻(?)?模型内部的一种分支。我认为这样的事情只有在RNN或其他异国情调的架构中才是典型的。递归网络是不同的。通常,您可以将递归网络视为一种具有反馈回路的网络,即一层的输出被传递回先前一层的输入。在这种情况下,网络是纯前馈的。这些图表通常的描述方式隐藏了这样一个事实,即叶张量存在于网络之外(通常用层封装)。事实上,所有可训练的权重都是叶张量。我仍然不太明白为什么
w2
的梯度使用它前面的一层来寻找它的导数,但是relu(
h_relu
)的梯度使用它后面的两个东西来寻找它的导数
grad_h_relu=grad_y_pred.mm(w2.t())
。我不是想挑剔,希望我不是在烦人,但是
grad_h_relu
来自
w2
,我不认为你的插图显示了来自
w2
的派生词。我也不明白为什么输入数据
x
有一个指向它的导数,因为模型不应该“作用于”输入数据,对吗?不,我的意思是dz/dy=x。老实说,我认为您缺少一些基本的先决条件,无法完全理解反向传播。我不确定你的动机到底是什么,但我认为在这些细节上花费太多的时间有点失去了重点。pytorch和tensorflow等框架的优点之一是