メインコンテンツ

このページは機械翻訳を使用して翻訳されました。最新版の英語を参照するには、ここをクリックします。

遺伝的アルゴリズムを用いた適応度関数のコーディングと最小化

この例では、次の 3 つの手法を使用して、遺伝的アルゴリズム ソルバー ga の適応度関数を作成し、最小化する方法を示します。

  • 標準

  • 追加パラメーターを含める

  • 速度向上のためベクトル化

基本的な適応度関数

基本的な適応度関数は、最適化ツールの一般的なテスト関数であるローゼンブロック関数です。この関数は平方和です。

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

この関数は、点 [1,1] で最小値がゼロになります。Rosenbrock 関数の傾きは非常に急なので、関数に 1 を加えた値の対数をプロットします。

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 関数ファイルは Rosenbrock 関数を実装します。

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;

適応度関数は1 つの入力 x を受け取る必要があります。ここで、x は問題内の変数の数と同じ数の要素を持つ行ベクトルです。適応度関数は関数の値を計算し、そのスカラー値を 1 つの戻り引数 y で返します。

gaを使用して最小化

ga を使用して適応度関数を最小化するには、適応度関数への関数ハンドルと、問題内の変数の数を渡します。ga に関連領域を調べさせるには、境界 -3 <= x(i) <= 3 を含めます。numberOfVariables の後の 5 番目と 6 番目の引数として境界を渡します。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 は、点 x で評価された関数 simple_fitness の値です。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 を取得します。1 つの入力 x を受け取り、xa、および b を使用して parameterized_fitness を呼び出す匿名関数への関数ハンドル FitnessFunction を作成します。匿名関数には、関数ハンドルの作成時に存在する 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

追加パラメーターの受け渡しを参照してください。

ベクトル化された適応度関数

速度を上げるには、適応度関数を ベクトル化 します。ベクトル化された適応度関数は、ポイントの集合の適応度を一度に計算するため、通常、これらのポイントを個別に評価するよりも時間が節約されます。ベクトル化された適応度関数を記述するには、関数に行列を受け入れさせ、各行列の行が 1 つのポイントを表すようにし、適応度関数に適応度関数値の列ベクトルを返させます。

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 を受け取り、 x と同じ行数を持つ列ベクトル y を返します。

'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.

この場合、適応度関数の計算にはほとんど時間がかからないため、ベクトル化による改善はそれほど大きくありませんでした。ただし、より時間のかかる適応度関数の場合、ベクトル化が役立つ場合があります。適応度関数をベクトル化するを参照してください。

参考

トピック