Optimization Pytorch中的弱优化器

Optimization Pytorch中的弱优化器,optimization,pytorch,gradient-descent,convergence,Optimization,Pytorch,Gradient Descent,Convergence,考虑一个简单的直线拟合a*x+b=x,其中a,b是优化的参数,x是由 import torch X = torch.randn(1000,1,1) 可以立即看到,对于任何x,精确解是a=1,b=0,并且可以很容易地找到: import numpy as np np.polyfit(X.numpy().flatten(), X.numpy().flatten(), 1) 我现在试图通过PyTorch中的梯度下降法来找到这个解决方案,其中均方误差被用作优化标准 import matplotlib

考虑一个简单的直线拟合
a*x+b=x
,其中
a
b
是优化的参数,
x
是由

import torch
X = torch.randn(1000,1,1)
可以立即看到,对于任何
x
,精确解是
a=1
b=0
,并且可以很容易地找到:

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) 我想知道,即使在这个非常简单的示例中,优化器也不能很好地工作,但在复杂的示例中,优化器如何能够很好地工作。或者(这是第二个问题)我错过的是他们上面的应用程序中有什么错误吗?

您调用的
zero\u grad
是错误的。在每个历元期间,梯度被添加到前一历元并反向传播。这使得损耗随着距离的接近而振荡,但之前的梯度会再次将其从解中抛出

下面的代码将轻松执行该任务:

import torch

X = torch.randn(1000,1,1)

net = SimpleNet()
optimizer = Adam(params=net.parameters())
for epoch in range(EPOCHS):
    optimizer.zero_grad()  # zero the gradient buffers
    loss = torch.mean((net.forward(X) - X) ** 2)
    if loss < 1e-8:
        print(epoch, loss)
        break
    loss.backward()
    optimizer.step()
导入火炬
X=火炬的随机数(1000,1,1)
net=SimpleNet()
optimizer=Adam(params=net.parameters())
对于范围内的历元(历元):
optimizer.zero_grad()#将渐变缓冲区归零
损失=火炬平均值((净远期(X)-X)**2)
如果损失<1e-8:
打印(历元、丢失)
打破
loss.backward()
optimizer.step()
1) 是否有可能仅通过以下方式实现任意小错误(损失) 什么是Pytorch优化器

是的,上面的精度大约在1500个时代内达到,你可以降低到机器的精度(在这种情况下是浮动的)

2) 我想知道优化器如何在复杂的环境中很好地工作 例如,即使在这种极其简单的情况下,它们也不能很好地工作 例如


目前,对于网络优化,我们没有比一阶方法更好的(至少是更广泛的)方法。使用这些方法是因为它比Hessians的高阶方法计算梯度要快得多。复杂的非凸函数可能有很多极小值,这些极小值可以完成我们的任务,不需要全局极小值本身(尽管在某些条件下它们可能会出现,请参见)。

您调用的
zero\u grad
的位置是错误的。在每个历元期间,梯度被添加到前一历元并反向传播。这使得损耗随着距离的接近而振荡,但之前的梯度会再次将其从解中抛出

下面的代码将轻松执行该任务:

import torch

X = torch.randn(1000,1,1)

net = SimpleNet()
optimizer = Adam(params=net.parameters())
for epoch in range(EPOCHS):
    optimizer.zero_grad()  # zero the gradient buffers
    loss = torch.mean((net.forward(X) - X) ** 2)
    if loss < 1e-8:
        print(epoch, loss)
        break
    loss.backward()
    optimizer.step()
导入火炬
X=火炬的随机数(1000,1,1)
net=SimpleNet()
optimizer=Adam(params=net.parameters())
对于范围内的历元(历元):
optimizer.zero_grad()#将渐变缓冲区归零
损失=火炬平均值((净远期(X)-X)**2)
如果损失<1e-8:
打印(历元、丢失)
打破
loss.backward()
optimizer.step()
1) 是否有可能仅通过以下方式实现任意小错误(损失) 什么是Pytorch优化器

是的,上面的精度大约在1500个时代内达到,你可以降低到机器的精度(在这种情况下是浮动的)

2) 我想知道优化器如何在复杂的环境中很好地工作 例如,即使在这种极其简单的情况下,它们也不能很好地工作 例如


目前,对于网络优化,我们没有比一阶方法更好的(至少是更广泛的)方法。使用这些方法是因为它比Hessians的高阶方法计算梯度要快得多。复杂的非凸函数可能有很多极小值,这些极小值可以完成我们的任务,不需要全局极小值本身(尽管在某些条件下它们可能会出现,请参见)。

太好了,谢谢你的回答。用错误的
zero\u grad
位置解释我的错误,完全回答了我的问题。将保留原样,也许对未来的读者有用。太好了,谢谢你的回答。用
zero\u grad
的错误位置解释我的错误完全回答了我的问题。答案将保持原样,也许对未来的读者有用。