python二元函数如何编写,Nelder_Mead算法的简介和用作求解二维函数最小值的Python实现...

一、Nelder-Mead算法介绍

Nelder-Mead算法主要应用于求解一些非线性(nonliner)、导函数未知的最大值或最小值问题。本文利用Nelder-Mead算法求解函数最小值问题。

当应用Nelder-Mead时,若函数有n个变量,则数据集合(simplex)需要构建n+1个元素。利用这n+1个元素,不停地替换掉函数值最大(小)的元素,同时维护更新中心点的值,当最终的函数值满足容忍条件时即可得出近似解的结果。

算法的流程如下:

1. 构建变量集合A = {

e6d00add34e63b91bcaff2e9197863f7.png},集合中的每个元素是一个多维的集合,例如对于

24591008c7e9762d8e39366d25641b6d.png

0e716f2c95281ea081ca17b2ccc25e92.png为1维。且该集合满足

71ff5e2d5c48abe01723d6287c2e66c5.png

2. 计算中心点

c032f6c2f578fd40eb4a34ab8bac839d.png,即A中每个元素对应的每一维的平均值。

3. 由于在之前的集合A中,已经可以知道最末尾的变量对应的函数值是最大的,因此对其进行替换,每一次替换后都要更新一次中心点的值。替换的方法共有四种:

(1)反射,将

259612b3054397b754cd3ad440259977.png

c032f6c2f578fd40eb4a34ab8bac839d.png为原点映射到对应的

0e716f2c95281ea081ca17b2ccc25e92.png倍距离位置,其中

01459ad5769f652df1535a1a39c0b6a7.png

(2)扩展反射,将

259612b3054397b754cd3ad440259977.png

c032f6c2f578fd40eb4a34ab8bac839d.png为原点映射到对应的

d070da0bf63fddde553e14b3b4a5166a.png倍距离位置,其中

47c3e92506e0eba7fa9a0e283e419343.png

(3)缩小距离,将

259612b3054397b754cd3ad440259977.png

c032f6c2f578fd40eb4a34ab8bac839d.png为原点缩小到

4f1a599084e166d266ab90abc2617f4f.png倍距离位置,其中

a21adef696dc0c61ef574eb78c4ca743.png

(4)缩小距离,将

259612b3054397b754cd3ad440259977.png

a0e07cef0a8f85e7dec2f7121187d153.png为原点缩小到

2bda88f7026021638b65b5fd9bd6e888.png倍距离位置,其中

9f681ecbc4dfca984e19493e66328f53.png

注意(3)和(4)中映射操作采用的原点不同,

4751a94b31890125b7367e6134574f4d.png的标准取值为

9090854c4e240d9f9568b5ecef651ac9.png。在四种替换方法中选择出相对更大(小)的

124858b89ad746efddf91bcd09733fa2.png,利用

1fc712b7e299276599420aa9a6407c92.png替换掉之前最大的

259612b3054397b754cd3ad440259977.png

注:四种替换方法从(1)到(4)执行,一旦满足替换条件则不向下继续求解替换,而是重新回归步骤1。

4. 重复上述过程,直到集合A中的值满足容忍条件即可停止,并认为已经定位到了可能的最大(小)值的点。(个人理解是会在一定情况下出现局部最优解的情况,即一直重复(1)和(2)的替换方法)。

为了使结果尽可能避免是局部最优解,在构建初始集(initial simplex)非常关键。当初始集构造范围过小时,大概率会出现局部解而非全局解,因此在构建初始集合时,要求各个元素构成的区域是非零容积。

二、Python实现

首先定义需要求解的目标函数:

def func(x, y):#目标函数

result = math.pow(x - y, 2) + math.pow(x - 2, 2) + math.pow(y - 3, 4)

return result

个人设计的存储结构是dict{

890c6bbbf979339d8948c5dd1b931f5b.png

04d1333e1b0518e957eb1c1328aab024.png}

def get_dict(res_dict):#获取坐标:值的dict

for i in range(4):

x = random.randint(-10, 10)

y = random.randint(-10, 10)

result = func(x, y)

loc = (x, y)

res_dict[loc] = result

return res_dict

由于在算法中对函数值排序的作用仅在于获取最大值和最小值对应的

0e716f2c95281ea081ca17b2ccc25e92.png,因此只需要得到dict中最大和最小value对应的key。因此设计两个函数返回对应的index或对应的key。本文中返回对应的index。

def get_max():

...

return index_max

def get_min():

...

return index_min

接下来设计5个函数,分别用作求中间值mean,以及4种探索方法计算对应的z1, z2, z3和z4。此处对算法进行了一点更改,即直接比较4种方法的值获得一个相对最优的解。目前测试的结果也能达到该算法执行的结果。

result_list = []#分析四种分散方法对应的z函数值

result_list.append(get_z1(index_max, mean, res_dict))

result_list.append(get_z2(index_max, mean, res_dict))

result_list.append(get_z3(index_max, mean, res_dict))

result_list.append(get_z4(index_max, index_min, mean, res_dict))

index = 0

flag = 0

min = result_list[0][1]#得到最小的函数值

for r in result_list:#获取最小的z值对应的坐标进行替换

if result_list[flag][1] <= min:

min = result_list[index][1]

index = flag

flag += 1

else:

flag += 1

z = result_list[index][1]

z_cord = tuple(result_list[index][0])#(x,y)

最后替换掉集合中的点,不断循环更新。最后满足容忍条件时结束循环。

代码详情见:https://github.com/olddaddy/data_mining_1.git

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值