ParentSelection#

Layer 3: Extend Components

GA(saealib.GA)は、交叉に使う親個体を個体群から選ぶ処理を、ParentSelectionという差し替え可能な演算子に委ねています。 選択圧(優れた個体をどれだけ優遇するか)を変えたいときは、GA本体ではなくこのParentSelectionだけを差し替えればよいです。

ParentSelectionの役割#

ParentSelectionが実装する必要があるメソッドはselect(ctx, population, n_pair, n_parents, rng)の1つだけです。n_parents個体からなる親のグループをn_pair組選び、そのインデックスを形状(n_pair, n_parents)の配列として返します。

組み込みParentSelection#

クラス

パラメータ

特徴

TournamentSelection

tournament_size

tournament_size個体をランダムに抽出し、最良個体を選ぶ操作をn_pair * n_parents回繰り返す[14]

SequentialSelection

なし

比較を行わず、個体群のインデックスを順番に割り当てるだけ

LinearRankSelection

なし

順位から導いた線形ランクベースの確率で選択する

TournamentSelectionは、ctx.comparator.compare_populationによる1対1比較を繰り返してトーナメント内の最良個体を選びます[15]。 compare_populationはSPEA2ComparatorやHypervolumeComparatorのように2点だけの直接比較(compare())が使えないComparatorでも定義されているため、どのComparatorと組み合わせても問題なく動作します。

SequentialSelectionは比較を一切行わないため、選択圧という概念自体を持たない最も単純な選択方式です。 どのComparatorとも組み合わせられます。

LinearRankSelectionは、生の適応度ではなくctx.comparator.sort_populationが返す順位を確率に変換します。 これにより、目的関数値が負の値を取ったりスケールが大きく異なったりする問題でも、数値的な問題を起こさずに選択確率を計算できます。

注釈

SequentialSelectionのみ@register()済みで、TournamentSelection/LinearRankSelectionは現状Registry未登録です。 Registry経由でクラスを文字列から解決する使い方をする場合はこの違いに注意してください。

独自ParentSelectionの実装方法#

独自の選択方式が必要な場合は、ParentSelectionを継承してselect()だけを実装すればよいです。 次の例は、比較を行わず親を完全にランダムに選ぶ選択方式です。

import numpy as np
from saealib import ParentSelection


class RandomPairSelection(ParentSelection):
    """A selection scheme that chooses parent individuals completely at random."""

    def select(
        self,
        ctx,
        population,
        n_pair,
        n_parents,
        rng: np.random.Generator,
    ):
        n_pop = len(population)
        return rng.integers(0, n_pop, size=(n_pair, n_parents))

ctx.comparatorを参照する実装にすれば、TournamentSelectionのように選択圧を持つ独自方式にもできます。

関連コンポーネント#

  • Algorithm:GAがParentSelectionをどう組み合わせるか

  • Crossover:ParentSelectionが選んだ親個体を受け取る演算子

  • Comparator:TournamentSelection/LinearRankSelectionが個体を比較する際に使う

参照#