粒子群算法与matlab代码实例使用
在网络中有很多的博客都已经粒子群算法的算法本质讲解的非常清晰明了,但是经本人在当初实际编程和使用中发现,对粒子群算法代码的实际使用还是存在着调参不便,适应度函数编辑不便等对新手较为不友好的现象,因此本文仅作于同样是小白的各位同学,以其达到交流学习的目的。
粒子群算法(也称粒子群优化算法(particle swarm optimization, PSO)),模拟鸟群随机搜索食物的行为。粒子群算法中,每个优化问题的潜在解都是搜索空间中的一只鸟,叫做“粒子”。所有的粒子都有一个由被优化的函数决定的适应值(fitness value),每个粒子还有一个速度决定它们“飞行”的方向和距离。
粒子群算法初始化为一群随机的粒子(随机解),然后根据迭代找到最优解。每一次迭代中,粒子通过跟踪两个极值来更新自己:第1个是粒子本身所找到的最优解,这个称为个体极值;第2个是整个种群目前找到的最优解,这个称为全局极值。也可以不用整个种群,而是用其中的一部分作为粒子的邻居,称为局部极值。
通过形象化的理解可以理解成在高低不平的山脉上有一个最低点的谷底藏着丰富的食物,一群鸟禽随机的分布在山脉的各个位置,所有鸟都不知道食物的方向,只知道据这些食物有多远,只能随机的进行寻找和移动,好在他们之间可以相互通讯并交换自己在距离食物最近的位置,当确认距离食物最近的鸟的位置后,所有的鸟群都会朝着这个方向搜索,但是在搜索过程中会发现有别的鸟路过距离食物更近的位置,这个时候为了让方向更加准确,就对两个位置进行矢量相加,最后确定新的搜索方向。
再将粒子群简化一下,将整个算法封装成一个不知道的黑箱。
让我们关注一下输入和输出:
输入是一个关于因变量Y和自变量Xi(i=1,2,3…)的多元多次函数,或者可以理解为一份地图,或者一个下界的收敛曲线
而输出是这个函数使得函数因变量值最小,即这份地图或者曲线的最低点。

总而言之,粒子群算法是用于对一个有上界或者有下界的凸函数的最优极值位置的定位函数。
首先,粒子群算法的不需要大量调试参数,也因此成为了广大优化算法中最为流行的几种算法之一,其次粒子群算法是一种高效的并行搜索算法,有效的提高了算法复杂度,且其速度在实际操作中是优于遗传算法。
但是粒子群算法同样具有不足,比如易于陷入局部最优解,在后期收敛速度慢等问题,需要具体场合进行具体分析。
假设我们已知加入水的量X与某化学试剂活性Y的关系函数:

要求找到最合适的加水量X使得试剂活性Y最低
matlab代码如下
clc;
clear;
close all;
% 参数赋值
tic;
E0=0.001;
MaxNum=500;
narvs=1;
particlesize=100;
c1=3;
c2=2;
w=0.6;
vmax=0.8;
x=8*rand(particlesize,narvs);
v=10*rand(particlesize,narvs);
fitness = @(x)exp(-x./3).*sin(3.*x); %定义适应度函数
f = zeros(1,particlesize); % 预分配
for i=1:particlesize
for j=1:narvs
f(i)=fitness(x(i,j));
end
end
personalbest_x=x;
personalbest_faval=f;
[globalbest_faval,i]=min(personalbest_faval);
globalbest_x=personalbest_x(i,:);
k=1;
while k<=MaxNum
for i=1:particlesize
for j=1:narvs
f(i)=fitness(x(i,j));
end
if f(i)<personalbest_faval(i)
personalbest_faval(i)=f(i);
personalbest_x(i,:)=x(i,:);
end
end
[globalbest_faval,i]=min(personalbest_faval);
globalbest_x=personalbest_x(i,:);
for i=1:particlesize
v(i,:)=w*v(i,:)+c1*rand*(personalbest_x(i,:)-x(i,:))...
+c2*rand*(globalbest_x-x(i,:));
for j=1:narvs
if v(i,j)>vmax
v(i,j)=vmax;
elseif v(i,j)<-vmax
v(i,j)=-vmax;
end
end
x(i,:)=x(i,:)+v(i,:);
end
if abs(globalbest_faval)<E0,break,end
k=k+1;
end
Value1=globalbest_faval-1; Value1=num2str(Value1);
disp(strcat('the min value','=',Value1));
%输出最优值所在的横坐标位置
Value2=globalbest_x; Value2=num2str(Value2);
disp(strcat('the corresponding coordinate','=',Value2));
x=0:pi/50:4*pi;
y=exp(-x/3).*sin(3*x);
plot(x,y,'r-','linewidth',3);
hold on;
x = str2num(Value2);
y=exp(-x./3).*sin(3.*x);%定义适应度函数;
plot( globalbest_x ,y,'kp','linewidth',4);
legend('目标函数','搜索到的最小值');
xlabel('x');
ylabel('y');
grid on;
toc;
运行结果:

在使用代码进行修改完成实例的过程中需要注意修改以下代码
fitness = @(x)exp(-x./3).*sin(3.*x); %定义适应度函数
这部分的代码是定义需要进行寻优,及是需要找到极值的函数
[globalbest_faval,i]=min(personalbest_faval);
这里通过matlab自带的min函数和max函数确定是进行极大值寻优还是极小值寻优。
x=0:pi/50:4*pi;
y=exp(-x/3).*sin(3*x);
这部分代码是根据自变量的范围进行曲线画图,在实际案例中,会出现自变量存在取值范围的问题,需要在代码中具体考虑
x = str2num(Value2);
y=exp(-x./3).*sin(3.*x);%定义适应度函数;
plot( globalbest_x ,y,'kp','linewidth',4);
这部分代码中,str2num(Value2)是在之前算法中已经找出的最有位置,及是使得试剂活性Y最低的加水量X,将它的值赋予x,并求取得到最低活性Y的值,在图上通过黑色的五角星进行标记
tic; %程序运行计时
E0=0.001; %允许误差
MaxNum=500; %粒子最大迭代次数
narvs=1; %目标函数的自变量个数
particlesize=100; %粒子群规模
c1=3; %每个粒子的个体学习因子,也称为加速常数
c2=2; %每个粒子的社会学习因子,也称为加速常数
w=0.6; %惯性因子
vmax=0.8; %粒子的最大飞翔速度
x=8*rand(particlesize,narvs); %粒子所在的位置
v=10*rand(particlesize,narvs); %粒子的飞翔速度
在以上代码参数中,需要重点注意的是惯性因子w,粒子所在位置x,以及粒子的飞翔速度v。当寻优结果陷入局部最优值时,可以调整这三个参数以实现找到全局最优值
其中粒子的最大迭代次数MaxNum可以据适应度函数的复杂度进行增加或减少以优化运行时间。
需要注意的是当适应度函数变为多个自变量时,除了在默认参数的部分对narvs参数值进行修改,在后面的运算代码同样需要进行修正。
如果只是单纯的使用和同纬度数据实例求解,修改以上代码可以达成目标。但是还是有很多情况下有多个自变量,在自变量较少的情况下该算法同样可以达到目标,当自变量个数过多的情况下可以通过结合主成分分析等降维算法进行寻优。
受时间与篇幅影响,多维的和改进的代码就不在细讲如果想进行更多的交流和沟通,或者了解多个自变量的粒子群算法代码与相关知识,可以关注我建立的公众号“狗头的成长日记”
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po