使用遗传算法编码并最小化适应度函数
此示例显示如何使用三种技术为遗传算法求解器 ga
创建和最小化适应度函数:
基本
包括附加参数
向量化以提高速度
基本适应度函数
基本适应度函数是罗森布洛克函数,这是优化器的常用测试函数。该函数是平方和:
该函数在点 [1,1]
处具有最小值零。由于 Rosenbrock 函数非常陡峭,因此绘制了函数的对数。
fsurf(@(x,y)log(1 + 100*(x.^2 - y).^2 + (1 - x).^2),[0,2]) title('log(1 + 100*(x(1)^2 - x(2))^2 + (1 - x(1))^2)') view(-13,78) hold on h1 = plot3(1,1,0.1,'r*','MarkerSize',12); legend(h1,'Minimum','Location','best'); hold off
适应度函数代码
simple_fitness
函数文件实现了罗森布洛克函数。
type simple_fitness
function y = simple_fitness(x) %SIMPLE_FITNESS fitness function for GA % Copyright 2004 The MathWorks, Inc. y = 100 * (x(1)^2 - x(2)) ^2 + (1 - x(1))^2;
适应度函数必须接受一个输入 x
,其中 x
是一个行向量,其元素数量与问题中的变量数量一样多。适应度函数计算函数的值并在其一个返回参量 y
中返回该标量值。
尽量减少使用 ga
为了使用 ga
最小化适应度函数,请将函数句柄以及问题中的变量数量传递给适应度函数。为了让 ga
检查相关区域,请包含边界 -3 <= x(i) <= 3
。将边界作为 numberOfVariables
之后的第五和第六个参量传递。有关 ga
语法的详细信息,请参阅 ga
。
ga
是一种随机算法。为了实现可再现性,请设置随机数流。
rng default % For reproducibility FitnessFunction = @simple_fitness; numberOfVariables = 2; lb = [-3,-3]; ub = [3,3]; [x,fval] = ga(FitnessFunction,numberOfVariables,[],[],[],[],lb,ub)
Optimization terminated: maximum number of generations exceeded.
x = 1×2
1.5083 2.2781
fval = 0.2594
求解器返回的 x
是 ga
计算的最终种群中的最佳点。fval
是函数 simple_fitness
在点 x
处求值的值。ga
没有找到特别好的解。有关改进解的方法,请参阅 遗传算法选项的影响。
具有附加参数的适应度函数
有时,您的适应度函数具有额外的参数,这些参数在优化期间充当常量。例如,广义的罗森布洛克函数可以具有表示常数 100 和 1 的额外参数:
a
和 b
是适应度函数的参数,在优化期间充当常量(它们不会作为最小化的一部分而变化)。parameterized_fitness.m
文件实现了这个参数化的适应度函数。
type parameterized_fitness
function y = parameterized_fitness(x,p1,p2) %PARAMETERIZED_FITNESS fitness function for GA % Copyright 2004 The MathWorks, Inc. y = p1 * (x(1)^2 - x(2)) ^2 + (p2 - x(1))^2;
尽量减少使用附加参数
使用匿名函数捕获附加参量的值,即常量 a
和 b
。创建一个函数句柄 FitnessFunction
到一个匿名函数,该函数接受一个输入 x
,并使用 parameterized_fitness
、x
和 a
调用 b
。匿名函数包含函数句柄创建时存在的 a 和 b 的值。
a = 100;
b = 1; % define constant values
FitnessFunction = @(x) parameterized_fitness(x,a,b);
[x,fval] = ga(FitnessFunction,numberOfVariables,[],[],[],[],lb,ub)
Optimization terminated: maximum number of generations exceeded.
x = 1×2
1.3198 1.7434
fval = 0.1025
请参阅 传递额外参数。
向量化适应度函数
为了提高速度,请向量化您的适应度函数。向量化适应度函数可以一次性计算一组点的适应度,这通常比单独评估这些点更节省时间。要编写向量化适应度函数,让您的函数接受一个矩阵,其中每个矩阵行代表一个点,并让适应度函数返回适应度函数值的列向量。
要将 parameterized_fitness
函数文件更改为向量化形式:
将各个变量
x(i)
改为x(:,i)
,即x(i)
对应变量的列向量。将每个向量乘法
*
更改为.*
,将每个指数运算^
更改为.^
,表明运算是逐元素的。此代码中没有向量乘法,因此只需改变指数。
type vectorized_fitness
function y = vectorized_fitness(x,p1,p2) %VECTORIZED_FITNESS fitness function for GA % Copyright 2004-2010 The MathWorks, Inc. y = p1 * (x(:,1).^2 - x(:,2)).^2 + (p2 - x(:,1)).^2;
适应度函数的这个向量化版本采用具有任意数量点、任意数量行的矩阵 x
,并返回具有与 y
相同行数的列向量 x
。
告诉求解器适应度函数在 'UseVectorized'
选项中是向量化的。
options = optimoptions(@ga,'UseVectorized',true);
将选项作为 ga
的最后一个参量。
VFitnessFunction = @(x) vectorized_fitness(x,100,1); [x,fval] = ga(VFitnessFunction,numberOfVariables,[],[],[],[],lb,ub,[],options)
Optimization terminated: maximum number of generations exceeded.
x = 1×2
1.6219 2.6334
fval = 0.3876
速度上有什么差别?对有和没有向量化两种情况的优化进行计时。
tic [x,fval] = ga(VFitnessFunction,numberOfVariables,[],[],[],[],lb,ub,[],options);
Optimization terminated: maximum number of generations exceeded.
v = toc; tic [x,fval] = ga(FitnessFunction,numberOfVariables,[],[],[],[],lb,ub);
Optimization terminated: maximum number of generations exceeded.
nv = toc;
fprintf('Using vectorization took %f seconds. No vectorization took %f seconds.\n',v,nv)
Using vectorization took 0.153337 seconds. No vectorization took 0.212880 seconds.
在这种情况下,向量化带来的改进并不大,因为计算适应度函数花费的时间很少。然而,对于更耗时的适应度函数,向量化可能会有所帮助。请参阅 向量化适应度函数。