栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

模拟退火+粒子群算法寻找最小值点

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

模拟退火+粒子群算法寻找最小值点

模拟退火+粒子群算法寻找最小值点
  • 原理简述
    • 1 模拟退火
    • 2.粒子群算法求解最优化问题

原理简述 1 模拟退火

和最简单的爬山法相比,模拟退火多了一个选择更差的解的概率,假设当前寻找到的解是 x o r g x_{org} xorg​,迭代一轮找到的新解为 x n e w x_{new} xnew​,适应度(简单问题中就是函数值)分别为 f ( x o r g ) , f ( x n e w ) f(x_{org}),f(x_{new}) f(xorg​),f(xnew​),如果新解的适应度比原来的适应度小,那么直接进行更新,进入下一轮迭代,否则以一定概率P
P = e − ( f ( x o r g ) − f ( x n e w ) ) / T P=e^{-(f(x_{org})-f(x_{new}))/T} P=e−(f(xorg​)−f(xnew​))/T
接受新解,其中 T T T是当前温度, f ( x o r g ) − f ( x n e w ) f(x_{org})-f(x_{new}) f(xorg​)−f(xnew​)是能量差。
之所以使用 e − x e^{-x} e−x函数是因为它在(0,+∞)上的函数值在0,1之间。 能量差值越大,选取该新解的可能性就越小。

下面给出模拟退火算法代码的基本流程:
1.设定模拟退火的参数,如初始温度 T 0 T_0 T0​,温度衰减率 α alpha α,每个温度下的迭代次数 L k Lk Lk,整体最大迭代次数max_iters
2.外层循环max_iters次。
3.内层循环Lk次,每次按照一定规则进行新解的产生,更新等,这个按照任务需求来。
4.将温度衰减,回到2。
5.输出最值点的信息。

Py代码

import numpy as np
import pandas as pd
import sklearn
import matplotlib as mlp
import seaborn as sns
import matplotlib.pyplot as plt
import random

def f(x):
    return 11*np.sin(x)+7*np.cos(5*x)

#模拟退火的初始值
narvs = 1 #变量个数
T0 = 100  # 初始温度
T = T0 # 迭代中温度会发生改变,第一次迭代时温度就是T0
maxgen = 200  # 最大迭代次数
Lk = 100  # 每个温度下的迭代次数
alfa = 0.95  # 温度衰减系数
x_lb = np.array([-3]) # x的下界
x_ub = np.array([3]) # x的上界
#随机生成一个初始解
x0=np.zeros(narvs)
# 生成随机解
for i in range(len(x0)):
    # 生成0~1随机数
    r = random.uniform(0, 1)
    x0[i] = x_lb + (x_ub - x_lb) * r
y0=f(x0)

max_y=y0
best_x=np.zeros(narvs)
max_y_lst=[]
maxgen = 200
plt.ion()
x = np.arange(-3, 3, 0.01)
plt.figure(figsize=(10, 10))
plt.plot(x, f(x), 'b--')
plt.scatter(x0, f(x0), color='b')
# 模拟退火过程
for iteration in range(maxgen):  # 迭代maxgen次
    for i in range(Lk):  # 每个温度下的迭代次数
        y = np.random.randn(narvs) # 每个维度的变动幅度
        z = y / sum(y ** 2) # 缩小
        x_new = x0 + z * T
        # 超出定义域
        for j in range(0, narvs):
            if x_new[j] < x_lb[j]:
                r = random.uniform(0, 1)
                x_new[j] = r * x_lb[j] + (1 - r) * x0[j]
            elif x_new[j] > x_ub[j]:
                r = random.uniform(0, 1)
                x_new[j] = r * x_ub[j] + (1 - r) * x0[j]
        x1 = x_new
        y1 = f(x1)
        if y1 > y0:  # 如果新解函数值大于当前解的函数值
            x0 = x1  # 更新当前解为新解
            y0 = y1
        else:
            # 以一定概率接受更差的解
            p = np.exp(-(y0 - y1) / T)
            r = np.random.uniform(0, 1)
            if r < p:
                x0 = x1
                y0 = y1
        if y0 > max_y:
            max_y = y0
            best_x = x0
    plt.clf()
    plt.plot(x, f(x), 'b--')
    plt.scatter(x0, f(x0), color='r')
    plt.pause(0.01)
    max_y_lst.append(*max_y)
    T = alfa * T
plt.ioff()

#模拟退火的主要流程是类似的,针对不同优化问题,找到适合的求处新解的方式即可

2.粒子群算法求解最优化问题

粒子群和模拟退火最直观的差别就是每轮中迭代的解数量不同,粒子群有 N N N个解在搜索最优处,最终选取一个适应度最好的,模拟退火就是单打独斗。直观上来说,粒子群应该更可能找到全局最优。
粒子群算法可以看B站教学粒子群算法讲的十分清晰明了。

粒子群算法最关键的两个步骤就是速度和位置的更新。
v = v ∗ w + c 1 ∗ ( x i n d b e s t − x ) + c 2 ∗ ( x t o t b e s t − x ) v=v*w+c_1*(x_{ind best}-x)+c_2*(x_{totbest}-x) v=v∗w+c1​∗(xindbest​−x)+c2​∗(xtotbest​−x)
其中 w w w是惯性权重, c 1 , c 2 c_1,c_2 c1​,c2​分别是个体学习因子和总体学习因子。按照迭代求解的任务需求,后期的变动应该尽可能小,才能获得稳定的输出,所以可以对这些参数进行函数化,使得越往后越小。此外,这三者的比例不同也会带来不同结果。
x = x + v x=x+v x=x+v

下面展示用粒子群算法求解 x s i n ( x ) ∗ c o s ( 2 x ) − 2 x s i n ( 3 x ) + 3 x s i n ( 4 x ) xsin(x) *cos(2 x) - 2 x sin(3 x) +3 x sin(4 x) xsin(x)∗cos(2x)−2xsin(3x)+3xsin(4x)的最小值。

初始点的位置如下

最终结果如下

寻得最小值点46.696。

不过有时候找到的是次优解。

因此我将粒子群算法写入模拟退火框架下,以一定概率选择更差的解,这样就加大了发现全局最优解的可能性。

多次运行,都能找到全局最优值,说明加上模拟退火后,算法找到全局最优的可能性大大增加。用模拟退火算法时,速度更新式中的 w , c 1 , c 2 w,c_1,c_2 w,c1​,c2​都可以像温度 T T T一样,设置一个衰减率,因此它们的初始值可以设置的大一些,在初期进行比较激进的迭代。根据任务需求,三个参数的衰减率可以按照重要程度不同规定。认为总体学习重要一些的,那就将总体学习因子的衰减率设置的小一点,比如0.95.其他设置为0.9.

import numpy as np
import pandas as pd
import sklearn
import matplotlib as mlp
import seaborn as sns
import matplotlib.pyplot as plt
import random
import copy

#粒子群算法+模拟退火

#目标函数
def f(x):
    return x *np.sin(x) * np.cos(2 * x) - 2 * x * np.sin(3 * x) +3 * x * np.sin(4 * x)

#先实现普通的粒子群算法
def PSO_org(init,demensions,iters,tol,limit,vlimit,w,c1,c2,f):
    '''
    粒子群搜索求解(求最小值)
    :param init:初始化多少只鸟
    :param demensions: 数据维度
    :param iters: 最大迭代轮数
    :param tol: 最小差值(没有使用)
    :param limit: 位置限制
    :param vlimit:速度限制
    :param w:惯性权重
    :param c1:自我学习因子
    :param c2:总体学习因子
    :param f:适应度函数
    :return:最小值点
    '''

    #生成N行d列的随机点
    points=np.random.uniform(limit[0],limit[1],[init,demensions])
    #初始各个随机点的速度
    v=np.random.rand(init,demensions)
    #每个个体的最佳位置
    indiviual_best=copy.deepcopy(points)
    #整个种群的历史最佳位置
    tot_best=np.zeros(demensions)
    #每个个体的历史最佳适应度
    f_indiviual_best=np.array([float('inf') for i in range(init)])
    #种群的历史最佳适应度
    f_tot_best=float('inf')
    record=[]
    plt.figure(1)
    scale=np.arange(limit[0],limit[1],0.1)
    plt.plot(scale, f(scale))
    plt.scatter(points,f(points),c='g')
    plt.title('initial state')
    plt.ion()
    plt.figure(2)
    scale=np.arange(limit[0],limit[1],0.1)
    plt.plot(scale, f(scale))
    plt.scatter(points,f(points),c='r')
    #迭代更新
    for i in range(iters):
        fx=f(points) #个体的适应度
        #更新个体历史适应度
        for i in range(init):
            if fx[i]vlimit[1]]=vlimit[1]
        v[vlimit[1]]=limit[1]
        points[pointslimit[1]]=limit[1]
            new_points[new_pointsvlimit[1]]=vlimit[1]
            v[v
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1025338.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号