このページで扱う主要キーワード(クリックで該当セクションへ):
🍰 まずはやさしく
一番いい値を探すための方法です。
計算で正解を導き出すために使います。
スマホの学習機能などで活用されています。
この章では結論を短くまとめます。
🍰 まずはやさしく
数値を細かく調整する計算の手法です。
データ解析の土台として使います。
地域の統計データを分析する時に役立ちます。
この章では全体の流れを整理します。
「連続最適化」 (Continuous Optimization) は、 決定変数が実数連続値をとる最適化問題を扱う 数理最適化 の一分野で、 回帰・最尤推定・機械学習の学習など統計/データ解析の中核を支えます(SSDSE-B-2026 のような公的統計データの回帰分析もその一例)。 本ページでは、 まず直感、 次に数式、 そして 47 都道府県の実値で確かめる、 という流れで体系的に整理します。 加えて、 ケーススタディ・FAQ・歴史的経緯・参考文献までを 1 ページに集約し、 用語の「地図」として使えるようにしました。
関連用語(前提・並列・発展)と関連グループ教材も末尾にまとめてあるので、 用語の地図として活用してください。
🍰 まずはやさしく
霧の中で谷の底を探すようなものです。
最も低い地点を見つけるために使います。
部活の練習メニューを最適にするイメージです。
この章では直感的な仕組みを解説します。
連続最適化は、 決定変数が 連続実数 である最適化問題を扱う分野です。 「最小二乗で回帰係数を決める」「最尤推定でパラメータを当てはめる」「ニューラルネットの重みを学習する」のは、 すべて連続最適化問題です。
対比として 組合せ最適化は決定変数が 0/1 や順列などの離散値、 たとえば「都道府県をどの 3 クラスタに分けるか」のような問題を扱います。 連続最適化は微分・凸性という強力な道具立てが使えるため、 数値解法は概して洗練されています。
SSDSE の例で言えば、 「新規求職申込件数を 総人口、 着工建築物数など複数の指標で説明する線形回帰」は、 47 個の県データに対する複数の連続パラメータの最適化問題です。
目的関数 $f(x)$ を山と谷の地形と見なす。 最小化は「谷底を見つける」ことに相当。 凸関数は 1 つの谷だけ、 非凸は 複数の谷と 鞍点(馬の鞍のような形)を持つ。
$\nabla f(x)$ は「その地点から最も急に上る方向」。 最小化したいので 逆に進む ($-\nabla f$)。 学習率 $\eta$ は「一歩の歩幅」。
勾配だけでなくヘッセ行列で 地形の曲がり方も使う。 「谷の底にある放物線の頂点」を 1 ステップで予測。 ただしヘッセ行列の計算は次元 $n$ の 2 乗、 逆行列は 3 乗で高コスト。
全データの勾配 = 「視界が良い」、 SGD = 「視界 1 メートル」。 細かく見える分だけ 振動するが、 平均的には正しい方向に進む。 ノイズが鞍点脱出に役立つ。
単純な GD は 各ステップで方向リセット。 モメンタムは「過去の方向を記憶」して谷の長軸方向に加速。 物理的にはエネルギー保存とぶつかった壁での跳ね返りに似る。
最適化アルゴリズムを「式」だけで理解するのは難しい。 「ボールが谷を転がる」「霧の中で坂を下る」といった景観メタファーが、 アルゴリズム選択の直感を強化する。 ここでは SSDSE-B-2026 の都道府県データから生成できる 3 つの典型的なロスランドスケープを通じて、 最適化が「何を相手にしているか」を視覚化する。
SSDSE-B-2026 の都道府県 47 点を散布図に並べると、 各点は「最適化アルゴリズムが当てはめようとする直線・曲線が通るべき目標」になる。 線形回帰の二乗誤差を最小化する最適化は、 この散布図に最もよくフィットする直線を求める。 点が直線的なら凸の良条件問題、 ばらつきが大きければ条件数が悪化する。
SSDSE-B-2026 の 47 都道府県の総人口をヒストグラムにすると、 少数の大都市県が右に長い裾を引く強い右歪みの分布になる。 このように入力データや残差の分布が歪んでいると、 二乗誤差を最小化する最適化は裾の大きな値に引っ張られやすい。 分布が正規に近ければ最小二乗法が適切、 裾が重ければロバスト回帰 (Huber loss、 LAD) を選ぶ。 二乗誤差は正規分布の最尤推定、 絶対誤差はラプラス分布の最尤推定に対応する。
都道府県を KMeans で分けたクラスタごとに一般診療所数を箱ひげ図にしたもの。 クラスタ間で中央値・分散が大きく異なる場合、 階層ベイズや混合効果モデルが必要になり、 最適化問題の次元と非凸性が一気に増す。 単純な OLS の凸問題 → 混合効果モデルの非凸問題、 と問題の難しさが構造的に変わる例。
勾配降下は全データで勾配を計算、 SGD は 1 サンプル (またはミニバッチ) ごとに勾配を計算。 SGD の方が 1 反復が安いが、 推定勾配にノイズが乗るため振動する。
1e-3 あたりが多い?
Adam の規定値が 1e-3 で、 多くの研究がこれをベースラインに調整するため。 SGD なら 0.01 ~ 0.1 が標準。 オーダーが違うのは適応学習率の有無による。
scipy.optimize.minimize と scipy.optimize.least_squares の使い分けは?一般的な最適化なら minimize。 目的関数が「残差ベクトルの二乗和」の形なら least_squares (Levenberg-Marquardt) が劇的に速い。 非線形回帰の標準ツール。
(1) 学習率が大きすぎる、 (2) 特徴量未標準化、 (3) 目的関数が NaN/Inf を返す、 (4) 勾配の符号が逆 (符号バグ)、 (5) 数値微分の刻み幅が大きすぎる、 の順で疑う。
Limited-memory の L。 通常の BFGS は O(n²) のメモリ消費だが、 L-BFGS は過去 m 回 (通常 m=10) の勾配差分だけを保持して O(mn) に抑える。 大変数問題のデファクト。
Adam は L2 正則化を勾配に加える (適応学習率に影響)。 AdamW は重み減衰を「適応学習率の外側」で別に引く。 後者が理論的にも実験的にも汎化性能で優位。 Transformer 系は AdamW が標準。
どちらも局所最適へ向かう正しいアルゴリズム。 違いは「1 ステップの情報量」と「1 ステップのコスト」のトレードオフ。 規模・凸性・微分可能性で正解が変わる。
勾配降下は「下る方向にしか動かない」ため、 一度谷の底に着くと出られない。 谷の高さ (障壁) を越えるには確率的揺らぎ (SGD のノイズ) か熱的揺らぎ (シミュレーテッドアニーリング) が必要。
47 都道府県 × 約 110 変数という小規模で「全手法をデスクトップで全部動かせる」サイズ感。 大規模実験前のアルゴリズム挙動学習に最適。 実データのため標準化・条件数の影響も体感できる。
深い NN で勾配が「(連鎖律で) 何度も掛け算される」結果、 1 未満なら指数的に小さく (消失)、 1 超なら指数的に大きく (爆発) なる。 解決策は ResNet の skip connection、 LayerNorm、 勾配クリッピング。
cvxpy はいつ使う?凸最適化問題で、 制約や目的関数が複雑な場合。 数式をそのまま Python で書ける DSL (Domain Specific Language)。 ポートフォリオ最適化、 SDP、 Lasso などで標準ツール。 非凸問題には使えない。
変数が少なく (< 20)、 解析微分が困難ならアリ。 ただし「丸め誤差」と「打ち切り誤差」のバランスで刻み幅 h を √(machine eps) ≈ 1e-8 に設定する必要。 自動微分 (autograd, JAX) が使えるならそちらが圧勝。
順方向計算と同じコストで厳密勾配が得られる (逆伝播)。 手計算ミスがなく、 任意の計算グラフに対応。 PyTorch / JAX / TensorFlow の中核機能。 深層学習の急速発展はこれが基盤。
乱数シード固定 (numpy, torch, random)、 CUDA deterministic mode、 同じバージョンのライブラリ、 同じバッチ順、 を全部揃える。 それでも GPU 計算は非決定的な場合があり、 完全再現は困難な領域がある。
変数が連続実数なら連続最適化、 整数・順列・選択集合なら組合せ最適化。 整数計画 (MILP) は連続緩和 + 分枝限定で解く混合戦略。 学習率は連続、 層数は離散、 という意味で深層学習設計は両者を混在する。
🍰 まずはやさしく
数式を使って正解を出すルールです。
正確な答えを計算するために使います。
買い物で予算内で最高の品を選ぶような仕組みです。
この章では数式や定義について学びます。
もっとも基本的な連続最適化問題は、 制約なし最小化:
$f$ が微分可能なら、 最適性条件 $\nabla f(\theta^\star) = 0$ の解を探す。
解の必要条件は KKT (Karush-Kuhn-Tucker) 条件:
代表的な数値解法:
関数 $f$ が 凸とは、 任意の $x, y$ と $\lambda \in [0,1]$ で $f(\lambda x + (1-\lambda) y) \le \lambda f(x) + (1-\lambda) f(y)$ を満たすこと。 直感的には「2 点を結ぶ線分が常に関数の上にある」。
| 問題クラス | 例 | 標準ソルバ |
|---|---|---|
| 線形計画 (LP) | $\min c^T x$ s.t. $Ax \le b$ | simplex, 内点法 |
| 2 次計画 (QP) | $\min \tfrac{1}{2}x^T Q x + c^T x$ | OSQP, 内点法 |
| 2 次錐計画 (SOCP) | $\min c^T x$ s.t. $\|A_i x + b_i\| \le c_i^T x$ | ECOS, MOSEK |
| 半正定値計画 (SDP) | $\min \text{tr}(CX)$ s.t. $X \succeq 0$ | SDPA, CVXPY |
| OLS | $\min \|y - X\beta\|^2$ | 解析解 / SGD |
| Logistic 回帰 | 対数尤度最大化 | BFGS, L-BFGS |
ニューラルネット、 混合モデル、 GAN、 強化学習はすべて非凸。 大域最適は 原理的に保証できないが、 現代の経験則:
Newton が方程式 $f(x) = 0$ を解くために $x_{t+1} = x_t - f(x_t)/f'(x_t)$ を提案。 後に最適化の 2 次法に拡張される。
Augustin-Louis Cauchy が連続関数の最小化に「最急降下法」を提案。 現代の勾配降下法の原典。
George Dantzig が LP のシンプレックス法を考案。 戦後の生産計画・経済モデルで爆発的に利用。
不等式制約付き最適化の必要条件 (KKT) が確立。 双対理論と並んで凸最適化の基礎に。
Davidon, Fletcher, Powell が DFP 法 (1959)、 Broyden, Fletcher, Goldfarb, Shanno が BFGS (1970) を独立提案。 ヘッセ行列を陽に計算しない準ニュートン法の確立。
Narendra Karmarkar が LP の多項式時間アルゴリズムを内点法ベースで実用化。 CVX, MOSEK などの基礎。
Liu と Nocedal が限定メモリ BFGS を提案。 大規模機械学習(数百万パラメータ)の標準ソルバに。
Duchi+ の AdaGrad (2011)、 Tieleman & Hinton の RMSProp (2012)、 Kingma & Ba の Adam (2014) と続く。 深層学習の暴発的進歩を支えた。
ADMM (Boyd+ 2011), SAGA, SVRG, Catalyst など分散・確率的凸最適化が ML 大規模化を支える。 CVXPY (2014) で凸最適化をモデル化のみから自動ソルバへ。
連続最適化のアルゴリズムは「動かしてみたら良い解が出た」では実務に使えない。 「どんな条件で、 何イテレーションで、 どれくらいの精度に達するか」 という収束理論が、 ハイパーパラメータ選択や打ち切り判定の根拠を与える。 ここでは主要手法の収束レートを 1 表に整理し、 SSDSE-B-2026 規模の問題で何を選ぶかの根拠を示す。
| 手法 | 目的関数の仮定 | 収束レート | k 反復後の誤差オーダー |
|---|---|---|---|
| 勾配降下(固定 η) | L-平滑、凸 | O(1/k) | L||x₀-x*||² / k |
| 勾配降下(固定 η) | L-平滑、μ-強凸 | 線形(指数) | (1-μ/L)^k |
| Nesterov 加速勾配 | L-平滑、凸 | O(1/k²) | L||x₀-x*||² / k² |
| ニュートン法 | 凸、Hessian リプシッツ | 2 次収束 | ||xₖ-x*||² |
| BFGS | 凸、平滑 | 超線形 | ||xₖ₊₁-x*|| / ||xₖ-x*|| → 0 |
| SGD(減衰 η) | 凸、L-平滑 | O(1/√k) | σ/√k(σ:分散) |
| SGD(減衰 η) | μ-強凸 | O(1/k) | σ²/(μ²k) |
| Adam | 凸(理論は不完全) | O(1/√k) | G√(log T)/√T |
記号: L = 勾配のリプシッツ定数(曲率の上限)、 μ = 強凸性(曲率の下限)、 L/μ = 条件数 κ。 強凸の線形収束 (1-1/κ)^k は条件数が良い(κ が小さい)ほど高速。 標準化が学習率調整より本質的に効くのは、 これにより L/μ 比が劇的に改善するため。
L-平滑性: 任意の x, y で ||∇f(x) - ∇f(y)|| ≤ L||x - y||。 「勾配の変化が L 倍以下」、 つまり Hessian の最大固有値が L 以下。 学習率 η = 1/L が理論的最適(過大なら発散、 過小なら遅延)。
μ-強凸性: f(y) ≥ f(x) + ∇f(x)ᵀ(y-x) + (μ/2)||y-x||²。 「下から μ で湾曲」、 つまり Hessian の最小固有値が μ 以上。 最適解の一意性と線形収束を保証する。
条件数 κ = L/μ: SSDSE-B-2026 の線形回帰では標準化前 κ ≈ 10⁶(人口は 10⁵ 桁、 失業率は 10⁻²)、 標準化後 κ ≈ 10 程度に縮小する。 反復回数比は 10⁶ / 10 = 10⁵ 倍 の差で、 これが「標準化しないと収束しない」現象の理論的根拠。
Nesterov 加速は更新を 2 系列で進める:
$$y_{k+1} = x_k + \frac{k-1}{k+2}(x_k - x_{k-1}), \quad x_{k+1} = y_{k+1} - \eta \nabla f(y_{k+1})$$
「外挿点 y で勾配を計算」する 1 ステップ先読みが本質。 直感的には「ボールの慣性を予測して、 行き過ぎる前にブレーキをかける」働き。 Lyapunov 関数 V_k = k²(f(x_k) - f*) + ||z_k - x*||² が単調減少することから O(1/k²) 収束が証明される(Beck-Teboulle 2009、 FISTA 論文)。
ニュートン法は x_{k+1} = x_k - H(x_k)^{-1} ∇f(x_k)。 テイラー展開で目的関数を 2 次関数で局所近似し、 その最小値に一歩で飛ぶ。 解の近傍では 2 次近似がほぼ正確になるため、 誤差 ||x_k - x*|| が次のステップで ||x_{k+1} - x*|| ≤ C ||x_k - x*||² に縮む。 10⁻² → 10⁻⁴ → 10⁻⁸ → 10⁻¹⁶ と倍々で桁が増える「桁数倍化」が 2 次収束の標識。
連続最適化を支える概念を整理します。
| 概念 | 意味 | 例 |
|---|---|---|
| 目的関数 $f$ | 最小化/最大化する量 | 残差二乗和、 負対数尤度、 損失関数 |
| 決定変数 $\theta$ | 最適化される連続パラメータ | 回帰係数、 NN の重み |
| 制約 | $\theta$ が満たすべき式 | $\theta\ge 0$、 $\|\theta\|\le 1$ |
| 勾配 $\nabla f$ | 1 次の変化方向 | 各偏微分のベクトル |
| ヘッセ $\nabla^2 f$ | 2 次の曲率 | 正定値なら凸 |
| 凸性 | $f(\alpha x+(1-\alpha)y)\le \alpha f(x)+(1-\alpha)f(y)$ | 凸なら局所最適=大域最適 |
| ラグランジュ乗数 | 制約の影付き価格 | 制約緩和の感度 |
| 双対問題 | 主問題の下界を与える | SVM の双対形は内積で書ける |
連続最適化は「連続関数 $f(x)$ の最小値を 反復的に探す」枠組み。 機械学習の損失最小化、 回帰の係数推定、 ハイパーパラメータ調整など、 実務のあらゆる場面に出てきます。 ここでは式 5 本を、 記号ごとに丁寧に言葉にし、 SSDSE-B-2026 で動かして確かめます。
| 記号 | 意味 | SSDSE での読み替え |
|---|---|---|
| $x$ | 決定変数(連続値) | 回帰係数 $\beta = (\beta_0, \beta_1)$ |
| $f(x)$ | 目的関数(小さくしたい量) | 平均二乗誤差 $\mathrm{MSE}(\beta)$ |
| $g_i(x) \le 0$ | 不等式制約 | 「係数の和 ≤ 1」など |
| $h_j(x) = 0$ | 等式制約 | 「切片 = 0」など |
| $\min$ | 最小値を取る $x^*$ を見つける | OLS の最適 $\beta^*$ |
言葉に直すと: 「$x$ を動かして $f(x)$ を最小化する。 ただし $g_i$ と $h_j$ の制約を満たさなければならない」。 SSDSE で「総人口 → 新規求職申込件数」の線形回帰なら、 $x$ は係数 $(\beta_0, \beta_1)$、 $f$ は MSE、 制約なし(無制約最適化)。
言葉に直すと: 「最適解 $x^*$ では、 全方向に向かう傾きがゼロ」。 凸関数ならこれが 大域最小の必要十分条件、 非凸なら局所最小・鞍点・極大の 必要条件(十分ではない)。 二階条件 ヘッセ行列が正定なら極小、 鞍点なら符号混在。
| 記号 | 意味 |
|---|---|
| $x_t$ | 反復 $t$ ステップ目のパラメータ |
| $\nabla f(x_t)$ | $x_t$ における勾配(最大上昇方向) |
| $\eta$ | 学習率(ステップサイズ) |
| $-\nabla f$ | 「下り坂」方向 |
言葉に直すと: 「現在地点から、 勾配と 逆向きに学習率 $\eta$ だけ進む」。 山の頂で霧に包まれて視界が悪くても、 足元の傾きを感じて 少しずつ下るイメージ。 $\eta$ を大きくしすぎると 谷を飛び越える、 小さすぎると 永遠に着かない。
言葉に直すと: 「勾配だけでなく ヘッセ行列の逆行列を掛けて方向と歩幅を決める」。 凸関数なら 2 次収束(1 ステップで桁数倍)、 ただしヘッセ行列の計算と逆行列が高コスト。 大規模問題では BFGS のような 準ニュートン法(ヘッセ行列を近似)が現実解。
言葉に直すと: 「データ全部の勾配ではなく、 ランダムに 1 件(または小バッチ)の勾配で更新」。 全件計算が重い深層学習でほぼ必須。 確率ノイズが入ることで 鞍点を脱出しやすいという思わぬ利点も。 Adam, RMSProp, AdaGrad などの拡張版が現代の標準。
SSDSE-B-2026 の 2023 年、 47 都道府県を使って $y$ = 新規求職申込件数(一般、 F3101)、 $x$ = 総人口(A1101)とする 1 次式 $y = a + b x$ の係数を最小二乗で求めます。 これは凸 2 次計画なので解析解があり、
$$b = \frac{\sum (x_i-\bar x)(y_i-\bar y)}{\sum (x_i-\bar x)^2},\quad a = \bar y - b\,\bar x$$実 SSDSE データでは、 $\bar x \approx 264.6$ 万人、 $\bar y \approx 6.0$ 万件、 相関 $r \approx 0.97$ で、 おおむね
この回帰問題は形式上、 凸 2 次計画 (QP) です。 制約を $b\ge 0$ と加えても閉形式は崩れますが、 KKT で解けます。
🎯 このコードでやること: SSDSE-B-2026 から 2023 年 47 県の総人口 (A1101) と新規求職申込件数(一般, F3101)を取得し、 勾配降下法を手書きで 100 イテレーション回して回帰係数 $a$ を求める。 学習率 $\eta=0.1$ で標準化空間 → 元スケールに復元。 解析的 OLS 解と一致を確認。
📥 入力データ(SSDSE-B-2026, 2023 年 47 行):
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 | import pandas as pd import numpy as np df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2, header=None) cols = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', nrows=0).columns df.columns = cols d = df[df['SSDSE-B-2026']==2023] pop = pd.to_numeric(d['A1101']).values.astype(float) house = pd.to_numeric(d['F3101']).values.astype(float) # 標準化 xn = (pop - pop.mean()) / pop.std() yn = (house - house.mean()) / house.std() def loss(a, b): return np.mean((a*xn + b - yn)**2) def grad(a, b): e = a*xn + b - yn return 2*np.mean(e*xn), 2*np.mean(e) a, b, eta = 0.0, 0.0, 0.1 for i in range(100): ga, gb = grad(a, b) a -= eta * ga b -= eta * gb if i in [0,1,5,10,50,99]: print(f"iter {i+1:3d}: a={a:.5f} b={b:.5f} loss={loss(a, b):.6f}") # 解析解 (OLS) a_an = np.sum(xn*yn) / np.sum(xn**2) print(f"\n解析解 OLS: a={a_an:.6f} loss={loss(a_an, 0):.6f}") # 元スケール係数 a_real = a_an * house.std() / pop.std() b_real = house.mean() - a_real * pop.mean() print(f"\n元スケール: house = {a_real:.6f} × pop + {b_real:.2f}") |
📤 実行結果:
💬 結果の読み方: $\eta=0.1$ で 50 イテレーション程度で 解析解 OLS と 5 桁一致。 元スケール係数 $a = 0.018345$ は「総人口 100 万人につき新規求職申込 18,345 件」と読める実用的な解釈。 $b = 11{,}867$ は基準切片(人口ゼロでの仮想的な件数)で、 そのままでは意味を持たないが回帰式の数学的構成要素。 勾配降下の iter ごとの loss 単調減少が確認でき、 凸関数で安定収束する基本パターン。
🎯 このコードでやること: 同じ SSDSE-B-2026 データで学習率 $\eta = 0.01, 0.1, 0.5, 1.05$ を試し、 学習率が大きすぎると発散することを実演する。 「ハイパーパラメータ調整の重要性」と「凸関数でも実用上の制約がある」ことを体感。
📥 入力データ: 実装 1 と同じ (人口, 新規求職申込件数) の標準化済みベクトル。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import pandas as pd import numpy as np df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2, header=None) cols = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', nrows=0).columns df.columns = cols d = df[df['SSDSE-B-2026']==2023] pop = pd.to_numeric(d['A1101']).values.astype(float) house = pd.to_numeric(d['F3101']).values.astype(float) xn = (pop-pop.mean())/pop.std(); yn = (house-house.mean())/house.std() for eta in [0.01, 0.1, 0.5, 1.05]: a = 0.0 diverged = False for i in range(100): g = 2*np.mean((a*xn-yn)*xn) a = a - eta*g if abs(a) > 1e6: diverged = True; break lo = np.mean((a*xn-yn)**2) if not diverged else np.inf print(f"η={eta:5.2f}: a={a:12.6f} loss={lo:.6f} {'発散' if diverged else '収束'}") |
📤 実行結果:
💬 結果の読み方: $\eta=0.01$ では 100 iter で未収束(最適 0.968 に対して 0.840 止まり)。 $\eta=0.1, 0.5$ では完全収束。 $\eta=1.05$ では 1 step で大谷を飛び越え、 振動 → 発散。 凸関数(MSE)の 1D 勾配降下の収束条件は $\eta < 2/L$ ($L$ はリプシッツ定数)。 ここではデータの標準化で $L \approx 2$ なので $\eta < 1$ が安全圏。 「学習率は理論上限の 1/2〜1/10 が実用解」という現代深層学習の経験則がここから来る。
🎯 このコードでやること: 同じ SSDSE-B-2026 線形回帰 MSE 最小化を、 scipy.optimize.minimize の 6 種類の手法(BFGS, Nelder-Mead, CG, Powell, L-BFGS-B, trust-ncg)で解き、 必要評価回数とイテレーション数を比較する。 「準ニュートン法は速い」「Nelder-Mead は遅いがロバスト」を実感。
📥 入力データ: 同じ標準化済みベクトル (xn, yn)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import pandas as pd import numpy as np from scipy.optimize import minimize df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2, header=None) cols = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', nrows=0).columns df.columns = cols d = df[df['SSDSE-B-2026']==2023] pop = pd.to_numeric(d['A1101']).values.astype(float) house = pd.to_numeric(d['F3101']).values.astype(float) xn = (pop-pop.mean())/pop.std(); yn = (house-house.mean())/house.std() def f(t): return np.mean((t[0]*xn+t[1]-yn)**2) def g(t): e = t[0]*xn+t[1]-yn return np.array([2*np.mean(e*xn), 2*np.mean(e)]) for method in ['BFGS', 'Nelder-Mead', 'CG', 'Powell', 'L-BFGS-B']: res = minimize(f, [0.0,0.0], jac=g if method in ['BFGS','CG','L-BFGS-B'] else None, method=method) print(f"{method:12s}: theta={res.x} nit={res.nit:3d} nfev={res.nfev:3d} fun={res.fun:.6f}") |
📤 実行結果(概略):
💬 結果の読み方: 全手法が同じ最適値 (loss=0.0629) に到達。 BFGS / L-BFGS-B / CG が 2 イテレーション・3 関数評価で爆速(2 次の情報を使う準ニュートン法の威力)。 Nelder-Mead は勾配を使わないので 53 イテ・104 評価とほぼ 40 倍遅い。 ただし Nelder-Mead は 微分不能関数や離散制約でも動くロバスト性が魅力。 本番では「滑らかな凸 → BFGS、 ノイジーな目的関数 → Nelder-Mead」と使い分けるのが定石。
🎯 このコードでやること: 同じ SSDSE-B-2026 47 県データに対して、 全バッチ勾配降下と SGD (1 サンプル更新) の収束軌道を比較。 SGD は確率ノイズで振動するが、 平均的には最適解へ向かう。 これが深層学習の基本動作。
📥 入力データ: SSDSE-B-2026 の標準化済み (xn, yn) ベクトル 47 件。
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 | import pandas as pd import numpy as np df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2, header=None) cols = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', nrows=0).columns df.columns = cols d = df[df['SSDSE-B-2026']==2023] pop = pd.to_numeric(d['A1101']).values.astype(float) house = pd.to_numeric(d['F3101']).values.astype(float) xn = (pop-pop.mean())/pop.std(); yn = (house-house.mean())/house.std() N = len(xn) # 全バッチ勾配降下 a_bg, eta = 0.0, 0.1 hist_bg = [a_bg] for i in range(50): g = 2*np.mean((a_bg*xn-yn)*xn) a_bg -= eta*g hist_bg.append(a_bg) # SGD (1 サンプル) - data の順番のみ実データから決定 a_sgd = 0.0 hist_sgd = [a_sgd] eta_sgd = 0.05 order = np.argsort(pop) # 人口順に提示 (固定順序、 乱数なし) for epoch in range(5): for i in order: g = 2*(a_sgd*xn[i]-yn[i])*xn[i] a_sgd -= eta_sgd*g hist_sgd.append(a_sgd) print(f"全バッチ GD 最終: a={a_bg:.6f} (50 iter)") print(f"SGD 最終: a={a_sgd:.6f} (5 epochs × 47 = 235 step)") print(f"SGD 終盤 10 step: a 軌道 {[round(v, 4) for v in hist_sgd[-10:]]}") |
📤 実行結果(概略):
💬 結果の読み方: 全バッチ GD は滑らかに 0.968 に収束。 SGD は最終値 1.040 と 大きくブレたが、 平均的には正しい解の周りで振動。 SGD の振動は ノイズによる正則化効果を生み、 鞍点脱出にも有利。 深層学習で「SGD + モメンタム」が定番なのは、 ① 大規模データで全勾配が不可能、 ② 局所最適・鞍点を脱しやすい、 という理由から。 SSDSE 47 件では全バッチで十分だが、 ImageNet 1400 万件では SGD 一択。
| アルゴリズム | 使う情報 | 収束速度 | 計算コスト/iter | 典型場面 |
|---|---|---|---|---|
| 勾配降下 (GD) | 勾配のみ | 線形 $O(1/t)$ | $O(n)$ | シンプル、 教育用 |
| SGD | 確率勾配 | $O(1/\sqrt{t})$ | $O(1)$ | 大規模 ML |
| モメンタム SGD | 勾配 + 速度 | $O(1/t)$ | $O(1)$ | 深層学習の基本 |
| Adam | 勾配 + 二乗勾配の指数移動平均 | 適応的 | $O(1)$ | 深層学習の標準 |
| ニュートン法 | 勾配 + ヘッセ行列 | 2 次収束 | $O(n^3)$ | 低次元・高精度 |
| BFGS | 勾配 + ヘッセ近似 | 超線形 | $O(n^2)$ | 中規模・滑らか |
| L-BFGS | 勾配 + 限定メモリヘッセ近似 | 超線形 | $O(n)$ | 大規模・滑らか |
| Conjugate Gradient | 勾配 + 直交方向 | 有限ステップ | $O(n)$ | 線形系・スパース |
| Nelder-Mead | 関数値のみ | 遅い | $O(n)$ 評価 | 微分不能・ノイジー |
| シミュレーテッドアニーリング | 関数値 + 確率 | 遅い (大域最適へ) | $O(1)$ | 非凸・離散 |
| 遺伝的アルゴリズム | 関数値 + 集団 | 遅い | $O(P)$ (P=集団) | 非凸・複雑 |
| ベイズ最適化 | 関数値 + GP | サンプル効率最高 | $O(t^3)$ | 高コスト関数 |
🎯 このコードでやること: SSDSE-B-2026 の 8 地方人口を「予算 1000 を割り振る」最適化問題に変換。 各地方の人口に応じて重みを最大化したいが、 非負制約と総和制約を満たさなければならない。 scipy.optimize.minimize の SLSQP 法で解く。
📥 入力データ: SSDSE-B-2026 (2023) の 8 地方別人口 (集計済み)。
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 | import pandas as pd import numpy as np from scipy.optimize import minimize df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2, header=None) cols = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', nrows=0).columns df.columns = cols d = df[df['SSDSE-B-2026']==2023] # 地方別人口 (SSDSE 実値から集計済み定数) regions = ['関東','近畿','中部','九州','東北','中国','北海道','四国'] pops = np.array([43527000,21990000,20749000,14029000, 8318000,7070000,5092000,3578000]) w = pops / pops.sum() # 重要度ウェイト # 目的関数: 配分 x に対して -Σ w_i log(x_i) (人口比例で大きく配りたい) def f(x): return -np.sum(w * np.log(x)) # 制約: Σx = 1000、 各 x ≥ 1 cons = [{'type':'eq', 'fun':lambda x: x.sum() - 1000}] bounds = [(1, None)] * 8 x0 = np.full(8, 125) # 均等配分から開始 res = minimize(f, x0, method='SLSQP', bounds=bounds, constraints=cons) print("最適配分 (合計 1000):") for r, v, pp in zip(regions, res.x, pops): print(f" {r:4s}: {v:6.2f} (人口 {pp:,})") print(f"総和: {res.x.sum():.2f} 目的値: {res.fun:.4f}") |
📤 実行結果(概略):
💬 結果の読み方: 最適配分は 人口シェアにほぼ正確に比例(数学的に $x_i^* = 1000 \cdot w_i$ が KKT 条件の最適解)。 関東 350 ≒ 人口シェア 35.0%、 四国 28.77 ≒ 2.88% という具合。 これは 等式制約 (Σ=1000)、 不等式制約 (各 x ≥ 1)、 凹目的関数の最大化を SLSQP が同時に解いた結果。 予算配分・ポートフォリオ最適化・在庫割当などの基本パターンで、 SSDSE 実データに適用できることを示している。
🎯 このコードでやること: 同じ線形回帰問題で、 単純な勾配降下と モメンタム付き勾配降下 の収束を比較する。 モメンタムは「過去の更新方向を慣性として保持」することで、 谷の長軸方向に加速し、 振動を抑える。 深層学習の SGD+Momentum の基本動作。
📥 入力データ: 同じ SSDSE-B-2026 標準化済み (xn, yn) ベクトル。
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 | import pandas as pd import numpy as np df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2, header=None) cols = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', nrows=0).columns df.columns = cols d = df[df['SSDSE-B-2026']==2023] pop = pd.to_numeric(d['A1101']).values.astype(float) house = pd.to_numeric(d['F3101']).values.astype(float) xn = (pop-pop.mean())/pop.std(); yn = (house-house.mean())/house.std() def grad(a): return 2*np.mean((a*xn-yn)*xn) def loss(a): return np.mean((a*xn-yn)**2) # 通常の GD (小さい η) a_gd, eta = 0.0, 0.05 for i in range(30): a_gd -= eta*grad(a_gd) # Momentum GD a_mom, v, mu = 0.0, 0.0, 0.9 for i in range(30): v = mu*v - eta*grad(a_mom) a_mom += v print(f"通常 GD (30 iter, η=0.05) : a={a_gd:.6f} loss={loss(a_gd):.6f}") print(f"Momentum GD (30 iter, η=0.05, μ=0.9): a={a_mom:.6f} loss={loss(a_mom):.6f}") print(f"OLS 解析解 : a=0.968035 loss=0.062909") |
📤 実行結果:
💬 結果の読み方: 同じ 30 イテで、 通常 GD は a=0.927 (まだ収束途中)、 Momentum は a=1.162 と OLS 解 0.968 を 行き過ぎてオーバーシュート(loss も 0.101 と悪化)。 モメンタム $\mu=0.9$ により 実効的な学習率が約 10 倍に増幅されるため、 30 イテ時点では谷を通り越して振動している。 このようにモメンタムが強すぎると振動・オーバーシュートが増える(さらに反復すれば OLS 解に収束する)。 Nesterov モメンタム(先読み付き)、 Adam(適応的学習率)と並んで、 深層学習の標準オプティマイザの基礎技術。
🎯 このコードでやること: 同じ SSDSE-B-2026 線形回帰問題を、 深層学習で標準の Adam(適応的学習率 + モメンタム + 二乗勾配の指数移動平均)で解く。 学習率を パラメータごとに自動調整するので、 ハイパラ調整なしでもうまくいく。
📥 入力データ: 同じ標準化済み (xn, yn) ベクトル。
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 | import pandas as pd import numpy as np df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2, header=None) cols = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', nrows=0).columns df.columns = cols d = df[df['SSDSE-B-2026']==2023] pop = pd.to_numeric(d['A1101']).values.astype(float) house = pd.to_numeric(d['F3101']).values.astype(float) xn = (pop-pop.mean())/pop.std(); yn = (house-house.mean())/house.std() # Adam ハイパラ (Kingma & Ba 2014 の推奨値) a = 0.0 m, v = 0.0, 0.0 lr, b1, b2, eps = 0.1, 0.9, 0.999, 1e-8 for t in range(1, 51): g = 2*np.mean((a*xn-yn)*xn) m = b1*m + (1-b1)*g v = b2*v + (1-b2)*g**2 m_hat = m / (1-b1**t) v_hat = v / (1-b2**t) a = a - lr * m_hat / (np.sqrt(v_hat) + eps) if t in [1,5,10,25,50]: lo = np.mean((a*xn-yn)**2) print(f"Adam iter {t:3d}: a={a:.6f} loss={lo:.6f}") |
📤 実行結果(概略):
💬 結果の読み方: Adam は $\beta_1=0.9$(モメンタム)+ $\beta_2=0.999$(二乗勾配 EMA)を組合せる。 学習率 $0.1$ ではいったん iter 25 で a=1.13 まで オーバーシュートし、 iter 50 で a≈0.984 と OLS 解 (0.968) 付近へ収束していく。 単純な GD と比べて 自動的に適切なステップサイズを計算するため、 ハイパラ調整が楽。 深層学習の事実上の標準オプティマイザ(PyTorch torch.optim.Adam、 TensorFlow tf.keras.optimizers.Adam)。 SSDSE のような単純問題でも動くし、 1 兆パラメータの LLM 学習でも使われる汎用性。
🎯 このコードでやること: SSDSE-B-2026 から「人口 ≥ 300 万なら大都市県 (1)、 それ以外 (0)」というラベルを作り、 出生率を特徴量とした 1 次元ロジスティック回帰を L-BFGS-Bで最適化する。 線形回帰と違って解析解がないので、 必ず数値最適化が必要。
📥 入力データ: SSDSE-B-2026 (2023) 47 行、 A4103 (出生率) を $x$、 A1101 (人口) ≥ 300 万を $y$。
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 | import pandas as pd import numpy as np from scipy.optimize import minimize df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2, header=None) cols = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', nrows=0).columns df.columns = cols d = df[df['SSDSE-B-2026']==2023] pop = pd.to_numeric(d['A1101']).values.astype(float) tfr = pd.to_numeric(d['A4103']).values.astype(float) x = (tfr - tfr.mean()) / tfr.std() y = (pop >= 3e6).astype(float) print(f"ラベル分布: 正例 {int(y.sum())} / 負例 {int(len(y)-y.sum())}") # 負の対数尤度 def nll(t): a, b = t z = a*x + b # numerically stable log(1 + exp(z)) log1pe = np.logaddexp(0, z) return -np.mean(y*z - log1pe) def grad_nll(t): a, b = t z = a*x + b p = 1/(1+np.exp(-z)) e = p - y return np.array([np.mean(e*x), np.mean(e)]) res = minimize(nll, [0.0,0.0], jac=grad_nll, method='L-BFGS-B') print(f"最適 (a, b) = {res.x}") print(f"最終 NLL = {res.fun:.6f}") print(f"nit={res.nit} nfev={res.nfev}") # 推定確率と分類 a, b = res.x prob = 1/(1+np.exp(-(a*x+b))) acc = ((prob > 0.5) == (y == 1)).mean() print(f"訓練精度: {acc:.4f}") |
📤 実行結果(概略):
💬 結果の読み方: 47 県のうち人口 300 万人以上は 10 県(正例)、 残り 37 県が負例。 ロジスティック回帰の最適係数 $a = -1.49$ は「出生率が低いほど大都市県の確率が上がる」を意味する負の符号。 L-BFGS-B は 7 イテレーションで収束、 訓練精度 79%。 OLS のような解析解は存在しないため、 必ず数値最適化が必要。 sklearn の LogisticRegression も内部で L-BFGS or liblinear で同じ計算をしている。
| キー数式 | 役割 |
|---|---|
| $\min_x f(x)$ s.t. $g_i(x)\le 0$ | 最適化問題の標準形 |
| $\nabla f(x^*) = 0$ | 一階の最適性条件 |
| $\nabla^2 f(x^*) \succeq 0$ | 二階の最適性条件(極小) |
| $x_{t+1} = x_t - \eta \nabla f(x_t)$ | 勾配降下 |
| $x_{t+1} = x_t - H^{-1}\nabla f$ | ニュートン法 |
| $v \leftarrow \mu v - \eta \nabla f, \; x \leftarrow x + v$ | モメンタム |
| $m_t = \beta_1 m_{t-1} + (1-\beta_1) g_t$ | Adam の 1 次モーメント |
| $\eta_t = \eta / (1 + \alpha t)$ | 学習率スケジュール |
numpy.linalg.lstsq または OLS 公式sklearn.linear_model.LogisticRegression(内部 L-BFGS)scipy.optimize.minimize(method='SLSQP')torch.optim.Adamscipy.optimize.differential_evolution または optunascipy.optimize.linprog または cvxpy
このコードでやること: SSDSE-B-2026 の総人口・着工建築物数・新規求職申込件数・合計特殊出生率を特徴量とする線形回帰について、 X^T X の条件数(最大固有値 / 最小固有値)を「標準化前」「標準化後」で比較し、 勾配降下の収束レートが何倍変わるかを示す(桁が大きく異なる列が混ざると条件数が悪化する点に注目)。
📥 入力データ (SSDSE-B-2026, 2023 年 抜粋):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import pandas as pd import numpy as np from sklearn.preprocessing import StandardScaler df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2, header=None) df.columns = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', nrows=0).columns d = df[df['SSDSE-B-2026'] == 2023] codes = ['A1101', 'C3301', 'F3101', 'A4103'] # 総人口, 着工建築物数, 新規求職, 出生率 X = d[codes].astype(float).values # 標準化前の条件数 eig_raw = np.linalg.eigvalsh(X.T @ X) cond_raw = eig_raw.max() / eig_raw.min() print(f"標準化前 κ(X^T X) = {cond_raw:.3e}") # 標準化後の条件数 X_std = StandardScaler().fit_transform(X) eig_std = np.linalg.eigvalsh(X_std.T @ X_std) cond_std = eig_std.max() / eig_std.min() print(f"標準化後 κ(X^T X) = {cond_std:.3e}") print(f"\n収束ステップ数の比: {cond_raw / cond_std:.3e} 倍") |
📤 実行すると次の出力が得られる:
💬 標準化前の条件数は 10¹³ 桁 (総人口 10⁶ と出生率 10⁰ の比が桁外れに大きい)。 強凸の線形収束レートは (1-1/κ)^k なので、 同精度に達するイテレーション数は条件数比で増える。 標準化後も κ ≈ 10² 残るのは特徴量間の相関(多重共線性)に由来するが、 標準化前より 11 桁改善している。 標準化を「前処理の慣習」と捉えず、 収束理論の必須条件と理解する根拠がここにある。
このコードでやること: SSDSE-B-2026 の多変量回帰で、 (a) 固定学習率 η = 0.01、 (b) Armijo ライン探索(バックトラッキング)を比較し、 同じ反復回数での損失減少幅を測る。 Armijo は「目的関数が十分減るまで η を半分にし続ける」単純戦略で、 学習率調整の手間を消す。
📥 入力データ (SSDSE-B-2026 抜粋、 標準化済み 47 都道府県):
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 | import pandas as pd import numpy as np from sklearn.preprocessing import StandardScaler df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2, header=None) df.columns = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', nrows=0).columns d = df[df['SSDSE-B-2026'] == 2023] X = StandardScaler().fit_transform(d[['A1101', 'C3301', 'A4103']].astype(float).values) y = StandardScaler().fit_transform(d[['F3101']].astype(float).values).ravel() def loss(w): return ((X @ w - y) ** 2).mean() def grad(w): return 2 * X.T @ (X @ w - y) / len(y) # (a) 固定学習率 w = np.zeros(3) for i in range(100): w -= 0.01 * grad(w) print(f"固定 η=0.01, 100 iter 後の損失: {loss(w):.6f}") # (b) Armijo ライン探索 w = np.zeros(3) for i in range(100): g = grad(w) eta = 1.0 while loss(w - eta * g) > loss(w) - 0.5 * eta * (g @ g): eta *= 0.5 w -= eta * g print(f"Armijo, 100 iter 後の損失: {loss(w):.6f}") |
📤 実行すると次の出力が得られる:
💬 Armijo は同じ 100 反復で固定学習率の約半分の損失に達する。 固定学習率は「安全な小さい値」を選ばざるを得ないが、 ライン探索は各ステップで適切な大きさを自動選択する。 scipy.optimize.minimize の BFGS / L-BFGS-B はすべて内部で Wolfe 条件付きライン探索を実装しているため、 「学習率を渡さなくても安定して収束する」のはこの仕組みのおかげ。
f(x)=x²-4x+5 の最急降下で 1 step 更新する。
1 2 3 4 5 6 7 8 | def f(x): return x**2 - 4*x + 5 def df(x): return 2*x - 4 x = 5.0 lr = 0.3 x1 = x - lr * df(x) print(f"f(x₀)={f(x)}, f'(x₀)={df(x)}") print(f"x₁ = {x1}") print(f"f(x₁) = {f(x1):.4f}") |
💬 手計算 (Step 2,3) x₁=3.2 / f(x₁)=2.44 と Python 出力が完全一致。
1 2 3 4 5 6 7 8 | import numpy as np from scipy.optimize import minimize def rosenbrock(x): return (1 - x[0])**2 + 100*(x[1] - x[0]**2)**2 res = minimize(rosenbrock, x0=[-1.2, 1.0], method='BFGS') print(res.x, res.fun) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import pandas as pd, numpy as np import cvxpy as cp df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='shift_jis') df.columns = df.iloc[0] df = df.iloc[1:].reset_index(drop=True) df = df[df['年度']=='2023'].reset_index(drop=True) x = df['総人口'].astype(float).to_numpy()/1e6 y = df['新規求職申込件数(一般)'].astype(float).to_numpy()/1e4 # 万件 n = len(x) X = np.column_stack([np.ones(n), x]) beta = cp.Variable(2) obj = cp.Minimize(cp.sum_squares(X @ beta - y)) cons = [beta[1] >= 0] # 「傾きは非負」という制約 prob = cp.Problem(obj, cons) prob.solve() print('係数:', beta.value, '残差^2:', prob.value) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import pandas as pd # ここは日本語の列名を使うので、2 行目を見出しにして読み直す # (直前のブロックが cvxpy 未導入で止まると df が残らないため、ここで用意する) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1) df = df[df['年度'] == 2023].reset_index(drop=True) from sklearn.linear_model import Ridge X_full = df[['総人口','15歳未満人口','15~64歳人口','65歳以上人口']].astype(float).to_numpy() model = Ridge(alpha=1.0) model.fit(X_full, df['新規求職申込件数(一般)'].astype(float)) print('回帰係数:', model.coef_) print('切片:', model.intercept_) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import pandas as pd # ここは日本語の列名を使うので、2 行目を見出しにして読み直す # (直前のブロックが cvxpy 未導入で止まると df が残らないため、ここで用意する) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1) df = df[df['年度'] == 2023].reset_index(drop=True) import numpy as np x = df['総人口'].astype(float).to_numpy()/1e6 y = df['新規求職申込件数(一般)'].astype(float).to_numpy()/1e4 X = np.column_stack([np.ones_like(x), x]) theta = np.zeros(2) eta = 1e-3 for k in range(2000): grad = X.T @ (X @ theta - y) / len(y) theta -= eta * grad print('GD 解:', theta) |
最小二乗問題:
$$\min_\beta \|y - X\beta\|^2 \quad\Leftrightarrow\quad \beta^\star = (X^\top X)^{-1} X^\top y$$これは凸 2 次計画 (QP) で、 解析解が存在します。
負の対数尤度を最小化:
$$\min_\beta \sum_i \log(1 + e^{-y_i X_i \beta})$$勾配は閉形ではないが凸なので、 Newton-Raphson や IRLS で大域最適に収束。
$\|\cdot\|_1$ が非滑らかなので、 座標降下法・近接勾配法 (ISTA/FISTA) を使う。
重み $W$ について損失 $L(W)$ が高度に非凸。 Adam・AdamW・SGD with momentum が標準。 局所最適より サドル点が問題 という研究もある。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import pandas as pd, numpy as np df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='shift_jis') df.columns = df.iloc[0] df = df.iloc[1:].reset_index(drop=True) df = df[df['年度']=='2023'].reset_index(drop=True) X = df[['総人口']].astype(float).to_numpy() / 1e6 y = df['新規求職申込件数(一般)'].astype(float).to_numpy() / 1e12 X = np.hstack([np.ones_like(X), X]) theta = np.zeros(2) for k in range(5000): grad = X.T @ (X @ theta - y) / len(y) theta -= 0.005 * grad if k % 1000 == 0: loss = ((X @ theta - y) ** 2).mean() print(f'iter {k}: loss={loss:.4f}, theta={theta}') |
ステップ 1:問題設定
$y$ = 新規求職申込件数(万件)、 $x_1$ = 総人口(百万人)、 $x_2$ = 65歳以上人口割合(%)。 回帰モデル $y = \beta_0 + \beta_1 x_1 + \beta_2 x_2$。 「$\beta_1$(人口係数)は非負」 という業務制約を加える。
ステップ 2:cvxpy で定式化
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 | import pandas as pd, numpy as np import cvxpy as cp df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='shift_jis') df.columns = df.iloc[0] df = df.iloc[1:].reset_index(drop=True) df = df[df['年度']=='2023'].reset_index(drop=True) df['総人口'] = df['総人口'].astype(int) df['65歳以上人口'] = df['65歳以上人口'].astype(int) df['新規求職申込件数(一般)'] = df['新規求職申込件数(一般)'].astype(int) df['65歳以上比率'] = df['65歳以上人口'] / df['総人口'] * 100 n = len(df) X = np.column_stack([np.ones(n), df['総人口'].to_numpy()/1e6, df['65歳以上比率'].to_numpy()]) y = df['新規求職申込件数(一般)'].to_numpy()/1e4 beta = cp.Variable(3) obj = cp.Minimize(cp.sum_squares(X @ beta - y)) cons = [beta[1] >= 0, beta[1] <= 10] # 業務知識からの制約 prob = cp.Problem(obj, cons) prob.solve() print('係数:', beta.value) print('残差二乗和:', prob.value) |
ステップ 3:KKT 条件の確認
1 2 3 4 | grad = 2 * X.T @ (X @ beta.value - y) # beta[1] が制約境界に当たっていれば、 対応するラグランジュ乗数 > 0 for i, c in enumerate(cons): print(f'制約 {i} 双対変数:', c.dual_value) |
ステップ 4:制約あり vs なし比較
1 2 3 4 | unc, *_ = np.linalg.lstsq(X, y, rcond=None) print('無制約解:', unc) print('制約解:', beta.value) # 残差・予測精度・解釈を比較 |
ステップ 5:感度分析
各係数を ±10% 動かしたときの残差変化を計算。 ラグランジュ乗数は「制約を 1 単位緩めたときの目的改善」を示す。
$\min_\theta L(\theta)$ — 損失 $L$ を連続パラメータ $\theta$ について最小化。 線形回帰・ロジスティック・SVM・NN すべて。
Markowitz の平均-分散最適化。 凸 QP。 制約付き SSDSE 県別投資配分にも応用可。
$\hat\theta = \arg\max \log p(D|\theta)$ — 統計推定の中核は連続最適化。
REINFORCE、 PPO、 SAC — 報酬期待値を最大化する連続パラメータ最適化。
勾配ベース NAS(DARTS)は連続最適化として定式化。
LQR・MPC — 二次形コスト最小化の連続制御。 自動運転・ロボット制御。
建築・機械部品の質量最小化、 強度制約付き。 SQP / 内点法。
発電配分の凸最適化。 LP / QP / 確率計画。
歴史と位置づけ:連続最適化は 17 世紀の微積分(Newton, Leibniz)にまで遡りますが、 現代的な体系化は 20 世紀。 主な節目:
機械学習・統計の 学習は事実上すべて連続最適化問題で、 損失関数の最小化として定式化されます。 凸最適化(Boyd & Vandenberghe, 2004)は本分野の標準教科書。
| 手法 | 必要情報 | 収束 | 適用 |
|---|---|---|---|
| 勾配降下 | 1 次勾配 | 線形 | NN, 大規模 SGD |
| Newton-Raphson | 1+2 次 | 2 次 | 低次元、 凸 |
| BFGS / L-BFGS | 1 次のみ | 準 2 次 | 中次元、 凸 |
| 共役勾配 | 1 次 | 準 2 次 | 巨大スパース |
| 内点法 | 1+2 次 | 多項式時間 | LP / QP / SDP |
| シンプレックス | 線形構造 | 有限 | LP |
| Adam | 1 次 + 履歴 | 準 1 次 | NN |
| SGD with momentum | 1 次 + 慣性 | 確率的 | NN, 大規模 |
| 近接勾配 (ISTA) | 1 次 + 近接 | 線形 | LASSO |
| 用語 | 意味 |
|---|---|
| 目的関数 | 最小化/最大化する関数 |
| 決定変数 | 最適化する変数 |
| 制約 | 変数が満たすべき条件 |
| 勾配 | 関数の 1 階偏微分ベクトル |
| ヘッセ | 2 階偏微分行列 |
| 凸関数 | 局所最適 = 大域最適となる関数 |
| KKT 条件 | 制約付き最適性の必要条件 |
| ラグランジュ乗数 | 制約の影付き価格 |
| 双対問題 | 主問題の下界を与える別問題 |
| Newton 法 | 2 次情報を使う反復法 |
| 勾配降下 | 1 次情報のみで進む反復法 |
| Adam | モメンタム + 適応学習率の SGD 系 |
| レシピ | コード | ||
|---|---|---|---|
| scipy.optimize.minimize |
| ||
| 勾配を渡す | minimize(f, x0, jac=grad_f, method='Newton-CG') | ||
| ヘッセを渡す | minimize(f, x0, jac=grad_f, hess=hess_f, method='trust-ncg') | ||
| 制約付き | minimize(f, x0, constraints=[{'type':'ineq', 'fun': g}]) | ||
| 境界付き | minimize(f, x0, bounds=[(0,1),(0,5)], method='L-BFGS-B') | ||
| cvxpy 凸最適化 |
| ||
| 最小二乗解析解 | beta, *_ = np.linalg.lstsq(X, y, rcond=None) | ||
| Ridge |
| ||
| Lasso |
| ||
| LogisticRegression | 📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行)
都道府県 A1101(総人口) A1301(15歳未満人口) A1303(65歳以上人口) A4101(出生数)
北海道 5,092,000 514,000 1,681,000 24,430
東京都 14,086,000 1,513,000 3,205,000 86,348
沖縄県 1,468,000 236,000 350,000 12,549
…(全 47 行)
| ||
| ロス関数勾配の自動微分 |
| ||
| PyTorch Adam | opt = torch.optim.Adam(model.parameters(), lr=1e-3) | ||
| SciPy linprog (LP) |
| ||
| 基底ニュートン法 | for k in range(N):
x -= np.linalg.solve(hess_f(x), grad_f(x)) | ||
| 収束判定 | if np.linalg.norm(grad) < tol: break |
連続最適化を中心とした「学習=最適化」の構図:
[損失/負尤度]─ 最小化 ─► [パラメータ]
▲ │
│ ▼
[データ]──────────► [勾配/ヘッセ]
│
▼
(勾配降下/ニュートン/BFGS/SGD/Adam)
凸 ←─ 線形回帰・ロジスティック・SVM(線形)・LASSO・Ridge ─→ 大域最適
非凸 ←─ NN・混合モデル・EM・GAN ─→ 局所最適 + 複数初期値
「目の前の最適化問題に何を使うか」を 1 分で判断するフロー。 SSDSE-B-2026 規模(変数 ~ 100、 サンプル ~ 数千)から深層学習規模(変数 ~ 億)まで網羅する。
| 問題の性質 | 第一選択 | 第二選択 | 理由 |
|---|---|---|---|
| 凸 + 閉形式あり (線形回帰) | 閉形式 (X^T X)^{-1} |
L-BFGS | 1 ステップで厳密解 |
| 凸・滑らか・中規模 (ロジスティック回帰) | L-BFGS | ニュートン法 | 超線形収束、 Hessian 不要 |
| 凸・非滑らか (Lasso, SVM) | 座標降下 / 近接勾配 | ADMM | 劣勾配で BFGS が無効 |
| 非凸・滑らか・小規模 (神経網ファインチューニング少数層) | L-BFGS | SGD + momentum | バッチ計算可能 |
| 非凸・大規模 (深層学習) | Adam / AdamW | SGD + momentum | 適応学習率、 雑音許容 |
| 非凸・微分なし (シミュレーション最適化) | Nelder-Mead | Bayesian Opt | 関数評価のみで進む |
| 制約付き・線形制約のみ | 線形計画 (scipy.linprog) | SLSQP | 単体法 / 内点法で厳密 |
| 制約付き・非線形制約 | SLSQP / trust-constr | 拡張ラグランジュ | 等式・不等式両対応 |
| 大域最適化(多峰) | differential_evolution | basinhopping | 多重初期値探索 |
| method | 勾配 | Hessian | 制約 | 主用途 |
|---|---|---|---|---|
| Nelder-Mead | 不要 | 不要 | なし | 微分なし関数 |
| Powell | 不要 | 不要 | なし | 微分なし、 中変数 |
| CG | 必要 | 不要 | なし | 大変数、 メモリ節約 |
| BFGS | 必要 | 不要 | なし | 中規模、 標準 |
| L-BFGS-B | 必要 | 不要 | 境界のみ | 大規模、 デファクト |
| Newton-CG | 必要 | 推奨 | なし | Hessian 利用 |
| SLSQP | 推奨 | 不要 | 等式/不等式 | 制約付き標準 |
| trust-constr | 必要 | 推奨 | 汎用 | 最新・高精度 |
Adam は学習率に対するロバスト性が高いだけで、 オーダーは依然として重要。 η = 10⁻¹ と 10⁻⁵ では結果が大きく違う。 経験則は 1e-3 から開始し、 ロスが減らなければ 1/10、 振動すれば 1/3。
非凸関数では「勾配ノルム ≈ 0」は局所最適、 鞍点、 高次の停留点のいずれの可能性もある。 大域最適の保証には凸性、 または大域最適化ラッパー(differential_evolution 等)が必要。
安全だが、 過小学習率は (a) 浅い局所最適から脱出できない、 (b) 鞍点近傍で停滞、 (c) 計算時間が爆発、 の 3 つの罠がある。 適切な大きさ(条件数で言えば 1/L 程度)が「速度と安全のスイートスポット」。
SGD はサンプル数 N に対し 1 epoch のコストが O(N) で、 一見データが多いほど SGD が有利。 しかし「同じ精度に達する勾配計算回数」は SGD の方が多い (O(1/√k) vs バッチの O(1/k))。 N が大きくバッチ計算が一括で済むなら、 L-BFGS の方が総合的に速いことも多い。
収束の局所漸近レートは 2 次で最速だが、 1 ステップあたりの計算量は O(n³)。 変数 1000 個なら 10⁹ 演算 / イテレーション、 L-BFGS の数千倍重い。 実務では「変数 100 個まで」が目安。
最適解は同じだが、 計算時間・数値安定性・実装手間が異なる。 SSDSE-B-2026 規模なら閉形式が圧勝、 N=10⁵ なら L-BFGS、 N=10⁹ なら SGD と、 規模で正解が変わる。
L1 正則化(Lasso)は微分不可点を持つため、 BFGS / Newton で正しく動かない。 座標降下や近接勾配法が必須。 L2(Ridge)は滑らかなので全手法が使える。 「正則化項の性質」と「最適化手法の選択」は連動する。
バッチサイズ・層数などは離散、 学習率は連続だが「目的関数」が訓練ループ全体(数時間)。 関数評価が高コストかつノイジーなため、 グリッド / ランダム探索 / ベイズ最適化が標準。 通常の連続最適化アルゴリズムは適用不可。
機械学習文脈では訓練ロスを「途中で止める」のがしばしば最適。 訓練ロスは下がり続けても汎化ロスは上昇する(過学習)ため、 検証ロスが最小の時点で打ち切るのが正解。 「収束させきる」が常に良いわけではない。
SGD / Adam は乱数(バッチサンプリング、 初期重み)に依存するため、 同じコード・同じデータでも実行ごとに最終解が異なる。 再現性確保には np.random.seed、 torch.manual_seed、 CUDA の deterministic mode を全部固定する必要がある。
教科書だけでは「アルゴリズムは分かったが、 何に使うのか」が見えにくい。 ここでは SSDSE-B-2026 を含む実データ問題で連続最適化が現にどう使われているかを 8 ケース紹介する。 各ケースには「目的関数」「変数」「制約」「使用される手法」を明示し、 自分の研究テーマに応用するためのテンプレートとする。
SSDSE-B-2026 の各都道府県教育費 (E2101 など) と学力指標を組み合わせ、 限られた中央予算 1 万件を 47 都道府県に配分して全国平均学力を最大化する問題。 目的関数: Σ score_i(budget_i)、 変数: 47 個の予算配分、 制約: Σ budget_i = 10000 億円 かつ budget_i ≥ 最低保障額。 SLSQP で解ける典型例。 限界生産性が逓減する関数を仮定すると、 「現在予算が少ない県ほど多く配分」が最適解となる。
47 都道府県のワクチン需要 (人口 ・ 高齢化率から算出) と物流コストを目的関数化。 連続変数として「各物流拠点 → 各県への配送量」を持ち、 制約は (a) 各拠点の供給上限、 (b) 各県の需要充足、 (c) 配送量 ≥ 0。 線形計画 (scipy.linprog) で大規模問題を 1 秒以内に解く。 災害時の食料・燃料配給にも同じ枠組みで応用される。
勾配ブースティング (XGBoost / LightGBM) の学習率 ・ 木の深さ ・ 正則化強度を SSDSE-B-2026 で交差検証 RMSE を最小化するように調整。 目的関数値は「モデルを訓練して検証スコアを返す」関数 (1 回数秒)。 微分不可で雑音あり。 Bayesian Optimization (scikit-optimize, Optuna) が標準。 グリッド探索より 10 倍少ない評価回数で良い解に到達する。
N 銘柄への投資比率 w について、 リスク (分散) を最小化しつつ期待リターンを μ 以上に保つ問題。 目的関数: w^T Σ w (二次関数)、 制約: w^T μ_vec ≥ μ, Σ w_i = 1, w_i ≥ 0。 凸 QP 問題で cvxpy 一行で解ける。 SSDSE-B-2026 の都道府県別経済指標を「資産」とみなすと、 リスク分散投資戦略の入門演習になる。
ResNet50 の 2500 万パラメータについて、 訓練データの分類誤差を最小化。 変数次元 n = 10⁷、 サンプル数 N = 10⁶。 SGD + momentum (momentum=0.9) + cosine learning rate schedule + weight decay。 1 epoch 数分、 200 epoch で訓練完了が標準。 Adam も使えるが最終精度で SGD に劣るため画像分野では非主流。
変数次元 10¹¹ (1000 億パラメータ)、 サンプル数 10¹² tokens。 AdamW (Adam + 重み減衰の分離) + warmup → cosine decay の学習率スケジューリング + 勾配クリッピング。 計算リソースが膨大なため、 学習率や warmup steps の調整 1 つで数千万円の計算費用が変わる。 連続最適化の実務インパクトが最大化する領域。
気候モデル / 燃焼シミュレーション / 量子化学計算のパラメータを実測データに合わせる「インバース問題」。 シミュレーション 1 回が分 ~ 時間かかり、 解析的勾配は無い。 Bayesian Optimization、 surrogate model (Gaussian Process)、 Nelder-Mead が標準。 SSDSE-B-2026 規模の小データでも同じ枠組みが応用できる。
ユーザー × アイテムの評価行列 R を 2 つの低次元行列 U, V の積で近似する非凸最適化。 目的関数: ||R - UV^T||² + λ(||U||² + ||V||²)。 U を固定して V を解く → V を固定して U を解く、 の交互最小化 (ALS) で凸部分問題に分解。 Netflix / Spotify / Amazon の主要レコメンドエンジンの基盤。
| 用語 | 意味 |
|---|---|
| 勾配 (gradient) | 関数の各変数に関する偏微分を並べたベクトル。 最も急な増加方向。 |
| Hessian | 2 階偏微分の行列。 関数の曲率を表現。 対称行列。 |
| 凸関数 | 任意の 2 点の中点での値が、 両端の平均以下。 局所最適 = 大域最適。 |
| 強凸関数 | 凸関数より厳しく、 下から二次関数で挟める。 最適解の一意性保証。 |
| L-平滑 | 勾配が L-リプシッツ連続。 Hessian の最大固有値 ≤ L。 |
| 条件数 | Hessian の最大固有値 / 最小固有値。 大きいほど収束が遅い。 |
| 局所最適 | 近傍内では最小、 大域的には最小とは限らない。 非凸の宿命。 |
| 大域最適 | 全変数空間で最小。 凸関数なら局所 = 大域。 |
| 鞍点 | 勾配ゼロだが最小でも最大でもない点。 高次元で頻出、 SGD で脱出可能。 |
| ライン探索 | 各反復で適切な学習率を自動選択。 Wolfe / Armijo 条件が標準。 |
| 信頼領域 (trust region) | 2 次近似を信頼する半径を動的に調整。 BFGS の代替戦略。 |
| モメンタム | 過去の勾配を慣性として加算。 振動抑制と高速化。 |
| Nesterov 加速 | 外挿点で勾配を計算する 1 ステップ先読み。 O(1/k²) 収束。 |
| 適応学習率 | 変数ごとに学習率を自動調整。 Adagrad / RMSprop / Adam。 |
| バイアス補正 | Adam の初期段階で移動平均の偏りを補正する 1/(1-β^t) 因子。 |
| 勾配クリッピング | 勾配ノルムが閾値超なら縮小。 RNN / Transformer の発散防止。 |
| weight decay | L2 正則化を勾配更新時に直接引く。 過学習抑制。 |
| エポック | 全訓練データを 1 回通すこと。 数十 ~ 数百エポックが標準。 |
| バッチサイズ | 1 回の勾配計算で使うサンプル数。 大きいほど安定だが遅い。 |
| 学習率スケジューリング | epoch ごとに η を変える。 step decay / cosine / warmup。 |
| early stopping | 検証ロスが改善しなくなったら打ち切る。 過学習回避。 |
| ペナルティ法 | 制約違反を目的関数に大きな項として加える。 単純だが近似的。 |
| ラグランジュ乗数法 | 等式制約付き問題を双対変数で無制約化。 厳密解。 |
| KKT 条件 | 制約付き最適解の必要条件。 ラグランジュ乗数の符号と等式系。 |
| 近接勾配法 | 微分不可な正則化項に対応する勾配法拡張。 Lasso の標準。 |
「連続最適化」は実数変数で目的関数を最小化する問題で、 上流の凸性・微分可能性の検証と下流の勾配法・準ニュートン法の選択を切り離すと、 局所最適に落ちるか発散して計算が無駄になる。
上流で凸性・滑らかさを確認し、 並列の勾配降下・準ニュートン (BFGS)・内点法をベンチマークし、 下流で収束判定・ステップサイズ調整を入れれば、 線形回帰の閉形式解から深層学習の確率的勾配降下まで「同じ枠組み」で扱える。
「連続最適化」を実際に使うとき、 何をどう選ぶかを順に判断する。 上から順に答えていくと、 使うべき手法と評価の仕方が決まる。
連続最適化は「なめらかに動かせる変数」を扱う。 「どの県を選ぶか」のような 0/1 の選択は微分できないので、 組合せ最適化の手法に移る。
連続最適化の代表的アルゴリズム 勾配降下法 $\theta^{k+1} = \theta^k - \eta\,f'(\theta^k)$ の「反復が進む様子」を、 1 変数関数の上で直接動かして体感するデモです。 曲線上をクリック / ドラッグして開始点を置き、 学習率 $\eta$ をスライダーで変えながら「1 ステップ実行」または「自動再生」してください。 各ステップで 現在点の接線(勾配) と 次の点への移動 が描画されます。
デモ関数(数式は解析的に正確、 勾配は手計算で検証済み):
① 凸: $f(x)=\tfrac{1}{2}x^2$、 $f'(x)=x$、 最小点 $x^\star=0$(曲率 $f''=1$ なので $\eta>2$ で必ず発散、 $\eta=2$ で永久振動)
② 非凸: $f(x)=0.05x^4-0.5x^2+0.2x+2$、 $f'(x)=0.2x^3-x+0.2$、 極小点 $x\approx-2.330$(大域的、 $f\approx0.293$)と $x\approx2.129$(局所的、 $f\approx1.187$)
このデモが示すように、 勾配降下の成否はほぼ学習率で決まる。 実務では次の 3 点を押さえる。
本文の収束理論では条件数 $\kappa = L/\mu$ が反復回数を支配することを紹介しました。 この節ではそれを一歩進め、 SSDSE-B-2026(2023 年・47 都道府県)の実データからヘッセ行列の固有値と条件数を実際に計算し、 悪条件には「スケール由来」と「相関由来」の 2 種類があること、 そして標準化で直るのは前者だけであることを実測で確かめます。 アルゴリズム側(学習率・手法選択)を扱った本文・デモに対し、 ここはデータ側から最適化問題の地形を診断するという補完的な視点です。
最小二乗の目的関数 $f(w)=\frac{1}{n}\|Xw-y\|^2$ のヘッセ行列は $H=\frac{2}{n}X^\top X$ で、 どこで計算しても同じ定数行列です。 つまり谷の形(各主軸方向の曲率 = 固有値)は勾配降下を始める前からデータ $X$ だけで確定しています。 最大固有値と最小固有値の比 $\kappa$ が「谷の細長さ」で、 これを SSDSE-B-2026 の設計行列で実測すると次のようになります(目的変数 $y$ = 新規求職申込件数 F3101 を標準化、 勾配降下は $\eta=1/L$、 収束判定 $\|\nabla f\|<10^{-6}$)。
| 設計行列(47 県) | ヘッセ行列の固有値 | 条件数 $\kappa$ | 安全な学習率 $\eta<2/L$ | GD 実測反復数 |
|---|---|---|---|---|
| 生スケール〔切片, 総人口 A1101〕 | $1.045$ と $2.93\times10^{13}$ | $2.8\times10^{13}$ | $6.8\times10^{-14}$ | 事実上収束不能 |
| 標準化〔切片, z(総人口)〕 | $2.000$ と $2.000$ | $1$(真円の谷) | $1.0$ | $\eta=1/L$ なら 1 ステップで厳密解 |
| 標準化 2 変数〔z(総人口 A1101), z(15歳未満人口 A1301)〕 相関 $r=0.9967$ | $0.0066$ と $3.9934$ | $601.0$ | $0.50$ | 5,410 回 |
| 標準化 2 変数〔z(総人口 A1101), z(降水日数 B4106)〕 相関 $r=-0.3753$ | $1.2494$ と $2.7506$ | $2.20$ | $0.73$ | 23 回 |
1 行目 → 2 行目:標準化はスケール由来の悪条件を $\kappa\approx10^{13}$ から $1$ まで消し去ります(本文・収束理論の節の概算 $\kappa\approx10^6$ よりさらに極端です。 総人口の分散は $(2{,}767{,}630)^2\approx7.7\times10^{12}$ で、 これがそのまま曲率の桁差になるため)。 一方 3 行目:標準化 済み でも、 2 つの説明変数が強く相関していると谷は再び細長くなります。 標準化 2 変数の場合、 固有値は厳密に $2(1\pm r)$ となるので $\kappa=\frac{1+|r|}{1-|r|}$。 総人口と 15 歳未満人口は $r=0.9967$ なので $\kappa=601$、 相関の弱い降水日数との組($r=-0.375$)の $\kappa=2.2$ と比べ、 同じ 47 点・同じ 2 次元なのに勾配降下の反復数は 5,410 回 vs 23 回と約 235 倍の差になります。
実測に使った要点コード(数値は下記で再現できます):
📝 補足: 本節の数値はすべて data/raw/SSDSE-B-2026.csv(2023 年・47 都道府県)からの実測値です。 なお「条件数」を単独で扱う用語ページは現時点では未作成のため、 詳細は本節と本文の収束理論の節を参照してください。