論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説
📚 用語解説
連続最適化
Continuous Optimization
数理最適化

🔖 キーワード索引

このページで扱う主要キーワード(クリックで該当セクションへ):

凸関数 勾配降下法 ニュートン法 KKT 条件 ラグランジュ乗数 二次計画 QP 線形計画 LP 制約あり最適化 微分可能性 局所最適 収束判定 SSDSE 都道府県回帰

💡 30秒で分かる結論

🍰 まずはやさしく

一番いい値を探すための方法です。

計算で正解を導き出すために使います。

スマホの学習機能などで活用されています。

この章では結論を短くまとめます。

📍 あなたが今見ているもの

🍰 まずはやさしく

数値を細かく調整する計算の手法です。

データ解析の土台として使います。

地域の統計データを分析する時に役立ちます。

この章では全体の流れを整理します。

連続最適化」 (Continuous Optimization) は、 決定変数が実数連続値をとる最適化問題を扱う 数理最適化 の一分野で、 回帰・最尤推定・機械学習の学習など統計/データ解析の中核を支えます(SSDSE-B-2026 のような公的統計データの回帰分析もその一例)。 本ページでは、 まず直感、 次に数式、 そして 47 都道府県の実値で確かめる、 という流れで体系的に整理します。 加えて、 ケーススタディ・FAQ・歴史的経緯・参考文献までを 1 ページに集約し、 用語の「地図」として使えるようにしました。

関連用語(前提・並列・発展)と関連グループ教材も末尾にまとめてあるので、 用語の地図として活用してください。

🎨 直感で掴む

🍰 まずはやさしく

霧の中で谷の底を探すようなものです。

最も低い地点を見つけるために使います。

部活の練習メニューを最適にするイメージです。

この章では直感的な仕組みを解説します。

連続最適化は、 決定変数が 連続実数 である最適化問題を扱う分野です。 「最小二乗で回帰係数を決める」「最尤推定でパラメータを当てはめる」「ニューラルネットの重みを学習する」のは、 すべて連続最適化問題です。

対比として 組合せ最適化は決定変数が 0/1 や順列などの離散値、 たとえば「都道府県をどの 3 クラスタに分けるか」のような問題を扱います。 連続最適化は微分・凸性という強力な道具立てが使えるため、 数値解法は概して洗練されています。

SSDSE の例で言えば、 「新規求職申込件数を 総人口着工建築物数など複数の指標で説明する線形回帰」は、 47 個の県データに対する複数の連続パラメータの最適化問題です。

🎨 直感で掴む — 「霧の中の谷下り」

直感 1: 山と谷

目的関数 $f(x)$ を山と谷の地形と見なす。 最小化は「谷底を見つける」ことに相当。 凸関数は 1 つの谷だけ、 非凸は 複数の谷鞍点(馬の鞍のような形)を持つ。

直感 2: 勾配は最大上昇方向

$\nabla f(x)$ は「その地点から最も急に上る方向」。 最小化したいので に進む ($-\nabla f$)。 学習率 $\eta$ は「一歩の歩幅」。

直感 3: ニュートン法は「地形を 2 次曲線で近似」

勾配だけでなくヘッセ行列で 地形の曲がり方も使う。 「谷の底にある放物線の頂点」を 1 ステップで予測。 ただしヘッセ行列の計算は次元 $n$ の 2 乗、 逆行列は 3 乗で高コスト。

直感 4: SGD は「霧の中を 1 メートルずつ進む」

全データの勾配 = 「視界が良い」、 SGD = 「視界 1 メートル」。 細かく見える分だけ 振動するが、 平均的には正しい方向に進む。 ノイズが鞍点脱出に役立つ。

直感 5: モメンタムは「ボールが転がる慣性」

単純な GD は 各ステップで方向リセット。 モメンタムは「過去の方向を記憶」して谷の長軸方向に加速。 物理的にはエネルギー保存とぶつかった壁での跳ね返りに似る。

🎨 連続最適化を視覚で掴む — 3 枚の図で景観を理解する

最適化アルゴリズムを「式」だけで理解するのは難しい。 「ボールが谷を転がる」「霧の中で坂を下る」といった景観メタファーが、 アルゴリズム選択の直感を強化する。 ここでは SSDSE-B-2026 の都道府県データから生成できる 3 つの典型的なロスランドスケープを通じて、 最適化が「何を相手にしているか」を視覚化する。

図 1: 散布図 — 損失関数の入力データ

SSDSE-B-2026 の特徴量と目的変数の散布図

SSDSE-B-2026 の都道府県 47 点を散布図に並べると、 各点は「最適化アルゴリズムが当てはめようとする直線・曲線が通るべき目標」になる。 線形回帰の二乗誤差を最小化する最適化は、 この散布図に最もよくフィットする直線を求める。 点が直線的なら凸の良条件問題、 ばらつきが大きければ条件数が悪化する。

図 2: ヒストグラム — 総人口の分布

SSDSE-B-2026 総人口の分布ヒストグラム

SSDSE-B-2026 の 47 都道府県の総人口をヒストグラムにすると、 少数の大都市県が右に長い裾を引く強い右歪みの分布になる。 このように入力データや残差の分布が歪んでいると、 二乗誤差を最小化する最適化は裾の大きな値に引っ張られやすい。 分布が正規に近ければ最小二乗法が適切、 裾が重ければロバスト回帰 (Huber loss、 LAD) を選ぶ。 二乗誤差は正規分布の最尤推定、 絶対誤差はラプラス分布の最尤推定に対応する。

図 3: グループ別箱ひげ図 — カテゴリ変数の影響

KMeans クラスタ別 一般診療所数の箱ひげ図

都道府県を KMeans で分けたクラスタごとに一般診療所数を箱ひげ図にしたもの。 クラスタ間で中央値・分散が大きく異なる場合、 階層ベイズや混合効果モデルが必要になり、 最適化問題の次元と非凸性が一気に増す。 単純な OLS の凸問題 → 混合効果モデルの非凸問題、 と問題の難しさが構造的に変わる例。

📝 連続最適化マスターまとめ — 「これだけ覚えれば実務で困らない」7 原則

  1. 標準化は最適化の前提: 条件数を下げるだけで反復回数が桁違いに減る。 「学習率を下げて凌ぐ」前に StandardScaler。
  2. 凸性が選択肢を決める: 凸なら閉形式 / BFGS で安心、 非凸なら multi-start / SGD / 大域最適化が必要。
  3. 規模で手法を切り替える: 変数 100 以下はニュートン、 1 万以下は BFGS、 100 万以上は SGD/Adam。
  4. 制約は SLSQP / trust-constr: ペナルティ法より厳密で堅実。 cvxpy も凸問題なら 1 行で済む。
  5. 収束判定は勾配ノルム + 目的関数差: 「success=True」だけを信用しない。 結果を別の初期値・別の手法で再現確認。
  6. 微分が無いなら Nelder-Mead / BayesOpt: 数値微分でも動くが、 計算回数 × 関数評価コストで詰む。
  7. 深層学習は AdamW + cosine schedule + warmup: 2020 年代の事実上の標準。 SGD+momentum も画像系で根強い。

❓ 実務で頻出する FAQ 15 連発

Q. SGD と勾配降下の違いを 1 文で言うと?

勾配降下は全データで勾配を計算、 SGD は 1 サンプル (またはミニバッチ) ごとに勾配を計算。 SGD の方が 1 反復が安いが、 推定勾配にノイズが乗るため振動する。

Q. なぜ深層学習の学習率は 1e-3 あたりが多い?

Adam の規定値が 1e-3 で、 多くの研究がこれをベースラインに調整するため。 SGD なら 0.01 ~ 0.1 が標準。 オーダーが違うのは適応学習率の有無による。

Q. scipy.optimize.minimizescipy.optimize.least_squares の使い分けは?

一般的な最適化なら minimize。 目的関数が「残差ベクトルの二乗和」の形なら least_squares (Levenberg-Marquardt) が劇的に速い。 非線形回帰の標準ツール。

Q. 「収束しない」と言われたらまず何を疑う?

(1) 学習率が大きすぎる、 (2) 特徴量未標準化、 (3) 目的関数が NaN/Inf を返す、 (4) 勾配の符号が逆 (符号バグ)、 (5) 数値微分の刻み幅が大きすぎる、 の順で疑う。

Q. L-BFGS の "L" は何?

Limited-memory の L。 通常の BFGS は O(n²) のメモリ消費だが、 L-BFGS は過去 m 回 (通常 m=10) の勾配差分だけを保持して O(mn) に抑える。 大変数問題のデファクト。

Q. Adam と AdamW の違いは?

Adam は L2 正則化を勾配に加える (適応学習率に影響)。 AdamW は重み減衰を「適応学習率の外側」で別に引く。 後者が理論的にも実験的にも汎化性能で優位。 Transformer 系は AdamW が標準。

Q. 勾配降下と Newton 法、 どちらが「正しい」?

どちらも局所最適へ向かう正しいアルゴリズム。 違いは「1 ステップの情報量」と「1 ステップのコスト」のトレードオフ。 規模・凸性・微分可能性で正解が変わる。

Q. なぜ非凸関数は局所最適に詰まる?

勾配降下は「下る方向にしか動かない」ため、 一度谷の底に着くと出られない。 谷の高さ (障壁) を越えるには確率的揺らぎ (SGD のノイズ) か熱的揺らぎ (シミュレーテッドアニーリング) が必要。

Q. SSDSE-B-2026 で連続最適化を学ぶメリットは?

47 都道府県 × 約 110 変数という小規模で「全手法をデスクトップで全部動かせる」サイズ感。 大規模実験前のアルゴリズム挙動学習に最適。 実データのため標準化・条件数の影響も体感できる。

Q. 「勾配消失」と「勾配爆発」の違いは?

深い NN で勾配が「(連鎖律で) 何度も掛け算される」結果、 1 未満なら指数的に小さく (消失)、 1 超なら指数的に大きく (爆発) なる。 解決策は ResNet の skip connection、 LayerNorm、 勾配クリッピング。

Q. cvxpy はいつ使う?

凸最適化問題で、 制約や目的関数が複雑な場合。 数式をそのまま Python で書ける DSL (Domain Specific Language)。 ポートフォリオ最適化、 SDP、 Lasso などで標準ツール。 非凸問題には使えない。

Q. 数値微分は使ってよい?

変数が少なく (< 20)、 解析微分が困難ならアリ。 ただし「丸め誤差」と「打ち切り誤差」のバランスで刻み幅 h√(machine eps) ≈ 1e-8 に設定する必要。 自動微分 (autograd, JAX) が使えるならそちらが圧勝。

Q. 自動微分は何が嬉しい?

順方向計算と同じコストで厳密勾配が得られる (逆伝播)。 手計算ミスがなく、 任意の計算グラフに対応。 PyTorch / JAX / TensorFlow の中核機能。 深層学習の急速発展はこれが基盤。

Q. 「再現できない」と言われたら?

乱数シード固定 (numpy, torch, random)、 CUDA deterministic mode、 同じバージョンのライブラリ、 同じバッチ順、 を全部揃える。 それでも GPU 計算は非決定的な場合があり、 完全再現は困難な領域がある。

Q. 連続最適化と組合せ最適化の境目は?

変数が連続実数なら連続最適化、 整数・順列・選択集合なら組合せ最適化。 整数計画 (MILP) は連続緩和 + 分枝限定で解く混合戦略。 学習率は連続、 層数は離散、 という意味で深層学習設計は両者を混在する。

📐 数式・定義

🍰 まずはやさしく

数式を使って正解を出すルールです。

正確な答えを計算するために使います。

買い物で予算内で最高の品を選ぶような仕組みです。

この章では数式や定義について学びます。

もっとも基本的な連続最適化問題は、 制約なし最小化:

【無制約最適化】
$$\min_{\theta\in\mathbb{R}^d}\; f(\theta)$$

$f$ が微分可能なら、 最適性条件 $\nabla f(\theta^\star) = 0$ の解を探す。

【制約付き最適化(一般形)】
$$\min_{\theta}\; f(\theta) \quad\text{s.t.}\quad g_i(\theta)\le 0,\;h_j(\theta)=0$$

解の必要条件は KKT (Karush-Kuhn-Tucker) 条件

$$\nabla f(\theta^\star)+\sum_i \lambda_i^\star \nabla g_i(\theta^\star)+\sum_j \mu_j^\star \nabla h_j(\theta^\star)=0,\;\; \lambda_i^\star \ge 0,\;\; \lambda_i^\star g_i(\theta^\star)=0$$

代表的な数値解法:

【勾配降下法】
$$\theta^{k+1} = \theta^k - \eta\,\nabla f(\theta^k)$$
【ニュートン法】
$$\theta^{k+1} = \theta^k - \bigl[\nabla^2 f(\theta^k)\bigr]^{-1}\nabla f(\theta^k)$$

📐 凸最適化 vs 非凸最適化

凸最適化の定義

関数 $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、 強化学習はすべて非凸。 大域最適は 原理的に保証できないが、 現代の経験則:

📜 連続最適化の歴史

17 世紀 — Newton 法の原型

Newton が方程式 $f(x) = 0$ を解くために $x_{t+1} = x_t - f(x_t)/f'(x_t)$ を提案。 後に最適化の 2 次法に拡張される。

1847 — Cauchy の勾配降下

Augustin-Louis Cauchy が連続関数の最小化に「最急降下法」を提案。 現代の勾配降下法の原典。

1947 — Dantzig のシンプレックス法

George Dantzig が LP のシンプレックス法を考案。 戦後の生産計画・経済モデルで爆発的に利用。

1951 — Karush-Kuhn-Tucker 条件

不等式制約付き最適化の必要条件 (KKT) が確立。 双対理論と並んで凸最適化の基礎に。

1959-1970 — 準ニュートン法 (DFP, BFGS)

Davidon, Fletcher, Powell が DFP 法 (1959)、 Broyden, Fletcher, Goldfarb, Shanno が BFGS (1970) を独立提案。 ヘッセ行列を陽に計算しない準ニュートン法の確立。

1984 — Karmarkar の内点法

Narendra Karmarkar が LP の多項式時間アルゴリズムを内点法ベースで実用化。 CVX, MOSEK などの基礎。

1997 — L-BFGS

Liu と Nocedal が限定メモリ BFGS を提案。 大規模機械学習(数百万パラメータ)の標準ソルバに。

2010s — Adam と適応的学習率

Duchi+ の AdaGrad (2011)、 Tieleman & Hinton の RMSProp (2012)、 Kingma & Ba の Adam (2014) と続く。 深層学習の暴発的進歩を支えた。

2010s-2020s — 大規模凸最適化と ML への融合

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-平滑性と μ-強凸性の定義

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 加速で 1/k² になるのか

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 論文)。

なぜニュートン法は 2 次収束するのか

ニュートン法は 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 で動かして確かめます。

式 ① — 最適化問題の標準形

$$\min_{x \in \mathbb{R}^n} f(x) \quad \text{s.t.} \quad g_i(x) \le 0,\; h_j(x) = 0.$$
記号意味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、 制約なし(無制約最適化)。

式 ② — 一階の最適性条件(勾配ゼロ)

$$\nabla f(x^*) = 0 \quad \Leftrightarrow \quad \frac{\partial f}{\partial x_i}(x^*) = 0 \quad \forall i.$$

言葉に直すと: 「最適解 $x^*$ では、 全方向に向かう傾きがゼロ」。 凸関数ならこれが 大域最小の必要十分条件、 非凸なら局所最小・鞍点・極大の 必要条件(十分ではない)。 二階条件 ヘッセ行列が正定なら極小、 鞍点なら符号混在。

式 ③ — 勾配降下法(最も基本のアルゴリズム)

$$x_{t+1} = x_t - \eta \nabla f(x_t).$$
記号意味
$x_t$反復 $t$ ステップ目のパラメータ
$\nabla f(x_t)$$x_t$ における勾配(最大上昇方向)
$\eta$学習率(ステップサイズ)
$-\nabla f$「下り坂」方向

言葉に直すと: 「現在地点から、 勾配と 逆向きに学習率 $\eta$ だけ進む」。 山の頂で霧に包まれて視界が悪くても、 足元の傾きを感じて 少しずつ下るイメージ。 $\eta$ を大きくしすぎると 谷を飛び越える、 小さすぎると 永遠に着かない

式 ④ — ニュートン法(2 次の情報を使う)

$$x_{t+1} = x_t - H_f(x_t)^{-1} \nabla f(x_t), \quad H_f = \nabla^2 f.$$

言葉に直すと: 「勾配だけでなく ヘッセ行列の逆行列を掛けて方向と歩幅を決める」。 凸関数なら 2 次収束(1 ステップで桁数倍)、 ただしヘッセ行列の計算と逆行列が高コスト。 大規模問題では BFGS のような 準ニュートン法(ヘッセ行列を近似)が現実解。

式 ⑤ — 確率的勾配降下 (SGD)

$$x_{t+1} = x_t - \eta \nabla f_i(x_t), \quad i \sim \mathrm{Uniform}(1,\ldots,N).$$

言葉に直すと: 「データ全部の勾配ではなく、 ランダムに 1 件(または小バッチ)の勾配で更新」。 全件計算が重い深層学習でほぼ必須。 確率ノイズが入ることで 鞍点を脱出しやすいという思わぬ利点も。 Adam, RMSProp, AdaGrad などの拡張版が現代の標準。

🧮 実値で計算してみる(SSDSE-B-2026)

実値計算:SSDSE で「総人口 → 新規求職申込件数」の最小二乗回帰

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$ で、 おおむね

  • 傾き $b \approx 0.0183$(単位:件 / 人 ≈ 1.83 万件 / 100 万人)
  • 切片 $a \approx 1.19$ 万件
  • つまり「総人口が 100 万人多い県ほど新規求職申込が約 1.83 万件多い」 という強い線形関係。 $R^2 \approx 0.94$。

この回帰問題は形式上、 凸 2 次計画 (QP) です。 制約を $b\ge 0$ と加えても閉形式は崩れますが、 KKT で解けます。

🧮 SSDSE-B-2026 実装 1: 勾配降下で線形回帰を解く

🎯 このコードでやること: SSDSE-B-2026 から 2023 年 47 県の総人口 (A1101) と新規求職申込件数(一般, F3101)を取得し、 勾配降下法を手書きで 100 イテレーション回して回帰係数 $a$ を求める。 学習率 $\eta=0.1$ で標準化空間 → 元スケールに復元。 解析的 OLS 解と一致を確認。

📥 入力データ(SSDSE-B-2026, 2023 年 47 行):

Prefecture A1101 (総人口) F3101 (新規求職申込件数) 東京都 14,086,000 270,954 大阪府 8,763,000 203,553 鳥取県 537,000 15,329 (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}")

📤 実行結果:

iter 1: a=0.19361 b=-0.00000 loss=0.662647 iter 2: a=0.34849 b=0.00000 loss=0.446742 iter 6: a=0.71427 b=0.00000 loss=0.127306 iter 11: a=0.88488 b=0.00000 loss=0.069824 iter 51: a=0.96802 b=0.00000 loss=0.062909 iter 100: a=0.96803 b=0.00000 loss=0.062909 解析解 OLS: a=0.968035 loss=0.062909 元スケール: house = 0.018345 × pop + 11866.94

💬 結果の読み方: $\eta=0.1$ で 50 イテレーション程度で 解析解 OLS と 5 桁一致。 元スケール係数 $a = 0.018345$ は「総人口 100 万人につき新規求職申込 18,345 件」と読める実用的な解釈。 $b = 11{,}867$ は基準切片(人口ゼロでの仮想的な件数)で、 そのままでは意味を持たないが回帰式の数学的構成要素。 勾配降下の iter ごとの loss 単調減少が確認でき、 凸関数で安定収束する基本パターン。

🧮 SSDSE-B-2026 実装 2: 学習率の効果を可視化(発散と収束)

🎯 このコードでやること: 同じ 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 '収束'}")

📤 実行結果:

η= 0.01: a= 0.839654 loss=0.079391 収束 (遅い) η= 0.10: a= 0.968035 loss=0.062909 収束 (最適) η= 0.50: a= 0.968035 loss=0.062909 収束 (許容) η= 1.05: a=-13339.140335 loss=177958491.378869 収束

💬 結果の読み方: $\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 実装 3: scipy.optimize.minimize で 6 手法を比較

🎯 このコードでやること: 同じ 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}")

📤 実行結果(概略):

BFGS : theta=[0.968 0.000] nit= 2 nfev= 3 fun=0.062909 Nelder-Mead : theta=[0.968 0.000] nit= 53 nfev=104 fun=0.062909 CG : theta=[0.968 0.000] nit= 2 nfev= 3 fun=0.062909 Powell : theta=[0.968 0.000] nit= 3 nfev= 81 fun=0.062909 L-BFGS-B : theta=[0.968 0.000] nit= 2 nfev= 3 fun=0.062909

💬 結果の読み方: 全手法が同じ最適値 (loss=0.0629) に到達。 BFGS / L-BFGS-B / CG が 2 イテレーション・3 関数評価で爆速(2 次の情報を使う準ニュートン法の威力)。 Nelder-Mead は勾配を使わないので 53 イテ・104 評価とほぼ 40 倍遅い。 ただし Nelder-Mead は 微分不能関数や離散制約でも動くロバスト性が魅力。 本番では「滑らかな凸 → BFGS、 ノイジーな目的関数 → Nelder-Mead」と使い分けるのが定石。

🧮 SSDSE-B-2026 実装 4: 確率的勾配降下 (SGD) とバッチ勾配の比較

🎯 このコードでやること: 同じ 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 最終: a=0.968021 (50 iter) SGD 最終: a=1.040439 (5 epochs × 47 = 235 step) SGD 終盤 10 step: a 軌道 [1.0151, 1.0976, 1.1384, 1.1289, 1.0284, 0.9385, 0.9045, 1.0659, 0.8735, 1.0404] 振動

💬 結果の読み方: 全バッチ 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)$高コスト関数

選択フロー

  1. 関数は滑らか? 微分可能? → Yes へ。 No なら Nelder-Mead / SA / GA
  2. 凸関数? → Yes なら BFGS / L-BFGS / CG。 No へ進む
  3. 非凸 + 大規模 ML? → Adam / SGD + Momentum
  4. 関数評価が極端に高コスト (実験・シミュレーション)? → ベイズ最適化
  5. 離散最適化が混じる? → 分枝限定法 / 整数計画法

🧮 SSDSE-B-2026 実装 5: 制約付き最適化(線形制約の取り扱い)

🎯 このコードでやること: SSDSE-B-2026 の 8 地方人口を「予算 1000 を割り振る」最適化問題に変換。 各地方の人口に応じて重みを最大化したいが、 非負制約と総和制約を満たさなければならない。 scipy.optimize.minimizeSLSQP 法で解く。

📥 入力データ: 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}")

📤 実行結果(概略):

最適配分 (合計 1000): 関東: 350.03 (人口 43,527,000) 近畿: 176.84 (人口 21,990,000) 中部: 166.86 (人口 20,749,000) 九州: 112.82 (人口 14,029,000) 東北: 66.89 (人口 8,318,000) 中国: 56.85 (人口 7,070,000) 北海道: 40.95 (人口 5,092,000) 四国: 28.77 (人口 3,578,000) 総和: 1000.00 目的値: -5.1121

💬 結果の読み方: 最適配分は 人口シェアにほぼ正確に比例(数学的に $x_i^* = 1000 \cdot w_i$ が KKT 条件の最適解)。 関東 350 ≒ 人口シェア 35.0%、 四国 28.77 ≒ 2.88% という具合。 これは 等式制約 (Σ=1000)不等式制約 (各 x ≥ 1)凹目的関数の最大化を SLSQP が同時に解いた結果。 予算配分・ポートフォリオ最適化・在庫割当などの基本パターンで、 SSDSE 実データに適用できることを示している。

🧮 SSDSE-B-2026 実装 6: モメンタム付き勾配降下

🎯 このコードでやること: 同じ線形回帰問題で、 単純な勾配降下と モメンタム付き勾配降下 の収束を比較する。 モメンタムは「過去の更新方向を慣性として保持」することで、 谷の長軸方向に加速し、 振動を抑える。 深層学習の 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")

📤 実行結果:

通常 GD (30 iter, η=0.05) : a=0.926998 loss=0.064593 Momentum GD (30 iter, η=0.05, μ=0.9): a=1.162198 loss=0.100609 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 実装 7: 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 iter 1: a=0.100000 loss=0.816393 Adam iter 5: a=0.491613 loss=0.289886 Adam iter 10: a=0.918973 loss=0.065316 Adam iter 25: a=1.128902 loss=0.088787 Adam iter 50: a=0.984470 loss=0.063179

💬 結果の読み方: 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 実装 8: ロジスティック回帰の数値最適化

🎯 このコードでやること: 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}")

📤 実行結果(概略):

ラベル分布: 正例 10 / 負例 37 最適 (a, b) = [-1.49334109 -1.82767074] 最終 NLL = 0.393702 nit=7 nfev=8 訓練精度: 0.7872

💬 結果の読み方: 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)$学習率スケジュール

即実装パターン

🧮 SSDSE-B-2026 実装 9: 条件数の実測 — 標準化の威力を数値で確認

このコードでやること: SSDSE-B-2026 の総人口・着工建築物数・新規求職申込件数・合計特殊出生率を特徴量とする線形回帰について、 X^T X の条件数(最大固有値 / 最小固有値)を「標準化前」「標準化後」で比較し、 勾配降下の収束レートが何倍変わるかを示す(桁が大きく異なる列が混ざると条件数が悪化する点に注目)。

📥 入力データ (SSDSE-B-2026, 2023 年 抜粋):

都道府県 A1101(総人口) C3301(着工建築物数) F3101(新規求職) A4103(出生率) 北海道 5,092,000 15,872 156,458 1.06 東京都 14,086,000 41,817 270,954 0.99 大阪府 8,763,000 25,017 203,553 1.19 沖縄県 1,468,000 5,217 43,877 1.60
 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} 倍")

📤 実行すると次の出力が得られる:

標準化前 κ(X^T X) = 3.126e+13 標準化後 κ(X^T X) = 2.528e+02 収束ステップ数の比: 1.236e+11 倍

💬 標準化前の条件数は 10¹³ 桁 (総人口 10⁶ と出生率 10⁰ の比が桁外れに大きい)。 強凸の線形収束レートは (1-1/κ)^k なので、 同精度に達するイテレーション数は条件数比で増える。 標準化後も κ ≈ 10² 残るのは特徴量間の相関(多重共線性)に由来するが、 標準化前より 11 桁改善している。 標準化を「前処理の慣習」と捉えず、 収束理論の必須条件と理解する根拠がここにある。

🧮 SSDSE-B-2026 実装 10: 学習率自動調整(ライン探索)の効果

このコードでやること: SSDSE-B-2026 の多変量回帰で、 (a) 固定学習率 η = 0.01、 (b) Armijo ライン探索(バックトラッキング)を比較し、 同じ反復回数での損失減少幅を測る。 Armijo は「目的関数が十分減るまで η を半分にし続ける」単純戦略で、 学習率調整の手間を消す。

📥 入力データ (SSDSE-B-2026 抜粋、 標準化済み 47 都道府県):

特徴量: A1101 総人口 / C3301 着工建築物数 / A4103 合計特殊出生率 (標準化済 z-score) 目的変数: F3101 新規求職申込件数 (標準化済) サンプル数: 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}")

📤 実行すると次の出力が得られる:

固定 η=0.01, 100 iter 後の損失: 0.100683 Armijo, 100 iter 後の損失: 0.050116

💬 Armijo は同じ 100 反復で固定学習率の約半分の損失に達する。 固定学習率は「安全な小さい値」を選ばざるを得ないが、 ライン探索は各ステップで適切な大きさを自動選択する。 scipy.optimize.minimize の BFGS / L-BFGS-B はすべて内部で Wolfe 条件付きライン探索を実装しているため、 「学習率を渡さなくても安定して収束する」のはこの仕組みのおかげ。

🧮 数式に値を入れて手で計算する: 最急降下法 1 step

f(x)=x²-4x+5 の最急降下で 1 step 更新する。

Step 1: f と勾配

f(x) = x² - 4x + 5 f'(x) = 2x - 4 最適解: x* = 2 (f'=0)

Step 2: 初期値 x₀=5, 学習率 lr=0.3

f(5) = 25-20+5 = 10 f'(5) = 2·5-4 = 6 x₁ = x₀ - lr · f'(x₀) = 5 - 0.3·6 = 5 - 1.8 = 3.2

Step 3: 1 step 後

f(3.2) = 10.24 - 12.8 + 5 = 2.44 誤差 |x₁ - x*| = |3.2 - 2| = 1.2 (初期 3 → 1.2 に減少)

🐍 Python で再現

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}")

📤 実行結果

f(x₀)=10.0, f'(x₀)=6 x₁ = 3.2 f(x₁) = 2.4400

💬 手計算 (Step 2,3) x₁=3.2 / f(x₁)=2.44 と Python 出力が完全一致。

🐍 Python 実装

例 1:scipy.optimize.minimize で非凸関数を解く

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)
📤 実行例(実測) [0.99999162 0.9999832 ] 7.040611147966066e-11

例 2:cvxpy で制約付き凸最適化(凸 QP)— SSDSE の制約付き回帰

 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)

例 3:scikit-learn で正則化付き回帰(連続凸最適化の代表)

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 SSDSE-B-2026(年度) A1101(総人口) A1301(15歳未満人口) A1303(65歳以上人口) F3101(新規求職申込件数(一般)) 北海道 2,023 5,092,000 514,000 1,681,000 156,458 東京都 2,023 14,086,000 1,513,000 3,205,000 270,954 沖縄県 2,023 1,468,000 236,000 350,000 43,877 …(全 47 行)
 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_)
📤 実行例(実測) 回帰係数: [ 2.02531162 -2.08485414 -2.01293845 -1.95611902] 切片: 5594.667241691168

例 4:勾配降下を手書きで(線形回帰)

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 SSDSE-B-2026(年度) A1101(総人口) F3101(新規求職申込件数(一般)) 北海道 2,023 5,092,000 156,458 東京都 2,023 14,086,000 270,954 沖縄県 2,023 1,468,000 43,877 …(全 47 行)
 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)
📤 実行例(実測) GD 解: [0.89008228 1.88991827]

📂 ケーススタディ・追加実装例

ケース 1:線形回帰 = 凸 2 次計画

最小二乗問題:

$$\min_\beta \|y - X\beta\|^2 \quad\Leftrightarrow\quad \beta^\star = (X^\top X)^{-1} X^\top y$$

これは凸 2 次計画 (QP) で、 解析解が存在します。

ケース 2:ロジスティック回帰 = 凸最尤

負の対数尤度を最小化:

$$\min_\beta \sum_i \log(1 + e^{-y_i X_i \beta})$$

勾配は閉形ではないが凸なので、 Newton-Raphson や IRLS で大域最適に収束。

ケース 3:SVM = 凸 QP(双対形)

$$\max_\alpha \sum_i \alpha_i - \tfrac{1}{2}\sum_{ij} \alpha_i \alpha_j y_i y_j K(x_i, x_j),\;\;\text{s.t.}\;\sum_i \alpha_i y_i = 0,\;0\le\alpha_i\le C$$

ケース 4:LASSO = 凸非滑らか最適化

$$\min_\beta \tfrac{1}{2}\|y-X\beta\|^2 + \lambda \|\beta\|_1$$

$\|\cdot\|_1$ が非滑らかなので、 座標降下法・近接勾配法 (ISTA/FISTA) を使う。

ケース 5:ニューラルネット = 非凸連続最適化

重み $W$ について損失 $L(W)$ が高度に非凸。 Adam・AdamW・SGD with momentum が標準。 局所最適より サドル点が問題 という研究もある。

ケース 6:実 SSDSE で勾配降下を試す

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 SSDSE-B-2026(年度) A1101(総人口) F3101(新規求職申込件数(一般)) 北海道 2,023 5,092,000 156,458 東京都 2,023 14,086,000 270,954 沖縄県 2,023 1,468,000 43,877 …(全 47 行)
 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}')
📤 実行例(実測) iter 0: loss=0.0000, theta=[3.02018191e-10 1.50166582e-09] iter 1000: loss=0.0000, theta=[1.12193790e-08 1.84657943e-08] iter 2000: loss=0.0000, theta=[1.18153761e-08 1.83543895e-08] iter 3000: loss=0.0000, theta=[1.18628335e-08 1.83455187e-08] iter 4000: loss=0.0000, theta=[1.18666123e-08 1.83448124e-08]

🪜 ステップバイステップ チュートリアル

チュートリアル:SSDSE で「制約付き回帰」を凸最適化として解く

ステップ 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 単位緩めたときの目的改善」を示す。

🚀 現場での応用シナリオ(8 例)

応用 1:機械学習の学習

$\min_\theta L(\theta)$ — 損失 $L$ を連続パラメータ $\theta$ について最小化。 線形回帰・ロジスティック・SVM・NN すべて。

応用 2:ポートフォリオ最適化

Markowitz の平均-分散最適化。 凸 QP。 制約付き SSDSE 県別投資配分にも応用可。

応用 3:最尤推定

$\hat\theta = \arg\max \log p(D|\theta)$ — 統計推定の中核は連続最適化。

応用 4:強化学習の方策勾配

REINFORCE、 PPO、 SAC — 報酬期待値を最大化する連続パラメータ最適化。

応用 5:ニューラルアーキテクチャ探索 (NAS)

勾配ベース NAS(DARTS)は連続最適化として定式化。

応用 6:制御工学

LQR・MPC — 二次形コスト最小化の連続制御。 自動運転・ロボット制御。

応用 7:構造最適化

建築・機械部品の質量最小化、 強度制約付き。 SQP / 内点法。

応用 8:エネルギーグリッド

発電配分の凸最適化。 LP / QP / 確率計画。

🏋️ 演習問題(8 題)

  1. SSDSE-B-2026 で「総人口 → 新規求職申込件数」 の線形回帰を、 numpy.linalg.lstsq で解け。
  2. 同じ問題を scipy.optimize.minimize(BFGS)で解き、 解析解と比較せよ。
  3. 切片を 0 に固定した「制約付き回帰」 を cvxpy で解け。
  4. 勾配降下法を手書きで実装し、 学習率を 0.001, 0.01, 0.1 で振った結果を比較せよ。
  5. Adam optimizer を numpy で実装し、 同じ問題に適用せよ。
  6. Rosenbrock 関数 (1-x)² + 100(y-x²)² を 5 種類の手法で最小化し、 反復数を比較せよ。
  7. LASSO 回帰 (L1 正則化) を ISTA で実装せよ。 sklearn の Lasso と比較。
  8. Ridge 回帰の閉形式解 $(X^TX + \lambda I)^{-1}X^T y$ を numpy で書け。

⚠️ よくある落とし穴

❌ 局所最適への収束
目的関数が非凸(NN・混合モデル)だと、 初期値次第で局所解に落ちる。 異なる初期値で複数試行し、 最良値を採用、 もしくはグローバル法(差分進化・群知能)を併用。
❌ 勾配の数値不安定性
数値微分で勾配を求めると桁落ちで誤差が大きい。 自動微分(PyTorch・JAX)か解析勾配を使う。
❌ ステップ幅 η の選び方
η が大きすぎると発散、 小さすぎると停止。 Backtracking line search や Adam のような適応学習率が実務的。
❌ 制約の表現ミス
等式 $h=0$ と不等式 $g\le 0$ の符号を間違えると、 解空間そのものがズレる。 数学的に書いてからコードに落とす。
❌ スケーリング
変数のスケールが大きく違うと条件数が悪化し、 1 次法は遅く、 ニュートン法は不安定。 標準化(平均 0・分散 1)してから解く。

❓ よくある質問(FAQ)

Q: 凸とは具体的に何が嬉しい?
A: 局所最適 = 大域最適 が保証される。 つまり「どこから始めても正解に着く」ので、 解法選択も結果解釈もシンプルになる。
Q: 微分不可能な目的関数はどうする?
A: 準勾配 (subgradient)、 近接演算子 (proximal operator)、 座標降下、 ADMM などの分解的手法。 LASSO・Total Variation 正則化はその代表例。
Q: ニュートン法と勾配降下、 どちらが速い?
A: 2 次収束のニュートンが理論的に速いが、 ヘッセ計算とその逆行列が高コスト。 大規模では BFGS・L-BFGS・Adam が現実解。
Q: 学習率はどう決めれば?
A: 損失曲線を見てチューニング。 自動化したいなら Adam・AdamW、 さらに学習率スケジューラ(cosine, step decay)と組合せ。
Q: 最適化と最尤推定の関係は?
A: 最尤推定 = 「対数尤度の最大化」 = 「負対数尤度の最小化」。 つまり統計的推定の中身はほぼすべて連続最適化問題。

📜 歴史と背景

歴史と位置づけ:連続最適化は 17 世紀の微積分(Newton, Leibniz)にまで遡りますが、 現代的な体系化は 20 世紀。 主な節目:

機械学習・統計の 学習は事実上すべて連続最適化問題で、 損失関数の最小化として定式化されます。 凸最適化(Boyd & Vandenberghe, 2004)は本分野の標準教科書。

⚠️ 連続最適化の落とし穴 10 件

❌ 学習率が大きすぎて発散
$\eta > 2/L$ ($L$ はリプシッツ定数) で必ず発散。 損失が単調減少していなければ即 $\eta$ を 1/10 にする。 学習率スケジューリング (warmup → decay) が標準。
❌ 局所最適に捕まる
非凸関数では初期値依存で異なる解。 複数初期値で多重実行、 SGD のノイズ、 シミュレーテッドアニーリングで脱出。
❌ 鞍点で停滞
高次元では鞍点が支配的(Dauphin+ 2014)。 純粋な勾配降下は鞍点で停止するが、 SGD のノイズや Adam の適応学習率で脱出可能。
❌ 勾配の数値不安定 (爆発/消失)
深層ネットで勾配が指数的に爆発/消失。 勾配クリッピング、 バッチ正規化、 残差結合で対処。
❌ スケール未調整
変数のスケールが桁違いだと勾配が偏り、 楕円的に振動。 標準化 (StandardScaler) や対数変換が必須。 SSDSE 人口 (10⁵〜10⁷) と出生率 (1〜2) を直接扱うと最適化が破綻する。
❌ 過学習を最適化と混同
訓練 loss を完璧に下げても汎化はしない。 早期停止・正則化 (L2/L1)・dropout を組み合わせる。
❌ ノイジー目的関数で勾配計算
確率的シミュレーションのような目的関数では、 数値微分が安定しない。 Nelder-Mead や CMA-ES、 ベイズ最適化を使う。
❌ 制約の取り扱いを忘れる
$x \ge 0$ や $\sum x = 1$ のような制約は、 ペナルティ項追加、 投影 (projection)、 ラグランジュ未定乗数で処理。 無視すると最適解が制約違反になる。
❌ ヘッセ行列が特異
ニュートン法でヘッセ行列が逆行列を持たない場合、 Levenberg-Marquardt (対角に微小値を足す) や信頼領域法へ。
❌ 早すぎる収束判定
$|f(x_{t+1}) - f(x_t)| < \epsilon$ だけで停止すると、 局所最適 or 鞍点で誤判定。 勾配ノルム $\|\nabla f\| < \epsilon$ も併用。

🗺 学習ロードマップ

🗺 学習ロードマップ

  1. レベル 1 — 関数の最小値・最大値、 1 次微分による停留点。
  2. レベル 2 — 多変数の偏微分、 勾配ベクトル、 ヘッセ行列。
  3. レベル 3 — 凸性の判定、 KKT 条件、 ラグランジュ乗数。
  4. レベル 4 — 勾配降下、 Newton 法、 BFGS。 SciPy/CVXPY の API。
  5. レベル 5 — 確率的勾配降下 (SGD)、 Adam、 学習率スケジュール、 NN の学習。
  6. レベル 6 — 双対性、 内点法、 SDP、 ADMM、 Frank-Wolfe、 鞍点問題、 ミニマックス最適化。

📊 比較表(兄弟手法・選択肢)

主要解法の比較

手法必要情報収束適用
勾配降下1 次勾配線形NN, 大規模 SGD
Newton-Raphson1+2 次2 次低次元、 凸
BFGS / L-BFGS1 次のみ準 2 次中次元、 凸
共役勾配1 次準 2 次巨大スパース
内点法1+2 次多項式時間LP / QP / SDP
シンプレックス線形構造有限LP
Adam1 次 + 履歴準 1 次NN
SGD with momentum1 次 + 慣性確率的NN, 大規模
近接勾配 (ISTA)1 次 + 近接線形LASSO

📖 用語ミニ辞典

用語意味
目的関数最小化/最大化する関数
決定変数最適化する変数
制約変数が満たすべき条件
勾配関数の 1 階偏微分ベクトル
ヘッセ2 階偏微分行列
凸関数局所最適 = 大域最適となる関数
KKT 条件制約付き最適性の必要条件
ラグランジュ乗数制約の影付き価格
双対問題主問題の下界を与える別問題
Newton 法2 次情報を使う反復法
勾配降下1 次情報のみで進む反復法
Adamモメンタム + 適応学習率の SGD 系

🍳 コードレシピ(コピペ用 15 連発)

レシピコード
scipy.optimize.minimize
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import numpy as np

# 最小化する関数と出発点。ここでは 2 変数のよくある試験関数(Rosenbrock)
def f(v):
    x, y = v
    return (1 - x) ** 2 + 100 * (y - x ** 2) ** 2
x0 = np.array([-1.2, 1.0])

from scipy.optimize import minimize
res = minimize(f, x0, method='BFGS')
勾配を渡す
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 凸最適化
1
2
import cvxpy as cp
x = cp.Variable(); prob = cp.Problem(cp.Minimize(cp.square(x-3))); prob.solve()
最小二乗解析解
beta, *_ = np.linalg.lstsq(X, y, rcond=None)
Ridge
1
2
from sklearn.linear_model import Ridge
Ridge(alpha=1.0).fit(X, y)
Lasso
1
2
from sklearn.linear_model import Lasso
Lasso(alpha=0.1).fit(X, y)
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 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import pandas as pd
from sklearn.preprocessing import StandardScaler

# 分類なので y は「クラス」でなければならない(連続値だと Unknown label type)
_d = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
_d = _d[_d['SSDSE-B-2026'] == 2023].reset_index(drop=True)
X = StandardScaler().fit_transform(_d[['A1301', 'A1303', 'A4101']].astype(float))
y = (_d['A1101'] >= _d['A1101'].median()).astype(int)   # 人口が中央値以上か

from sklearn.linear_model import LogisticRegression
LogisticRegression().fit(X, y)
ロス関数勾配の自動微分
1
import jax; grad_f = jax.grad(f)
PyTorch Adam
opt = torch.optim.Adam(model.parameters(), lr=1e-3)
SciPy linprog (LP)
1
2
3
4
5
6
7
8
9
import numpy as np

# 線形計画の材料。min c^T x  s.t. A x <= b
c = np.array([-3.0, -2.0])                 # 最大化したいので符号を反転
A = np.array([[1.0, 1.0], [2.0, 1.0]])
b = np.array([4.0, 6.0])

from scipy.optimize import linprog
res = linprog(c, A_ub=A, b_ub=b)
基底ニュートン法
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 多重初期値探索

scipy.optimize.minimize の method 引数早見表

method 勾配 Hessian 制約 主用途
Nelder-Mead不要不要なし微分なし関数
Powell不要不要なし微分なし、 中変数
CG必要不要なし大変数、 メモリ節約
BFGS必要不要なし中規模、 標準
L-BFGS-B必要不要境界のみ大規模、 デファクト
Newton-CG必要推奨なしHessian 利用
SLSQP推奨不要等式/不等式制約付き標準
trust-constr必要推奨汎用最新・高精度

🚫 連続最適化にまつわる 10 の誤解 — 「常識」を疑う

誤解 1: 「Adam を使えば学習率調整は不要」

Adam は学習率に対するロバスト性が高いだけで、 オーダーは依然として重要。 η = 10⁻¹10⁻⁵ では結果が大きく違う。 経験則は 1e-3 から開始し、 ロスが減らなければ 1/10、 振動すれば 1/3。

誤解 2: 「収束 = 大域最適到達」

非凸関数では「勾配ノルム ≈ 0」は局所最適、 鞍点、 高次の停留点のいずれの可能性もある。 大域最適の保証には凸性、 または大域最適化ラッパー(differential_evolution 等)が必要。

誤解 3: 「学習率を小さくすれば安全」

安全だが、 過小学習率は (a) 浅い局所最適から脱出できない、 (b) 鞍点近傍で停滞、 (c) 計算時間が爆発、 の 3 つの罠がある。 適切な大きさ(条件数で言えば 1/L 程度)が「速度と安全のスイートスポット」。

誤解 4: 「データが多いほど SGD が有利」

SGD はサンプル数 N に対し 1 epoch のコストが O(N) で、 一見データが多いほど SGD が有利。 しかし「同じ精度に達する勾配計算回数」は SGD の方が多い (O(1/√k) vs バッチの O(1/k))。 N が大きくバッチ計算が一括で済むなら、 L-BFGS の方が総合的に速いことも多い。

誤解 5: 「ニュートン法は常に最速」

収束の局所漸近レートは 2 次で最速だが、 1 ステップあたりの計算量は O(n³)。 変数 1000 個なら 10⁹ 演算 / イテレーション、 L-BFGS の数千倍重い。 実務では「変数 100 個まで」が目安。

誤解 6: 「凸関数なら何で解いても結果は同じ」

最適解は同じだが、 計算時間・数値安定性・実装手間が異なる。 SSDSE-B-2026 規模なら閉形式が圧勝、 N=10⁵ なら L-BFGS、 N=10⁹ なら SGD と、 規模で正解が変わる。

誤解 7: 「正則化は最適化と独立」

L1 正則化(Lasso)は微分不可点を持つため、 BFGS / Newton で正しく動かない。 座標降下や近接勾配法が必須。 L2(Ridge)は滑らかなので全手法が使える。 「正則化項の性質」と「最適化手法の選択」は連動する。

誤解 8: 「ハイパーパラメータ最適化も連続最適化」

バッチサイズ・層数などは離散、 学習率は連続だが「目的関数」が訓練ループ全体(数時間)。 関数評価が高コストかつノイジーなため、 グリッド / ランダム探索 / ベイズ最適化が標準。 通常の連続最適化アルゴリズムは適用不可。

誤解 9: 「early stopping は最適化の失敗」

機械学習文脈では訓練ロスを「途中で止める」のがしばしば最適。 訓練ロスは下がり続けても汎化ロスは上昇する(過学習)ため、 検証ロスが最小の時点で打ち切るのが正解。 「収束させきる」が常に良いわけではない。

誤解 10: 「最適化の結果は決定的」

SGD / Adam は乱数(バッチサンプリング、 初期重み)に依存するため、 同じコード・同じデータでも実行ごとに最終解が異なる。 再現性確保には np.random.seedtorch.manual_seed、 CUDA の deterministic mode を全部固定する必要がある。

🚀 現場ケース集 — 連続最適化が解いている社会課題

教科書だけでは「アルゴリズムは分かったが、 何に使うのか」が見えにくい。 ここでは SSDSE-B-2026 を含む実データ問題で連続最適化が現にどう使われているかを 8 ケース紹介する。 各ケースには「目的関数」「変数」「制約」「使用される手法」を明示し、 自分の研究テーマに応用するためのテンプレートとする。

ケース 1: 都道府県別教育予算配分の最適化

SSDSE-B-2026 の各都道府県教育費 (E2101 など) と学力指標を組み合わせ、 限られた中央予算 1 万件を 47 都道府県に配分して全国平均学力を最大化する問題。 目的関数: Σ score_i(budget_i)、 変数: 47 個の予算配分、 制約: Σ budget_i = 10000 億円 かつ budget_i ≥ 最低保障額。 SLSQP で解ける典型例。 限界生産性が逓減する関数を仮定すると、 「現在予算が少ない県ほど多く配分」が最適解となる。

ケース 2: ワクチン配送ルート最適化

47 都道府県のワクチン需要 (人口 ・ 高齢化率から算出) と物流コストを目的関数化。 連続変数として「各物流拠点 → 各県への配送量」を持ち、 制約は (a) 各拠点の供給上限、 (b) 各県の需要充足、 (c) 配送量 ≥ 0。 線形計画 (scipy.linprog) で大規模問題を 1 秒以内に解く。 災害時の食料・燃料配給にも同じ枠組みで応用される。

ケース 3: 機械学習モデルのハイパーパラメータ探索

勾配ブースティング (XGBoost / LightGBM) の学習率 ・ 木の深さ ・ 正則化強度を SSDSE-B-2026 で交差検証 RMSE を最小化するように調整。 目的関数値は「モデルを訓練して検証スコアを返す」関数 (1 回数秒)。 微分不可で雑音あり。 Bayesian Optimization (scikit-optimize, Optuna) が標準。 グリッド探索より 10 倍少ない評価回数で良い解に到達する。

ケース 4: 株式ポートフォリオ最適化 (Markowitz)

N 銘柄への投資比率 w について、 リスク (分散) を最小化しつつ期待リターンを μ 以上に保つ問題。 目的関数: w^T Σ w (二次関数)、 制約: w^T μ_vec ≥ μ, Σ w_i = 1, w_i ≥ 0。 凸 QP 問題で cvxpy 一行で解ける。 SSDSE-B-2026 の都道府県別経済指標を「資産」とみなすと、 リスク分散投資戦略の入門演習になる。

ケース 5: 画像分類モデル (CNN) の訓練

ResNet50 の 2500 万パラメータについて、 訓練データの分類誤差を最小化。 変数次元 n = 10⁷、 サンプル数 N = 10⁶。 SGD + momentum (momentum=0.9) + cosine learning rate schedule + weight decay。 1 epoch 数分、 200 epoch で訓練完了が標準。 Adam も使えるが最終精度で SGD に劣るため画像分野では非主流。

ケース 6: 大規模言語モデル (LLM) の事前学習

変数次元 10¹¹ (1000 億パラメータ)、 サンプル数 10¹² tokens。 AdamW (Adam + 重み減衰の分離) + warmup → cosine decay の学習率スケジューリング + 勾配クリッピング。 計算リソースが膨大なため、 学習率や warmup steps の調整 1 つで数千万円の計算費用が変わる。 連続最適化の実務インパクトが最大化する領域。

ケース 7: 物理シミュレーションのパラメータ較正

気候モデル / 燃焼シミュレーション / 量子化学計算のパラメータを実測データに合わせる「インバース問題」。 シミュレーション 1 回が分 ~ 時間かかり、 解析的勾配は無い。 Bayesian Optimization、 surrogate model (Gaussian Process)、 Nelder-Mead が標準。 SSDSE-B-2026 規模の小データでも同じ枠組みが応用できる。

ケース 8: 推薦システムの行列分解

ユーザー × アイテムの評価行列 R を 2 つの低次元行列 U, V の積で近似する非凸最適化。 目的関数: ||R - UV^T||² + λ(||U||² + ||V||²)。 U を固定して V を解く → V を固定して U を解く、 の交互最小化 (ALS) で凸部分問題に分解。 Netflix / Spotify / Amazon の主要レコメンドエンジンの基盤。

📖 連続最適化の重要用語ミニ辞典(補強版 25 項)

用語意味
勾配 (gradient)関数の各変数に関する偏微分を並べたベクトル。 最も急な増加方向。
Hessian2 階偏微分の行列。 関数の曲率を表現。 対称行列。
凸関数任意の 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 decayL2 正則化を勾配更新時に直接引く。 過学習抑制。
エポック全訓練データを 1 回通すこと。 数十 ~ 数百エポックが標準。
バッチサイズ1 回の勾配計算で使うサンプル数。 大きいほど安定だが遅い。
学習率スケジューリングepoch ごとに η を変える。 step decay / cosine / warmup。
early stopping検証ロスが改善しなくなったら打ち切る。 過学習回避。
ペナルティ法制約違反を目的関数に大きな項として加える。 単純だが近似的。
ラグランジュ乗数法等式制約付き問題を双対変数で無制約化。 厳密解。
KKT 条件制約付き最適解の必要条件。 ラグランジュ乗数の符号と等式系。
近接勾配法微分不可な正則化項に対応する勾配法拡張。 Lasso の標準。
continuous optimization 微分可能性・凸性 勾配降下 / BFGS 内点法・確率的勾配降下 回帰係数推定 組合せ最適化 最適化問題定式化

🔗 隣接手法への橋渡し

「連続最適化」は実数変数で目的関数を最小化する問題で、 上流の凸性・微分可能性の検証と下流の勾配法・準ニュートン法の選択を切り離すと、 局所最適に落ちるか発散して計算が無駄になる。

上流で凸性・滑らかさを確認し、 並列の勾配降下・準ニュートン (BFGS)・内点法をベンチマークし、 下流で収束判定・ステップサイズ調整を入れれば、 線形回帰の閉形式解から深層学習の確率的勾配降下まで「同じ枠組み」で扱える。

🌳 手法選択フロー

「連続最適化」を実際に使うとき、 何をどう選ぶかを順に判断する。 上から順に答えていくと、 使うべき手法と評価の仕方が決まる。

  1. 目的関数は凸か
    凸なら局所最小=大域最小なので 1 回解けば終わる。 線形回帰の二乗誤差やロジスティック回帰の対数尤度は凸。 非凸なら初期値を変えて何度も解く。
  2. 勾配が計算できるか
    計算できるなら勾配法(最急降下法・準ニュートン法)が速い。 式が複雑なら自動微分に任せる。 勾配が得られないなら、 ネルダー・ミードのような微分を使わない方法へ。
  3. 制約はあるか
    「合計 100%」「非負」のような制約があるなら、 制約付き最適化として解く。 無理に罰則項で表すと、 罰則の重みが結果を左右してしまう。
  4. 収束をどう判定するか
    勾配のノルム、 目的関数の変化量、 反復回数のどれで止めるかを決める。 許容誤差を変えれば「最適解」も変わるので、 報告に書いておく。

連続最適化は「なめらかに動かせる変数」を扱う。 「どの県を選ぶか」のような 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$)

関数: 開始点はグラフをドラッグ
プリセット:
開始点を置いてスタート
k = 0 | x = — | f(x) = — | f'(x) = —

🧭 観察ポイント — 反復過程で何が起きているか

⚠️ 落とし穴 — 学習率の選択と収束判定

このデモが示すように、 勾配降下の成否はほぼ学習率で決まる。 実務では次の 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 倍の差になります。

実測に使った要点コード(数値は下記で再現できます):

import pandas as pd, numpy as np df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) d = df[df['SSDSE-B-2026']==2023] # 2023 年 47 都道府県 z = lambda c: (lambda v: (v-v.mean())/v.std())(pd.to_numeric(d[c]).astype(float).values) X = np.column_stack([z('A1101'), z('A1301')]) # 総人口 と 15歳未満人口, r=0.9967 ev = np.linalg.eigvalsh(2/47 * X.T @ X) print(ev, ev[-1]/ev[0]) # → [0.0066 3.9934] 601.04

⚠️ 落とし穴(重要) — 「標準化したから大丈夫」ではない

❌ 標準化はスケール由来の悪条件しか直せない
StandardScaler は各列を 個別に 伸縮するだけで、 列同士の相関(座標軸に対して斜めに伸びた谷)には手を出せない。 上の実測どおり、 標準化後でも $\kappa=\frac{1+|r|}{1-|r|}$ は残る($r=0.9967$ で $\kappa=601$)。 「標準化したのに収束が遅い」ときは、 学習率ではなくまず説明変数間の相関行列を疑う。
❌ 収束の遅さと係数の不安定さは同じ固有値が原因(多重共線性の最適化的正体)
最小固有値 $0.0066$ の固有ベクトル方向($w_1\approx-w_2$ の方向)では損失がほぼ平坦。 だから勾配降下はこの方向で這うように遅く、 同時に 最適解もこの方向にわずかなノイズで大きく動く。 実測でも、 単相関は総人口 $r=0.968$・15 歳未満人口 $r=0.962$ とどちらも強い正なのに、 重回帰係数は $(1.353,\ -0.386)$ と符号が割れた。 統計学で「多重共線性による係数の不安定化」と呼ぶ現象は、 最適化の言葉では「ヘッセ行列の最小固有値がほぼ 0」という同一の事実の別名である。
❌ 「収束した」の意味が条件数に依存する
強凸なら誤差上界 $\|w-w^\star\|\le\|\nabla f(w)\|/\mu$ が成り立つ。 $\mu=0.0066$ の悪条件問題では、 勾配ノルム $10^{-3}$ で停止しても係数には最大 $10^{-3}/0.0066\approx0.15$ の誤差が残りうる。 同じ停止基準でも $\mu=1.25$ の良条件問題なら誤差は $10^{-3}$ 未満。 停止基準の $\varepsilon$ は「一律の定数」ではなく、 問題の $\mu$ を見て決めるべき量である。

🚀 発展 — 条件数を「直す」3 つの戦略

📝 補足: 本節の数値はすべて data/raw/SSDSE-B-2026.csv(2023 年・47 都道府県)からの実測値です。 なお「条件数」を単独で扱う用語ページは現時点では未作成のため、 詳細は本節と本文の収束理論の節を参照してください。

🔗 関連ページ

多重共線性 標準化 リッジ回帰 Lasso 正則化 固有値 勾配降下法 学習率 線形回帰 数理最適化 組合せ最適化