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

抛砖引玉

在深度学习中,优化算法是训练神经网络时至关重要的一部分。
优化算法的目标是最小化(或最大化)一个损失函数,通常通过调整神经网络的参数来实现。
这个过程可以通过梯度下降法来完成,其中梯度指的是损失函数关于参数的偏导数。
本文将介绍一阶优化算法和二阶优化算法,并详细讲解常用的梯度下降法,包括梯度下降法、随机梯度下降法、动量法、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;```cppi++) {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.mzph.cn/news/832123.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Grafana:云原生时代的数据可视化与监控王者

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Grafana&#xff1a;让数据说话的魔术师》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、Grafana简介 2、Grafana的重要性与影响力 …

全方位了解 Meta Llama 3

本文将为您提供 Llama 3 的全面概览&#xff0c;从其架构、性能到未来的发展方向&#xff0c;让您一文了解这一革命性大语言模型的所有要点。 Meta Llama 发展历程 Llama 1 Llama 是由 Meta(FaceBook) AI 发布的一个开源项目&#xff0c;允许商用&#xff0c;影响力巨大。Lla…

力扣每日一题111:二叉树的最小深度

题目 简单 给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说明&#xff1a;叶子节点是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;2示例 2&#x…

C语言:文件操作(上)

片头 嗨&#xff01;小伙伴们&#xff0c;今天我们来学习新的知识----文件操作&#xff0c;准备好了吗&#xff1f;我要开始咯! 目录 1. 为什么使用文件&#xff1f; 2. 什么是文件&#xff1f; 3. 二进制文件和文本文件&#xff1f; 4. 文件的打开和关闭 5. 文件顺序读写…

启发式算法解魔方——python

未完待续&#xff0c;填坑ing…… 魔方操作的表示——辛马斯特标记 辛马斯特标记&#xff08;Singmaster Notation&#xff09;是一种用于描述魔方和类似拼图的转动操作的标记系统。它以大卫辛马斯特&#xff08;David Singmaster&#xff09;的名字命名&#xff0c;辛马斯特…

C 认识指针

目录 一、取地址操作符&#xff08;&&#xff09; 二、解引用操作符&#xff08;*&#xff09; 三、指针变量 1、 指针变量的大小 2、 指针变量类型的意义 2.1 指针的解引用 2.2 指针 - 整数 2.3 调试解决疑惑 认识指针&#xff0c;指针比较害羞内敛&#xff0c;我们…

单调栈-java

本次主要通过数组模拟单调栈来解决问题。 目录 一、单调栈☀ 二、算法思路☀ 1.暴力做法&#x1f319; 2.优化做法&#x1f319; 3.单调递增栈和单调递减栈&#x1f319; 三、代码如下☀ 1.代码如下&#xff08;示例&#xff09;&#xff1a;&#x1f319; 2.读入数据&a…

Ubuntu MATE系统下WPS显示错位

系统&#xff1a;Ubuntu MATE 22.04和24.04&#xff0c;在显示器设置200%放大的情况下&#xff0c;显示错位。 显示器配置&#xff1a; WPS显示错位&#xff1a; 这个问题当前没有找到好的解决方式。 因为4K显示屏设置4K分辨率&#xff0c;图标&#xff0c;字体太小&#xff…

prometheus搭建

1.prometheus下载 下载地址:Download | Prometheus 请下载LTS稳定版本 本次prometheus搭建使用prometheus-2.37.1.linux-amd64.tar.gz版本 2.上传prometheus-2.37.1.linux-amd64.tar.gz至服务器/opt目录 CentOS7.9 使用命令rz -byE上传 3.解压缩prometheus-2.37.1.linux…

【C++之map的应用】

C学习笔记---021 C之map的应用1、map的简单介绍1.1、基本概念1.2、map基本特性 2、map的基本操作2.1、插入元素2.2、访问元素2.3、删除元素2.4、遍历map2.5、检查元素是否存在2.6、获取map的大小2.7、清空map2.8、基本样例 3、map的基础模拟实现4、测试用例4.1、插入和遍历4.2、…

Flutter笔记:Widgets Easier组件库(11)- 使用提示吐丝

Flutter笔记 Widgets Easier组件库&#xff08;11&#xff09;使用提示吐丝 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this …

【多模态】29、OCRBench | 为大型多模态模型提供一个 OCR 任务测评基准

文章目录 一、背景二、实验2.1 测评标准和结果2.1.1 文本识别 Text Recognition2.1.2 场景文本中心的视觉问答 Scene Text-Centric VQA2.1.3 文档导向的视觉问答 Document-Oriented VQA2.1.4 关键信息提取 Key Information Extraction2.1.5 手写数学公式识别 Handwritten Mathe…

Ubuntu安装配置网络

参考 https://blog.csdn.net/qq_59633155/article/details/131252293https://blog.csdn.net/qq_59633155/article/details/131252293 Ubuntu配置网络 1&#xff0c;查看网络是否连接 终端输入 ping baidu.com 如若成功则如下图所示 如未能成功&#xff0c;则继续按下面步骤…

解决HTTP 403 Forbidden错误:禁止访问目录索引问题的解决方法

解决HTTP 403 Forbidden错误&#xff1a;禁止访问目录索引问题的解决方法 过去有人曾对我说&#xff0c;“一个人爱上小溪&#xff0c;是因为没有见过大海。”而如今我终于可以说&#xff0c;“我已见过银河&#xff0c;但我仍只爱你一颗星。” 在Web开发和服务器管理中&#x…

【精品毕设推荐】基于JSP物流信息网的设计与实现

点击免费下载原文及代码、PPT 摘要 本文讲述了基于JSP物流信息网的设计与实现。该系统使用java语言开发&#xff0c;使系统具有更好的平台性和可扩展性。 该系统实现了用户登录、注册、查询快递信息、快递公司注册成为合作伙伴以及系统管理员对信息进行管理等功能。系统的主…

(三)JVM实战——对象的内存布局与执行引擎详解

对象的内存布局 对象的实例化 对象的创建方式 - new的方式 - Class的newInstance():反射的方式 - Construct的newInstance() - clone:实现Cloneable接口,默认浅拷贝 - 使用反序列化&#xff1a;将二进制流转化为内存对象 创建对象的步骤 - 判断对象对应的类是否加载、链接、初…

You don’t have permission.

The document “XXX” could not be saved. You don’t have permission. 1.查看修改了iOS系统库导致的, 根据提示, 进入到"XXX"文件中, 然后commandz回退/取消 2. Xcode 调试遇到的报错&#xff08;持续更新&#xff09;

18_Scala面向对象编程trait

文章目录 trait1.定义trait2.向类中混入特质2.1没有父类2.2有父类 3.动态混入3.1动态混入查询功能到公司业务中 4.父类&#xff0c;子类&#xff0c;特质初始化优先级5.Scala功能执行顺序6.常用API trait –特质的学习需要类比Java中的接口&#xff0c;源码编译之后就是interf…

练习题(2024/5/3)

1对称二叉树 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false提示&#xff1a; 树中…

(论文阅读-优化器)A Cost Model for SPARK SQL

目录 Abstract 1 Introduction 2 Related Work 3 Background and Spark Basics 4 Cost Model Basic Bricks 4.1 Cluster Abastraction and Cost Model Parameters 4.2 Read 4.3 Write 4.4 Shuffle Read 4.5 Broadcast 5 Modeling GPSJ Queries 5.1 Statistics and S…