主要内容

本页采用了机器翻译。点击此处可查看最新英文版本。

使用遗传算法编码并最小化适应度函数

此示例显示如何使用三种技术为遗传算法求解器 ga 创建和最小化适应度函数:

  • 基本

  • 包括附加参数

  • 向量化以提高速度

基本适应度函数

基本适应度函数是罗森布洛克函数,这是优化器的常用测试函数。该函数是平方和:

f(x)=100(x12-x2)2+(1-x1)2.

该函数在点 [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

求解器返回的 xga 计算的最终种群中的最佳点。fval 是函数 simple_fitness 在点 x 处求值的值。ga 没有找到特别好的解。有关改进解的方法,请参阅 遗传算法选项的影响

具有附加参数的适应度函数

有时,您的适应度函数具有额外的参数,这些参数在优化期间充当常量。例如,广义的罗森布洛克函数可以具有表示常数 100 和 1 的额外参数:

f(x,a,b)=a(x12-x2)2+(b-x1)2.

ab 是适应度函数的参数,在优化期间充当常量(它们不会作为最小化的一部分而变化)。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;

尽量减少使用附加参数

使用匿名函数捕获附加参量的值,即常量 ab。创建一个函数句柄 FitnessFunction 到一个匿名函数,该函数接受一个输入 x,并使用 parameterized_fitnessxa 调用 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.

在这种情况下,向量化带来的改进并不大,因为计算适应度函数花费的时间很少。然而,对于更耗时的适应度函数,向量化可能会有所帮助。请参阅 向量化适应度函数

另请参阅

主题