• 聊聊神经网络的优化算法


    优化算法主要用于调整神经网络中的超参数,使得训练数据集上的损失函数尽可能小。其核心逻辑是通过计算损失函数对参数的梯度(导数)来确定参数更新方向。

    SGD

    Stochastic Gradient Descent(随机梯度下降法):随机梯度下降算法是一种改进的梯度下降方法,它在每次更新参数时,只随机选择一个样本来计算梯度。这样可以大大减少计算量,提高训练速度。随机梯度下降算法在训练大规模数据集时非常有效。

    其Python实现是

    class SGD:
        """随机梯度下降法(Stochastic Gradient Descent)"""
        def __init__(self, lr=0.01):
            self.lr = lr
        # 更新超参数
        def update(self, params, grads):
            for key in params.keys():
                params[key] -= self.lr * grads[key]
    

    参数lr表示学习率,参数params和grads是字典变量,保存了权重参数(prams['W1'])与梯度(grads['W1']),update方法执行的是超参数的梯度更新。
    使用这个SGD类,可以按如下伪代码进行神经网络的参数更新:

    network = nn.layernet()
    optimizer = SGD()
    
    for i in range(10000):
        x_batch, t_batch = get_batch(..)
        # 获取参数的梯度信息
        grads = network.gradient(x_batch, t_batch)
        # 获取参数
        params = network.params
        optimizer.update(params,grads)
    

    Momentum

    Momentum是"动量"的意思,是物理学的概念。其数学表达式如下:


    这里新出现的参数,对应物理上的速度。类似小球在斜面上的滚动。
    image.png
    可以使物体逐渐减速,对应物理上的地面磨擦与空气阻力。其Python实现如下

    class Momentum:
    
        """Momentum SGD"""
    
        def __init__(self, lr=0.01, momentum=0.9):
            self.lr = lr
            self.momentum = momentum
            self.v = None
        # 更新超参数
        def update(self, params, grads):
            if self.v is None:
                self.v = {}
                for key, val in params.items():                                
                    self.v[key] = np.zeros_like(val)
                    
            for key in params.keys():
                self.v[key] = self.momentum*self.v[key] - self.lr*grads[key] 
                params[key] += self.v[key]
    

    AdaGrad

    在神经网络中,学习率的值很重要。学习率过小会导致学习花费过多的时间;反之,学习率过大会导致学习发散,不能正确进行。
    AdaGrad会为参数的每个元素适当的(Adaptive)调整学习率,与此同时进行学习。其数学表达式如下:


    参数 保存了以前的所有参数的梯度值的平方和(表示对应矩阵元素的乘法)。更新参数时,通过乘以,调整学习的尺度。即按参数的元素进行学习率衰减,使得变动大的参数的学习率逐渐减小。
    其python实现如下:

    class AdaGrad:
    
        """AdaGrad"""
    
        def __init__(self, lr=0.01):
            self.lr = lr
            self.h = None
            
        def update(self, params, grads):
            if self.h is None:
                self.h = {}
                for key, val in params.items():
                    self.h[key] = np.zeros_like(val)
                
            for key in params.keys():
                self.h[key] += grads[key] * grads[key]
                params[key] -= self.lr * grads[key] / (np.sqrt(self.h[key]) + 1e-7)
    

    Adam

    Momentum参照小球在碗中滚动的物理规则进行移动,AdaGrad为参数的每个元素适当的调整更新步伐。将两者融合就是Adam方法的基本思路。
    Adam算法的公式如下,流程比较复杂,简单的理解就是其基本思路。

    1. 初始化:设 ( t = 0 ),初始化模型参数,学习率,以及超参数 。为每个参数 初始化一阶矩估计 和二阶矩估计
    2. 在第 ( t ) 步,计算目标函数 对参数 的梯度
    3. 更新一阶矩估计:
    4. 更新二阶矩估计:
    5. 校正一阶矩估计和二阶矩估计中的偏差:
    6. 计算自适应学习率:
    7. 使用自适应学习率更新模型参数:
    8. ( t = t + 1 ),重复步骤 2-7 直到收敛。
      通过上述公式,Adam算法能够自适应地调整每个参数的学习率,从而在训练过程中加速收敛。

    其Python实现:

    class Adam:
    
        """Adam (http://arxiv.org/abs/1412.6980v8)"""
    
        def __init__(self, lr=0.001, beta1=0.9, beta2=0.999):
            self.lr = lr
            self.beta1 = beta1
            self.beta2 = beta2
            self.iter = 0
            self.m = None
            self.v = None
            
        def update(self, params, grads):
            if self.m is None:
                self.m, self.v = {}, {}
                for key, val in params.items():
                    self.m[key] = np.zeros_like(val)
                    self.v[key] = np.zeros_like(val)
            
            self.iter += 1
            lr_t  = self.lr * np.sqrt(1.0 - self.beta2**self.iter) / (1.0 - self.beta1**self.iter)         
            
            for key in params.keys():
                self.m[key] += (1 - self.beta1) * (grads[key] - self.m[key])
                self.v[key] += (1 - self.beta2) * (grads[key]**2 - self.v[key])
                params[key] -= lr_t * self.m[key] / (np.sqrt(self.v[key]) + 1e-7)
    
  • 相关阅读:
    LayUI(会议oi项目增删改查)
    2022.11.14-11.20 AI行业周刊(第124期):给自己的礼物
    coppercam入门手册[6]
    为什么ArcGIS添加的TIFF栅格数据是一片纯色
    泰克AFG31000系列任意波函数发生器应用
    Linux C/C++ 多线程开发 - 基础介绍
    【QT】实现频谱图框选缩放
    【postgresql】postgresql行转列
    如何解决git 发生冲突的场景?
    linux服务器更改网络配置
  • 原文地址:https://www.cnblogs.com/zhiyong-ITNote/p/17911599.html