深度学习中的优化问题与优化算法实现(二)之优化算法实现

优化算法实现

(1)小批量随机梯度下降

 设⽬标函数 f ( x ) : R d → R f(x):\mathbf R^d \rightarrow \mathbf R f(x):RdR。在迭代开始前的时间步设为0。该时间步的⾃变量记为 ,通常由
随机初始化得到。在接下来的每⼀个时间步 中,⼩批量随机梯度下降随机均匀采样⼀个由训练数
据样本索引组成的⼩批量 。

     g t ← ∇ f B t ( x t − 1 ) = 1 ∣ B ∣ ∑ i ∈ B t ∇ f i ( x t − 1 ) \mathbf g_t \leftarrow \nabla f_{B_t}(x_{t-1})=\frac{1}{|B|}\sum_{i \in B_t}\nabla f_i(x_{t-1}) gtfBt(xt1)=B1iBtfi(xt1)

计算时间步t的小批量 B t B_t Bt上目标函数位于 x t − 1 x_{t-1} xt1处的梯度 g t \mathbf g_t gt,这里的B代表批量的大小,是一个超参数。

设学习率为 η t \eta_t ηt,小批量随机梯度下降对自变量的迭代如下:

     x t ← x t − 1 − η t g t x_t \leftarrow x_{t-1}-\eta_t\mathbf g_t xtxt1ηtgt

基于随机采样得到的梯度的⽅差在迭代过程中⽆法减⼩,因此在实际中,(⼩批量)随机梯度下降的学
习率可以在迭代过程中⾃我衰减,或者每迭代若⼲次后将学习率衰减⼀次。

我们将使⽤⼀个来⾃NASA的测试不同⻜机机翼噪⾳的数据集来⽐较各个优化算法(1)。我们使⽤
该数据集的前1,500个样本和5个特征,并使⽤标准化对数据进⾏预处理。

%matplotlib inline
import numpy as np
import time
import torch
from torch import nn, optim
import sys
import matplotlib.pylab as plt

def getdata():
    data=np.genfromtxt('C:/Users/mingming/airfoil_self_noise.dat',delimiter='\t')
    data=(data-data.mean(axis=0))/data.std(axis=0)
    return torch.tensor(data[:1500,:-1],dtype=torch.float32),\
                        torch.tensor(data[:1500,-1],dtype=torch.float32
                    )
features,labels=getdata()
features.shape  #torch.size([1500,5])

torch.Size([1500, 5])
#定义模型
def linreg(X, w, b): 
    return torch.mm(X, w) + b
#定义损失
def squared_loss(y_hat, y): #
# 注意这⾥返回的是向量, 另外, pytorch⾥的MSELoss并没有除以 2
    return (y_hat - y.view(y_hat.size())) ** 2 / 2
#定义优化器
def general_sgd(params,states,hyperparams):
    for param in params:
        param.data-=hyperparams['lr']*param.grad.data
#定义训练函数
def train_my(optimizer_fn, states, hyperparams, features, labels,
batch_size=10, num_epochs=2):
    # 初始化模型
    net, loss = linreg, squared_loss      #不用带参数
    # 初始化模型参数
    w = torch.nn.Parameter(torch.tensor(np.random.normal(0, 0.01,
    size=(features.shape[1], 1)), dtype=torch.float32),requires_grad=True)
    b = torch.nn.Parameter(torch.zeros(1, dtype=torch.float32),requires_grad=True)
    def eval_loss():
        return loss(net(features, w, b), labels).mean().item()
    ls = [eval_loss()]
    data_iter = torch.utils.data.DataLoader(torch.utils.data.TensorDataset(features, labels),
                batch_size, shuffle=True)
    
    for _ in range(num_epochs):
        start = time.time()
        for batch_i, (X, y) in enumerate(data_iter):
            l = loss(net(X, w, b), y).mean() # 使⽤平均损失
            
            # 梯度清零
            if w.grad is not None:
                w.grad.data.zero_()
                b.grad.data.zero_()
                
            l.backward()
            optimizer_fn([w, b], states, hyperparams) # 迭代模型参数
            if (batch_i + 1) * batch_size % 100 == 0:
                ls.append(eval_loss()) # 每100个样本记录下当前训练误差
    # 打印结果和作图
    print('loss: %f, %f sec per epoch' % (ls[-1], time.time() -start))
    figure1=plt.figure()#创建图表窗口
    plt.plot(np.linspace(0, num_epochs, len(ls)), ls)
    plt.title('gradient descent trace ')      #图名 
    plt.xlabel('epoch')
    plt.ylabel('loss')
                   
def train_sgd(lr, batch_size, num_epochs=2):
    train_ch7(general_sgd, None, {
   'lr': lr}, features, labels, batch_size,num_epochs)
train_sgd(1, 1500, 6)
loss: 0.242716, 0.051032 sec per epoch

在这里插入图片描述

# 当批次为1时,没有对学习率进自我衰减,直接采用较小的学习率 。
train_sgd(0.005,1)
loss: 0.242812, 0.622511 sec per epoch

在这里插入图片描述

#当批量⼤⼩为10时,优化使⽤的是⼩批量随机梯度下降。它在每个迭代周期的耗时介于梯度下降和随机梯度下降的耗时之间。
train_sgd(0.05,10)
loss: 0.244277, 0.067048 sec per epoch

在这里插入图片描述

利用pytorch 进行简洁实现

def train_pytorch(optimizer_fn, optimizer_hyperparams,features, labels,
                      batch_size=10, num_epochs=2):
    # 初始化模型
    net = nn.Sequential(nn.Linear(features.shape[-1], 1))
    loss = nn.MSELoss()
    optimizer = optimizer_fn(net.parameters(),**optimizer_hyperparams)
    
    def eval_loss():
        return loss(net(features).view(-1), labels<
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值