首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >火炬中的弱优化器

火炬中的弱优化器
EN

Stack Overflow用户
提问于 2020-05-14 15:19:23
回答 1查看 558关注 0票数 0

考虑一个简单的线拟合a * x + b = x,其中ab是优化的参数,x是所给出的观测向量

代码语言:javascript
运行
复制
import torch
X = torch.randn(1000,1,1)

可以立即看到,确切的解决方案是a=1b=0,对于任何x,它可以很容易地找到,就像:

代码语言:javascript
运行
复制
import numpy as np
np.polyfit(X.numpy().flatten(), X.numpy().flatten(), 1)

我现在试图通过梯度下降的方法在PyTorch中找到这个解,这里的均方误差被作为一个优化准则。

代码语言:javascript
运行
复制
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)我想知道优化器如何能在复杂的例子中很好地工作,即使在这个非常简单的例子中,它们也不能很好地工作。或者(这是第二个问题),我错过了他们在上面的应用中有什么问题吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-14 17:12:51

你打电话给zero_grad的地方是错的。在每个时代,梯度被添加到前一个,并反向传播。这使得损失随着它的接近而振荡,但先前的梯度又将它从解中抛出。

下面的代码将很容易地执行任务:

代码语言:javascript
运行
复制
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()

( 1)是否可以仅仅通过某些Pytorch优化器来实现任意的小错误(损失)?

是的,以上的精度是在大约1500年代达到的,你可以走到更低的机器(在这种情况下是浮子)精度。

2)我想知道优化器如何能在复杂的例子中很好地工作,即使在这个非常简单的例子中,它们也不能很好地工作。

目前,我们没有比一阶方法更好(至少更广泛)的网络优化方法了。这些方法用于高阶方法,因为计算梯度比Hessians要快得多。而复杂的、非凸的函数可能有大量的极小值来完成我们抛给它的任务,因此不需要全局极小值本身(尽管在某些条件下,它们可以参见本论文)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61801066

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档