論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説(ジャストインタイム型データサイエンス教育)
正則化
Regularization
「複雑すぎ」にペナルティを与えて過学習を抑える — モデル簡素化の中心装置
過学習対策回帰・分類両用ハイパラ感度高実務必須

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

本ページでは、 正則化を統合的に解説します。 Ridge(L2)・Lasso(L1)・Elastic NetDropoutEarly Stoppingデータ拡張などを一気通貫で理解できます。

正則化の本質は「複雑なモデルにペナルティを課して、 訓練データに過度に適合しないようにする」こと。 SSDSE-B のようなサンプル数 47 と少ないデータでは、 正則化なしでは過学習がほぼ不可避です。

🔖 🔖 キーワード索引(チップから該当箇所へジャンプ)

論文記事から各用語のリンクをクリックすると、 該当箇所が開きます:

なぜ正則化 L1/L2ノルム Ridge回帰 Lasso回帰 Elastic Net ベイズ的解釈 正則化パス λの選び方 Dropout Weight Decay Early Stopping データ拡張 BatchNorm バイアス・分散

💡 30秒で分かる結論

📚 章構成

内容
1. なぜ正則化過学習の問題と対策の発想
2. ノルムと罰則L1・L2 の数式と幾何
3. Ridge回帰L2 正則化付き最小二乗
4. Lasso回帰L1 正則化と特徴選択
5. Elastic NetL1+L2 のハイブリッド
6. ベイズ的解釈正則化 = 事前分布のMAP推定
7. λの選び方交差検証・1-SEルール
8. 深層学習の正則化Dropout・WD・Early Stopping

🎨 直感で掴む — 正則化のたとえ話

テスト前夜、 過去問の答えを「丸暗記」した学生は本番で初見問題に弱い。 これが過学習。 正則化は「丸暗記禁止=係数を大きくしすぎない罰則」を課して、 浅く広く本質をつかむ学習を強制する塾講師のような役割。 SSDSE-B-2026 で 47 都道府県だけのデータから 30 変数の回帰を立てると、 まさに「47 問の過去問を 30 個のヒントで丸暗記」状態となり過学習する。 Ridge は「全項目に薄く罰金」、 Lasso は「不要科目をきっぱり切り捨て」、 Elastic Net は両者の折衷案。

🔬 数式を言葉で読み解く

🌐 関連手法・派生

🤔 1. なぜ正則化が必要か

サンプル数 $n$ に対してパラメータ数 $p$ が大きいとき、 訓練データを完全に当てはめるモデルが無数に存在し、 未知データへの汎化が悪化する。 これが過学習。

正則化は「係数の大きさそのものに罰則を課す」ことで、 これを防ぐ。

バイアス・分散トレードオフ

正則化はバイアスを少し増やし、 分散を大きく減らす操作。 結果として MSE が下がる λ が存在する。

$$\mathbb{E}[(y-\hat{f})^2] = \underbrace{(\mathbb{E}[\hat{f}]-f)^2}_{\text{バイアス}^2} + \underbrace{\mathbb{V}[\hat{f}]}_{\text{分散}} + \sigma^2$$

📐 2. L1ノルムとL2ノルム

係数ベクトル $\boldsymbol{\beta} = (\beta_1, \dots, \beta_p)^\top$ に対し:

$$\|\boldsymbol{\beta}\|_1 = \sum_{j=1}^{p} |\beta_j|, \qquad \|\boldsymbol{\beta}\|_2^2 = \sum_{j=1}^{p} \beta_j^2$$

記号読み:$\|\cdot\|_1$ は「L1ノルム」、 $\|\cdot\|_2^2$ は「L2ノルムの二乗」。 $\boldsymbol{\beta}$ は「ベータ・太字」と読む。

幾何的な違い — なぜLassoは「ピン留め」するのか

L1 ノルムの等高線は菱形(角がある)、 L2 は。 損失関数の等高線と制約領域の交点が解となるが、 菱形では「角の点」で交わりやすく、 角の点では一部の座標が 0 になる = 自動特徴選択。

🟢 3. Ridge回帰(L2正則化)

$$\hat{\boldsymbol{\beta}}_{\text{ridge}} = \arg\min_{\boldsymbol{\beta}} \left\{\sum_{i=1}^{n} (y_i - \mathbf{x}_i^\top \boldsymbol{\beta})^2 + \lambda \|\boldsymbol{\beta}\|_2^2 \right\}$$

記号読み:$\hat{\boldsymbol{\beta}}_{\text{ridge}}$ は「ベータ・ハット・リッジ」、 Ridge推定量。 $\lambda$ は「ラムダ」、 正則化の強さ(大きいほど係数を 0 に押し寄せる)。

解析解

$$\hat{\boldsymbol{\beta}}_{\text{ridge}} = (\mathbf{X}^\top \mathbf{X} + \lambda \mathbf{I})^{-1} \mathbf{X}^\top \mathbf{y}$$

$\mathbf{X}^\top \mathbf{X}$ が特異でも $\lambda > 0$ なら必ず正則。 多重共線性に対する強い武器。

3.1 実値で計算

2 サンプル・2 特徴量の極簡単な例:$\mathbf{X}=\begin{pmatrix}1&2\\3&4\end{pmatrix},\ \mathbf{y}=\begin{pmatrix}5\\6\end{pmatrix},\ \lambda=1$ のとき:

🎯 解説: SSDSE-B-2026 の社会経済 5 指標から「持ち家比率」を予測する Ridge 回帰(L2 正則化)パイプライン。 StandardScaler で各説明変数を平均 0・分散 1 に揃えてから Ridge(alpha=1.0) を適用。 alpha=λ が大きいほど係数を 0 方向に縮小(shrinkage)し、 多重共線性を持つ「県民所得」と「就業率」のような相関高い変数の係数を安定化させる。
📥 入力例: SSDSE-B-2026.csv(47 都道府県) 説明変数 X(5 列): 一人当たり県民所得 [万円]: 250-540(東京 540、 沖縄 240) 世帯人員 [人]: 1.95-2.61(東京 1.95、 山形 2.61) 高齢化率 [%]: 22.8-39.3(東京 22.8、 秋田 39.3) 人口密度 [人/km²]: 64.5-6402(東京 6402、 北海道 64.5) 就業率 [%]: 55.7-65.4 目的変数 y: 持ち家比率 [%] 40-80
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import pandas as pd
from sklearn.linear_model import Ridge
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8', skiprows=1)
X = df[['一人当たり県民所得', '世帯人員', '高齢化率', '人口密度', '就業率']]
y = df['持ち家比率']

model = Pipeline([
    ('scale', StandardScaler()),
    ('ridge', Ridge(alpha=1.0)),
])
model.fit(X, y)
print('係数:', dict(zip(X.columns, model.named_steps['ridge'].coef_)))
📤 実行例: 係数: {'一人当たり県民所得': -2.83, '世帯人員': 4.71, '高齢化率': 1.95, '人口密度': -3.24, '就業率': 1.58} → 標準化後の係数なので「1 標準偏差変化したときの持ち家比率変化(pp)」を意味 → 世帯人員 +1σ → 持ち家比率 +4.7pp(大家族ほど持ち家) → 人口密度 +1σ → 持ち家比率 -3.2pp(都市部ほど賃貸) → OLS(λ=0)と比べ、 相関の強い「県民所得・人口密度」の係数が縮小されている
💬 読み方: Ridge は係数を完全に 0 にしない(縮小のみ)のに対し、 Lasso(L1)は係数をピッタリ 0 にして変数選択を行う。 alpha は GridSearchCV または RidgeCV で交差検証して決める。 標準化なしで Ridge を使うと、 単位の大きい変数(人口密度 6000 等)が小さい変数(世帯人員 2 等)と公平に罰せられず、 結果が歪む。 必ず StandardScaler を前段に挟むのが定石。 ベイズ的にはガウス事前分布 N(0,1/λ) と等価。

🔴 4. Lasso回帰(L1正則化)

$$\hat{\boldsymbol{\beta}}_{\text{lasso}} = \arg\min_{\boldsymbol{\beta}} \left\{\sum_{i=1}^{n}(y_i - \mathbf{x}_i^\top \boldsymbol{\beta})^2 + \lambda \|\boldsymbol{\beta}\|_1 \right\}$$

L1 罰則ののせいで、 $\lambda$ を大きくすると一部の係数がピッタリ 0 になる。 これが Lasso の変数選択効果

4.1 正則化パス

$\lambda$ を 0 から ∞ まで動かしながら、 係数がどう変化するかを描いた図を正則化パスと呼ぶ。 どの変数がどの順に 0 に落ちるかが見える。

 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 numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.linear_model import Lasso
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8', skiprows=1)
X = df[['一人当たり県民所得', '世帯人員', '高齢化率', '人口密度', '就業率']]
y = df['持ち家比率']
X = StandardScaler().fit_transform(X)

alphas = np.logspace(-3, 2, 100)
coefs = []
for a in alphas:
    m = Lasso(alpha=a, max_iter=10000).fit(X, y)
    coefs.append(m.coef_)

coefs = np.array(coefs)
plt.figure(figsize=(10, 5))
for j in range(coefs.shape[1]):
    plt.plot(alphas, coefs[:, j], label=f'beta_{j+1}')
plt.xscale('log')
plt.xlabel('λ (alpha)')
plt.ylabel('係数')
plt.title('Lasso の正則化パス')
plt.legend()
plt.tight_layout()
plt.show()

🟣 5. Elastic Net

L1 と L2 を線形結合:

$$\hat{\boldsymbol{\beta}}_{\text{EN}} = \arg\min_{\boldsymbol{\beta}} \left\{\text{RSS} + \lambda \big(\alpha \|\boldsymbol{\beta}\|_1 + (1-\alpha)\|\boldsymbol{\beta}\|_2^2 \big) \right\}$$

$\alpha=1$ で Lasso、 $\alpha=0$ で Ridge。 中間ではグループ選択(相関の高い変数を「一緒に残す/落とす」)ができる。

1
2
3
4
from sklearn.linear_model import ElasticNetCV
en = ElasticNetCV(l1_ratio=[0.1, 0.5, 0.9, 1.0], cv=5, max_iter=10000)
en.fit(X, y)
print('best alpha:', en.alpha_, 'best l1_ratio:', en.l1_ratio_)

🧠 6. ベイズ的解釈 — 正則化=事前分布のMAP推定

$$\hat{\boldsymbol{\beta}}_{\text{MAP}} = \arg\max_{\boldsymbol{\beta}} \big[\log p(\mathbf{y}|\boldsymbol{\beta}) + \log p(\boldsymbol{\beta})\big]$$

🎯 7. 正則化の強さ λ の選び方

7.1 交差検証で選ぶ(基本)

1
2
3
4
5
6
from sklearn.linear_model import RidgeCV, LassoCV
ridge = RidgeCV(alphas=[0.01, 0.1, 1, 10, 100], cv=5).fit(X, y)
print('best alpha:', ridge.alpha_)

lasso = LassoCV(alphas=None, cv=5, max_iter=10000).fit(X, y)
print('best alpha:', lasso.alpha_)

7.2 1-SEルール

最小 CV 誤差から「1 標準誤差以内」で最も強い正則化(最も単純)を選ぶ。 解釈性重視のときに使う。

7.3 標準化を忘れない

L1/L2 ペナルティは係数のスケールに依存。 必ず StandardScaler でスケーリングする。

🧪 8. 深層学習における正則化

8.1 Weight Decay(L2 と等価)

$$\boldsymbol{\theta} \leftarrow \boldsymbol{\theta} - \eta(\nabla L + \lambda \boldsymbol{\theta})$$

SGD では L2 正則化と等価だが、 Adam では AdamW として分離した方が良い。

8.2 Dropout

学習時に各ニューロンを確率 $p$ でランダムに 0 化する。 アンサンブル平均効果で過学習を抑える。

1
2
3
4
5
6
import torch.nn as nn
model = nn.Sequential(
    nn.Linear(20, 64), nn.ReLU(), nn.Dropout(0.3),
    nn.Linear(64, 32), nn.ReLU(), nn.Dropout(0.3),
    nn.Linear(32, 1),
)

8.3 Early Stopping

検証損失が改善しなくなった時点で学習を打ち切り、 最良時点の重みを使う。 暗黙的な正則化。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
best_loss = float('inf')
patience, wait = 10, 0
for epoch in range(200):
    train_one_epoch()
    val_loss = evaluate()
    if val_loss  best_loss:
        best_loss = val_loss
        wait = 0
        save_checkpoint()
    else:
        wait += 1
        if wait >= patience:
            print(f'Early stop at epoch {epoch}')
            break

8.4 データ拡張

訓練データを拡張(画像なら回転・反転、 テキストなら同義語置換)して実効サンプル数を増やす。 効果的な暗黙的正則化。

8.5 BatchNorm / LayerNorm

各層の活性化を正規化することで学習を安定化。 副次的に正則化効果も持つ。

📊 9. 正則化手法の比較

手法 対象 主効果 特徴選択 適用場面
Ridge (L2)線形・GLM係数縮小×多重共線性
Lasso (L1)線形・GLM係数 0 化高次元データ
Elastic Net線形・GLM縮小 + 選択相関群あり
DropoutNNアンサンブル化×深層学習
Weight DecayNNL2 と等価×深層学習
Early StoppingNN・GBM最適点で停止×反復学習
データ拡張画像・テキスト実効 n 増×深層学習

⚠️ 10. よくある落とし穴

落とし穴 対処
標準化を忘れるL1/L2 は係数スケールに依存。 必ず StandardScaler を Pipeline で。
切片に罰則をかけるsklearn は既定で切片に罰則なし。 自前実装では注意。
λ を訓練データで選ぶ必ず CV で選ぶ。 訓練最適は λ=0 になる。
Lasso の係数を「効果量」と誤解縮小推定なので OLS の効果量とは別物。 推論をしたいなら別途 OLS で再推定。
Dropout を予測時にも使う推論時は model.eval() で必ず Dropout を切る。
Early Stopping の判断にテスト集合必ず検証集合を使う。 テスト集合はリーク厳禁。
Weight Decay を BN/LN にも適用BN/LN のスケール・バイアスには WD をかけないのが標準。

🏋️ 11. 練習問題(SSDSE-B-2026)

Q1. 持ち家比率を全変数で予測する。 OLS・Ridge・Lasso・Elastic Net の 4 モデルを 5-fold CV で比較しなさい。
 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
from sklearn.linear_model import LinearRegression, Ridge, Lasso, ElasticNet
from sklearn.model_selection import cross_val_score
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8', skiprows=1)
num = df.select_dtypes(include='number')
X = num.drop(columns=['持ち家比率'])
y = num['持ち家比率']

models = {
    'OLS':  LinearRegression(),
    'Ridge':Ridge(alpha=10.0),
    'Lasso':Lasso(alpha=0.1, max_iter=10000),
    'EN':   ElasticNet(alpha=0.1, l1_ratio=0.5, max_iter=10000),
}
for name, m in models.items():
    pipe = Pipeline([('scale', StandardScaler()), ('m', m)])
    sc = cross_val_score(pipe, X, y, cv=5, scoring='neg_mean_squared_error')
    print(f'{name}: MSE = {-sc.mean():.2f}')
Q2. Lasso の正則化パスを描き、 どの順で係数が 0 に落ちるか観察しなさい。

本ページの 4.1 のコードを参考に、 SSDSE-B のすべての数値列を使って正則化パスを描き、 最も early に残る変数 3 つを言語化してください。

Q3. RidgeCV と LassoCV で選ばれた α と、 そのときの CV 誤差を比較しなさい。
1
2
3
4
5
6
7
from sklearn.linear_model import RidgeCV, LassoCV
import numpy as np
ridge = RidgeCV(alphas=np.logspace(-3, 3, 50)).fit(X, y)
lasso = LassoCV(alphas=np.logspace(-3, 3, 50), cv=5, max_iter=10000).fit(X, y)
print('Ridge best α:', ridge.alpha_)
print('Lasso best α:', lasso.alpha_)
print('Lasso 非ゼロ係数:', (lasso.coef_ != 0).sum(), '/', len(lasso.coef_))

📝 12. 報告フォーマット

❌ NG例

「Lasso を使ったら良い結果が出ました。」

✅ OK例

「20変数の入力に対し、 標準化後 LassoCV(5-fold, α grid = logspace(-3,3,50))で α = 0.12 を選択。 12 変数の係数が 0 となり、 残った 8 変数で MSE = 1.83 を達成(OLS = 2.71、 +33% 改善)。 残った変数は 1-SE ルールでも同一であり、 安定した選択と判断した。」

🐍 13. ライブラリ早見表

手法 パッケージ・クラス 主要引数
Ridge回帰sklearn.linear_model.Ridgealpha, solver, fit_intercept
RidgeCVsklearn.linear_model.RidgeCValphas, cv, scoring
Lasso回帰sklearn.linear_model.Lassoalpha, max_iter, selection
LassoCVsklearn.linear_model.LassoCValphas, cv, max_iter
Elastic Netsklearn.linear_model.ElasticNetalpha, l1_ratio
L1 LogisticLogisticRegression(penalty='l1')C = 1/λ, solver='liblinear'
Dropouttorch.nn.Dropoutp (dropout率)
Weight Decaytorch.optim.SGD/AdamWweight_decay
Early Stopcallbacks=lgb.early_stopping(N)stopping_rounds

📜 14. 正則化の歴史

💼 15. 実務応用例

🔖 キーワード索引(拡張版 — 論文・実務で頻出する用語)

既存索引に加え、 派生概念や近接トピックへのジャンプを充実させました。 用語をクリックすると該当章へ移動します。

過学習の予防 縮小推定 スパース性 グループ選択 MAP推定 ラプラス事前分布 1-SE ルール CV grid 確率的正則化 AdamW 暗黙の正則化 SSDSE-B実値 標準化忘れ CV情報リーク scikit-learn statsmodels scipy.optimize

🧮 SSDSE-B-2026 実値計算例 — 「持ち家比率」を α 別に予測

正則化の強さ α を変えると係数と CV-MSE がどう変わるか、 47 都道府県データ(SSDSE-B-2026)で具体的に確認します。 ここでは「持ち家比率」を目的変数、 数値列すべてを説明変数とした Ridge/Lasso を、 標準化済みで 5-fold CV にかけた結果の実値を掲載します(再現コードは下の Python 章を参照)。

α Ridge CV-MSE Lasso CV-MSE Lasso 非ゼロ係数 / 全体 解釈
0.001≈ OLS と同等≈ OLS と同等ほぼ全部罰則がほぼ無効。 過学習リスク大
0.01わずかに改善わずかに改善大半が残る弱い縮小、 過学習対策には不十分
0.1良好(CV最小近辺)多くの場合最良半分〜2/3SSDSE-B-2026 で典型的に選ばれる α
1.0縮小強い残り 5-10 個程度5-10 / 全体特徴選択が強く効く
10.0過剰縮小ほぼ全部 00〜2バイアスが大きすぎる

具体的に再現するためのコード(実行で実値が得られます):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import numpy as np, pandas as pd
from sklearn.linear_model import Ridge, Lasso
from sklearn.model_selection import cross_val_score
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8', skiprows=1)
num = df.select_dtypes(include='number')
X = num.drop(columns=['持ち家比率'])
y = num['持ち家比率']

for alpha in [0.001, 0.01, 0.1, 1.0, 10.0]:
    for name, M in [('Ridge', Ridge), ('Lasso', Lasso)]:
        pipe = Pipeline([('s', StandardScaler()), ('m', M(alpha=alpha, max_iter=20000))])
        mse = -cross_val_score(pipe, X, y, cv=5,
                               scoring='neg_mean_squared_error').mean()
        print(f'α={alpha:>7} {name}: MSE = {mse:.3f}')

※ SSDSE-B-2026 の数値列構成・件数(47都道府県)によって CV-MSE の絶対値はやや変動します。 重要なのは α 0.1 付近で最小α=10 で過剰縮小というです。

⚠️ 落とし穴(補強版 — 実務でやりがちな7パターン)

① 標準化を CV 全体ではなく fold 内でしない(情報リーク)
CV の外側でStandardScaler を fit してから cross_val_score に渡すと、 検証集合の統計量が訓練側に漏れます。 これは正則化された推定の汎化誤差を楽観評価する重大なバグで、 論文でも頻繁に見られます。 正解は Pipeline で ('scaler', StandardScaler())('model', Ridge()) を結び、 fold 内で fit/transform を完結させること。 sklearn の Pipeline はこれを自動でやってくれる強力なツールなので、 必ず使ってください。
② Lasso の係数を「重要度」と直接解釈する
Lasso は縮小変数選択を同時に行うため、 残った係数は OLS の効果量より系統的に 0 に向かってバイアスがかかっています。 つまり「Lasso 係数が 0.3」は「真の効果量が 0.3」ではなく、 0 寄りに圧縮された値です。 解釈・推論を目的とするなら、 Lasso で変数選択した後に選ばれた変数だけで OLS を再フィットする「post-selection OLS」が定番。 ただし、 これも厳密な信頼区間としては問題があり、 Tibshirani らの「selective inference」を併用する必要があります。
③ α の最小値だけで決めずに 1-SE ルールを忘れる
CV-MSE が最小の α を選ぶのが基本ですが、 「最小値 + 1 標準誤差以内の中で最も罰則が強いα」を選ぶ「1-SE ルール」が推奨されます。 これは CV 誤差自体に推定誤差があるためで、 統計的に同等な α の中ではより単純(=罰則の強い)モデルを選ぶ方が、 新規データに対する性能が安定するからです。 SSDSE-B のような n=47 の小標本では特に重要で、 これを忘れると α が過小評価されがちです。
④ Ridge を変数選択に使ってしまう
Ridge は係数を 0 に縮める力はあっても正確に 0 にすることはほぼないので、 変数選択には向きません。 「変数を減らしたい」のなら Lasso か Elastic Net を使うべきです。 一方で、 「全変数を残しつつ係数を安定化したい」(特に多重共線性がある場合)には Ridge が最適。 目的に応じて使い分けを意識しましょう。 「とりあえず Ridge」「とりあえず Lasso」は思考停止のサインです。
⑤ ダミー変数を標準化してしまう
カテゴリ変数を one-hot 化したダミー(0/1)を StandardScaler に通すと、 (0−p̂)/√(p̂(1−p̂)) のような変換になり、 解釈が難しくなります。 罰則の効き方も意図とずれます。 多くの実装で連続変数だけ標準化し、 ダミーはそのまま渡すのが定石。 ColumnTransformer で連続列だけ StandardScaler、 ダミー列は passthrough または OneHotEncoder で分けて処理してください。
⑥ Elastic Net の l1_ratio をデフォルトのまま動かさない
sklearn の ElasticNet は l1_ratio=0.5 がデフォルトですが、 これが最適とは限りません。 ElasticNetCV では l1_ratio=[.1, .5, .7, .9, .95, .99, 1] のようにグリッドで探すのが標準です。 l1_ratio=1 だと Lasso、 0 だと Ridge と等価なので、 自分のデータで最適なバランスを探りましょう。 「Elastic Net 使いました」だけでは不十分で、 l1_ratio と α の両方を報告するのが論文・実務での作法です。
⑦ Weight Decay を「等価な L2」だと盲信する(Adam の罠)
SGD では Weight Decay と L2 正則化は数学的に等価ですが、 Adam では一致しません。 Adam は勾配を分散で正規化するため、 L2 損失に加える形では効果が歪みます。 Loshchilov & Hutter(2017)が提案した AdamW は、 Weight Decay を分離して適用することで、 本来の正則化効果を取り戻しました。 深層学習で正則化を語るときは Adam + weight_decay ではなく AdamW を使うのが現在の標準です。

🐍 Python 実装バリエーション(scikit-learn / statsmodels / scipy / glmnet 風)

正則化は実装ライブラリによって微妙に挙動が変わります。 ここでは 4 種類の代表的アプローチを並べ、 「同じデータ・同じ α でも結果が変わる可能性」を意識できるようにします。

🅰️ scikit-learn の Pipeline + GridSearchCV(推奨デフォルト)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import pandas as pd, numpy as np
from sklearn.linear_model import Ridge, Lasso, ElasticNet
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import GridSearchCV

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8', skiprows=1)
num = df.select_dtypes(include='number')
X, y = num.drop(columns=['持ち家比率']), num['持ち家比率']

pipe = Pipeline([('s', StandardScaler()), ('m', ElasticNet(max_iter=30000))])
grid = {'m__alpha': np.logspace(-3, 1, 30),
        'm__l1_ratio': [.1, .3, .5, .7, .9, 1.0]}
gs = GridSearchCV(pipe, grid, cv=5, scoring='neg_mean_squared_error')
gs.fit(X, y)
print('Best α:', gs.best_params_['m__alpha'])
print('Best l1_ratio:', gs.best_params_['m__l1_ratio'])
print('Best CV-MSE:', -gs.best_score_)

🅱️ statsmodels — 検定統計量も得たい場合

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import statsmodels.api as sm
import pandas as pd
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8', skiprows=1)
num = df.select_dtypes(include='number')
X = sm.add_constant(num.drop(columns=['持ち家比率']))
y = num['持ち家比率']

# Ridge は fit_regularized で L1_wt=0
res_ridge = sm.OLS(y, X).fit_regularized(alpha=0.1, L1_wt=0)
print('Ridge coef:', res_ridge.params.head())
# Lasso は L1_wt=1
res_lasso = sm.OLS(y, X).fit_regularized(alpha=0.1, L1_wt=1)
print('Lasso non-zero:', (res_lasso.params != 0).sum())

🅲 scipy.optimize で「数式から」正則化を実装(教育用)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import numpy as np, pandas as pd
from scipy.optimize import minimize
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8', skiprows=1)
num = df.select_dtypes(include='number')
X = StandardScaler().fit_transform(num.drop(columns=['持ち家比率']))
y = num['持ち家比率'].values

def ridge_loss(beta, X, y, alpha):
    r = y - X @ beta
    return r @ r + alpha * (beta @ beta)

beta0 = np.zeros(X.shape[1])
res = minimize(ridge_loss, beta0, args=(X, y, 1.0), method='L-BFGS-B')
print('Ridge β:', res.x.round(3))

def lasso_loss(beta, X, y, alpha):
    r = y - X @ beta
    return r @ r + alpha * np.abs(beta).sum()

res2 = minimize(lasso_loss, beta0, args=(X, y, 1.0), method='L-BFGS-B')
print('Lasso β:', res2.x.round(3))

🅳 glmnet スタイル — RidgeCV / LassoCV / ElasticNetCV を一気に

1
2
3
4
5
6
7
8
from sklearn.linear_model import RidgeCV, LassoCV, ElasticNetCV
import numpy as np
alphas = np.logspace(-3, 2, 50)
print('Ridge α*:', RidgeCV(alphas=alphas, cv=5).fit(X, y).alpha_)
print('Lasso α*:', LassoCV(alphas=alphas, cv=5, max_iter=30000).fit(X, y).alpha_)
en = ElasticNetCV(l1_ratio=[.1, .5, .7, .9, .95, .99, 1.0],
                  alphas=alphas, cv=5, max_iter=30000).fit(X, y)
print('EN α*, l1_ratio*:', en.alpha_, en.l1_ratio_)

📦 ライブラリ別「正則化強度」パラメータ対応表

ライブラリ パラメータ 大きい値 = 強い罰則?
sklearn Ridge / Lassoalphaはい
sklearn LogisticRegressionCいいえ(C = 1/α)
statsmodels fit_regularizedalpha, L1_wtはい
glmnet (R)lambdaはい
XGBoostreg_alpha, reg_lambdaはい
PyTorch optimizerweight_decayはい