【发布时间】:2020-08-31 04:57:24
【问题描述】:
考虑一个简单的线拟合a * x + b = x,其中a、b 是优化后的参数,x 是由下式给出的观察向量
import torch
X = torch.randn(1000,1,1)
您可以立即看到确切的解决方案是a=1,b=0 任何x,并且可以很容易地找到它:
import numpy as np
np.polyfit(X.numpy().flatten(), X.numpy().flatten(), 1)
我现在正在尝试通过 PyTorch 中的梯度下降来找到这个解决方案,其中均方误差用作优化标准。
import matplotlib.pyplot as plt
import numpy as np
import torch
import torch.nn as nn
from torch.optim import Adam, SGD, Adagrad, ASGD
X = torch.randn(1000,1,1) # Sample data
class SimpleNet(nn.Module): # Trivial neural network containing two weights
def __init__(self):
super(SimpleNet, self).__init__()
self.f1 = nn.Linear(1,1)
def forward(self, x):
x = self.f1(x)
return x
# Testing default setting of 3 basic optimizers
K = 500
net = SimpleNet()
optimizer = Adam(params=net.parameters())
Adam_losses = []
optimizer.zero_grad() # zero the gradient buffers
for k in range(K):
for b in range(1): # single batch
loss = torch.mean((net.forward(X[b,:,:]) - X[b,:, :])**2)
loss.backward()
optimizer.step()
Adam_losses.append(float(loss.detach()))
net = SimpleNet()
optimizer = SGD(params=net.parameters(), lr=0.0001)
SGD_losses = []
optimizer.zero_grad() # zero the gradient buffers
for k in range(K):
for b in range(1): # single batch
loss = torch.mean((net.forward(X[b,:,:]) - X[b,:, :])**2)
loss.backward()
optimizer.step()
SGD_losses.append(float(loss.detach()))
net = SimpleNet()
optimizer = Adagrad(params=net.parameters())
Adagrad_losses = []
optimizer.zero_grad() # zero the gradient buffers
for k in range(K):
for b in range(1): # single batch
loss = torch.mean((net.forward(X[b,:,:]) - X[b,:, :])**2)
loss.backward()
optimizer.step()
Adagrad_losses.append(float(loss.detach()))
令我惊讶的是,默认设置下算法的收敛速度非常慢。因此我有两个问题:
1) 是否有可能纯粹通过一些 Pytorch 优化器来实现任意小错误(损失)?由于损失函数是凸的,所以肯定是可能的,但是,我无法弄清楚如何使用 PyTorch 实现这一点。请注意,上述 3 个优化器无法做到这一点 - 查看 20000 次迭代的对数规模损失进度:
2) 我想知道优化器如何在复杂示例中正常工作,即使在这个极其简单的示例中也不能正常工作。或者(这是第二个问题)我错过了他们上面的应用程序有什么问题吗?
【问题讨论】:
标签: optimization pytorch gradient-descent convergence