Pytorch入门之一文看懂SGD

pytorch.optim包中可以直接调用SGD进行构建优化器,很简单,也很方便,但仍有一些细节需要注意一下

参考:Pytorch中优化器源码解析

PyTorch由4个主要包装组成:
1.Torch:类似于Numpy的通用数组库,可以在将张量类型转换为(torch.cuda.TensorFloat)并在GPU上进行计算。
2.torch.autograd:用于构建计算图形并自动获取渐变的包
3.torch.nn:具有共同层和成本函数的神经网络库
4.torch.optim:具有通用优化算法(如SGD,Adam等)的优化包

这里调用SGD的常用格式是:

optimizer = optim.SGD(net.parameters(), lr=0.03)  #例化对象

这里是例化了一个对象,优化器的实现需要给出网络的参数空间param_groups,然后就会得到优化器optimizer,该优化器叫SGD,即随机梯度下降。在神经网络中,优化器通过反向传播计算得到的梯度来更新网络的参数,达到训练的目的,从而降低目标函数的值。常见目标函数有平均误差和交叉熵(cross entropy)

 

那么,这个优化器是如何实现参数的优化的呢?那就得进入SGD的源码来看了

下面直接根据SGD的源码进行说明(截取一部分,帮助我们去理解内部在干什么)

  class SGD(Optimizer):
      def __init__(self, params, lr=required, momentum=0, dampening=0,
               weight_decay=0, nesterov=False):
         defaults = dict(lr=lr, momentum=momentum, dampening=dampening,
                    weight_decay=weight_decay, nesterov=nesterov)
         if nesterov and (momentum <= 0 or dampening != 0):
         raise ValueError("Nesterov momentum requires a momentum and zero dampening")
         super(SGD, self).__init__(params, defaults)

这是SGD的__init__方法,我们从这里只需要知道SGD中的param_group是一个长度为2的list,其中params, lr=required, momentum=0, dampening=0, weight_decay=0, nesterov=False组成一个字典,即param_groups[0],至于param_group[1]表明了优化器状态。其他参数简单提一下,learningRate(梯度下降速率),learningRateDecay(梯度下降速率的衰减),weightDecay(权重衰减),momentum(动量 or 冲量)等等

def step(self, closure=None):
    ...
    for group in self.param_groups:
        weight_decay = group['weight_decay']
        momentum = group['momentum']
        dampening = group['dampening']
        nesterov = group['nesterov']

        for p in group['params']:
            if p.grad is None:
                continue
            d_p = p.grad.data
            if weight_decay != 0:
                d_p.add_(weight_decay, p.data)
            if momentum != 0:
                ...

            p.data.add_(-group['lr'], d_p)

方法step是SGD进行参数优化的核心,其实只要看到最后一行p.data.add_(-group['lr'], d_p),你就能明白这是什么了,没错,这就是w -= learning rate * (w的梯度)。从这里我们就知道了,梯度的计算要在step函数之前进行,否则你拿什么来更新参数呢?

这里要注意一下 y.add_(a,b) 就是  y+a*b,而不是y+a+b!

于是乎,就有了我们常见的一种写法:

ls = loss(output, y.view(-1, 1))  # 计算损失函数
optimizer.zero_grad()  # 梯度清零
ls.backward()  # 计算反向梯度
optimizer.step()  # 更新以及对梯度求平均

Note:

1、进行新一轮backward之前,一定要清空之前那个batch输入在计算图中留下的梯度,否则下面的backward产生的新梯度将会和旧梯度形成梯度累加。

2、我们一般都会把model移到GPU上,故模型参数将会从cpu变成gpu上的参数,参数的变化要求我们必须得在创建优化器之前就得做好转移的工作。

SGD具体的源码我也给在这了:https://github.com/pytorch/pytorch/blob/cd9b27231b51633e76e28b6a34002ab83b0660fc/torch/optim/sgd.py#L63

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
L-SGD(Local Stochastic Gradient Descent)是一种分布式优化算法,用于在分布式计算环境进行大规模机器学习模型的训练。L-SGD算法将数据集分成多个子集,每个子集由一个独立的处理器处理。每个处理器使用随机梯度下降算法计算局部梯度,然后将这些局部梯度组合起来计算全局梯度。以下是用PyTorch实现L-SGD算法的示例代码: ```python import torch import torch.distributed as dist # Initialize distributed communication dist.init_process_group(backend='gloo') # Set up the data batch_size = 64 train_dataset = torch.utils.data.TensorDataset(X_train, y_train) train_sampler = torch.utils.data.distributed.DistributedSampler(train_dataset) train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, sampler=train_sampler) # Set up the model model = MyModel() model = torch.nn.parallel.DistributedDataParallel(model) # Set up the optimizer optimizer = torch.optim.SGD(model.parameters(), lr=0.01) # Train the model for epoch in range(num_epochs): train_sampler.set_epoch(epoch) for batch_idx, (data, target) in enumerate(train_loader): optimizer.zero_grad() output = model(data) loss = loss_fn(output, target) loss.backward() optimizer.step() ``` 在这个示例代码,我们首先初始化了分布式通信。然后我们设置了数据集、模型和优化器。在每个epoch,我们通过设置sampler来确保每个处理器都处理数据集的不同部分。在每个batch,我们通过计算局部梯度来更新模型参数,并使用dist.all_reduce()函数将所有处理器计算出的梯度聚合成全局梯度。最后,我们通过optimizer.step()函数更新模型参数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值