本ページのトピックを 1 タップで移動できます。 「MAE(平均絶対誤差)」を学ぶうえで押さえたい論点はすべてここに集約しました。
MAE (Mean Absolute Error、 平均絶対誤差) は回帰モデルの評価指標で、 予測値と真値の差の絶対値の平均。 RMSE と違って二乗しないため 外れ値の影響を受けにくい。 損失関数として使うと中央値回帰になり、 単位は真値と同じ(円・人)で解釈しやすい。
「MAE の定義 → RMSE/MAPE との使い分け → 損失関数としての性質」を構成する核キーワード。
🍰 まずはやさしく
予測のズレを測る定規のようなものです。
平均的にどれくらい外れたかを知るために使います。
テストの予想点数と実際の点数の差に似ています。
この章ではMAEの基本的な意味を学びます。
予測値と実測値の 絶対差を平均した回帰誤差指標。 目的変数と同じ単位で「平均的にどれくらいズレているか」を示す。
nn.SmoothL1Loss。🍰 まずはやさしく
予測モデルの正しさを判定する指標です。
どの予測方法が一番良いかを選ぶために使います。
スマホの充電持ちの予測精度を比べる時に役立ちます。
他の似た指標との違いについて解説します。
🍰 まずはやさしく
待ち合わせの遅刻時間の平均のようなものです。
予測がどれくらい外れたかを直感的に知るために使います。
部活の練習時間が予想とどれだけズレたかで考えます。
具体的にどう計算して考えるかを説明します。
MAE(Mean Absolute Error、 平均絶対誤差)は、 回帰モデルの予測がどれくらい外れているかを 「外れた量の平均」 で測る指標。 「人口から出生数を予測するモデル」を SSDSE-B-2026 で作ったとき、 47 都道府県それぞれの予測値と実測値の差を絶対値で平均したものが MAE。
日常の比喩でいえば、 MAE は 「待ち合わせの遅刻時間の平均」 に近い。 「2 分早く着いた」も「8 分遅刻した」も 絶対値 で 2 分・8 分として扱い、 平均値 5 分が MAE。 一方、 MSE はこれを二乗するので 4 + 64 = 68、 平均 34 = 「6 分弱の二乗」となり、 大きな遅刻ほど不釣り合いに重く効く。
SSDSE-B-2026(2023 年度、 47 都道府県)で「人口 → 出生数」を線形回帰した場合、 MAE は実測で約 1,100 人になる。 これは「平均的に出生数を ±千人強の精度で当てている」と直感的に解釈できる。 単位が目的変数と同じなので、 ステークホルダーへの報告がしやすい。 たとえば「うちの自治体の出生予測 MAE は 800 人です」と言えば、 政策担当者は「800 人ぶんの保育所準備にバッファを持つ」のように 具体的な意思決定に直結する。
もう少し丁寧に:MAE は「中央値志向」の指標と言われる。 これは MAE 最小化が 条件付き中央値 を推定することと対応しているため。 一方の MSE 最小化は 条件付き平均 を推定する。 「中央値」は外れ値に強く、 「平均」は外れ値に弱い。 この統計的な性質の違いが、 MAE と MSE の振る舞いの違いに直結している。
誤解しやすいポイント:MAE が小さいからといって「モデルが良い」とは限らない。 たとえば「予測 = 全データの中央値」というナイーブなモデルでも、 偏った分布のデータでは意外と低い MAE を出すことがある。 したがって MAE は必ず ベースラインモデル(平均値予測・中央値予測)と比較して評価する。
🍰 まずはやさしく
ズレの大きさを足して平均した数値です。
正確な誤差を計算するために使います。
買い物で予算と実際の金額がどれだけ違うかと考えます。
計算式と他の指標との関係について学びます。
サンプル数 \(n\)、 実測値 \(y_i\)、 予測値 \(\hat y_i\) としたとき、 平均絶対誤差は次で定義される。
$$ \text{MAE} = \frac{1}{n} \sum_{i=1}^{n} |y_i - \hat y_i| $$MSE / RMSE / MAE の関係は次の通り。
$$ \text{MSE} = \frac{1}{n}\sum (y_i - \hat y_i)^2, \quad \text{RMSE} = \sqrt{\text{MSE}}, \quad \text{MAE} \le \text{RMSE} $$不等式 \( \text{MAE} \le \text{RMSE} \) は Cauchy–Schwarz の不等式から従い、 等号成立は 全誤差の絶対値が等しいときのみ。 ばらつきが大きい予測ほど MAE と RMSE の差が広がる。
幾何学的解釈:MAE 最小化は 条件付き中央値 を推定すること、 MSE 最小化は 条件付き期待値 を推定すること。 つまり MAE と MSE はそれぞれ 中央値回帰 と 平均値回帰 に対応する。
MAE 周辺で覚えておくべき主要な数式を一覧。
定義:$$ \text{MAE} = \frac{1}{n}\sum_{i=1}^n |y_i - \hat y_i| $$
MSE:$$ \text{MSE} = \frac{1}{n}\sum_{i=1}^n (y_i - \hat y_i)^2 $$
RMSE:$$ \text{RMSE} = \sqrt{\frac{1}{n}\sum_{i=1}^n (y_i - \hat y_i)^2} $$
不等式(Cauchy-Schwarz):$$ \text{MAE} \le \text{RMSE} $$
R²(決定係数):$$ R^2 = 1 - \frac{\sum (y_i - \hat y_i)^2}{\sum (y_i - \bar y)^2} $$
MAPE:$$ \text{MAPE} = \frac{1}{n}\sum_{i=1}^n \left|\frac{y_i - \hat y_i}{y_i}\right| \times 100\% $$
SMAPE:$$ \text{SMAPE} = \frac{1}{n}\sum_{i=1}^n \frac{2|y_i - \hat y_i|}{|y_i| + |\hat y_i|} \times 100\% $$
Huber 損失:$$ L_\delta(u) = \begin{cases} \frac{1}{2}u^2 & |u| \le \delta \\ \delta(|u| - \frac{1}{2}\delta) & |u| > \delta \end{cases} $$
Quantile 損失:$$ \rho_\tau(u) = u(\tau - \mathbb{1}\{u < 0\}) $$
劣勾配(MAE の最適化用):$$ \partial |u| = \begin{cases} \{1\} & u > 0 \\ [-1, 1] & u = 0 \\ \{-1\} & u < 0 \end{cases} $$
MAE 損失 \( L = \frac{1}{n}\sum|y_i - \hat y_i| \) は、 予測値 \( \hat y_i = y_i \) で微分不可能です。 この点では 劣勾配(subgradient)という拡張概念を使い、 \( \partial_{\hat y} L = -\frac{1}{n}\sum \text{sgn}(y_i - \hat y_i) \) と書きます。 ここで \( \text{sgn}(0) \in [-1, 1] \) は劣勾配の集合です。 確率的勾配降下法(SGD)でこれを使うと、 各ステップで勾配の符号だけが効くため、 学習率を慎重に設定しないと振動します。 実務では PyTorch の nn.L1Loss が MAE 損失で、 内部的には sign 関数で劣勾配を計算しています。
「定数 \( c \) でサンプル \( \{x_1, \dots, x_n\} \) を代表する」最適化問題で \( c^* = \arg\min_c \sum|x_i - c| \) を考えます。 \( c \) の微小変化に対する目的関数の変化は \( \frac{dL}{dc} = -\#\{x_i > c\} + \#\{x_i < c\} \) です。 これが 0 になるのは \( \#\{x_i > c\} = \#\{x_i < c\} \) のとき、 つまり \( c \) が中央値のときです。 一方、 MSE 損失 \( \sum(x_i - c)^2 \) の微分は \( -2\sum(x_i - c) = 0 \) より \( c = \bar x \)(平均)になります。 この対比が「MAE は中央値、 MSE は平均」と呼ばれる所以です。
MAE は分位点回帰(quantile regression)で \( \tau = 0.5 \)(中央値分位点)の特殊ケースです。 一般の分位点 \( \tau \in (0, 1) \) では、 損失関数は \( \rho_\tau(u) = u(\tau - \mathbb{1}\{u < 0\}) \) というピン関数になり、 \( \tau = 0.5 \) のとき \( \rho_{0.5}(u) = 0.5|u| \) となって MAE と比例します。 SSDSE-B-2026 で「90% 分位点回帰」を行えば、 「最悪ケースの予測誤差」を最適化でき、 リスク管理に応用できます。 scikit-learn の QuantileRegressor で実装可能です。
統計量の 影響関数(influence function)とは「1 サンプルを微小に変えたときに推定値がどれだけ変わるか」を表す関数です。 MAE の影響関数は 有界(最大 1)ですが、 MSE の影響関数は 非有界(誤差に比例して無限大)です。 これが「MAE は外れ値にロバスト、 MSE はロバストでない」という主張の数理的な根拠です。 SSDSE-B-2026 のように東京・沖縄のような特異な観測値を含むデータでは、 MAE のロバスト性が活きる場面が多いです。
Huber 損失は \( L_\delta(u) = \begin{cases} \frac{1}{2}u^2 & |u| \le \delta \\ \delta(|u| - \frac{1}{2}\delta) & |u| > \delta \end{cases} \) で定義されます。 小さい誤差は MSE のように二次関数、 大きい誤差は MAE のように線形関数として扱います。 \( \delta \) はハイパーパラメータで、 経験的には目的変数の標準偏差の 1.345 倍が「ガウス分布で 95% 効率」のロバスト推定量を与えます。 SSDSE-B-2026(2023 年度)の出生数予測では、 出生数の標準偏差 ≒ 17,000 人なので \( \delta = 23,000 \) 程度が目安です。
類似の指標として Median Absolute Error(MedianAE)があります。 MAE が「絶対誤差の平均」なのに対し、 MedianAE は「絶対誤差の中央値」です。 SSDSE-B-2026 で 47 都道府県の絶対誤差を並べたとき、 MAE は全 47 県の平均、 MedianAE は 24 番目(中央順位)の県の絶対誤差です。 外れ値が極端に大きいデータでは、 MedianAE のほうが「典型的な誤差」を反映しやすいと言われます。 ただし MedianAE は感度が低く、 「半分以上の県の誤差が改善した」場合のみ動くため、 モデル比較の感度が落ちる弱点があります。
サンプルごとに重要度が異なる場合、 重み付き MAE \( \text{WMAE} = \sum w_i |y_i - \hat y_i| / \sum w_i \) を使います。 SSDSE-B-2026 で「人口比例で重み付けする」と、 東京都の予測誤差が小さい県の 20 倍以上の重みを持ち、 「全国民の総体としての誤差」を最小化することになります。 これは政策評価で重要で、 「住民数の多い県の予測精度を優先する」場合に有効です。
評価指標の選択は ① 単位の解釈性、 ② 外れ値感度、 ③ 最適化の容易さ、 ④ 比較の文脈の 4 軸で決めます。 SSDSE-B-2026 の出生数予測なら、 ① 単位が「人」で読みやすい → MAE / RMSE、 ② 外れ値(北海道・沖縄)を緩和したい → MAE、 ③ 線形回帰でフィット → どちらでも OK(OLS は MSE 最適化)、 ④ ステークホルダー報告 → MAE(人間が読める)、 という流れで MAE が選ばれます。 一方、 ニューラルネット学習なら ③ で MSE / Huber が選ばれます。
「総人口 → 出生数」予測の完全な再現コード(読み込みから可視化まで)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.linear_model import LinearRegression, HuberRegressor, QuantileRegressor from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score, median_absolute_error from sklearn.model_selection import KFold # 1) データ読み込み(SSDSE-B-2026、先頭列は年度) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023].reset_index(drop=True) # 2023 年度・47 都道府県 print(f'読み込み: {len(df)} 都道府県') # 2) 説明変数・目的変数 X = df[['A1101']].values # 総人口 y = df['A4101'].values # 出生数 prefs = df['Prefecture'].values # 3) 複数モデルで MAE を比較 models = { '線形回帰 (MSE 最適化)': LinearRegression(), 'Huber 回帰 (ロバスト)': HuberRegressor(epsilon=1.35), '分位点回帰 τ=0.5 (MAE 最適化)': QuantileRegressor(quantile=0.5, alpha=0), '分位点回帰 τ=0.9 (上位予測)': QuantileRegressor(quantile=0.9, alpha=0), } results = [] for name, model in models.items(): model.fit(X, y) y_pred = model.predict(X) mae = mean_absolute_error(y, y_pred) rmse = np.sqrt(mean_squared_error(y, y_pred)) medae = median_absolute_error(y, y_pred) r2 = r2_score(y, y_pred) results.append({ 'model': name, 'MAE': mae, 'RMSE': rmse, 'MedianAE': medae, 'R²': r2, 'RMSE/MAE': rmse / mae, }) results_df = pd.DataFrame(results) print(results_df.to_string(index=False)) # 4) 寄与上位 5 県の特定 y_pred = models['線形回帰 (MSE 最適化)'].predict(X) residuals = np.abs(y - y_pred) top5_idx = np.argsort(residuals)[-5:][::-1] print('\n[MAE 寄与トップ 5 都道府県]') for i in top5_idx: print(f' {prefs[i]}: |残差| = {residuals[i]:,.0f} 人 (実測={y[i]:,.0f}, 予測={y_pred[i]:,.0f})') # 5) 5-fold CV print('\n[5-fold CV with MAE]') maes_cv = [] for tr, te in KFold(n_splits=5, shuffle=True, random_state=0).split(X): m = LinearRegression().fit(X[tr], y[tr]) maes_cv.append(mean_absolute_error(y[te], m.predict(X[te]))) print(f'CV-MAE = {np.mean(maes_cv):,.0f} ± {np.std(maes_cv):,.0f} 人') # 6) 可視化 fig, axes = plt.subplots(1, 2, figsize=(13, 5)) axes[0].scatter(X.ravel(), y, alpha=0.6, label='実測') xs = np.linspace(X.min(), X.max(), 100).reshape(-1, 1) for name, m in models.items(): axes[0].plot(xs, m.predict(xs), label=name) axes[0].set_xlabel('総人口 A1101 (人)'); axes[0].set_ylabel('出生数 A4101 (人)') axes[0].legend(); axes[0].set_title('SSDSE-B-2026 出生数モデル比較') axes[1].bar(range(len(results_df)), results_df['MAE']) axes[1].set_xticks(range(len(results_df))) axes[1].set_xticklabels(results_df['model'], rotation=30, ha='right') axes[1].set_ylabel('MAE (人)'); axes[1].set_title('MAE で見るモデル比較') plt.tight_layout() plt.savefig('outputs/mae_full_comparison.png', dpi=120, bbox_inches='tight') |
実行結果(2023 年度実測):単回帰の MAE ≒ 1,146 人、 Huber 回帰の MAE ≒ 1,148 人、 分位点回帰 τ=0.5 の MAE ≒ 1,144 人。 このデータでは総人口と出生数の直線関係が非常に強い(R² = 0.991)ため 3 モデルの差はわずかで、 MAE を直接最適化する分位点回帰がごく僅かに小さい。 分位点回帰 τ=0.9 は MAE ≒ 1,832 人と大きくなる(上位側の予測を狙う指標なので当然)。 「指標が違えば最適モデルも違う」ことを確認できる例。
SSDSE-B-2026 を題材に、 MAE を含む回帰評価の報告書テンプレートを示します。 統計検定・データサイエンスコンペ・自治体報告書のいずれにも応用可能です。
| セクション | 記述例 |
|---|---|
| データ | SSDSE-B-2026 2023 年度 47 都道府県データ、 説明変数 A1101 (総人口)、 目的変数 A4101 (出生数) |
| モデル | 線形回帰 \( \hat y = a \cdot x + b \)、 OLS で学習 |
| 評価指標 | MAE = 1,146 人、 RMSE = 1,622 人、 R² = 0.991、 5-fold CV-MAE = 1,204 ± 494 人(実測) |
| 解釈 | 「平均的に ±1,146 人の予測精度。 RMSE/MAE = 1.42 で軽度の外れ値あり。 R² = 0.991 で説明力は十分。」 |
| 外れ値診断 | 北海道 (−5,976 人)、 沖縄県 (+4,265 人) が大きく外れる。 出生率の地域差を反映。 |
| 改善案 | 老年人口・大学数を追加 → 重回帰の in-sample MAE = 1,008 人。 ただし CV-MAE は 1,472 人と単回帰より悪化(n=47 での過学習)し、 変数追加が常に有効とは限らない |
| 限界 | 単年度データのため経年変化を捉えない。 都道府県という粗い空間単位での予測。 |
cross_val_score 呼び出しを書け。 (答:cross_val_score(model, X, y, scoring='neg_mean_absolute_error', cv=5))本セクションでは、 SSDSE-B-2026 の出生数予測を題材に、 MAE の使い方を 段階的に体験できるケーススタディを示します。 統計初学者・データサイエンス入門者が「MAE を実務でどう活かすか」を理解できる構成です。
最も単純なモデルとして「全 47 都道府県の出生数の平均値で予測する」ベースラインを考えます。 SSDSE-B-2026(2023 年度)の出生数の全国平均は約 15,500 人/県。 各県の実測値と平均値の差を 47 件平均すると、 MAE = 約 11,800 人(ばらつきが大きいため)になります。 これが 「何もしないモデル」の MAEであり、 これ以上小さい MAE を出せないモデルは作る意味がありません。
「総人口 A1101 で出生数 A4101 を予測する」単回帰モデルを学習すると、 MAE は約 1,146 人まで下がります(実測)。 ベースライン 11,800 人から約 1/10 に削減。 これは「人口情報を 1 つ足すだけで予測精度が劇的に向上する」ことを示します。 解釈:「平均的にどの県の出生数も ±1,100 人強の精度で当たる」。
説明変数を 3 つ(総人口 A1101・老年人口 A1303・大学数 E6102)に増やした重回帰では、 in-sample MAE が約 1,008 人までわずかに低下(実測)。 総人口だけでほぼ説明できるため、 改善幅は小さい。 「変数を足せば必ず大きく改善する」わけではないことを示す好例です。
Random Forest(非線形)で同じ 3 変数を入力すると、 in-sample MAE は約 924 人までさらに低下(実測)。 ただしこれは学習データへの当てはまりに過ぎず、 次のステップで見るように汎化性能はむしろ悪化します。 解釈性も低下するため、 自治体報告書では線形モデルの方が好まれることも。
in-sample MAE(学習データで評価)は楽観的なので、 5-fold CV で out-of-sample MAE を測ります。 実測では単回帰の CV-MAE = 1,204 人に対し、 重回帰は CV-MAE = 1,472 人(in-sample 1,008 より悪い)、 Random Forest は CV-MAE = 2,470 人(in-sample 924 より大幅に悪い)。 複雑なモデルほど CV と in-sample の差が大きく、 n=47 では過学習が顕著。 「自分のモデルは新しいデータで本当に同じ精度を出すか?」を確認するのが交差検証の役割です。
単回帰の残差を県別に見ると、 北海道(−5,976 人)、 沖縄県(+4,265 人)、 福岡県(+3,469 人)が大きく外れる傾向(実測)。 沖縄・福岡は 出生率が相対的に高いため人口から予測されるより出生数が多く、 北海道は少子高齢化が進み予測より少ない。 これら「外れ県」のパターンを理解することで、 モデル改善の方向性(地方区分ダミー追加、 出生率の階層モデル化など)が見えてきます。
最終報告書では「MAE = 1,204 ± 494 人(5-fold CV)、 R² = 0.991、 RMSE = 1,622 人(in-sample)」とセットで報告。 「平均的に ±1,200 人の精度で各都道府県の出生数を予測。 RMSE/MAE = 1.42 で軽度の外れ値あり。 大半の県は ±1,000 人以内に収まるが、 北海道・沖縄で大きく外れる」と解釈を添える。
残差 \( \epsilon_i = y_i - \hat y_i \) がラプラス分布(両側指数分布)\( p(\epsilon) = \frac{1}{2b}\exp(-|\epsilon|/b) \) に従うと仮定すると、 対数尤度は \( \log L = -n\log(2b) - \frac{1}{b}\sum |\epsilon_i| \)。 これを最大化する \( \hat\theta \) は MAE 最小化と等価。 つまり MAE 最小化は ラプラス分布ノイズの最尤推定と同じ。 ラプラス分布は正規分布より裾が重く、 外れ値を許容する分布です。
分位点回帰では τ-分位点を予測。 τ=0.5 が中央値で、 損失関数が MAE と一致。 \( \rho_{0.5}(u) = 0.5|u| \)。 つまり MAE 回帰 = 中央値回帰。 一般の τ に対し \( \rho_\tau(u) = u(\tau - \mathbb{1}\{u<0\}) \) で「上位 10%」「下位 10%」のような分位点予測ができる。 リスク管理では τ=0.95 で「95% パーセンタイル予測」を用いる。
M 推定(一般化最尤推定)の枠組みで、 MAE は 影響関数が有界な推定量のシンプルケース。 Huber 損失(\( |\epsilon| \le \delta \) で MSE、 \( |\epsilon| > \delta \) で MAE)は MAE と MSE のハイブリッドで、 ガウス分布のもとで漸近効率を保ちつつ外れ値耐性を持つ。 SSDSE のような実データでは Huber 損失が実務的に最良であることが多い。
| ライブラリ | 関数 | 用途 | 補足 |
|---|---|---|---|
| sklearn | mean_absolute_error | 標準 MAE 計算 | sample_weight 指定可 |
| sklearn | median_absolute_error | 中央値版(よりロバスト) | 外れ値多い場合に推奨 |
| sklearn | QuantileRegressor | 中央値回帰(=MAE 最適化) | τ=0.5 で MAE と等価 |
| sklearn | HuberRegressor | MAE と MSE のハイブリッド | epsilon でしきい値 |
| PyTorch | nn.L1Loss | NN 訓練の MAE 損失 | 劣勾配で SGD 可能 |
| PyTorch | nn.SmoothL1Loss | Huber 損失 | 小誤差は MSE、 大誤差は MAE |
| XGBoost | objective='reg:absoluteerror' | MAE 目的関数 | 勾配ブースティングで MAE 最適化 |
| LightGBM | objective='mae' | MAE 目的関数 | 勾配ブースティング |
SSDSE-B-2026 で「総人口 → 出生数」の回帰問題を MAE で評価する完全ワークフロー。 各ステップにコード断片と解説を付けます。
1 2 3 | df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023].reset_index(drop=True) # 2023 年度・47 都道府県 print(df[['Prefecture', 'A1101', 'A4101']].head()) |
読み込みエラーは encoding を shift-jis や cp932 で試す。 BOM が付いている場合は utf-8-sig。
1 2 | print(df[['A1101', 'A4101']].isnull().sum()) print(df[['A1101', 'A4101']].dtypes) |
SSDSE-B-2026 は欠損が少ないが、 型が object(文字列)になっている場合は pd.to_numeric で変換。
1 | print(df[['A1101', 'A4101']].describe()) |
5 数要約(min, 25%, 50%, 75%, max)と平均・標準偏差で分布の概形を把握。
plt.scatter(df['A1101'], df['A4101'])
plt.xlabel('総人口'); plt.ylabel('出生数')
plt.savefig('outputs/scatter.png', dpi=120)
「線形回帰で当てはまりそうか」「外れ値は?」を目視確認。
1 2 3 | from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split( df[['A1101']], df['A4101'], test_size=0.3, random_state=42) |
47 件と少ないので、 5-fold CV のほうが推奨。 学習データに過学習しないように。
1 2 3 | y_baseline = np.full_like(y_test, y_train.mean()) mae_baseline = mean_absolute_error(y_test, y_baseline) print(f'Baseline MAE: {mae_baseline:,.0f}') |
「自分のモデル」が「平均値モデル」より良いことを必ず確認。
1 2 3 4 5 | model = LinearRegression().fit(X_train, y_train) y_pred = model.predict(X_test) mae = mean_absolute_error(y_test, y_pred) print(f'Linear MAE: {mae:,.0f}') print(f'Improvement: {(mae_baseline - mae) / mae_baseline * 100:.1f}%') |
ベースラインからの改善率を計算。 50% 以上なら良いモデル。
1 2 3 4 | print(f'MAE: {mean_absolute_error(y_test, y_pred):,.0f}') print(f'RMSE: {np.sqrt(mean_squared_error(y_test, y_pred)):,.0f}') print(f'R²: {r2_score(y_test, y_pred):.3f}') print(f'MedianAE: {median_absolute_error(y_test, y_pred):,.0f}') |
MAE 単独では不十分。 RMSE・R²・MedianAE で多面的に評価。
residuals = y_test - y_pred
plt.scatter(y_pred, residuals)
plt.axhline(0, color='red'); plt.xlabel('予測'); plt.ylabel('残差')
plt.savefig('outputs/residuals.png', dpi=120)
残差プロットで「予測の偏り」を可視化。 ランダムに散らばっていれば OK、 パターンがあるとモデル改善余地あり。
1 2 3 4 | from sklearn.model_selection import cross_val_score scores = cross_val_score(model, df[['A1101']], df['A4101'], cv=5, scoring='neg_mean_absolute_error') print(f'CV-MAE: {-scores.mean():,.0f} ± {scores.std():,.0f}') |
5-fold CV で汎化性能を確認。 in-sample MAE より大幅に大きいなら過学習。
1 2 3 4 5 | from sklearn.ensemble import RandomForestRegressor for name, m in [('Linear', LinearRegression()), ('RF', RandomForestRegressor())]: cv_mae = -cross_val_score(m, df[['A1101']], df['A4101'], cv=5, scoring='neg_mean_absolute_error').mean() print(f'{name}: CV-MAE = {cv_mae:,.0f}') |
線形・非線形モデルの MAE を比較し、 最適なモデルを選択。
1 2 3 4 5 6 7 8 | report = f''' データ: SSDSE-B-2026 47 都道府県 モデル: 線形回帰(説明変数=総人口、 目的変数=出生数) CV-MAE: {-scores.mean():,.0f} ± {scores.std():,.0f} 人 解釈: 平均的に ±{int(-scores.mean()):,} 人の精度で予測 改善余地: 説明変数の追加は CV-MAE で必ず再検証(n=47 では過学習で悪化しうる) ''' print(report) |
報告書テンプレート:データ・モデル・指標・解釈・改善余地の 5 点セット。
MAE (平均絶対誤差) は (1/n) Σ |y_i - ŷ_i|。 言葉で読み解けば「全予測誤差の絶対値を平均しただけ」。 シンプルだが、 RMSE と並ぶ回帰評価の双璧。 SSDSE-B-2026 で 4 ステップで体感する。
このコードでやること: SSDSE-B-2026 から人口を読み、 「全県の平均」をベースラインとして予測。 各県の誤差を絶対値で平均して MAE を出す。
📥 入力データ (抜粋):
1 2 3 4 5 6 7 8 9 10 11 12 | import pandas as pd import numpy as np df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023 年度・47 都道府県 y_true = (df['A1101'] / 1000).values # 総人口 (千人) y_pred = np.full_like(y_true, fill_value=int(y_true.mean())) # ベースライン: 全県平均 mae = np.mean(np.abs(y_true - y_pred)) print(f'全県平均 (予測値): {y_pred[0]}') print(f'MAE (手計算): {mae:.1f}') |
📤 実行例:
💬 MAE 1960 (千人) = 平均的に予測が約 196 万人ずれる。 47 県中、 東京 1409 万・神奈川 923 万・大阪 876 万のような大都市が平均を大きく超えるため誤差が大きい。 これが「ベースライン MAE」。
mean_absolute_error で同値確認このコードでやること: 手計算と sklearn の API で結果が一致することを確認。 実務では sklearn.metrics.mean_absolute_error を使う。
1 2 3 4 5 6 | from sklearn.metrics import mean_absolute_error mae_sklearn = mean_absolute_error(y_true, y_pred) print(f'手計算 MAE: {mae:.4f}') print(f'sklearn MAE: {mae_sklearn:.4f}') print(f'一致: {np.isclose(mae, mae_sklearn)}') |
📤 実行例:
💬 当然完全一致。 sklearn API は内部で同じ式を計算しているだけ。 量産環境では sklearn を使うとサンプル重み・多変量対応・並列化の恩恵が受けられる。
このコードでやること: 同じデータで MAE と RMSE を比較。 RMSE は二乗で平均するので外れ値 (東京・大阪) の影響を強く受ける。 MAE は線形なので外れ値の影響が穏やか。
1 2 3 4 5 6 7 8 | from sklearn.metrics import mean_squared_error mae_val = mean_absolute_error(y_true, y_pred) rmse_val = np.sqrt(mean_squared_error(y_true, y_pred)) print(f'MAE = {mae_val:.0f}') print(f'RMSE = {rmse_val:.0f}') print(f'RMSE / MAE = {rmse_val/mae_val:.2f}') print(f'(理論最小 1.0、 RMSE が大きいほど外れ値影響あり)') |
📤 実行例:
💬 RMSE/MAE = 1.41 で、 外れ値の影響が顕著。 47 県のような長い裾分布では MAE の方が「典型的な誤差」を反映する。 評価指標選びの基準: 外れ値が「本当の誤差」なら RMSE、 「測定ノイズ」なら MAE。
このコードでやること: 老年人口 A1303 から総人口 A1101 を予測する単回帰モデルを作り、 5-fold CV で MAE と RMSE を比較。 ベースライン MAE との改善幅を観察。
1 2 3 4 5 6 7 8 9 10 11 12 13 | from sklearn.linear_model import LinearRegression from sklearn.model_selection import cross_val_score X = (df[['A1303']] / 1000).values # 老年人口(65歳以上、千人) y = (df['A1101'] / 1000).values # 総人口 (千人) lr = LinearRegression() mae_cv = -cross_val_score(lr, X, y, cv=5, scoring='neg_mean_absolute_error').mean() rmse_cv = -cross_val_score(lr, X, y, cv=5, scoring='neg_root_mean_squared_error').mean() print(f'単回帰 MAE (CV): {mae_cv:.0f} (ベースライン {mae_val:.0f} から改善)') print(f'単回帰 RMSE (CV): {rmse_cv:.0f}') |
📤 実行例:
💬 ベースライン MAE 1960 → 単回帰 248 (約 1/8)。 「総人口は老年人口 A1303 でほぼ予測できる」と定量的に言える (両者は強く相関する)。 RMSE や 決定係数 と併用して評価の頑健性を保つ。
本セクションは「MAE という指標が、 都道府県データという 外れ値の宝庫 でどう振る舞うのか」を、 散布図・ヒストグラム・箱ひげ図の 3 種類の図で 視覚的に 確認するための拡張パートです。 ここでの議論は、 本文で示した「MAE は外れ値の影響が MSE より小さい」「単位が直感的」という性質を、 実データで体感するための補強材料です。 教育用ハンズオン教材として、 図とコードと数値解釈をセットで提示します。
下の散布図は、 SSDSE-B-2026 の「総人口 A1101」と「一般診療所数 I5102」の対応関係を都道府県別にプロットしたものです。 両者の相関係数は r ≈ 0.972 と極めて強く、 この関係を単回帰でモデル化したとき、 各点と回帰直線の 垂直距離 がそのまま「絶対誤差 \(|y_i - \hat y_i|\)」に該当し、 これを 47 都道府県で平均したものが MAE です。 RMSE が「点と直線の距離の 二乗平均の平方根」であるのに対し、 MAE は「素直に絶対値の平均」なので、 散布図上の 距離をそのまま読める 直感性が魅力です。
図 R618-1: SSDSE-B-2026 の総人口 A1101(横軸)と一般診療所数 I5102(縦軸)の散布図(r ≈ 0.972)。 回帰直線を引けば、 各点と直線の垂直距離 (絶対値) を 47 都道府県で平均したものが MAE になる。 東京のような 大人口県 の点は絶対値のズレも大きくなりやすく、 RMSE では二乗されて影響が肥大化するが、 MAE では線形のため影響が抑えられる。
この散布図から読み取るべきポイントは 3 つです。 第 1 に、 点がほぼ一直線に乗る (r ≈ 0.972) ため、 総人口だけで診療所数をかなり正確に予測できること。 第 2 に、 それでも直線から浮いた県は存在し、 MAE 指標はこれらの外れ値に対して 線形 の影響しか受けないが、 RMSE は二乗されるため外れ値の影響を強く受けること。 第 3 に、 もし「ロバストな予測精度を 1 つの数字で報告したい」ならば、 MAE の方が 説明責任を果たしやすい こと。 「平均すると 1 県あたり◯◯施設の誤差です」と書けば中学生でも分かる。
下のヒストグラムは、 SSDSE-B-2026 の「総人口 A1101」の 47 都道府県分布です。 少数の大都市県 (東京・神奈川・大阪など) が形成する 長い右裾 が特徴で、 このような歪んだ分布の変数を目的変数・説明変数に使うと、 回帰の絶対誤差 \(|y_i - \hat y_i|\) の分布も右に歪みがちになります。 MAE は誤差分布の 算術平均、 中央値絶対誤差 (MedAE) はその中央値であり、 右裾の影響の受け方が異なります。
図 R618-2: SSDSE-B-2026 の総人口 A1101 のヒストグラム。 多くの県は数百万人以下 (左側のピーク) だが、 数県だけ桁違いに大きい。 こうした右裾の長い変数を扱う回帰では、 誤差も一部の県で大きくなりやすい。 MAE は全体の 算術平均 なので右裾の影響を一定程度受け、 MedAE (中央値) を併用すると「典型的な都道府県での誤差はどのくらいか」がより頑健に分かる。
分布の形状から判断すべきことは、 「MAE 単独で報告するか、 MAE と MedAE の両方を報告するか」です。 もし誤差分布が 左右対称 なら MAE = MedAE に近づくので MAE 単独で十分。 もし 右裾が長い なら MAE > MedAE となり、 両方を併記することで「外れ値を含めた誤差」と「典型的な誤差」を読者が区別できます。 総人口のような歪んだ変数を含む SSDSE の都道府県データでは誤差の右裾も長くなりやすいため、 報告書では両指標の併記を推奨します(実測例: 総人口→出生数の単回帰で MAE 1,146 人に対し MedAE 855 人)。
下の箱ひげ図は、 SSDSE-B-2026 の都道府県を KMeans でクラスタリングし、 クラスタ別に一般診療所数 I5102 の分布 を比較したものです。 横軸がクラスタ、 縦軸が一般診療所数。 箱の高さが クラスタ内のばらつき を表し、 髭や外れ点が 特異な県 の指標になります。
図 R618-3: KMeans クラスタ別に見た一般診療所数 I5102 の箱ひげ図。 クラスタ (人口規模などの特徴が近い県のグループ) ごとに水準もばらつきも大きく異なる。 MAE の文脈では、 このように サブグループ別に誤差や分布を確認する 発想が重要で、 「全体 MAE は小さいが特定グループだけ誤差が大きい」問題の検出につながる。
箱ひげ図でグループ比較を行う際の判断基準は次の通りです。 第 1 に 箱が重ならない ならば、 グループ間の差は統計的に意味がある可能性が高い (検定で確認推奨)。 第 2 に 箱が重なる ならば、 「サンプルサイズ不足」または「真にグループ間で差がない」かのどちらか。 第 3 に 髭や外れ点が極端に離れている グループには特異な県が含まれており、 回帰モデルの MAE を押し上げる候補になる。 モデル比較でも同様に、 5-fold CV の fold 別 MAE を箱ひげ図にすれば「安定して良いモデルか」を視覚判断できます。
散布図・ヒストグラム・箱ひげ図の 3 つを並べることで、 「MAE は単なる 1 つの数字ではなく、 分布全体の特徴を 1 つに圧縮した要約値」 だと理解できます。 1 つの数字だけ報告するなら他の人に MAE を再現させることはできませんが、 分布の形と並べて報告すれば、 読者は「外れ値の影響度」「グループ間ばらつき」「典型誤差 vs 平均誤差」を独自に判断できます。 これが 透明性ある報告 の基盤です。
| 指標 | 単位 | 外れ値耐性 | 最適化のしやすさ | 解釈のしやすさ |
|---|---|---|---|---|
| MAE | 目的変数と同じ | 高い (線形) | 中 (微分不可能点あり) | 最高 (平均誤差として読める) |
| MSE | 目的変数の二乗 | 低い (二乗で肥大化) | 最高 (滑らか) | 低 (単位が読みにくい) |
| RMSE | 目的変数と同じ | 低い (MSE の平方根) | 高い (滑らか) | 高 (平均誤差より大きく出る) |
| MedAE | 目的変数と同じ | 最高 (中央値) | 低 (微分不可能) | 高 (典型誤差) |
| MAPE | パーセント (無次元) | 中 | 低 (\(y=0\) で発散) | 高 (相対誤差) |
| R² | 無次元 (0-1) | 低 (MSE 由来) | 最高 | 中 (分散説明率) |
| Huber | 目的変数の関数 | 高い (区分線形) | 最高 (滑らかに接続) | 中 |
| 場面 | 推奨指標 | 理由 |
|---|---|---|
| 人口総数を予測する単回帰モデルの誤差を住民向けに報告 | MAE | 「平均で 1 県あたり◯◯人の誤差」と直感的 |
| 外れ値を含めた厳しい評価で警鐘を鳴らす | RMSE | 大きな誤差を二乗で強調できる |
| ニューラルネットの損失関数として学習に使う | MSE または Huber | MAE は \(y=\hat y\) で微分不可能 |
| スケールの異なるモデルを比較 | MAPE または R² | MAE は単位依存で比較不能 |
| 時系列で予測区間も含めて評価 | MAE + Pinball loss | 分位点回帰の評価指標 |
| 外れ値を完全に無視したい (中央値感覚) | MedAE | 典型誤差を捉える |
| RMSE/MAE 比 | 分布の特徴 | 推奨アクション |
|---|---|---|
| ≈ 1.0 | 誤差はほぼ一定 (全県均一) | モデルが安定。 そのまま報告 OK |
| 1.0–1.3 | 軽度の右裾 (数県だけ大きい) | 外れ県を特定して原因分析 |
| 1.3–2.0 | 明確な右裾 (東京・大阪等) | 対数変換または分位回帰を検討 |
| > 2.0 | 外れ値が極端 (沖縄・離島) | サブグループ分割または除外を検討 |
| 項目 | 確認内容 |
|---|---|
| 単位 | 「人」「円」「%」などを明示したか |
| サンプルサイズ | 何件で計算したか (n=47 都道府県) |
| train/test 分離 | train で評価していないか |
| CV の有無 | 単一 split か k-fold か |
| RMSE 併記 | 外れ値感度の差を見せたか |
| ベースライン比較 | 「平均値予測」より良いか |
| 目的変数 | 説明変数の候補 | 期待される MAE スケール |
|---|---|---|
| 出生数 A4101 | 総人口 A1101・婚姻件数 A9101 | 約 1 千人 (実測 in-sample MAE ≒ 950 人) |
| 総人口 A1101 | 老年人口 A1303・大学数 E6102 | 十数万人 (実測 in-sample MAE ≒ 18 万人) |
| 高齢化率 | 出生数 A4101・老年人口 A1303 | 数 % (実測 in-sample MAE ≒ 1.6 %) |
| 大学数 E6102 | 総人口 A1101・老年人口 A1303 | 数校 (実測 in-sample MAE ≒ 5 校) |
| 老年人口 A1303 | 総人口 A1101・出生数 A4101 | 数万人 (実測 in-sample MAE ≒ 5 万人) |
| 用語 | 1 行説明 |
|---|---|
| L1 ノルム | 絶対値の和。 MAE は L1 ノルム / n。 |
| L2 ノルム | 二乗和の平方根。 RMSE は L2 ノルム / √n。 |
| 分位回帰 | 中央値最小化が MAE 最適化と等価。 |
| Huber 損失 | 小誤差は MSE、 大誤差は MAE のハイブリッド。 |
| Pinball 損失 | 非対称 MAE。 分位点予測の評価。 |
| ベースライン | 「平均値で全予測」した時の MAE。 |
ここでは「47 都道府県の出生数 A4101 を、 総人口 A1101 から単回帰で予測した場合の MAE」を 手順を追って 計算します。 教科書では 5-10 行のコードで済ませるところを、 あえて 1 県ごとの計算過程を示すことで、 「MAE とは何の 平均 なのか」を腹落ちさせるのが目的です。
単回帰式 \(\hat y = a + b x\) において、 \(x\) を総人口 A1101 (千人)、 \(y\) を出生数 A4101 (人) とします。 粗出生率は 2023 年度実測で全国 5.85‰(出生数合計 ÷ 総人口合計)なので、 \(\hat y \approx 6x\)(総人口 1 千人あたり約 6 人)という比例モデルが目安になります。
各都道府県 \(i\) について、 \(\hat y_i = 6 x_i\) を計算し、 \(|y_i - \hat y_i|\) を求めます。 例えば北海道なら \(x = 5{,}092\)(千人)、 \(\hat y = 6 \times 5{,}092 = 30{,}552\)、 実際の出生数 \(y = 24{,}430\)(2023 年度実測)なので絶対誤差は \(|24{,}430 - 30{,}552| = 6{,}122\) (人) となります。 こうした計算を 47 都道府県全部で行います。
47 個の絶対誤差を足して 47 で割れば MAE。 比例モデル \(\hat y = 6x\) では実測で MAE ≈ 1,232 (人) になります。 つまり「平均的に 1 県あたり約 1,200 人の予測誤差」と読めます。 単位を含めて報告することで、 読者は「精度が高いか低いか」を 自分の感覚 で判断できます。
最も外れるのは北海道で、 比例モデルでは \(\hat y = 30{,}552\) と予測されますが、 実際の出生数は 24,430 人。 この 1 県だけで絶対誤差が 6,122 (人) にのぼり、 全体の MAE を押し上げます。 試しに北海道を除いた 46 都道府県で MAE を再計算すると、 1,232 → 1,126 (人) に下がります(実測)。 こうした感度分析で「特定の県に引っ張られていないか」が分かります。
「全県の出生数を 平均値 で予測する」というナイーブモデルの MAE を計算します。 出生数の全国平均は約 15,500 (人)/県で、 各県の絶対誤差を平均すると約 11,800 (人) になります(実測)。 この 11,800 が ベースライン MAE。 比例モデルの MAE 1,232 がベースライン 11,800 を大きく下回るので、 このモデルは意味があると言えます。
47 都道府県を 5 つの fold に分け、 4 fold で学習、 1 fold でテストを 5 回繰り返します。 5 つの fold MAE の平均と標準偏差を報告することで、 「サンプルの偏り」によって MAE が異常値を取っていないかが分かります。 OLS 単回帰の実測では 5-fold CV-MAE = 1,204 ± 494 (人) のような形で報告するのがベストプラクティスです。
単回帰 (1 変数) を、 重回帰 (例: 総人口 A1101 + 老年人口 A1303 + 大学数 E6102) や Random Forest と比較します。 実測の 5-fold CV-MAE は「単回帰 1,204、 重回帰 1,472、 Random Forest 2,470」で、 このデータでは 説明変数を増やすほど悪化 しました。 総人口だけでほぼ説明できるうえ n=47 と小さいため、 複雑なモデルが過学習で テスト MAE を悪化 させる典型例です。 学習 MAE とテスト MAE の差を必ず確認すべきです。
最終的に報告書には次のように書きます: 「SSDSE-B-2026 (2023 年度、 n=47 都道府県) における出生数 A4101 の予測モデルとして、 説明変数に総人口 A1101 を採用した単回帰を構築した。 5-fold 交差検証の結果、 MAE = 1,204 ± 494 (人)、 in-sample で RMSE = 1,622 (人)、 R² = 0.991 を得た。 ベースライン (平均値予測) の MAE は約 11,800 (人) であり、 本モデルは 大幅な精度改善 を達成した。 RMSE が MAE の約 1.4 倍となっており、 北海道・沖縄の県で大きな予測誤差を生じている。 老年人口・大学数を追加した重回帰は CV-MAE が悪化したため採用しなかった。」
Q1. なぜ MAE は損失関数として人気がないのに評価指標としては人気なの?
学習時 (損失関数) は微分のしやすさが重要で、 MSE のような滑らかな関数が好まれる。 一方、 評価時 (テスト) は微分する必要がなく、 解釈のしやすさが重要なので MAE が好まれる。 これは「学習時と評価時で異なる指標を使うべき」という典型例。
Q2. MAE と MedAE どちらを優先すべき?
原則は両方併記。 報告書のスペースが限られていれば、 一般読者向けには「平均的にどれくらい外す?」が知りたいので MAE。 異常値の影響を排除したいなら MedAE。 SSDSE のような外れ値が多いデータでは MedAE が 本質を捉えやすい。
Q3. n が極端に小さい (n=10 等) でも MAE は使える?
使えるが 信頼区間が広く なる。 ブートストラップで 95% CI を出すと「MAE = 20 (95% CI: 5–40)」のように広くなり、 「精度が高い」とは言いにくくなる。 n=10 では LOO-CV (Leave-One-Out) で各サンプルごとの予測誤差を出すのが現実的。
Q4. MAE をパーセントで表示する MAPE との違いは?
MAE は単位ありの絶対値、 MAPE は単位なしの相対値。 MAPE = 平均(|誤差| / |実値|) × 100。 異なるスケールのモデル間 (人口モデル vs 大学数モデル) を比較するには MAPE が便利だが、 実値が 0 に近いとき発散 するため SSDSE で「転入超過数」のような正負混在変数では使えない。
Q5. MAE がモデルにとって不利なケースはある?
あります。 「すべての都道府県で誤差が均等な平均回帰モデル」と「大都市だけ大きく外す省エネモデル」を比較する際、 MAE は前者を有利に評価する。 もし利用者が 大都市の精度を特に重視 しているなら、 MAE ではなく重み付き MAE や top-N MAE を使うべき。
Q6. MAE が下がっても R² が下がるのは起こる?
理論上は稀だが、 起こり得る。 MAE は線形誤差の平均、 R² は分散ベース。 例えば「すべての予測を実値より少し低く出す系統的バイアスを持つモデル」は MAE は小さいが、 平均からの分散説明という観点で R² が悪化することがある。 両者を併記して総合判断するのが安全。
Q7. SSDSE-B-2026 で MAE が極端に大きくなったら?
原因の切り分けが必要。 (1) 説明変数の選択ミス (相関の低い変数のみ使用)、 (2) 線形仮定の破綻 (非線形モデルが必要)、 (3) 外れ値の影響 (1-2 県の極端値が引っ張っている)、 (4) 単位ミス (千人と人を混在) のいずれか。 散布図と残差プロットで確認する。
Q8. MAE の信頼区間はどう出す?
最も簡単なのはブートストラップ。 47 都道府県からランダムに 47 件を復元抽出し、 MAE を計算 → これを 1,000 回繰り返し → 1,000 個の MAE の 2.5% と 97.5% 分位点を CI とする。 sklearn には組み込みがないので numpy で自前実装になる。
Q9. 分類問題でも MAE を使える?
原則は 回帰用。 ただし「順序付き分類」(例: 低・中・高の 3 段階予測) では順序を数値化して MAE を使うことがある。 例えば真値 「高=3」、 予測 「中=2」なら絶対誤差 1。 これにより「予測がどれくらい 順序として近いか」を評価できる。
Q10. SSDSE-B-2026 の年次変化を予測する時、 MAE は使える?
使えるが 時系列分割 が必須。 普通の KFold だと「未来から過去を予測する」漏れが起きる。 TimeSeriesSplit を使い、 2020-2023 を学習、 2024-2025 をテストのように 時系列順 で分けて MAE を計算する。 結果は通常 KFold より MAE が高めに出るが、 これが本番運用に近い数字となる。
MAE は 18 世紀から知られる「絶対偏差の平均」を回帰評価に応用したものです。 最小絶対偏差法 (LAD: Least Absolute Deviations) はラプラス (Pierre-Simon Laplace) が最小二乗法 (LSE) と並んで議論しましたが、 計算が困難であったため 19-20 世紀には最小二乗法が圧勝。 1950 年代以降、 線形計画法の発展で LAD の計算が現実的となり、 ロバスト統計学の文脈で再評価されました (Huber 1964 など)。
機械学習文脈では、 1990 年代以降のニューラルネットブームで MSE が主流となりましたが、 2010 年代以降 外れ値耐性 や 非対称損失 への関心が高まり、 MAE・Huber・Pinball loss が回帰タスクで頻繁に使われるようになりました。 特に Kaggle 等のコンペでは「評価指標が MAE」のコンペが定期的に開催され、 LightGBM や XGBoost が MAE 損失を直接最適化する機能を備えています。
2020 年代の話題としては、 分布回帰 (distributional regression) の文脈で MAE が分位点回帰 (中央値最小化) と等価であることが再認識され、 「点予測ではなく予測区間を出す」アプローチで MAE が改めて重要視されています。 Quantile Random Forest や Conformal Prediction といった手法は、 MAE の自然な拡張です。
日本の公的統計の文脈では、 SSDSE-B-2026 のような都道府県データの予測モデルにおいて、 MAE は 政策議論の場で最も伝わりやすい指標 として推奨されています。 「平均すると 1 県あたり 5,000 人の誤差です」という説明は、 国会議員から地方自治体職員まで全員が同じ単位で議論できるからです。 RMSE や MSE では「単位が二乗されている」ことに違和感を持つ非専門家が多いため、 MAE が選ばれます。
SSDSE-B-2026(2023 年度)の 「総人口 A1101 → 出生数 A4101」を単回帰で予測したときの MAE を概算してみる。 全国で総人口 1 千人あたり約 6 人が新生児として生まれる(粗出生率、 実測 5.85‰)と近似すると、 線形モデルは \( \hat y = 0.006 x \)(\(x\) は人単位の総人口)になる。
| 都道府県 | 総人口 (千人) | 出生数 実測 | 予測 \(\hat y\) | |誤差| |
|---|---|---|---|---|
| 北海道 | 5,092 | 24,430 | 30,552 | 6,122 |
| 東京都 | 14,086 | 86,348 | 84,516 | 1,832 |
| 愛知県 | 7,477 | 48,402 | 44,862 | 3,540 |
| 大阪府 | 8,763 | 55,292 | 52,578 | 2,714 |
| 沖縄県 | 1,468 | 12,549 | 8,808 | 3,741 |
| 鳥取県 | 537 | 3,263 | 3,222 | 41 |
| 6 県の平均誤差(MAE 概算) | 約 3,000 人 |
この 6 県は外れやすい県を含むため平均誤差約 3,000 人だが、 47 都道府県全体で計算した比例モデルの実際の MAE は 約 1,232 人(切片付き OLS では 1,146 人)になる。 「北海道 1 県だけで 6 千人超 外れている」ことから、 北海道・沖縄のような外れ的県の存在が誤差を押し上げていると分かる(沖縄県は 出生率が全国トップ級に高い ため予測より多く生まれる)。
同じデータを 多変量化(人口に加えて老年人口 A1303、 大学数 E6102 を説明変数に追加)しても、 in-sample MAE は約 1,008 人までの小幅改善にとどまり、 交差検証ではむしろ悪化する(総人口だけでほぼ説明できるため)。 つまり MAE はモデルの説明力を 絶対値の単位で 見せてくれるだけでなく、 変数追加が本当に効いているか の判定にも使える。
合成回帰の予測誤差から MAE を計算する。
| i | y | ŷ | |誤差| |
|---|---|---|---|
| 1 | 10 | 9 | 1 |
| 2 | 15 | 17 | 2 |
| 3 | 20 | 22 | 2 |
| 4 | 25 | 23 | 2 |
| 5 | 30 | 28 | 2 |
1 2 3 4 5 | import numpy as np y = np.array([10, 15, 20, 25, 30]) yhat = np.array([9, 17, 22, 23, 28]) mae = np.abs(y - yhat).mean() print(f"MAE: {mae}") |
💬 手計算 (Step 2) 1.8 と Python 出力が完全一致。
下の図には 5 つの実測点(縦位置がデータ値 \(y\))と、 全点に同じ値を返す 予測定数 \(\hat y = c\)(青緑の水平線)があります。 点や水平線をドラッグ(スマホはタップして指を動かす)すると、 各点から水平線までのオレンジの縦線=絶対誤差 \(|y-\hat y|\) と、 MAE・MSE・RMSE がリアルタイムに更新されます。 1 点を大きく引っぱって「外れ値」にすると、 MAE(線形に増える)と MSE/RMSE(二乗で急増する)の 感応度の違いを体感できます。
🎯 直感:MAE は「オレンジの縦線(絶対誤差)の平均の高さ」です。 水平線を 中央値(緑の破線)に合わせると縦線の合計が最短になり MAE が最小、 平均(青の破線)に合わせると二乗和が最短になり MSE/RMSE が最小になります。 「MAE は中央値、 MSE は平均」という性質を目で確かめられます。
🚀 発展:この「予測定数=中央値で MAE 最小」という事実は、 分位点回帰の \(\tau=0.5\)(中央値回帰)の特殊ケースです。 外れ値耐性と最適化のしやすさを両立させたいときは、 小さな誤差を二乗・大きな誤差を線形に扱う Huber 損失が中庸として使われます。 関連指標は MSE・RMSE、 統計的背景は 中央値・平均・ロバスト統計 を参照。
SSDSE-B-2026 で「総人口 → 出生数」を単回帰し、 MAE を計算する完全コード。
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 sklearn.linear_model import LinearRegression from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score from sklearn.model_selection import KFold # 1) SSDSE-B-2026 を読み込み(2023 年度・47 都道府県に絞る) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2) 説明変数 X(総人口)、目的変数 y(出生数) X = df[['A1101']].values # 総人口 y = df['A4101'].values # 出生数 # 3) 学習&予測(全データで in-sample 評価) model = LinearRegression().fit(X, y) y_pred = model.predict(X) # 4) MAE / MSE / RMSE / R² を比較 mae = mean_absolute_error(y, y_pred) mse = mean_squared_error(y, y_pred) rmse = np.sqrt(mse) r2 = r2_score(y, y_pred) print(f'MAE = {mae:,.0f} 人 ← 平均的にこのくらい予測がズレている') print(f'RMSE = {rmse:,.0f} 人 ← 外れ値を強く罰した版') print(f'MSE = {mse:,.0f} 人²') print(f'R² = {r2:.3f} ← 説明力(1 が完璧、 0 が定数モデルと同等)') |
交差検証で out-of-sample の MAE を見る
1 2 3 4 5 6 7 8 | # 5-fold CV で汎化性能を測定 maes = [] for tr_idx, te_idx in KFold(n_splits=5, shuffle=True, random_state=0).split(X): m = LinearRegression().fit(X[tr_idx], y[tr_idx]) maes.append(mean_absolute_error(y[te_idx], m.predict(X[te_idx]))) print(f'CV-MAE = {np.mean(maes):,.0f} ± {np.std(maes):,.0f} 人') # in-sample MAE より大きい → 過学習の兆候 |
複数モデルの MAE 比較
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | from sklearn.linear_model import Lasso, Ridge from sklearn.ensemble import RandomForestRegressor # 説明変数を増やす features = ['A1101', 'A1303', 'A4101', 'E6102', 'E6302'] # 人口、高齢者数、出生数、大学数、大学学生数 df_clean = df.dropna(subset=features + ['A4101']) X = df_clean[features].drop(columns=['A4101']).values y = df_clean['A4101'].values models = { '線形回帰': LinearRegression(), 'Lasso (L1)': Lasso(alpha=1.0), 'Ridge (L2)': Ridge(alpha=1.0), 'Random Forest': RandomForestRegressor(n_estimators=100, random_state=0), } for name, m in models.items(): m.fit(X, y) mae = mean_absolute_error(y, m.predict(X)) print(f'{name:20s}: MAE = {mae:,.0f} 人') |
補足:MAE と Median Absolute Error は似て非なる指標。 MAE は 平均、 MedianAE は 中央値。 外れ値が多いデータでは MedianAE のほうがロバスト。 sklearn では median_absolute_error を使う。
残差プロットで MAE の偏り分布を可視化
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 | import os os.makedirs('outputs', exist_ok=True) # 保存先のフォルダを作っておく import matplotlib.pyplot as plt # 単回帰の残差をプロット residuals = y - y_pred abs_residuals = np.abs(residuals) prefectures = df['Prefecture'].values # MAE 寄与上位 5 都道府県を表示 top5_idx = np.argsort(abs_residuals)[-5:] print('MAE への寄与トップ 5 都道府県:') for i in top5_idx: print(f' {prefectures[i]}: |残差| = {abs_residuals[i]:,.0f} 人') # 残差ヒストグラム fig, ax = plt.subplots(1, 2, figsize=(12, 4)) ax[0].hist(residuals, bins=20, color='#00897B', edgecolor='white') ax[0].axvline(0, color='red', linestyle='--') ax[0].set_title('残差の分布') ax[0].set_xlabel('y - ŷ') ax[1].scatter(y_pred, residuals, alpha=0.6, color='#00695C') ax[1].axhline(0, color='red', linestyle='--') ax[1].set_title('予測値 vs 残差') ax[1].set_xlabel('予測値 ŷ') ax[1].set_ylabel('残差') plt.tight_layout() plt.savefig('outputs/mae_residual_plots.png', dpi=120) |
scoring パラメータで Grid Search
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | from sklearn.model_selection import GridSearchCV from sklearn.ensemble import GradientBoostingRegressor param_grid = { 'n_estimators': [50, 100, 200], 'max_depth': [3, 5, 7], 'learning_rate': [0.05, 0.1, 0.2], } gs = GridSearchCV( GradientBoostingRegressor(random_state=0), param_grid, scoring='neg_mean_absolute_error', # MAE を最小化(負値で最大化) cv=5, n_jobs=-1, ) gs.fit(X, y) print(f'最良パラメータ: {gs.best_params_}') print(f'CV-MAE (best): {-gs.best_score_:,.0f} 人') # best estimator で予測 best = gs.best_estimator_ print(f'最終 MAE: {mean_absolute_error(y, best.predict(X)):,.0f} 人') |
本セクションは既存の解説を壊さずに、 MAE の 直感・落とし穴・発展を一段深掘りする追記です。 数値はすべて SSDSE-B-2026(2023 年度・47 都道府県、 総人口 A1101 → 出生数 A4101 の単回帰)の実測で、 明示した箇所のみ架空の思考実験です。
MAE の本質は「誤差の絶対値の平均」であり、 元の単位(人・円)のまま解釈できる点が最大の武器です。 そして MAE を最小にする予測値は 中央値だという性質が、 外れ値へのロバスト性の源泉になっています。 これは実データでも確認できます。
同じ「定数で予測する」でも、 中央値で予測したほうが MAE が小さい(11,839 → 9,714 人)。 これは「MAE を最小化する定数=中央値」という定理の生きた証拠です。 逆に MSE を最小化する定数は平均値になります(MSE 参照)。 だから MAE と MSE は最適解そのものが違う——MAE は条件付き中央値、 MSE は条件付き平均を推定します(中央値 / 分位点回帰)。
回帰にすると差はさらに縮みますが、 傾向は残ります:OLS(MSE 最適化)の傾き 0.006104 に対し、 MAE 最適化(分位点回帰 τ=0.5)の傾きは 0.006181(いずれも実測)。 本データは総人口と出生数の直線関係が極めて強い(R²=0.991)ため差はわずかですが、 外れ値が増えるほど両者の乖離は広がります。
MAE を起点に、 目的に応じてどの指標/損失へ跳ぶかを整理します。
| やりたいこと | 選ぶもの | 理由・対応ページ |
|---|---|---|
| 外れ値に強く・元単位で解釈 | MAE | 中央値回帰、 影響関数が有界(中央値) |
| 大外しを重く罰したい | MSE / RMSE | 平均回帰、 二乗で大誤差を強調(RMSE は元単位) |
| スケールを跨いで比較 | MAPE / SMAPE | 無次元。 ただしゼロ近傍で発散(SMAPE で緩和) |
| ロバスト+微分可能で学習 | Huber / SmoothL1 | 小誤差 L2・大誤差 L1(損失関数) |
| 非対称コスト・分位点予測 | Quantile 損失 | \(\tau\) で過大/過小を傾ける(分位点回帰 / 分位点) |
MAE 最小化 = 条件付き中央値という等価性を軸に、 「中央値では物足りない」ときに何へ拡張するかを覚えると迷いません。 上側・下側のリスクを見たいなら分位点回帰へ、 外れ値耐性と学習の滑らかさを両立したいなら Huber へ、 頑健な回帰係数そのものが欲しいなら L1 系の頑健回帰(分位点回帰の τ=0.5 が最小絶対偏差 LAD 回帰に一致)へ、 という具合に地続きです。
補足:本ページ内に個別ページが無い指標(SMAPE・Huber 損失・頑健回帰・MASE)は、 リンクを張らずテキストで示しています(該当 HTML が glossary 内に未整備のため)。 MSE / RMSE / MAPE / 損失関数 / 中央値 / 分位点回帰 / 分位点 は実在ページへの相対リンクです。
MAE を完全に使いこなすには、 単に定義を覚えるだけでは不十分です。 SSDSE-B-2026 のような実データで何度も計算を回し、 「外れ値が来た時の感覚」「サンプル数による変動の感覚」「ベースラインとの相対値の感覚」を体得することが鍵です。 以下は教育用ハンズオン教材として推奨する学習順序です。
SSDSE-B-2026 から 5 都道府県だけを取り出し、 紙とペンで MAE を計算します。 ここで「絶対値とは何か」「平均とは何か」を 体感 します。 同じデータで RMSE、 MedAE も手計算し、 3 つの違いを目で見て確認します。
47 都道府県全件で sklearn.metrics.mean_absolute_error を使った計算を実行します。 ベースライン (平均値予測) との比較、 train/test 分割の意味を学びます。 ここで「過学習」と「汎化性能」の概念を、 MAE という具体的な数字を通じて理解します。
5-fold CV で MAE の安定性を確認し、 fold 間ばらつきの意味を学びます。 また東京・神奈川・大阪を除外した感度分析を行い、 「外れ値が結論に与える影響」を定量化します。 ここで初めて MedAE や Huber loss の必要性が腹落ちします。
単回帰・重回帰・Random Forest・LightGBM の 4 モデルを SSDSE-B-2026 で構築し、 5-fold MAE で比較します。 結果を A4 1 枚の報告書にまとめ、 「政策議論で使える誤差の単位はどれか」を考えます。 MAE の単位の直感性 (「人口の MAE = 5,000 人」と書ける) が、 RMSE や R² より説得力を持つ場面を実感します。
最後に、 MAE は数ある回帰評価指標の中でも もっとも教育的価値の高い指標 です。 数式は単純で、 単位は直感的で、 外れ値の議論にも耐えうる。 SSDSE-B-2026 のような公的統計データを使って繰り返し計算することで、 「データサイエンスの中核となる感覚」が身につきます。 本ページの内容を 1 週間に 1 章ずつ消化していけば、 1 か月で MAE をマスターできます。 さらに進んで Huber loss や Pinball loss、 分位回帰といった発展指標に進めば、 現代的な機械学習の評価指標体系を一望できる視野が得られます。
地方自治体の政策立案では「人口予測の誤差をどう報告するか」が頻繁な論点となります。 ここでも MAE は強力な味方です。 例えば「2030 年の県人口予測モデルで MAE 12,000 人」と報告すれば、 議会・市民・記者すべてが「平均で 1 万 2 千人ずれる可能性がある」と同じ単位で議論できます。 RMSE 25,000 や MSE 6.25e8 では、 非専門家には伝わりません。
また MAE は 誤差予算 (error budget) の発想にも親和的です。 「来年の予算策定では人口予測の誤差を ±5,000 人以内に収めたい」というゴールを立て、 それを MAE で評価できる。 RMSE では「±5,000 人」を直接 RMSE と比較できないため、 ゴール設定が遠回りになります。 SSDSE-B-2026 のような公的データで MAE を計算する習慣をつけておくと、 こうした政策議論で即座にエビデンスベースの提案ができます。
教育の現場でも、 高校・大学初年次の統計入門で「MAE と RMSE を SSDSE で比較する」という実習は、 学生の理解度を飛躍的に高めることが知られています。 計算量が少なく、 概念がシンプルで、 単位が分かりやすい。 47 都道府県という現実的なサンプルサイズが、 「サンプルサイズが小さい時の挙動」を直感的に学ばせてくれます。 こうした教材としての側面でも、 MAE は他の指標を圧倒する魅力を持っています。
今後、 機械学習の現場では XAI (説明可能 AI) や責任ある AI の文脈で、 「指標の解釈可能性」がますます重視されます。 ブラックボックスモデルが「精度 99%」と言われても、 単位の不明確な指標では信頼を得られません。 MAE のような単位の明確な指標を 第一報告指標 として併記する文化を、 データサイエンティスト全員が共有することが、 社会との信頼関係を築く第一歩です。
最後に MAE のもう一つの利点として、 分位回帰や非対称損失への自然な拡張性 が挙げられます。 MAE を非対称化した Pinball loss は、 「過大予測のコスト」と「過小予測のコスト」が違う実務問題に最適です。 例えば人口予測で「過大予測すると予算を過剰計上して批判される」「過小予測すると行政サービスが不足して市民が困る」という非対称な状況では、 単純な MAE ではなく重み付きの MAE (例: 過小予測の絶対誤差を 2 倍カウント) を使うのが正解です。 こうした柔軟性も MAE のシンプルさから生まれる長所であり、 SSDSE-B-2026 のような公的データで何度も計算を回しているうちに、 自然に拡張のアイデアが湧いてくるはずです。 是非、 本ページを起点に MAE の世界を深く探索してみてください。
なお、 MAE は単一の数字だけでなく 都道府県別のサブグループ分析 にも有効です。 全体 MAE = 18 (千人) と報告したあとに「うち関東は MAE 25、 近畿は MAE 22、 九州は MAE 12」のようにブロック別に出すと、 「どの地域の予測が苦手か」が明確になります。 SSDSE-B-2026 は地域ブロックの情報も持っているので、 groupby と組み合わせれば 1 行で集計できます。 こうした分析は公平性・透明性の観点からも極めて重要で、 「全国平均では良いけど、 特定地域は誤差が 2 倍」というモデルを許容するか否かは、 政策判断に直結します。 MAE はそのような議論の出発点として、 引き続き第一線の指標であり続けるでしょう。
本ページのまとめとして特に強調したい点は、 MAE は「単純で、 解釈しやすく、 拡張性が高い」 という 3 拍子そろった非常に優れた評価指標であるということです。 数式は中学生でも理解でき、 単位は目的変数と完全に同じなので誰でも読める。 そして必要に応じて Huber や Pinball、 分位回帰へと自然に拡張できる柔軟性も併せ持つ。 SSDSE-B-2026 の都道府県データという身近で実在する公的統計を題材に、 MAE を繰り返し計算する経験を積めば、 データサイエンスにおける誤差評価の 礎 となる感覚が必ず身につきます。 これからモデル評価指標を学ぶ全ての人に、 まず MAE から始めることを強くお薦めします。
MAE (平均絶対誤差) は単独の指標で完結せず、 上流の予測モデル出力、 並列の MSE / RMSE / MAPE、 下流の精度モニタリングダッシュボードと組み合わせて使う。 単位がそのまま意味を持つので、 SHAP 値・予測区間と一緒に表示すると解釈しやすい。
SSDSE-B-2026 の出生数 A4101 を回帰予測する場合、 上流で説明変数を並べ、 中段で線形回帰・勾配ブースティングを比較、 下流で MAE と RMSE を併記して「平均約 1,100 人ずれる、 外れ県 (北海道) では約 6,000 人ずれる」(2023 年度実測)と二軸で報告するのが標準。
MAE を採用するか RMSE / MAPE / Huber 損失に切り替えるかは、 (1) 外れ値の扱い、 (2) 単位とスケールの解釈性、 (3) 学習時の最適化容易性、 で判断する。 報告では MAE と RMSE を併記するのが定石。
SSDSE-B-2026 の出生数 A4101 を予測する場合、 単位がそのまま「人」で読めるので MAE が第一選択。 ただし北海道・沖縄のような特異な県の予測誤差を厳しく評価したいなら RMSE を併用。 報告書には「MAE = 平均 1,146 人ずれる、 RMSE = 1,622 人 → 一部の県で誤差が膨らんでいる」(2023 年度実測)と二軸で書く。
この式を 4 つの要素に分解して、 もう少し丁寧に「言葉」で読み解きます。 数式 \( \text{MAE} = \frac{1}{n}\sum_{i=1}^{n}|y_i - \hat y_i| \) は一見シンプルですが、 ① 各サンプルの誤差を計算する、 ② 絶対値で符号を取り除く、 ③ 全サンプルを足す、 ④ サンプル数で割って平均化する、 という 4 段階の手順を 1 行で表現したものです。 SSDSE-B-2026 の「47 都道府県 × 出生数予測」の場合、 各都道府県に対し「予測した出生数 \( \hat y_i \) と実際の出生数 \( y_i \) の差」を計算し、 その絶対値を 47 個分足してから 47 で割ります。 こうすることで「平均的にどれくらいズレているか」が、 目的変数(出生数)と同じ「人」という単位で得られます。
要素 ①「差を取る」:\( y_i - \hat y_i \) は 残差と呼ばれる量です。 これは「観測値 - 予測値」の順番で計算するのが慣例で、 正なら「予測がアンダー(過小評価)」、 負なら「予測がオーバー(過大評価)」を意味します。 SSDSE-B-2026(2023 年度)で東京都の出生数は実測 86,348 人・単回帰の予測 85,308 人なので、 残差 = +1,040 人で「予測が約 1 千人足りていない」と分かります。
要素 ②「絶対値を取る」:\( |y_i - \hat y_i| \) は符号を消す操作です。 もし符号を残したまま単純平均すると、 正の残差と負の残差が打ち消し合って 常に 0 に近い値になってしまい、 予測精度の評価になりません。 絶対値を取ることで「ズレの大きさ」だけを純粋に評価できます。 別の選択肢として「二乗」を取る方法もあり、 これが MSE の発想です。 絶対値は外れ値に対して線形に増加するため、 二乗(外れ値が二次的に増加)よりロバストです。
要素 ③「全サンプルを足す」:\( \sum_{i=1}^n \) は 1 番目のサンプルから \( n \) 番目までを順に足す総和記号です。 SSDSE-B-2026 なら \( n = 47 \) で、 47 都道府県分の絶対誤差をすべて加算します。 これは「集団全体の誤差総量」を表しています。
要素 ④「サンプル数で割る」:\( \frac{1}{n} \) で総和を平均化します。 これがないと「サンプル数が増えれば必ず誤差総量が増える」という、 サンプル数依存の指標になってしまい、 比較ができなくなります。 平均化することで「1 サンプルあたりの平均誤差」となり、 異なるデータセット間でも誤差水準を比較できる無次元な指標に近づきます(ただし単位は y と同じ)。 SSDSE-B-2026(2023 年度)の単回帰では 47 都道府県の絶対誤差合計が実測 53,847 人なので、 MAE = 53,847 / 47 ≈ 1,146 人となり、 「平均的にどの県も ±1,146 人ズレている」と読めます。