找回密码
 注册
Simdroid-非首页
查看: 73|回复: 0

[原创]:坐标轮换法程序中匿名函数的使用心得

[复制链接]
发表于 2013-3-20 22:00:47 | 显示全部楼层 |阅读模式 来自 新疆乌鲁木齐
本帖最后由 bainhome 于 2013-3-23 22:52 编辑

从前写过坐标轮换法多维无约束优化程序,当时用6,没匿名函数,加之水平眼界有限,符号函数实现,又笨又慢。最近因接触现代设计方法这本书,看到这个算法流程,来了兴致重写一遍。

言归正传,坐标轮换法是利用函数值信息直接寻优最基础的一个算法,迭代步数较多,效能取决于目标函数的形式,目标函数等值线椭圆形长短轴与坐标轴不平行时迭代计算曲折,收敛速度慢。对很多问题搜索不到合理解,算法本身没太多值得提倡的东西,不过匿名函数的用法倒还不错,另外算法实现方面,rocwoods这货今天给出重要提示,因此拿来和大家共享。




  1. function [ outX,outY,count ] = CoodinateOpt( fx,x0,epsx,epsf )
  2. % ================================
  3. % 用于解决多维函数无约束优化问题
  4. % 算法:坐标轮换法
  5. % 用户测试代码:
  6. % fx=@(x)100*(x(1).^2+x(2)-5).^2+(x(1)-x(2)).^2;
  7. % [ outX,outY,count ] = CoodinateOpt( fx,[1,1],1e-2,1e-3 )
  8. % ================================
  9. clc
  10. tic
  11. lenX=length(x0);
  12. x00=x0(:);
  13. xStart=x0(:);
  14. xn1=100*eye(lenX,1);
  15. dir1=eye(lenX);
  16. fx0=fx(x0);
  17. count=0;
  18. fn=1000;
  19. while norm(xn1-x00)>epsx&&abs(fn-fx0)>epsf&&count<=5000
  20.     xIter=xStart;
  21.     x00=xStart;
  22.     fx0=fx(xStart);
  23.     xmin=0;
  24.     for i=1:lenX
  25.         f=@(a) fx(xIter+a*dir1(:,i));
  26.         xmin=Xquad(f,xmin,.01,.001);
  27.         xIter=xIter+xmin*dir1(:,i);
  28.     end
  29.     xStart=xIter;
  30.     xn1=xIter;
  31.     fn=fx(xn1);
  32.     count=count+1;
  33. end
  34. outX=xn1;
  35. outY=fx(xn1);
  36. toc
  37. function xmin=Xquad(f,x1,h,t)
  38. % ***********************************************
  39. % 二次插值法计算最优步长子程序
  40. % ***********************************************
  41. clc
  42. [ax,bx,countjintui]=jintui(f,x1,h);
  43. count=0;
  44. a1=(ax+bx)/2;
  45. xx=[ax,a1,bx];
  46. for i=1:3
  47.     Y(i)=f(xx(i));
  48. end
  49. c1=(Y(3)-Y(1))/(bx-ax);
  50. c2=((Y(2)-Y(1))/(a1-ax)-c1)/(a1-bx);
  51. xp=.5*(ax+bx-c1/c2);
  52. if abs(f(xp)-f(a1))<=t
  53.     xmin=min([xp,a1]);
  54.     fmin=f(xmin);
  55.     step_opt=xmin-x1;
  56. else
  57.     while abs(f(xp)-f(a1))>=t
  58.        [ax,a1,xp,bx]=quadCompute(f,ax,a1,xp,bx);
  59.     end
  60.      xmin=min([xp,a1]);
  61.      fmin=f(xmin);
  62.      step_opt=xmin-x1;
  63.     count=count+1;
  64. end
  65. count;
  66. function [ax,a1,xp,bx]=quadCompute(f,ax,a1,xp,bx)
  67. if f(a1)<f(xp)&&xp>a1
  68.     bx=xp;
  69. elseif f(a1)>f(xp)&&xp>a1
  70.     ax=a1;
  71.     a1=xp;
  72. elseif f(a1)<f(xp)&&xp<a1
  73.     ax=xp;
  74. elseif f(a1)>f(xp)&&xp<a1
  75.     bx=a1;
  76.     a1=xp;   
  77. end
  78. xx=[ax,a1,bx];
  79. for i=1:3
  80.     Y(i)=f(xx(i));
  81. end
  82. c1=(Y(3)-Y(1))/(bx-ax);
  83. c2=((Y(2)-Y(1))/(a1-ax)-c1)/(a1-bx);
  84. xp=.5*(ax+bx-c1/c2);
  85. function [a,b,countjintui]=jintui(f,x1,h)
  86. % ================================
  87. % 进退法确定搜索区间
  88. % ================================
  89. f1=f(x1);
  90. x2=x1+h;
  91. f2=f(x2);
  92. countjintui=0;
  93. if f1<f2
  94.     h=-h;
  95.     x2=x1;
  96.     f2=f1;
  97.     x3=x2+h;
  98.     f3=f(x3);
  99. else
  100.     h=2*h;
  101.     x3=x2+h;
  102.     f3=f(x3);
  103. end
  104. while f2>f3
  105.     if countjintui<5000
  106.         x1=x2;
  107.         x2=x3;
  108.         x3=x2+h;
  109.         f1=f2;
  110.         f2=f3;
  111.         f3=f(x3);
  112.         countjintui=countjintui+1;
  113.     else
  114.         disp('该搜索区间不存在“高-低-高”的正确搜索形态,请修改后再试!')
  115.         return
  116.     end
  117. end
  118. a=min(x1,x3);
  119. b=max(x1,x3);
复制代码
基本思想是将一个无约束n维优化问题转化为依次沿着相应的n个坐标轴方向的一维优化问题求解。
以二维目标函数f(X)=f(x1,x2)为例,从某个初始点X^(0)作为第一轮迭代起始点X0^(1)。

1.以x1坐标轴的单位向量$e_1=[1,0]^T作为搜索方向,用一维优化方法确定其最优步长k1^(1),获得第一轮第一个迭代点X1^(1)=X0^(1)+k1^(1)e1;
2.以X1^(1)为新起点,改以x2坐标轴的单位向量e2=[0,1]^T为搜索方向,用一维优化方法确定其最优步长k2^(1),获得第一轮第二个迭代点X2^(1)=X1^(1)+k2^(1)e2
3.对二维问题,经过依次沿着e1和e2的两次搜索,完成第一轮迭代,得到第一轮迭代极小点X^(1)=X2^(1);
4.如经过第一轮迭代计算后仍然没有得到收敛到目标函数f(X)的极小点X*,则以第一轮迭代的极小点X^{1}作为第二轮迭代的起始点X2^(0)=X^(1),依次再沿着e1和e2方向搜索,按上述方法做第3,4,...搜索,直至迭代逼近目标函数f(X)的极小点X*。

难点:例如如下二维无约束问题目标函数应如何使其被降为一维搜索问题,以确定每一次的最优步长因子。

  1. fx=@(x) 100*(x(1).^2+x(2)-5).^2+(x(1)-x(2)).^2;
复制代码
解决办法是构造如下匿名函数:
  1. fx=@(x)100*(x(1).^2+x(2)-5).^2+(x(1)-x(2)).^2;
  2. d1=[1:5;1:5]';
  3. d2=.5*d1;
  4. x=arrayfun(@(i) fminsearch(@(a) fx(d1(i,:)+a*d2(i,:)),0),1:length(d1))
复制代码
计算结果:
  1. x =
  2. 1.5826 -0.20869 -0.80581 -1.1044 -1.2835
复制代码
匿名函数的确是MATLAB中比较有特色的编程方法。

用该算法计算上述二维无约束极值问题,结果如下:
  1. Elapsed time is 0.429963 seconds.
  2. outX =
  3.        1.7913
  4.        1.7914
  5. outY =
  6.    9.6461e-08
  7. count =
  8.    274
复制代码

fminunc命令的计算结果:
x =
1.7913 1.7913
fval =
7.3758e-12
exitflag =
1
output =
iterations: 17
funcCount: 69
stepsize: 1
firstorderopt: 5.3476e-08
algorithm: 'medium-scale: Quasi-Newton line search'
message: [1x438 char]
Elapsed time is 0.251491 seconds.

fminunc采用拟牛顿法17次迭代到1e-8容差,自编程序迭代274次,再次证明梯度法收敛速度的确不是盖的。

ps1:从前倒看过很多优化问题书籍,很多优化算法仍在使用inline函数定义目标函数,这个命令的效率比较低。
ps2:很久没来,冒个泡再急速下潜...






评分

1

查看全部评分

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|小黑屋|联系我们|仿真互动网 ( 京ICP备15048925号-7 )

GMT+8, 2024-4-20 16:08 , Processed in 0.030011 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表