machine-learning - 我将几层修改为一个神经网络的例子,看看我是否可以。它出什么问题了?
问题描述
我发现一个简单的神经网络有 w1、Relu 和 w2 层。我尝试在中间添加一个新的权重层,然后添加第二个 Relu。因此,层如下 w1、Relu、w_mid、Relu 和 w2。
如果它可以工作的话,它比原来的 3 层网络要慢得多。我不确定是否一切都得到了前向传递,以及后向道具是否在每个部分都正常工作。
神经网络来自这个链接。这是页面下方的第三个代码块。
这是我更改的代码。
下面是原文。
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, 250, 250, 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)
w_mid = torch.randn(H, H, device=device, dtype=dtype)
w2 = torch.randn(H, D_out, device=device, dtype=dtype)
learning_rate = 1e-5
for t in range(5000):
# Forward pass: compute predicted y
h = x.mm(w1)
h_relu = h.clamp(min=0)
k = h_relu.mm(w_mid)
k_relu = k.clamp(min=0)
y_pred = k_relu.mm(w2)
# Compute and print loss
loss = (y_pred - y).pow(2).sum().item()
if t % 1000 == 0:
print(t, loss)
# Backprop to compute gradients of w1, mid, and w2 with respect to loss
grad_y_pred = (y_pred - y) * 2
grad_w2 = k_relu.t().mm(grad_y_pred)
grad_k_relu = grad_y_pred.mm(w2.t())
grad_k = grad_k_relu.clone()
grad_k[k < 0] = 0
grad_mid = h_relu.t().mm(grad_k)
grad_h_relu = grad_k.mm(w1.t())
grad_h = grad_h_relu.clone()
grad_h[h < 0] = 0
grad_w1 = x.t().mm(grad_h)
# Update weights
w1 -= learning_rate * grad_w1
w_mid -= learning_rate * grad_mid
w2 -= learning_rate * grad_w2
损失为..
0 1904074240.0
1000 639.4848022460938
2000 639.4848022460938
3000 639.4848022460938
4000 639.4848022460938
这是来自 Pytorch 网站的原始代码。
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
解决方案
的梯度计算h_relu
不正确。
grad_h_relu = grad_k.mm(w1.t())
那应该是w_mid
not w1
:
grad_h_relu = grad_k.mm(w_mid.t())
除此之外,计算是正确的,但你应该降低学习率,因为梯度在开始时非常大,使权重非常大,导致值溢出(无穷大),进而产生 NaN 损失和梯度. 这被称为爆炸梯度。
在您的示例中,学习率1e-8
似乎有效。
推荐阅读
- python - Discord dm bot 可以通过 python dm 返回
- android - Gradle,不同的“平台(”)与否?
- java - org.springframework.web.reactive.function.UnsupportedMediaTypeException:bodyType= 不支持内容类型'text/html;charset=iso-8859-1'
- r - Emacs:运行 R shell
- ruby-on-rails - 结合 Rails 搜索模式 'matches' 和 'LIKE'
- mysql - Google Apps - Mysql 连接失败
- java - RecyclerView 和 GONE 可见性问题
- r - 如何以特定 id 为条件运行回归?
- c# - 如何在 KeyDown 方法之外的 C# Windows Form App 中抑制 Windows Beep?
- makefile - 在 Makefile 中使用条件指令