【算法】模拟退火算法学习记录

        写这篇博客的原因是博主本人在看某篇文章的时候,发现自己只是知道SGD这个东西,但是到底是个啥不清楚,所以百度了一下,然后在通过博客学习的时候看到了退火两个字,想到了本科做数模比赛的时候涉猎过,就上bilibili搜索讲解视频学习了退火的算法,感觉看完之后收获还蛮大的,所以写下这篇博客作为记录。话不多说,上正文——

一、算法介绍

        模拟退火算法(Simulated Annealing, SA)是一种概率型优化算法,它受到物理学中固体物质退火过程的启发。退火过程是指将固体加热后再慢慢冷却,使其达到能量最低的稳定状态。模拟退火算法将这一过程应用于组合优化问题,通过模拟退火过程来寻找问题的全局最优解。

        举个栗子,逼近下图函数的最大值,利用退火的思想就是经过多次迭代(退火),逼近函数上的A点。

         因为模拟退火算法借鉴的是固体的退货原理,相信理科生都能很快get到,温度越高,固体内部的分子能量越高,均处于快速无序的运动,当温度慢慢降低时,分子的能量降低,慢慢地趋于有序,到最后达到常温的时候,能量达到最小,此时内部的分子最为稳定。从前面这段话我们可以解析出几个点——

  • 温度越高,分子越乱,放在退火算法里就是温度越高,x的跳变范围越大
  • 温度变化是缓慢的,特别特别慢那种
  • 温度不再变化之后,也就是趋于有序,放在退火算法里也就是达到了最优 

二、算法大框架

模拟退火算法本质上就是一个循环算法。(博主本人在练习代码的时候,感觉核心有点像暴力枚举,啊哈哈哈哈)

  1. 设定一个初始的温度T
  2. 每个循环就是退火一次
  3. 降低T(通过将T和一个降温系数相乘来达到慢慢降温的效果)
  4. T无限接近于0的时候退出循环

将上面的流程以伪代码的形式展示:

double T; //初始温度
double dt; //降温系数,小于1但是趋于1,类似0.99这种
const double eps = 1e-4; //用于判断T是否趋于0

while(T > eps)
{
    //退火流程
    //……
    

    T = T * dt; //降温
}

三、退火算法详解

        这一部分主要是来详细介绍模拟退火算法的核心部分。首先需要现在定义域中随机取一个自变量x,这样根据函数又可以得到f(x)。下一步,自变量根据当前温度进行随机变化得到x0,又得到f(x0)。最后,根据我们的具体需要来决定是一定接受还是按概率接受。

        可能有的同学看完上面这段脑袋都大了,我们就拿上面的函数求最大值来举个栗子——

        图中的x就是随机选择的一个自变量,x0是根据当前温度随机跳变后的自变量。在俺们这个例子中,我们是想要找到函数的最大值,如果随机跳变后的自变量对应的函数值大于当前自变量的函数值是百分百接受的,也就是直接进行数据更新,也就是上图中从x跳变到x1的情况;但是如果跳变后的自变量对应的函数值小于当前自变量的函数值,这样的情况是按概率接受的(这种情况也很好理解,如果小于就直接拒绝,这样很容易就陷入到局部最优了)。

        那么这个按概率接受又是啥嘞?我们用一个公式来表示,具体的推导大家感兴趣可以自己找一下,俺在这里就不详细展开了。

e^{\tfrac{\Delta f}{KT}}

其中,\Delta f是函数值的变化量,K是一个物理学常数,T是当前温度。根据指数函数的性质,整个指数部分小于0时函数值是小于1的,才满足概率小于等于1的条件,所以同学们在判断接受的时候要尤其注意指数部分的形式。

所以总结一下就是:

  • 随机跳变后的函数值如果结果更好,我们一定接受它(即x=x0,f(x)=f(x0))
  • 随机跳变后的函数值如果结果更差,我们以​的概率e^{\tfrac{\Delta f}{KT}}接受它

 将模拟退火算法以伪代码形式展示:

//三板斧
double T = 2000; //初始温度
double dt = 0.993;  //退火率(温度下降率)
const double eps = 1e-14;  //用来判定T是否无限趋近于0

//函数,传入自变量参数x,得到f(x)
double func(double x)
{
	return f(x);//函数内部的功能具体问题具体分析
}

//退火算法的核心
void SA()
{
	//先随机生成一个x值,这里的x值不是说只能是一个参数,可以是一组参数,也是具体情况具体分析
	double x = rand();
	//得到随机数对应的f(x)
	double y = func(x);
    //退火算法开始
	while (T > eps)
	{
		//先算出随机跳变后的自变量,可以是减小,也可以增大
		double dx = x + (2 * rand() - RAND_MAX) * T; //因为是与当前温度相关的跳变,所以要乘以T

		double dy = func1(dx);//计算得到跳变后自变量对应的函数值
		//退火函数的关键!!
		if (满足百分百接受的条件) 
		{
			y = dy;
			x = dx;
		}
		else if(exp((y-dy)/T) * RAND_MAX > rand())//否则按一定概率接受
		{
			y = dy;
			x = dx;
		}
		else
		{
			T = T * dt; //温度缓慢降低
		}
	}
	cout << x << endl; //打印结果
}

四、应用举例

        利用模拟退火算法来实现计算一个数的平方根,给出完整的c++代码,方便同学们学习调试。(因为博主也是从其他博主那里学习的,我感觉这块的代码还有蛮多可以改进的,因为c++很少使用全局变量,会破坏封装性,而且使得代码不好迁移)

#include<iostream>
using namespace std;

double n;
//三板斧
double T = 2000; //初始温度
double dt = 0.993;  //退火率(温度下降率)
const double eps = 1e-14;  

double func1(double x)
{
	return abs(x * x - n);
}

void SA1()
{
	//先随机生成一个x值
	double x = rand();
	//得到随机数对应的f(x)
	double y = func1(x);
	while (T > eps)
	{
		//先算出x的跳变数,可正可负
		double dx = x + (2 * rand() - RAND_MAX) * T;
		//保证dx为正数,因为只有正数才有平方根
		while (dx < 0)
		{
			dx = x + (2 * rand() - RAND_MAX) * T;
		}
		double dy = func1(dx);
		//退火函数的关键!!
		//需要计算得到的func函数值足够小
		if (dy < y) //当得到的函数值小于原来的函数值时百分百接受 
		{
			y = dy;
			x = dx;
		}
		else if(exp((y-dy)/T) * RAND_MAX > rand())//否则按一定概率接受
		{
			y = dy;
			x = dx;
		}
		else
		{
			T = T * dt;
		}
	}
	cout << x << endl;
}

void testSA1()
{
	cout << "请输入要计算的数:" << endl;
	cin >> n;
	SA1();
}

int main()
{
	testSA1();
	return 0;
}

        整体的流程跟前两点讲的是完全吻合的,同学们可以结合着前面的理论内容、代码以及注释来理解学习,整个的学习脉络还是非常清楚的。

        模拟退火算法就先写到这,有任何问题欢迎同学们指出,大家一起学习进步嗷~

参考:

详解随机梯度下降法(Stochastic Gradient Descent,SGD)_随机梯度下降公式-CSDN博客

速通模拟退火 - 分享今天心情

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

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

相关文章

Visual Point Cloud Forecasting enables Scalable Autonomous Driving——点云论文阅读(12)

此内容是论文总结,重点看思路!! 文章概述 这篇文章介绍了一个名为 ViDAR 的视觉点云预测框架,它通过预测历史视觉输入生成未来点云,作为自动驾驶的预训练任务。ViDAR 集成了语义、三维几何和时间动态信息,有效提升了感知、预测和规划等自动驾驶核心任务的性能。实验表明…

AI 将在今年获得“永久记忆”,2028美国会耗尽能源储备

AI的“永久记忆”时代即将来临 谷歌前CEO施密特揭示了AI技术的前景&#xff0c;他相信即将在2025年迎来一场伟大的变化。AI将实现“永久记忆”&#xff0c;改变我们与科技的互动过程。施密特将现有的AI上下文窗口比作人类的短期记忆&#xff0c;难以持久保存信息。他的设想是…

工控主板ESM7000/6800E支持远程桌面控制

英创公司ESM7000 是面向工业领域的双核 Cortex-A7 高性能嵌入式主板&#xff0c;ESM6800E则为单核Cortex-A7 高性价比嵌入式主板&#xff0c;ESM7000、ESM6800E都是公司的成熟产品&#xff0c;已广泛应用于工业很多领域。ESM7000/6800E板卡中Linux系统配置为linux-4.9.11内核、…

越权漏洞简介及靶场演示

越权漏洞简介及靶场演示 文章目录 一、什么是越权&#xff1f; &#xff08;一&#xff09;越权漏洞的概念&#xff08;二&#xff09;越权漏洞的分类&#xff08;三&#xff09;常见越权方法&#xff08;四&#xff09;未授权访问 二、越权漏洞测试过程 &#xff08;一&…

VIT:视觉transformer|学习微调记录

一、了解VIT结构 vit提出了对于图片完全采用transformer结构而不是CNN的方法&#xff0c;通过将图片分为patch&#xff0c;再将patch展开输入编码器&#xff08;grid_size网格大小&#xff09;&#xff0c;最后用MLP将输出转化为对应类预测。 详细信息可以看下面这个分享&…

coredns报错plugin/forward: no nameservers found

coredns报错plugin/forward: no nameservers found并且pod无法启动 出现该报错原因 是coredns获取不到宿主机配置的dns地址 查看宿主机是否有dns地址 resolvectl status 我这里是配置正确后&#xff0c;如果没配置过以下是不会显示出dns地址的 给宿主机增加静态dns地址之后将…

使用Diffusion Models进行图像超分辩重建

Diffusion Models专栏文章汇总:入门与实战 前言:图像超分辨率重建是一个经典CV任务,其实LR(低分辨率)和 HR(高分辨率)图像仅在高频细节上存在差异。通过添加适当的噪声,LR 图像将变得与其 HR 对应图像无法区分。这篇博客介绍一种方式巧妙利用这个规律使用Diffusion Mod…

NineData 荣获年度“创新解决方案奖”

近日&#xff0c;国内知名 IT 垂直媒体 & 技术社区 IT168 再次启动“技术卓越奖”评选&#xff0c;由行业 CIO/CTO 大咖、技术专家及 IT 媒体多方联合评审&#xff0c;NineData 凭借技术性能和产品创新等方面表现出色&#xff0c;在数据库工具领域荣获“2024 年度创新解决方…

liunx下载gitlab

1.地址&#xff1a; https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/ 安装 postfix 并启动 yum install postfix systemctl start postfix systemctl enable postfix ssh服务启动 systemctl enable sshd systemctl start sshd开放 ssh 以及 http 服务&#xff0c…

SQL—替换字符串—replace函数用法详解

SQL—替换字符串—replace函数用法详解 REPLACE() 函数——查找一个字符串中的指定子串&#xff0c;并将其替换为另一个子串。 REPLACE(str, old_substring, new_substring)str&#xff1a;要进行替换操作的原始字符串。old_substring&#xff1a;要被替换的子串。new_substri…

Android笔试面试题AI答之Android基础(11)

Android入门请看《Android应用开发项目式教程》&#xff0c;视频、源码、答疑&#xff0c;手把手教 文章目录 1.Android的权限有哪些&#xff1f;**1. 普通权限****常见普通权限** **2. 危险权限****权限分组****常见危险权限组及权限** **3. 特殊权限****常见特殊权限** **4. …

机器学习之正则化惩罚和K折交叉验证调整逻辑回归模型

机器学习之正则化惩罚和K折交叉验证调整逻辑回归模型 目录 机器学习之正则化惩罚和K折交叉验证调整逻辑回归模型1 过拟合和欠拟合1.1 过拟合1.2 欠拟合 2 正则化惩罚2.1 概念2.2 函数2.3 正则化种类 3 K折交叉验证3.1 概念3.2 图片理解3.3 函数导入3.4 参数理解 4 训练模型K折交…

[AHK]用大模型写ahk脚本

问题背景 遇到程序在运行&#xff0c;但是在屏幕上看不到的窘境&#xff0c;于是想用AHK来实现一键在主屏幕上居中显示。 解决思路 手撸是不可能手撸的&#xff0c;我有豆包我有cursor&#xff0c;于是想看看她俩到底能力咋样。 提示词 用AHK v2实现&#xff1a;热键WinC …

Word如何插入图片并移动到某个位置

Word如何插入图片并移动到某一个位置 新建word→插入→图片 选择合适的位置→选择图片→打开 点击图片→布局选项→选择文字环绕下的任意一个→固定在页面上 点击图片就可以将图片移动到任意位置

ElasticSearch7.10-分词器

文章目录 分词器1.字符过滤器1.介绍2.过滤html标签3.mappings过滤规则&#xff08;屏蔽非文明用语&#xff09;4.正则替换 2.自定义分词器1.代码2.查询 3.中文分词器1.下载ik分词器7.10.0版本&#xff08;跟es对应&#xff09;2.应用ik分词器1.进入插件目录下创建一个ik目录2.将…

python利用selenium实现大麦网抢票

大麦网&#xff08;damai.cn&#xff09;是中国领先的现场娱乐票务平台&#xff0c;涵盖演唱会、音乐会、话剧、歌剧、体育赛事等多种门票销售。由于其平台上经常会有热门演出&#xff0c;抢票成为许多用户关注的焦点。然而&#xff0c;由于票务资源的有限性&#xff0c;以及大…

Linux 笔记 SELinux 常见操作与介绍

SELinux&#xff08;Security-Enhanced Linux&#xff09;是 Linux 操作系统中的一种安全模块&#xff0c;旨在提供更细粒度的访问控制。它最初由美国国家安全局&#xff08;NSA&#xff09;开发&#xff0c;目的是增强 Linux 系统的安全性。SELinux 通过强制访问控制&#xff…

Elasticsearch VS Easysearch 性能测试

压测环境 虚拟机配置 使用阿里云上规格&#xff1a;ecs.u1-c1m4.4xlarge&#xff0c;PL2: 单盘 IOPS 性能上限 10 万 (适用的云盘容量范围&#xff1a;461GiB - 64TiB) vCPU内存 (GiB)磁盘(GB)带宽&#xff08;Gbit/s&#xff09;数量1664500500024 Easysearch 配置 7 节点…

javacript中function (res) {}与箭头函数表达式(res) =>{}的区别

javacript中function (res) {}与(res) &#xff1e;{}的区别 function (res) {} 代码演示 let shape {name:长方形,say:function(){console.log(我是this.name)setTimeout(function(){console.log(3秒后输出我是: this.name); //this.name为undefined}, 3000)} }shape.sa…

[IT项目管理]十.项目人力资源管理

十&#xff0e;项目人力资源管理 *10.0基础知识 1&#xff09;动力与激励 10.1人力资源管理的重要性 很多项目经理都说过&#xff0c;“人是我们最重要的资产。”&#xff0c;人的因素决定着一个 组织或者项目的成败。 10.2人力资源管理对未来的其启示 对于组织来说&#…