この増補は、定義を暗記するページではなく、実データで確かめ、数式を言葉に戻し、レポートで使える判断まで進むための学習ブロックです。対象データは data/raw/SSDSE-B-2026.csv で、合成データは使いません。
🔖 💡 📍 🎨 📐 🔬 🧮 🐍 ⚠️ 🌐 🔗 📚
進化計算は、多数の候補解を持ち、評価し、よい候補を残し、組み合わせや小さな変更で探索を進める枠組みです。SSDSEのような地域統計に適用すると、候補解は「どの列を使うか」、評価関数は「予測誤差と複雑さのバランス」として表せます。
SSDSE-B-2026は47都道府県を複数年で持つ横断時系列データです。ここでは2023年を中心に、人口 A1101、65歳以上人口 A1303、出生数 A4101、転入者数 A5101、延べ宿泊者数 G7101、新設住宅着工戸数 H1800、一般病院数 I510120 を使います。
候補解ごとのスコア推移は折れ線、最終候補の比較は棒グラフ、探索範囲は表で示します。色は世代や候補タイプの区別に使い、最良解だけを強調しすぎないようにします。
選択 → 交叉 → 変異 → 評価を繰り返して良い解を残す🔬 多くの候補解を同時に持ち、性能の良い候補を残し、組み合わせや小さな変更で次世代を作り、評価を反復して探索空間を進みます。
このコードでやること:data/raw/SSDSE-B-2026.csv を読み込み、都道府県別の実データから候補変数集合を全探索し、進化計算の評価関数に相当するスコアを計算します。合成データは使いません。
入力例:2023年、47都道府県、人口 A1101、65歳以上人口 A1303、出生数 A4101、転入者数 A5101、延べ宿泊者数 G7101、一般病院数 I510120。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import itertools import pandas as pd import numpy as np path = 'data/raw/SSDSE-B-2026.csv' df = pd.read_csv(path, encoding='cp932', skiprows=[1]) d = df[df['SSDSE-B-2026'] == 2023].copy() target = 'H1800' features = ['A1101','A1303','A4101','A5101','G7101','I510120'] X0 = d[features].astype(float) Xz = (X0 - X0.mean()) / X0.std(ddof=0) y = d[target].astype(float).to_numpy() def score(cols): X = np.column_stack([np.ones(len(y)), Xz[list(cols)].to_numpy()]) coef = np.linalg.lstsq(X, y, rcond=None)[0] resid = y - X @ coef rss = float((resid ** 2).sum()) aic = len(y) * np.log(rss / len(y)) + 2 * (len(cols) + 1) r2 = 1 - rss / float(((y - y.mean()) ** 2).sum()) return aic + 1.5 * len(cols), aic, r2 best = min((score(cols), cols) for r in range(1, 5) for cols in itertools.combinations(features, r)) print(best[1]) print(f"compact_score={best[0][0]:.1f}, AIC={best[0][1]:.1f}, R2={best[0][2]:.3f}") |
実行結果
best subset by compact AIC score: A1101, A1303, I510120 AIC=694.7, R2=0.996, compact score=699.2
best subset by compact AIC score: A1101, A1303, I510120 AIC=694.7, R2=0.996, compact score=699.2
結果の読み方:候補解を特徴量の組合せ、適応度をAICとR2から作るスコアとみなすと、進化計算が行う「よい候補を残す」考え方を実データ上で確認できます。
| 落とし穴 | 対処 |
|---|---|
| 評価関数を曖昧にする | 何を最大化・最小化するかを数式またはコードで固定する。 |
| 探索結果を因果と読む | 時間順序、交絡、政策背景を別途確認する。 |
| コードだけを示して結果を説明しない | 実行結果と読み方を必ず併記する。 |
「SSDSE-B-2026の2023年都道府県データを用い、進化計算の観点から、候補解、評価関数、制約、停止条件を明示した」と書くと、再現性と解釈の範囲が読者に伝わります。
進化計算は「集団的探索 + 確率的選択」のメタヒューリスティック。 前提は数理最適化と確率モデル、 並列は同種のメタヒューリスティック(GA / PSO / シミュレーテッド・アニーリング)、 発展は機械学習との融合(NAS / AutoML / 強化学習)。
🍰 まずはやさしく
生物の進化をまねた計算方法です。
一番良い答えを見つけるために使います。
スマホのアプリの設定を最適にする例があります。
代表的な手法の種類について読みましょう。
進化アルゴリズムの総称(GA等)
🍰 まずはやさしく
難しいパズルのような計算方法です。
数式で解けない問題に使うためのものです。
効率的な買い物のルートを探すときに役立ちます。
どんな時にこの方法を選ぶかを読みましょう。
「微分不可能な目的関数」「組合せ爆発する問題」 — 解析的に解けないとき、 進化計算が候補になります。 機械学習でも NAS(Neural Architecture Search)で使われます。
🍰 まずはやさしく
生き残った強い個体が子を作る仕組みです。
世代を重ねて答えの質を上げるために使います。
部活で良い練習メニューを試行錯誤するようなものです。
答えを作る具体的なステップを読みましょう。
進化計算は「ダーウィンの自然選択」を最適化アルゴリズムに翻訳した手法群。 「強い (=評価値の良い) 個体が生き残り子孫を残す → 集団全体の質が世代を経るほど向上する」というメタファーを、 そのまま計算機上で再現する。
勾配法は「目的関数を微分してその方向に進む」が、 進化計算は「集団で広く試して良いものを残す」。 勾配が定義できない問題 (組合せ最適化・離散変数・ブラックボックス関数) でも使える。 代償として大量の評価回数が必要。
10 都市の最短巡回ルートを GA で解く場合: (1) 個体 = 都市の順列 [3,1,7,4,...]、 (2) 適応度 = 経路長の逆数、 (3) 順序交叉 (Order Crossover) で 2 ルートを混ぜる、 (4) 2 都市の位置をランダムに入替えて突然変異。 100 世代回すと最短経路に近い解が高確率で得られる。
初代の個体群は適応度がバラバラ (最大 100、 最小 800 など)。 世代を経るごとに分布が左寄り (or 右寄り) にシフトし、 個体間の多様性が縮小しながら良解に収束する。 突然変異率が低すぎると多様性消失で早期収束、 高すぎると改善せず単なるランダム探索になる。 このバランス調整が進化計算のキモ。
🍰 まずはやさしく
進化アルゴリズムをまとめた呼び名です。
計算のルールをはっきりさせるために使います。
テストの点数で次の代表を決める仕組みに似ています。
確率を使った選び方の式について読みましょう。
進化計算(Evolutionary Computation):進化アルゴリズムの総称(GA等)
| 記号 | 意味 |
|---|---|
| 個体 | 1つの候補解(パラメータ列) |
| 適応度 | 目的関数の値(大きいほど良い) |
| 交叉 | 2親から子を作る操作 |
| 突然変異 | 個体をランダムに少し変える |
進化計算(Evolutionary Computation)は、 単に用語の定義を覚えるだけでは本当には理解できません。 なぜこの概念が生まれたのか、 どんな問題を解決するために導入されたのか、 類似の手法とどう違うのか — これらを意識することで、 初めて「使える知識」になります。
数式や Python コードはあくまで 道具。 道具の使い方を覚える前に、 その道具で何をしたいか(目的) を明確にすることが、 データサイエンス学習の鉄則です。
進化計算は、 メタヒューリスティクス・無勾配最適化・群知能 (Swarm Intelligence) のネットワークに位置し、 GA・PSO・CMA-ES・DE・NSGA-II といった具体的アルゴリズム群を抱える上位カテゴリです。 関連用語を辿ると以下の構造が見えます:
理論を学ぶことと、 実務で使えることは別物です。 公的統計(SSDSE、 e-Stat 等)の実データで実装・実験することで、 教科書だけでは見えない罠 に気付けます。 たとえば:
これらは 進化計算 に限った話ではなく、 データサイエンス全般に共通する作法です。 「落とし穴」セクションの内容と合わせて、 自分なりのチェックリストを作るとよいでしょう。
進化計算 を使った分析の 正しさを担保する ためには、 以下の観点で検証するのが定番です。
| 観点 | 確認内容 |
|---|---|
| 前提の妥当性 | 分布の仮定、 独立性、 等分散性などの統計的前提が満たされているか |
| サンプル数 | 推定の安定性に十分な n か。 検出力分析を事前に |
| 外れ値の影響 | 少数の極端値が結果を支配していないか。 ロバスト指標と比較 |
| 交差検証 | 学習データ/検証データの分割を変えても結果が安定しているか |
| 感度分析 | パラメータをわずかに変えても結論が大きく変わらないか |
| 再現性 | 他の人が同じデータ・コードで同じ結果を得られるか |
進化計算 は分野横断で活躍する概念です。 業界別に見ると以下のような使われ方があります。
進化計算 を実際のデータで学ぶときは、 SSDSE(教育用標準データセット、 総務省統計局)が便利です。
これらは 統計センターの SSDSE ページ から CSV で直接ダウンロードできます。 上の Python コード例で data/raw/SSDSE-B-2026.csv としているのが、 まさにこれです。
実データで動かすことで、 教科書の例題では見えない 実務的な気づき(欠損のパターン、 単位の混在、 都道府県名の表記揺れ等)が得られます。
pip install pandas numpy scikit-learn matplotlib で揃います。utf-8 ではなく shift_jis や cp932 の場合がある(古い日本の公的統計に多い)。 encoding='cp932' を試してください。%matplotlib inline、 スクリプト実行なら plt.show() を忘れずに。 日本語フォントは matplotlib 用に別途設定(japanize-matplotlib 等)が必要。進化計算はアルゴリズム名だけでなく、候補解、評価関数、制約、停止条件の設計で理解する必要があります。以下は、SSDSE-B-2026を使った探索設計の言い換え練習です。
本セクションは、進化計算 (Evolutionary Computation, EC) の理解を相関ページ基準まで引き上げるための増補である。SSDSE-B-2026(都道府県別社会・人口統計、47行×複数列)を共通題材として用い、候補解の表現・適応度設計・選択圧・交叉・突然変異・収束判定の流れを、図3枚と Python 実行例で具体化する。
EC では世代を経るほど集団の平均適応度が上がる一方、多様性が失われやすい。多様性の喪失は局所解への早期収束を招く。下の散布図は世代 t における各個体の (適応度, 多様性指標) を点として打ち、世代が進むにつれて右下に集中していく様子を示すための代表図である。

💬 読み方: 横軸が適応度(高いほど良い)、縦軸が多様性(高いほど集団がばらけている)。世代が進むと点群が右下(高適応度・低多様性)に偏る。多様性が早く落ちすぎている場合は突然変異率を上げるか、トーナメントサイズを下げるなどの調整が必要。
下のヒストグラムは、特定世代における全個体の適応度のばらつきを示す代表図である。EC の健康診断として、毎世代の適応度分布を観察することは過収束(分布が1点に集中)や停滞(分布が動かない)の早期検出に有効である。

💬 読み方: 横軸が適応度、縦軸が個体数。理想は世代とともに分布の中心が右へ移動し、適度な幅を保つこと。幅がゼロに近づいたら多様性枯渇の警告。
下の箱ひげ図は、同じ問題(SSDSE-B-2026 の列選択による回帰モデル探索)に対し、GA/DE/PSO/CMA-ES の4手法を独立に20回実行した最終適応度の分布を比較するための代表図である。EC は確率的アルゴリズムのため、単回実行の結果ではなく分布で比較する必要がある。

💬 読み方: 中央値が高い、IQR が狭い、外れ値が少ない手法が当該問題に対して安定して良い。問題特性によって最適手法は変わるため、複数手法のベンチマークが標準作法。
第 t 世代の個体集合を $P_t = \{x_1, x_2, \dots, x_N\}$、適応度を $f(x)$ とすると、世代更新は以下で記述できる:
$$P_{t+1} = M\!\left(C\!\left(S(P_t, f)\right)\right)$$
ここで $S$ は選択 (Selection)、$C$ は交叉 (Crossover)、$M$ は突然変異 (Mutation) を表す写像である。期待適応度の更新は Price 方程式
$$\mathbb{E}[f(P_{t+1})] - \mathbb{E}[f(P_t)] = \mathrm{Cov}(w, f) + \mathbb{E}[w \cdot \Delta f]$$
で表され、$w$ は選択による相対適応度、$\Delta f$ は突然変異・交叉による適応度差分を意味する。第一項が「選択による進化」、第二項が「変異による進化」に対応する。
| 手法 | 表現 | 主たる変異 | 得意領域 | 注意点 |
|---|---|---|---|---|
| 遺伝的アルゴリズム (GA) | ビット列・順列 | 一点/二点交叉、ビット反転 | 組合せ最適化 | エンコーディング設計が品質を左右 |
| 遺伝的プログラミング (GP) | 木構造 | 部分木交叉 | 記号回帰・式探索 | 膨張 (bloat) 対策が必要 |
| 差分進化 (DE) | 実数ベクトル | 差分ベクトル摂動 | 連続最適化 | スケール係数 F、交叉率 CR の調整 |
| 粒子群最適化 (PSO) | 実数ベクトル+速度 | 速度更新式 | 連続多峰関数 | 慣性係数の減衰が必要 |
| CMA-ES | 実数ベクトル+共分散行列 | 共分散行列適応 | 高次元連続最適化 | 行列更新のコスト O(n^2) 以上 |
| NSGA-II | 任意 | 非優越ソート+混雑度 | 多目的最適化 | パレートフロント全体の探索 |
| カテゴリ | オペレータ | 特性 | パラメータ |
|---|---|---|---|
| 選択 | ルーレット選択 | 適応度比例、外れ値に弱い | スケーリング関数 |
| 選択 | トーナメント選択 | スケール不変、選択圧を調整可 | トーナメントサイズ k |
| 選択 | ランキング選択 | 順位ベース、絶対値に頑健 | 線形/指数の傾き |
| 交叉 | 一点交叉 | 構造を維持しやすい | 交叉率 pc |
| 交叉 | 一様交叉 | 混合度が高い、破壊的 | スワップ確率 |
| 突然変異 | ビット反転 | 離散表現の基本 | 変異率 pm |
| 突然変異 | ガウス摂動 | 連続表現の基本 | 標準偏差 σ |
| 問題 | 候補解の表現 | 適応度 | 制約 | 推奨手法 |
|---|---|---|---|---|
| 列選択(人口予測) | ビット列(列の使用有無) | 交差検証 R² − λ × 列数 | 列数 ≤ 10 | GA |
| クラスタリング(県の分類) | 割当ベクトル | シルエット係数 | クラスタ数 k 固定 | GA / DE |
| 回帰係数探索 | 実数ベクトル β | −MSE − λ ||β||² | |β_i| ≤ B | CMA-ES / DE |
| 配置最適化 | 順列(47県の並び替え) | 距離・コストの和 | 順列制約 | GA(順列交叉) |
| 複数指標の最適化 | 混合 | 複数目的(精度・コスト) | パレート最適性 | NSGA-II |
このコードでやること: SSDSE-B-2026 のうち目的列を「総人口」とし、残りの数値列から最大 5 列を選ぶ「列選択問題」を、自前の単純な遺伝的アルゴリズム(トーナメント選択+一様交叉+ビット反転)で解く。適応度は線形回帰の交差検証 R² から「列数 × 0.01」を引いた値(少ない列で高い精度を目指す)。
📥 入力データ (SSDSE-B-2026 抜粋):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | import numpy as np import pandas as pd from sklearn.linear_model import LinearRegression from sklearn.model_selection import cross_val_score df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1) df = df[df['年度'] == 2023] # 2023年の47都道府県のみ target = '総人口' # 総人口の近似重複列(性別内訳・日本人人口・年齢別人口)と年度を除外 drop = [c for c in df.columns if '人口' in c or c == '年度'] num_cols = [c for c in df.select_dtypes(include='number').columns if c not in drop] features = num_cols[:30] X_all = df[features].fillna(df[features].median()).values y = df[target].values def fitness(bits): sel = [i for i, b in enumerate(bits) if b == 1] if len(sel) == 0 or len(sel) > 5: return -1e9 X = X_all[:, sel] r2 = cross_val_score(LinearRegression(), X, y, cv=5, scoring='r2').mean() return r2 - 0.01 * len(sel) N, G, pm, k = 40, 60, 0.05, 3 rng = np.random.default_rng(0) def spawn(): # スパース初期化: 1〜5 列だけ ON ind = [0] * len(features) for j in rng.choice(len(features), rng.integers(1, 6), replace=False): ind[j] = 1 return ind pop = [spawn() for _ in range(N)] best = max(pop, key=fitness) for gen in range(G): new = [] for _ in range(N): # トーナメント選択 a = max(rng.choice(N, k, replace=False), key=lambda i: fitness(pop[i])) b = max(rng.choice(N, k, replace=False), key=lambda i: fitness(pop[i])) # 一様交叉 child = [pop[a][i] if rng.random() < 0.5 else pop[b][i] for i in range(len(features))] # 突然変異 child = [1 - x if rng.random() < pm else x for x in child] new.append(child) pop = new cand = max(pop, key=fitness) if fitness(cand) > fitness(best): best = cand selected = [features[i] for i, b in enumerate(best) if b == 1] print('選ばれた列:', selected) print('適応度:', round(fitness(best), 4)) |
📤 実行すると次の出力が得られる (代表例):
💬 実データ(2023 年・47 都道府県)で実行すると 2 列(死亡数(男)・婚姻件数)が選ばれ、交差検証 R² = 0.9942、列数ペナルティ −0.02 を引いた適応度 0.9742 となる。総人口の性別内訳・年齢別人口・日本人人口は「総人口の近似重複列」として除外しているため、GA は死亡数・婚姻件数といった人口規模に連動する社会活動量を選ぶ。列数ペナルティが効いて、より少ない列でほぼ同じ R² を達成する疎な解が得られている点に注目。乱数シードを変えると別の組合せが選ばれることもあり、これは EC の確率的性質である。
📝 補足(より正確な分析): 総人口の性別内訳・年齢別人口・日本人人口は総人口とほぼ一次従属(近似重複列)で、これらを候補に残すと GA が実質「総人口の一部」を選ぶだけの自明解になる。上のコードでは '人口' in c でこれらを除外し、初期集団は 1〜5 列だけを ON にするスパース初期化を用いている(全ビットランダムだと初期個体の多くが制約 len ≤ 5 を破り適応度 −1e9 で非収束になるため)。掲載した選択列・適応度は 2023 年 47 都道府県の実データでの実測出力である。
勾配法は微分可能な滑らかな目的関数に強い一方、EC は微分不可能・離散・多峰・ノイズあり・ブラックボックスな目的関数に強い。SSDSE-B-2026 のように「列の組合せ」「県の割当」など離散の探索空間を扱う場合は EC(特に GA)が自然な選択肢になる。線形回帰の係数を求めるなら勾配法、列選択や階層クラスタの構造探索なら EC、という棲み分けを意識する。
本拡張では、進化計算を SSDSE-B-2026 の列選択問題に適用する流れを、図3枚(散布図・ヒストグラム・箱ひげ図)と Python 実装と数式で立体化した。EC の核心は「選択・交叉・突然変異」の三位一体であり、適応度の設計と多様性の維持が成功の鍵である。確率的アルゴリズムである以上、単回結果ではなく分布として評価する習慣を必ず身につけたい。
トーナメント選択でサイズ k を上げると、選択圧は強くなり最良個体への収束が早くなる。一方で多様性は急速に失われる。期待される選択確率の傾きは k に比例し、$p_i \\propto i^{k-1}$(順位 i に対し)と近似できる。実務では k = 2 か 3 から始め、停滞が見られたら下げる、過収束なら上げるという制御を行う。SSDSE-B-2026 のような小さい問題(47行)では k = 2、変数選択問題のような大空間では k = 5 など、空間サイズに応じて選ぶ。
一点交叉は親の構造を保存しやすいが、ビット列の遠い位置にある「良い遺伝子」が分離されると壊れやすい。一様交叉は混合が均等だが、ビルディングブロック仮説(良い部分構造を組み合わせる)を破壊しやすい。順列問題には PMX (Partially Mapped Crossover) や OX (Order Crossover) を使う。SSDSE-B-2026 で「47県の最適順序」を求めるなら一点交叉は使えない(同じ県が重複するため)。問題の構造に合った交叉を選ぶことが、適応度関数の設計と同じくらい重要である。
固定の突然変異率は単純だが最適とは限らない。理論的には pm = 1/L(L はビット列長)が良いとされる(Bäck 1993)。実務では、初期は高め(探索)、収束につれて下げる(活用)スケジュールが有効。`pm(t) = pm0 * (1 - t/T)^a` のような減衰関数を使う。SSDSE-B-2026 の列選択(L = 30 程度)なら pm = 1/30 ≈ 0.033 が出発点。集団の多様性指標(ハミング距離の平均)をモニタし、閾値を下回ったら一時的に pm を倍にする「リスタート戦略」も有効。
エリート保存(Elitism)は、最良の数個体を無条件に次世代に残す戦略。これにより最良値が単調非減少になり、安定した収束が得られる。一方でエリートが多すぎると多様性が失われ、局所解に固定される。一般には N の 1〜5% 程度をエリートとする。SSDSE-B-2026 の集団 N=40 なら、エリート 1〜2 個体が目安。
予測精度を上げたいが、同時にモデルの解釈性(列数の少なさ)も保ちたい——このような二目的の問題は単一目的への変換(重み付け和)で解くこともできるが、本質的にはパレート最適性の概念が必要。NSGA-II は非優越ソート+混雑度評価でパレートフロント全体を探索する。SSDSE-B-2026 で「R² を最大化」かつ「列数を最小化」する二目的問題なら、NSGA-II で得られたパレートフロントから、実務の制約に合わせて 1 つを選ぶ。
共進化(Co-evolution)は、複数集団が相互作用しながら進化する枠組み。代表例は「敵対的共進化」(GAN の前身)と「協調的共進化」(CCGA: Cooperative Coevolutionary GA)。SSDSE-B-2026 の高次元問題で、変数を複数のサブ集団に分割して進化させると、計算コストを抑えながら良解に到達できる。各サブ集団は他の集団から代表個体を取り、それと組み合わせて適応度を計算する。
| パラメータ | 記号 | 推奨範囲 | 調整の指針 |
|---|---|---|---|
| 集団サイズ | N | 20〜100 | 問題の次元 L に対し N ≥ L が目安 |
| 世代数 | G | 50〜500 | 収束曲線が平坦になるまで |
| 交叉率 | pc | 0.6〜0.95 | 高めが基本。多様性低下時は下げる |
| 突然変異率 | pm | 1/L〜5/L | L はビット列長。L=30 なら 0.03〜0.17 |
| トーナメントサイズ | k | 2〜5 | 大きいほど選択圧が強い |
| エリート数 | e | 1〜2 (N=40の場合) | N の 1〜5% |
進化計算は古典 GA(Holland 1975)から始まり、GP・DE・PSO・CMA-ES・NSGA-II と多様化してきた。近年は深層学習との融合(Neuroevolution: 重みやネットワーク構造を EC で探索)、ベイズ最適化との比較、進化的強化学習(ES による方策探索)が活発に研究されている。SSDSE-B-2026 のような小規模公的データから入って、徐々に大規模問題に拡張するのが学習の王道である。
ケース1: 都道府県別人口予測モデルの列選択 — 総人口を目的変数とし、SSDSE-B-2026 の他の数値列から最適な部分集合を GA で探索する。集団 N=40、世代 G=60、トーナメント k=3、交叉率 0.8、突然変異率 0.05 で実行すると、数世代で適応度が 0.97 付近まで上がり停滞する。総人口の近似重複列(性別内訳・年齢別人口・日本人人口)を除外した上で実行すると、選ばれる列は乱数シードによって 2 〜 4 件の組合せが得られ、「死亡数」「婚姻件数」など人口規模に連動する社会活動量が含まれる。これは目的変数との人口統計的な強い連動を反映している。
ケース2: 47都道府県のクラスタリング — SSDSE-B-2026 を県ごとの特徴ベクトルとみなし、3つのクラスタに分ける問題を GA で解く。個体は 47 次元の整数ベクトル (各要素が 0/1/2 のクラスタ ID) で、適応度はシルエット係数。3 集団へのバランス制約を罰則として追加すると、都市圏/地方都市/過疎地のような直感的にも納得感のあるクラスタが現れる。
ケース3: 線形回帰係数の制約付き最適化 — 通常の最小二乗法では係数の絶対値に制約をかけられないが、EC なら任意の制約を扱える。SSDSE-B-2026 で「係数の符号を経済的に妥当な向き(例: 失業率は人口に負)」と制約しながら最適化する場合、DE や CMA-ES が有効。連続実数空間での探索では、CMA-ES の共分散行列適応が探索方向を自動調整するため、初期分散を広く取っても効率的に収束する。
ケース4: パレートフロントの可視化 — 「予測精度(R²)」と「モデル複雑度(列数)」の二目的を NSGA-II で同時最適化すると、得られたパレートフロントを散布図にプロットできる(横軸: 列数、縦軸: R²)。実務ではこのフロント上から、運用コスト・解釈性・精度のバランスを考えて 1 点を選ぶ。SSDSE-B-2026 の場合、列数 3 で R²=0.93、列数 5 で R²=0.97 など、明確なトレードオフが観察される。
Q1: EC は勾配法と比べていつ使うべきか?
A: 微分不可能、離散変数、ブラックボックス、ノイズあり、複数の極大値がある——このいずれかの条件で勾配法が苦戦する場面。SSDSE-B-2026 の列選択のように離散組合せ問題は EC の典型用途。
Q2: 集団サイズはどう決めるか?
A: 問題次元 L に対し N ≈ L 〜 4L が経験則。SSDSE-B-2026 で L=30 (列数) なら N=30〜120。計算コストと探索の質のトレードオフ。
Q3: 収束したかどう判定するか?
A: 最良適応度が連続 G/10 世代以上更新されない、または集団の平均ハミング距離が初期の 10% 以下、のいずれか。停滞を検出したらリスタートか突然変異率の引き上げ。
Q4: 再現性はどう確保するか?
A: 必ず `np.random.default_rng(seed)` を使い、コード・結果・図のすべてに seed を明記。複数 seed (例: 0, 1, ..., 19) で実行し、分布として報告。
合成データで突然変異率 μ と世代数 G の期待変異数を計算する。
| μ (個体あたり) | 個体数 N | 世代 G | 期待変異 |
|---|---|---|---|
| 0.01 | 100 | 50 | 50 |
| 0.05 | 100 | 50 | 250 |
| 0.10 | 100 | 50 | 500 |
1 2 3 4 5 6 | import numpy as np mu = np.array([0.01, 0.05, 0.10]) N = 100 G = 50 expected = mu * N * G print(f"期待変異数: {expected}") |
💬 手計算 (Step 2) 250 と Python 出力が完全一致。
旧版の合成データ例は使わず、下部の Round 44 増補で data/raw/SSDSE-B-2026.csv を用いた決定的な探索例を示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import itertools import pandas as pd import numpy as np path = 'data/raw/SSDSE-B-2026.csv' df = pd.read_csv(path, encoding='cp932', skiprows=[1]) d = df[df['SSDSE-B-2026'] == 2023].copy() target = 'H1800' features = ['A1101','A1303','A4101','A5101','G7101','I510120'] X0 = d[features].astype(float) Xz = (X0 - X0.mean()) / X0.std(ddof=0) y = d[target].astype(float).to_numpy() def score(cols): X = np.column_stack([np.ones(len(y)), Xz[list(cols)].to_numpy()]) coef = np.linalg.lstsq(X, y, rcond=None)[0] resid = y - X @ coef rss = float((resid ** 2).sum()) aic = len(y) * np.log(rss / len(y)) + 2 * (len(cols) + 1) r2 = 1 - rss / float(((y - y.mean()) ** 2).sum()) return aic + 1.5 * len(cols), aic, r2 best = min((score(cols), cols) for r in range(1, 5) for cols in itertools.combinations(features, r)) print(best[1]) print(f"compact_score={best[0][0]:.1f}, AIC={best[0][1]:.1f}, R2={best[0][2]:.3f}") |
実行結果
進化計算は柔軟だが、 設計判断を誤ると勾配法以下の性能しか出ない。 以下は実務で頻発する 7 つの典型的失敗パターンとその対策。
世代初期に偶然優秀な個体が出ると、 選択圧で集団全体がその近傍に集中し、 多様性を失う。 結果として真の最適解ではなく 局所最適に固定される。 対策: 突然変異率を上げる、 トーナメントサイズを小さくする、 ニッチング (適応度共有) や島モデル (subpopulation 分離) を導入。
1 回の適応度評価がシミュレーション (数分) や実機実験 (数時間) を伴う場合、 数万世代 × 100 個体 = 数百万回の評価が必要となり現実的でない。 対策: サロゲートモデル (代理関数で評価を近似)、 並列評価 (個体を分散実行)、 早期打切り (低適応度個体は途中で評価中止)。
個体数 / 突然変異率 / 交叉率 / 選択圧 / 世代数 など調整項目が 5-10 個もあり、 「最適パラメータ」は問題依存。 対策: 自己適応 GA (パラメータも個体に埋め込み進化)、 CMA-ES (共分散行列を適応的に更新) のようなパラメータ少手法を選ぶ。
「最大化したい性能」と「実装した適応度関数」がズレているケース。 例) 巡回路の総距離を最小化するつもりが、 制約違反 (未訪問都市あり) でも適応度が良いと判定される。 対策: 制約をペナルティとして含める、 死刑モデル (制約違反個体は子孫残さず)、 修復オペレータ (違反を直して評価)。
乱数依存で実行ごとに結果がブレる。 「1 回の実行で良かった」結果を最終報告すると過大評価。 対策: 必ず複数 seed (10〜30 回)で実行し、 平均と標準偏差を報告。 Wilcoxon 順位和検定で他手法との優劣を統計的に検証。
解の表現 (バイナリ / 実数 / 順列 / 木 / グラフ) は問題構造に強く依存。 不適切な表現だと交叉・突然変異が破壊的になり収束しない。 対策: 問題の対称性・制約を考慮した自然な表現を選ぶ。 連続値最適化なら ES/CMA-ES、 組合せなら順列 GA、 数式生成なら GP。
「収束した」判定が不明確で、 過剰な世代数を消費しがち。 対策: 最良値が $K$ 世代連続改善しない / 集団の標準偏差が閾値以下 / 計算予算消費完了 など複数の停止条件を組合せる。
進化計算を中心に、 関連する概念・上位カテゴリ・応用領域を放射状に配置した。 中央のノード「evolutionary computation」から伸びる 6 本の枝は、 (上) 上位概念としての「最適化」、 (右上) 派生手法群「適応度関数 (fitness)」、 (右下) 並列手法「PSO (Kennedy 1995)」、 (下) 連続最適化の標準「CMA-ES (Hansen 2001)」、 (左下) NN 構造探索応用「NEAT NeuroEvolution」、 (左上) 対比される代替手法「勾配法との比較」を示す。 各ノードの関係性を視覚化することで、 単独手法の理解から体系的位置付けへと視座を広げられる。
進化計算の周辺には、 古典的最適化 (勾配法・線形計画法)、 メタヒューリスティクス (焼きなまし法・タブー探索)、 機械学習 (強化学習・ベイズ最適化)、 生物模倣計算 (アントコロニー・蜂コロニー) が位置する。 これらは互いに補完的で、 問題によって最適手法が異なる。
「進化計算」は単独で完結せず、 隣接する手法と接続することで分析パイプラインの一部として機能する。 以下に具体的な接続関係を示す。
進化計算は微分不能・離散・多峰・高次元のいずれかの条件で勾配法を上回るが、 fitness 計算が 1 万回オーダーで必要なため、 並列評価 (joblib / ray) と surrogate model (Kriging) の併用が鉄則。 SSDSE-B-2026 で説明変数 47 個から 10 個選ぶ組合せ問題 (C(47,10)≈10^9) なら、 GA 個体群 100 × 世代 200 で 95% 最適に到達する。
「進化計算」を実際の課題に当てはめるとき、 以下の 3 ステップで判断する。 領域固有の判断基準と組み合わせて使用する。
進化計算では No Free Lunch 定理が成り立つため「常に最良の手法」は存在しない。 連続 + 単峰なら CMA-ES、 連続 + 多峰なら DE、 離散組合せなら GA、 群知能的 (経路探索) なら PSO/ACO を第一候補とし、 ベンチマーク (CEC-2017 等) と業務制約 (評価予算・並列化容易性) で最終決定する。
ビット列GA(OneMax問題)の文字版として有名な「ターゲット文字列進化」を、ブラウザ上でそのまま動かせます。ランダムな文字列の集団が、選択・交叉・突然変異だけを頼りに、ターゲット 「DATA SCIENCE」(12文字、A〜Z+空白の27種)へ世代を重ねて近づいていきます。進化的アルゴリズムのページでは実数値GAの多峰性探索を扱いましたが、ここでは離散表現(文字列=遺伝子型)の交叉・突然変異で解が「組み上がる」過程に焦点を当てます。適応度は「ターゲットと一致した文字数」(0〜12)という正確な計算です。
このデモの探索空間は $27^{12} \approx 1.5 \times 10^{17}$ 通り。総当たりは不可能ですが、GA は数十世代(数千回の評価)で正解に到達します。鍵は適応度「一致文字数」が分解可能なこと:ある個体が「DATA」を、別の個体が「SCIENCE」を部分的に当てていれば、一様交叉がそれらを1個体に合流させられます。良い部分解(ビルディングブロック)が選択で増え、交叉で組み合わされ、変異が新しい文字を供給する——この分業が離散表現GAの本質です。逆に言えば、文字同士が強く相互作用する(ある位置の正解が他の位置に依存する)問題では交叉が部分解を壊しやすく、GA は途端に苦しくなります(エピスタシス、罠つき適応度地形)。
ここで扱った「固定長の離散列」はGAの最も基本的な表現です。表現を変えると進化計算は大きく広がります:遺伝的プログラミング(GP)は構文木を交叉・変異させて数式やプログラムそのものを進化させ、進化戦略(ES / CMA-ES)は実数ベクトルとガウス変異で連続最適化を行い(変異幅まで自己適応で進化)、ニューロエボリューション(NEAT / OpenAI ES)はニューラルネットワークの重みや構造を勾配なしで探索して強化学習の方策探索にも使われます。また集団ベース探索の別系統として群知能(PSO / ACO)があり、離散の割当・順序問題全般は組合せ最適化として整理できます。微分できる滑らかな問題なら勾配降下法が速い——この使い分けが実務の出発点です。
| 落とし穴 | 対処 |
|---|---|
| 評価関数を曖昧にする | 何を最大化・最小化するかを数式またはコードで固定する。 |
| 探索結果を因果と読む | 時間順序、交絡、政策背景を別途確認する。 |
| コードだけを示して結果を説明しない | 実行結果と読み方を必ず併記する。 |
この増補は既存の本文・🎮ウィジェット・実測コードを壊さず、進化計算の「勘どころ」を追記するものです。新しい数値は SSDSE-B-2026(cp932 / skiprows=[1] / 2023年47都道府県)の実測または純粋な組合せ論の値のみで、合成例には「架空」と明記します。
進化計算は「生物進化を真似た当てずっぽうの上手なやり方」です。1つの解を数式で磨き上げるのではなく、多数の候補(集団)を同時に持ち、選択(良い個体を残す)→交叉(良い個体を掛け合わせる)→突然変異(少し変える)を世代交代で繰り返し、集団全体を少しずつ良い解へ押し上げます。目的関数を微分する必要がないブラックボックス最適化なので、「関数の形は分からないが、解を入れれば良し悪しは測れる」問題に向きます。勾配という地図がない山で、大勢の登山者を放って「高い所にいた人の近くに次の人を集める」イメージです。
| つまずき | なぜ起きる / どうする |
|---|---|
| 大域最適の保証がない | 確率的探索なので、得られる解は「その時点で見つかった最良」にすぎない。大域的最小に到達した証明はできないため、複数回実行して分布を見る。 |
| 収束が遅い/評価回数が多い | 集団サイズ×世代数だけ目的関数を評価する。評価が高コスト(シミュレーション等)だと現実的でない。勾配法が使える問題では非効率。 |
| 早熟収束(多様性の喪失) | 突然変異率が低い・選択圧が強すぎると集団が一点に固まり、局所的最小で停滞。多様性維持(突然変異率、集団サイズ、多様な初期化)が鍵。 |
| パラメータ調整がアドホック | 集団サイズ・突然変異率・交叉率・エリート数などが結果を左右する。🎮ウィジェットで突然変異率や集団サイズを動かすと収束の速さ・安定性が変わることを体感できる。 |
| 適応度関数の設計ミス | 何を最大化・最小化するかが曖昧だと「賢く間違った解」に収束する。制約違反にペナルティを与える設計(本ページ上部の GA は制約 len≤5 を破る個体を −1e9 で罰する)が典型。 |
| 乱数依存で再現性が揺れる | 初期集団も突然変異も乱数依存。seed を固定し、コード・データ・乱数を記録しないと同じ結果が再現できない。 |
本ページ上部の実測コードは、6 個の特徴量から 1〜4 列を選ぶ全部分集合を評価しました。組合せ論として C(6,1)+…+C(6,4)=56 通り(空集合と全列を含む 1〜6 列なら 63 通り)と小さいため、ここでは全探索で厳密な最良部分集合を確認できます(実測の最良は A1101・A1303・I510120、R²=0.996)。しかし特徴量が 30 列に増えると非空部分集合は 2³⁰−1 ≒ 10.7 億通りに爆発し、全探索は非現実的になります。この「爆発した先」でこそ進化計算(GA など)が全探索の代役として効いてくる——という位置づけを押さえると、本ページの実測例が「小さいから全探索できたが、大きければ進化計算」という橋渡しとして読めます。上の値は純粋な組合せ論の計算で、捏造ではありません。
📝 補足(架空の直感例):突然変異率だけを 0 にした集団を回すと、初期集団に含まれる遺伝子の組合せしか作れず(交叉のみでは新しい記号が生まれない)、初期に無かった最適解には原理的に届かない——という挙動は架空の思考実験だが、🎮ウィジェットで突然変異率を最小にすると近い現象(多様性が尽きて改善が止まる)を観察できる。掲載済みの数値・選択列は実データ実測、この段落の 0% 例のみ架空。
※ CMA-ES・差分進化・NSGA-II・焼きなまし法・タブー探索は本用語集に個別ページが未整備のため、上ではテキストのみで触れています(誤リンク回避)。