神经网络中的算法优化(皮毛讲解)

抛砖引玉

在深度学习中,优化算法是训练神经网络时至关重要的一部分。
优化算法的目标是最小化(或最大化)一个损失函数,通常通过调整神经网络的参数来实现。
这个过程可以通过梯度下降法来完成,其中梯度指的是损失函数关于参数的偏导数。
本文将介绍一阶优化算法和二阶优化算法,并详细讲解常用的梯度下降法,包括梯度下降法、随机梯度下降法、动量法、AdaGrad、RMSProp和Adam。
在这里插入图片描述

一阶优化算法

一阶优化算法主要根据损失函数的一阶导数(梯度)来更新模型参数。常见的一阶优化算法包括梯度下降法、随机梯度下降法、动量法等。

1. 梯度下降法(Gradient Descent)

梯度下降法是最基本的优化算法之一,它通过计算损失函数关于参数的梯度,并沿着梯度的反方向更新参数,从而使损失函数不断减小。
在这里插入图片描述
在这里插入图片描述
因为这里的损失函数是在整个数据集上进行计算得到的均值,所以每更新一次模型参数,就要对整个数据集进行一个计算,可想而知这样非常的慢,并且当数据集变得非常大的时候,如此多的数据没法都load到内存中。

void gradient_descent(float *params, float *gradients, float learning_rate, int n)
 {
    for (int i = 0; i < n; i++)
     {
        params[i] -= learning_rate * gradients[i];
    }
}

在这里插入图片描述

2. 随机梯度下降法(Stochastic Gradient Descent)

在这里插入图片描述
随机梯度下降法和梯度下降法其实是走的两个极端,梯度下降法是每次更新都计算整个数据集的loss,而随机梯度下降法每次更新都只用了一对样本,即上面公式中的一对样本(在这里插入图片描述由于每个样本都会对模型进行更新,所以模型更新的特别频繁,参数就会变成高方差,损失函数的波动也会有很大强度的变化。有时候,这是好事,因为这样的可以帮助我们探索新的更新方向,找到更加好的局部极值点。但是,由于频繁的更新和波动,会导致模型的损失收敛的非常不稳定。

在这里插入图片描述
上图就是随机梯度下降法更新过程中loss值的变化,可以发现loss值的变化非常大,这就是模型超调了,整个模型比较不稳定

随机梯度下降法是梯度下降法的一种变种,它在每次迭代中随机选取一部分样本来计算梯度,从而加快了训练速度。

void stochastic_gradient_descent(float *params, float *gradients, float learning_rate, int n) 
{
    for (int i = 0; i < n; i++) 
    {
        params[i] -= learning_rate * gradients[i];
    }
}

在这里插入图片描述

3. 动量法(Momentum)

带momentum(动量)的梯度下降法也是一种很常用的的优化算法。这种方法因为引入了momentum量,所以能够对梯度下降法起到加速的作用。

打个比方,一个球顺着斜坡往下滚动,会因为地心引力的原因而一直加速,速度越来越快的往坡低滚去。梯度下降法中的Momentum量就和地心引力的作用很类似,能够让梯度下降法沿着下降的方向逐渐扩大幅度。起到对梯度下降法进行加速的作用。在这里插入图片描述
从上述公式(1)可以看出,当当前的梯度方向在这里插入图片描述的正负号)和在这里插入图片描述的方向相同时,在这里插入图片描述
所以参数 θ 的变化幅度会增大,从而加快梯度下降法的幅度;而当方向不同时,会逐步减小当前更新的幅度。这样可以有效的对梯度下降法进行加速,同时提高模型的稳定性。

动量法通过引入动量项来加速收敛过程,它模拟了物体运动时的惯性,可以减少梯度更新的波动,从而加快了训练速度。

void momentum(float *params, float *gradients, float learning_rate, float momentum_rate, float *velocities, int n) {
    for (int i = 0; i < n; i++) {
        velocities[i] = momentum_rate * velocities[i] + learning_rate * gradients[i];
        params[i] -= velocities[i];
    }
}

二阶优化算法

二阶优化算法基于损失函数的二阶导数(Hessian矩阵)来更新模型参数。常见的二阶优化算法包括AdaGrad、RMSProp和Adam。

1. AdaGrad

在mini batch梯度下降法中,因为对所有的参数均使用相同的学习率,而当有的参数的梯度很大,有的很小时,显然不合适。另外,对于不同的样本,如果有的样本出现的较为频繁,导致其对应的一些参数更新较为频繁,而有的样本出现的频率很低,导致一些参数更新频率很低时,再采用相同的学习率有时候也不太合适。我们更加希望那些出现更新频率比较低的参数能够有更大的更新幅度。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

AdaGrad算法通过动态调整学习率来提高收敛速度,它根据参数的历史梯度调整学习率,对于频繁出现的参数会降低学习率,对于不经常出现的参数会增加学习率。

void adagrad(float *params, float *gradients, float learning_rate, float epsilon, float *accumulators, int n)
 {
    for (int i = 0; i < n; i++)
     {
        accumulators[i] += gradients[i] * gradients[i];
        params[i] -= learning_rate * gradients[i] / (sqrt(accumulators[i]) + epsilon);
    }
}

2. RMSProp

RMSProp算法是对AdaGrad算法的改进,它通过引入一个衰减系数来控制历史梯度的衰减速度,从而减少了学习率的波动。

void rmsprop(float *params, float *gradients, float learning_rate, float decay_rate, float epsilon, float *accumulators, int n) 
{
    for (int i = 0; i < n; i++) 
    {
        accumulators[i] = decay_rate * accumulators[i] + (1 - decay_rate) * gradients[i] * gradients[i];
        params[i] -= learning_rate * gradients[i] / (sqrt(accumulators[i]) + epsilon);
    }
}

3. Adam

前面我们从最经典的梯度下降法开始,介绍了几个改进版的梯度下降法。
Momentum方法通过添加动量,提高收敛速度;
Nesterov方法在进行当前更新前,先进行一次预演,从而找到一个更加适合当前情况的梯度方向和幅度;
Adagrad让不同的参数拥有不同的学习率,并且通过引入梯度的平方和作为衰减项,而在训练过程中自动降低学习率;
AdaDelta则对Adagrad进行改进,让模型在训练后期也能够有较为适合的学习率。
在这里插入图片描述

Adam算法是一种结合了动量法和RMSProp算法的优化算法,它不仅考虑了梯度的一阶矩(均值),还考虑了梯度的二阶矩(方差),从而更加准确地更新参数。

void adam(float *params, float *gradients, float learning_rate, float beta1, float beta2, float epsilon, float *m, float *v, int t, int n) {
    for (int i = 0; i < n; i++) 
    {
        m[i] = beta1 * m[i] + (1 - beta1) * gradients[i];
        v[i] = beta2 * v[i] + (1 - beta2) * gradients[i] * gradients[i];
        float m_hat = m[i] / (1 - pow(beta1, t));
        float v_hat = v[i] / (1 - pow(beta2, t));
        params[i] -= learning_rate * m_hat / (sqrt(v_hat) + epsilon);
    }
}

代码实现

下面是一个简单示例,演示了如何使用上述优化算法训练一个简单的线性回归模型。

#include <iostream>
#include <cmath>

void gradient_descent(float *params, float *gradients, float learning_rate, int n) 
{
    for (int i = 0; i < n; i++)
     {
        params[i] -= learning_rate * gradients[i];
    }
}

void stochastic_gradient_descent(float *params, float *gradients, float learning_rate, int n)
 {
    for (int i = 0; i < n;```cpp
 i++) {
        params[i] -= learning_rate * gradients[i];
    }
}

void momentum(float *params, float *gradients, float learning_rate, float momentum_rate, float *velocities, int n) 
{
    for (int i = 0; i < n; i++)
     {
        velocities[i] = momentum_rate * velocities[i] + learning_rate * gradients[i];
        params[i] -= velocities[i];
    }
}

void adagrad(float *params, float *gradients, float learning_rate, float epsilon, float *accumulators, int n)
 {
    for (int i = 0; i < n; i++)
     {
        accumulators[i] += gradients[i] * gradients[i];
        params[i] -= learning_rate * gradients[i] / (sqrt(accumulators[i]) + epsilon);
    }
}

void rmsprop(float *params, float *gradients, float learning_rate, float decay_rate, float epsilon, float *accumulators, int n)
 {
    for (int i = 0; i < n; i++) 
    {
        accumulators[i] = decay_rate * accumulators[i] + (1 - decay_rate) * gradients[i] * gradients[i];
        params[i] -= learning_rate * gradients[i] / (sqrt(accumulators[i]) + epsilon);
    }
}

void adam(float *params, float *gradients, float learning_rate, float beta1, float beta2, float epsilon, float *m, float *v, int t, int n) 
{
    for (int i = 0; i < n; i++)
     {
        m[i] = beta1 * m[i] + (1 - beta1) * gradients[i];
        v[i] = beta2 * v[i] + (1 - beta2) * gradients[i] * gradients[i];
        float m_hat = m[i] / (1 - pow(beta1, t));
        float v_hat = v[i] / (1 - pow(beta2, t));
        params[i] -= learning_rate * m_hat / (sqrt(v_hat) + epsilon);
    }
}

int main()
 {
    // 参数初始化
    float params[2] = {0};
    float gradients[2] = {0};
    float velocities[2] = {0};
    float accumulators[2] = {0};
    float m[2] = {0};
    float v[2] = {0};
    
    // 数据初始化
    float x[5] = {1, 2, 3, 4, 5};
    float y[5] = {2, 4, 6, 8, 10};
    
    // 学习率
    float learning_rate = 0.01;
    // 动量因子
    float momentum_rate = 0.9;
    // AdaGrad参数
    float epsilon_adagrad = 1e-8;
    // RMSProp参数
    float decay_rate_rmsprop = 0.9;
    float epsilon_rmsprop = 1e-8;
    // Adam参数
    float beta1_adam = 0.9;
    float beta2_adam = 0.999;
    float epsilon_adam = 1e-8;
    
    // 训练
    int epochs = 100;
    int n = 2;
    for (int epoch = 1; epoch <= epochs; epoch++) {
        float loss = 0;
        for (int i = 0; i < 5; i++) {
            float prediction = params[0] * x[i] + params[1];
            float error = prediction - y[i];
            loss += error * error;
            gradients[0] = 2 * error * x[i];
            gradients[1] = 2 * error;
            
            // 使用各种优化算法更新参数
            // gradient_descent(params, gradients, learning_rate, n);
            // stochastic_gradient_descent(params, gradients, learning_rate, n);
            // momentum(params, gradients, learning_rate, momentum_rate, velocities, n);
            // adagrad(params, gradients, learning_rate, epsilon_adagrad, accumulators, n);
            // rmsprop(params, gradients, learning_rate, decay_rate_rmsprop, epsilon_rmsprop, accumulators, n);
            adam(params, gradients, learning_rate, beta1_adam, beta2_adam, epsilon_adam, m, v, epoch, n);
        }
        loss /= 5;
        std::cout << "Epoch " << epoch << ", Loss = " << loss << ", Params = " << params[0] << ", " << params[1] << std::endl;
    }
    
    return 0;
}

这段代码演演示了实现梯度下降法、随机梯度下降法、动量法、AdaGrad、RMSProp和Adam等优化算法来训练一个简单的线性回归模型
在这里插入图片描述

总结 Gradient Descent Algorithm

Gradient Descent is one of the fundamental optimization algorithms used in machine learning and deep learning. It is used to minimize a loss function by iteratively adjusting the parameters of a model. The basic idea behind Gradient Descent is to compute the gradient of the loss function with respect to the model’s parameters and update the parameters in the opposite direction of the gradient to minimize the loss.

Algorithm Steps:

  1. Initialize Parameters: Start by initializing the parameters of the model with random values.

  2. Compute Gradients: Compute the gradient of the loss function with respect to each parameter of the model using backpropagation.

  3. Update Parameters: Update the parameters of the model using the following update rule:

  4. 在这里插入图片描述在这里插入图片描述

  5. Repeat: Repeat steps 2 and 3 until the loss converges to a minimum or for a fixed number of iterations.

Pseudocode:

function gradient_descent(params, gradients, learning_rate):
    for each parameter theta in params:
        theta = theta - learning_rate * gradient

Implementation in C++:

void gradient_descent(float *params, float *gradients, float learning_rate, int n) {
    for (int i = 0; i < n; i++) {
        params[i] -= learning_rate * gradients[i];
    }
}

Conclusion:

Gradient Descent is a powerful optimization algorithm used to train machine learning and deep learning models. It is simple to implement and computationally efficient, making it the go-to choice for optimizing a wide range of models.


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/594381.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Unity】位图字体制作工具:蒲公英

一般来讲&#xff0c;如果需要制作位图字体&#xff0c;一般是使用 BMFont 这种第三方工具&#xff1a;BMFont - AngelCode.comhttp://www.angelcode.com/products/bmfont/ 然而这个工具对于非程序员来说&#xff0c;操作起来较为繁琐困难。每次美术修改了字体之后&…

【短剧在线表格搜索-附模板】

短剧在线表格搜索-附模板 介绍电脑界面手机界面送附加功能&#xff1a;反馈缺失短剧送&#xff1a;资源更新源头获取 介绍 你好&#xff01; 这是你第一次使用 金山在线文档 所生成的短剧搜索表格&#xff0c;支持批量导入自己转存的短剧名字和链接&#xff0c;实现在线搜索&a…

【AI】openai-quickstart 运行Jupyter Lab

openai-quickstart/openai_api /README-CN.md 【AI】指定python3.10安装Jupyter Lab 可以安装3.10版本的jupyter lab 但是直接输入命令无法启动 突然发现自己电脑2023年安装过anaconda3 C:\ProgramData\anaconda3\python.exe C:\ProgramData\anaconda3\cwp.py C:\ProgramData…

一款开源的原神工具箱,专为现代化 Windows 平台设计,旨在改善桌面端玩家的游戏体验

Snap.Hutao 胡桃工具箱是一款以 MIT 协议开源的原神工具箱&#xff0c;专为现代化 Windows 平台设计&#xff0c;旨在改善桌面端玩家的游戏体验。通过将既有的官方资源与开发团队设计的全新功能相结合&#xff0c;提供了一套完整且实用的工具集&#xff0c;且无需依赖任何移动设…

WordPress MasterStudy LMS插件 SQL注入漏洞复现(CVE-2024-1512)

0x01 产品简介 WordPress和WordPress plugin都是WordPress基金会的产品。WordPress是一套使用PHP语言开发的博客平台。该平台支持在PHP和MySQL的服务器上架设个人博客网站。WordPress plugin是一个应用插件。 0x02 漏洞概述 WordPress Plugin MasterStudy LMS 3.2.5 版本及之…

SpringCloudAlibaba:4.1云原生网关higress的搭建

概述 简介 Higress是基于阿里内部的Envoy Gateway实践沉淀、以开源Istio Envoy为核心构建的下一代云原生网关&#xff0c; 实现了流量网关 微服务网关 安全网关三合一的高集成能力&#xff0c;深度集成Dubbo、Nacos、Sentinel等微服务技术栈 定位 在虚拟化时期的微服务架构…

STM32 PWM波定时溢出中断

打开定时器和中断 主函数初始化开启PWM和中断 HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1); __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, Pwm_data); HAL_TIM_Base_Start_IT(&htim2); 回调函数中判断是否为tim2 void HAL_TIM_PeriodElapsedCallback(TIM_Han…

【ARM】ARM寄存器和异常处理

1.指令的执行过程 &#xff08;1&#xff09;一条指令的执行分为三个阶段 1.取址&#xff1a; CPU将PC寄存器中的地址发送给内存&#xff0c;内存将其地址中对应的指令返回 到CPU中的指令寄存器&#xff08;IR&#xff09; 2.译码&#xff1a; 译码器对IR中的指令…

51单片机入门:DS1302时钟

51单片机内部含有晶振&#xff0c;可以实现定时/计数功能。但是其缺点有&#xff1a;精度往往不高、不能掉电使用等。 我们可以通过DS1302时钟芯片来解决以上的缺点。 DS1302时钟芯片 功能&#xff1a;DS1302是一种低功耗实时时钟芯片&#xff0c;内部有自动的计时功能&#x…

裸金属服务器,云用户的新体验

定义 裸金属服务器&#xff08;Bare Metal Server&#xff09;&#xff0c;是一台既具有传统物理服务器特点的硬件设备&#xff0c;又具备云计算技术的虚拟化服务功能&#xff0c;是硬件和软件优势结合的产物。可以为企业提供专属的云上物理服务器&#xff0c;为核心数据库、关…

15_Scala面向对象编程_访问权限

文章目录 Scala访问权限1.同类中访问2.同包不同类访问3.不同包访问4.子类权限小结 Scala访问权限 知识点概念 private --同类访问private[包名] --包私有&#xff1b; 同类同包下访问protected --同类&#xff0c;或子类 //同包不能访问(default)(public)默认public --公…

学习大数据,所需要的shell基础(1)

文章目录 Shell概述shell脚本入门变量系统预定义变量自定义变量特殊变量$n$#\$*、$$&#xff1f; 运算符条件判断流程控制&#xff08;重点&#xff09;if判断case语句for循环while循环 Shell概述 shell是一个命令解释器&#xff0c;他接受应用程序/用户命令&#xff0c;然后调…

【Python项目】基于opencv的的【疲劳检测系统】

技术简介&#xff1a;使用Python技术、OpenCV图像处理库、MYSQL数据库等实现。 系统简介&#xff1a;用户可以通过登录系统平台实现实时的人脸照片的拍摄和上传&#xff0c;结合上传图像的内容进行后台的图像预处理和运算分析&#xff0c;用户可以通过照片分析界面查看到当前检…

【iOS】KVO

文章目录 前言一、KVO使用1.基本使用2.context使用3.移除KVO通知的必要性4.KVO观察可变数组 二、代码调试探索1.KVO对属性观察2.中间类3.中间类的方法3.dealloc中移除观察者后&#xff0c;isa指向是谁&#xff0c;以及中间类是否会销毁&#xff1f;总结 三、KVO本质GNUStep窥探…

虚拟化技术 使用Vsphere Client管理ESXi服务器系统

使用Vsphere Client管理ESXi服务器系统 一、实验目的与要求 1.掌握使用vSphere Client管理ESXi主机 2.掌握将CentOS的安装介质ISO上传到ESXi存储 3.掌握在VMware ESXi中创建虚拟机 4.掌握在所创建的虚拟机中安装CentOS6.5操作系统 5.掌握给CentOS6.5安装VMware Tools 6.掌…

HCIP的学习(11)

OSPF的LSA详解 LSA头部信息 ​ [r2]display ospf lsdb router 1.1.1.1----查看OSPF某一条LSA的详细信息&#xff0c;类型以及LS ID参数。 链路状态老化时间 指一条LSA的老化时间&#xff0c;即存在了多长时间。当一条LSA被始发路由器产生时&#xff0c;该参数值被设定为0之后…

RK3568 学习笔记 : u-boot 千兆网络无法 ping 通PC问题的解决方法二

参考 RK3568 学习笔记 : u-boot 千兆网络无法 ping 通PC问题的解决 前言 rk3568 rockchip 提供的 u-boot&#xff0c;默认的设备树需要读取 单独分区 resouce.img 镜像中的 设备树文件&#xff0c;也就是 Linux 内核的设备树 dtb 文件&#xff0c;gmac 网络才能正常的 ping 通…

知识图谱和大语言模型的共存之道

导读 知识图谱和大型语言模型都是用来表示和处理知识的手段。大模型补足了理解语言的能力&#xff0c;知识图谱则丰富了表示知识的方式&#xff0c;两者的深度结合必将为人工智能提供更为全面、可靠、可控的知识处理方法。在这一背景下&#xff0c;OpenKG组织新KG视点系列文章—…

Microsoft Remote Desktop Beta for Mac:远程办公桌面连接工具

Microsoft Remote Desktop Beta for Mac不仅是一款远程桌面连接工具&#xff0c;更是开启远程办公新篇章的利器。 它让Mac用户能够轻松访问和操作远程Windows计算机&#xff0c;实现跨平台办公的无缝衔接。无论是在家中、咖啡店还是旅途中&#xff0c;只要有网络连接&#xff0…

如何使用DEEPL免费翻译PDF

如何使用DEEPL免费翻译PDF 安装DEEPL取消PDF限制 安装DEEPL 安装教程比较多&#xff0c;这里不重复。 把英文pdf拖进去&#xff0c;点翻译&#xff0c;在下面的框中有已经翻译完毕的文档。 但是存在两个问题 问题1&#xff1a;这些文档是加密的。 问题2&#xff1a;带有DeepL标…
最新文章