Main Content

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

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

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

  • 標準

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

  • スピードのためにベクトル化

基本的なフィットネス関数

基本的な適応度関数は、最適化プログラムの一般的なテスト関数である Rosenbrock 関数です。この関数は二乗の合計です:

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

この関数は、点 [1,1] で最小値 0 になります。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.

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

関連するトピック