論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説
📚 用語解説
特徴量
Feature
ML基礎

🔖 キーワード索引

この用語と一緒に検索・参照されやすいタグ。 関連ページに飛ぶときの手がかりにも使えます。

#ML基礎#特徴量#前処理#エンジニアリング#選択

feature」は統計データ分析の文脈で扱う重要概念のひとつ。 本ページでは「feature」を取り巻く中核キーワードを以下にチップで一覧化する。 各キーワードは関連する概念・手法・道具立てを含み、 文献検索や学習計画の起点になる。

feature統計分析SSDSE-B-2026前提条件適用範囲落とし穴関連手法Python 実装検証方法

これらのキーワードは「feature の理解 → 適用 → 検証」のプロセスを構成する。 各章で詳しく解説する。

💡 30秒で分かる結論

🍰 まずはやさしく

データを数値の表に直したものです。

AIに学習させるために使います。

スマホの利用時間を数値にする例です。

ここでは特徴量の種類や作り方を学びます。

特徴量は、 機械学習モデルへの入力ベクトルの各成分。 「データを数値テーブルに翻訳した結果」。

ここまでが要点です。 ただし実際に使う前に、 このページの「⚠️ よくある落とし穴」で挙げた リーケージ/高カーディナリティのカテゴリ/スケーリングの忘れ には必ず目を通してください。 つまずくのは知識が無いときより、 知ってはいたが確認を飛ばしたときです。

📍 文脈:「特徴量」はどんな場面で出てくる?

🍰 まずはやさしく

予測の精度を決める重要な道具です。

より正確な答えを出すために使います。

部活の得点から勝ち負けを予測する例です。

どんな場面でどう使うかを学びます。

回帰・分類いずれでも「予測精度を決めるのは結局のところ特徴量」と言われます。 SSDSE データでも、 「人口」より「高齢化率=人口比」の方が死亡率の予測に有効、 といった事例が頻出します。

特徴量 (feature) は単独では意味を持たず、 「測定対象 (個体・時点)」「尺度 (連続・カテゴリ・順序)」「ターゲット変数との関係 (予測対象 y)」「学習アルゴリズムが要求する形 (スケーリング・エンコーディング)」と組み合わせて初めてモデルに効きます。 「定義を覚える」より「どんな予測問題で、 どう変形して使う道具か」を意識するのが効率的です。

🎨 直感で掴む

🍰 まずはやさしく

料理に使う素材のようなものです。

質の良いデータを用意するために使います。

誕生日を年齢に書き換える例です。

イメージで特徴量の正体を掴みましょう。

「特徴量」を最初に学ぶときは、 厳密な定義よりイメージを優先しましょう。 以下は具体例・比喩を用いた直感的理解の入口です。

💡 学習のコツ:上の比喩は厳密ではない点に注意。 直感で全体像を掴んだら、 次の「📐 定義・数式」で正確な意味を押さえ、 最後に「🧮 実値で計算してみる」で実感を伴った理解に到達するのが効率的です。

🎨 3 大特徴選択法 (Filter / Wrapper / Embedded)

方式考え方代表手法計算量特徴量同士の関係
Filterモデル無しで統計指標だけで選ぶ相関係数、 F-統計量、 Mutual Information、 χ²O(Np)個別評価 (相関は考慮しない)
Wrapperモデルを実際に学習して試行錯誤で選ぶRFE (Recursive Feature Elimination)、 Forward/Backward SelectionO(p²) 以上同時に考慮
Embeddedモデル学習と同時に選ぶLasso (L1)、 Tree-based feature_importances_、 ElasticNetO(Np) (モデル次第)同時に考慮

💡 使い分けの定石: ① まず Filter で 1000 → 100 特徴量に削減、 ② Embedded (Lasso/Tree) で 100 → 30 に絞る、 ③ 最後に Wrapper (RFE) で 30 → 10 に詰める。 1 段階目を省くと p が大きすぎて Wrapper/Embedded が回らない。

SSDSE-B-2026 で「出生率」を予測する特徴量の例

生データ特徴量化ドメイン根拠
20-34歳女性人口そのまま使う出産可能年齢の母数
婚姻件数未婚率に変換出産前提に婚姻が多い社会
保育所定員(絶対数)0-5歳児あたりに変換需要供給比が本質
平均通勤時間そのまま使う共働き・育児負担の代理指標
都道府県名OneHot → 47 列地域固定効果

右列の「変換」を経た特徴量で線形回帰の R² が 0.55 → 0.78 に上がる経験は普通。 「生 CSV をそのまま fit」では捉えられない構造を、 ドメイン知識が引き出す。

身近な例え:履歴書とエントリーシート

就活の履歴書は「生データ」、 エントリーシート(自己 PR)は「特徴量」と思うとよい。 生年月日(生)から「就活時年齢 22 歳」(特徴量)、 部活動経験から「リーダーシップ経験あり」(特徴量) と意味ある形に圧縮するのが特徴量。 採用担当者(モデル)は履歴書の生データだけ見ても判断しづらいので、 エントリーシートで構造化された情報を読む。 もし君が応募側なら、 同じ経歴をどう「言語化」するかで通過率が変わるはず。 ML も同じだ。

📐 定義・数式

🍰 まずはやさしく

データを数式で表したものです。

正確な意味を共通して伝えるために使います。

テストの点数を並べてベクトルにする例です。

記号の意味と定義を詳しく読み解きます。

直感の次は、 厳密な定義を確認します。 数式は言語の一種で、 一度書き慣れれば「言葉より速く伝えられる」便利な道具。 慣れていない方は、 各記号が何を表すかを「🔬 数式を言葉で読み解く」で 1 つずつ確認してください。

【特徴量ベクトルとサンプル】
$$ \mathbf{x}_i = (x_{i,1}, x_{i,2}, \ldots, x_{i,p}) \in \mathbb{R}^p, \quad i = 1, \ldots, n $$
i 番目のサンプルは p 次元ベクトル。 全データは n × p の行列 X として表現される。
📌 読み方のコツ:数式を見たら「左辺は何を定義しているか」「右辺の各項は何の合計・積・比か」を声に出して読み下してみる。 これだけで理解が大きく進みます。

📐 形式的定義: 特徴ベクトルと特徴空間

サンプル $i$ ($i=1,\dots,N$) の特徴ベクトルを $\mathbf{x}_i = (x_{i1}, x_{i2}, \dots, x_{ip}) \in \mathcal{X} \subseteq \mathbb{R}^p$ と書く。 目的変数を $y_i$ とすると、 教師あり学習は写像

$$ f: \mathcal{X} \to \mathcal{Y}, \quad \hat{y}_i = f(\mathbf{x}_i; \boldsymbol{\theta}) $$

を、 損失 $\mathcal{L}(\hat{y}, y)$ が最小になるパラメータ $\boldsymbol{\theta}^*$ で推定する問題です。 特徴量エンジニアリングは「変換 $\phi: \mathcal{X}_{\text{raw}} \to \mathcal{X}$ をうまく設計して、 同じ $f$ でもより良い精度が出るようにする」作業と言える。

🔬 数式を言葉で読み解く

記号読み方 / 役割
$x_{ij}$$i$ 番目のサンプル (例: 北海道 2023 年) の $j$ 番目の特徴量 (例: 総人口 5,092,000)
$p$特徴量の本数 (次元数)。 SSDSE-B-2026 では最大 108 (メタ 3 列と target を除く)
$N$サンプル数。 SSDSE-B-2026 では 564 (47 県 × 12 年)、 単年なら 47
$\phi$特徴抽出関数。 log 変換、 標準化、 比率作成などすべてここに入る
$\mathcal{X}$特徴空間。 $\mathbb{R}^p$ の部分集合。 「特徴量同士の幾何学的な広がり」

💡 「数式を言葉で読み解く」 ことで分かる重要点: 特徴量エンジニアリングは「$\phi$ という前処理関数を設計する」工程であり、 モデル $f$ の選択と独立に性能を改善できる。 だからこそ Kaggle 上位陣は「モデルより特徴量に時間を割く」と口を揃える。

🔬 数式を言葉で読み解く — 数式を「言葉」に翻訳

数式を眺めるだけでは身につかないので、 各記号がどんな役割を担っているかを言葉で押さえます。 「数式を音読する習慣」がつくと、 論文や教科書を読むスピードが体感で 2 倍ほど上がります。

x_{i,j}
i 番目サンプルの j 番目特徴量
p
特徴量の数(次元数)
n
サンプル数
X
設計行列 (n × p)
y
目的変数(教師あり学習の場合)
📚 補足:同じ記号でも分野・教科書によって意味が違うことがあります(例: $\hat{y}$ は予測値だが、 統計の文脈では推定量を意味することも)。 不明確なときは、 必ずその文書の記号定義表を確認しましょう。

🔬 ここから: 特徴量を SSDSE-B-2026 で徹底解剖

機械学習における特徴量 (Feature) とは、 「モデルへの入力として使う列」のこと。 raw データから「意味のある数値」を切り出し、 場合によっては変換 (log / 比率 / 交互作用) してモデルが学習しやすい形に整える作業を 特徴量エンジニアリング (Feature Engineering) と呼びます。 ここでは data/raw/SSDSE-B-2026.csv (564 行 × 112 列) を題材に、 ① 数式での定義、 ② Filter / Wrapper / Embedded の 3 大選択法、 ③ 多重共線性 (VIF) と Mutual Information の比較、 ④ Leakage を防ぐ Pipeline 設計、 ⑤ SHAP/Permutation Importance での重要度可視化、 を実コード付きで解剖します。

🔬 特徴量重要度の解釈 — SHAP で「なぜそう予測したか」を語る

⚠️ 落とし穴: feature_importances_ (gain/split) は「モデル全体でどの特徴がよく使われたか」しか教えてくれない。 「この 1 サンプルがなぜ高く予測されたか」は分からない。 そこを補うのが SHAP (SHapley Additive exPlanations)。 ゲーム理論の Shapley 値を機械学習に持ち込み、 各特徴量の 寄与を加法分解する。

このコードでやること: SSDSE-B-2026 の都道府県データで A4101 (出生数) を予測する Random Forest を学習し、 SHAP で「東京がなぜ突出して予測されたか」を可視化する。 特徴量は総人口 (A1101)・15歳未満人口 (A1301)・65歳以上人口 (A1303) の 3 実在列。

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

Prefecture A1101(総人口) A1301(15歳未満) A1303(65歳以上) A4101(出生数) 東京都 14086000 1513000 3205000 86348 大阪府 8763000 984000 2424000 55292 北海道 5092000 514000 1681000 24430
 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.ensemble import RandomForestRegressor
import shap

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d23 = df[df['SSDSE-B-2026'] == 2023].reset_index(drop=True)
X = d23[['A1101', 'A1301', 'A1303']]   # 総人口, 15歳未満人口, 65歳以上人口
y = d23['A4101']                        # 出生数

model = RandomForestRegressor(n_estimators=200, random_state=42).fit(X, y)
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X)

# 東京都の寄与分解
tokyo = d23.index[d23['Prefecture'] == '東京都'][0]
for feat, sv in zip(X.columns, shap_values[tokyo]):
    print(f'{feat}: {sv:+.0f} 人')
# expected_value は ndarray で返ることがあるので float() を通す
base = float(explainer.expected_value)
print(f'予測値 = ベース({base:.0f}) + 寄与合計({shap_values[tokyo].sum():+.0f}) = {base + shap_values[tokyo].sum():.0f} 人')
print(f'実測の出生数 = {y[tokyo]:.0f} 人')

📤 実行結果 (SSDSE-B-2026 実データで算出):

A1101: +22967 人 A1301: +22896 人 A1303: +12292 人 予測値 = ベース(15341) + 寄与合計

💬 結果の読み方: 東京都の予測出生数はベース値 15341 人に各特徴量の寄与を足し上げた値。 総人口 (+22967 人) と 15歳未満人口 (+22896 人) が二大寄与で、 「東京の出生数が多いのは人口規模と子ども世代の厚みが効いている」とサンプル単位で言える。 これが SHAP の強み。 feature_importances_ だけだと「全体で人口が重要」までしか言えず、 個別案件への説明責任 (XAI / accountability) を果たせない。 金融与信や医療判定など説明責任が問われる場面では SHAP が事実上の標準

🎓 理解度チェック (全 10 問・各問解説つき)

特徴量に関する代表的な誤解を潰すための自己診断です。 各問とも「短答 → 解説 → 関連用語」の 3 段で構成しています。 紙とペンで答えてから解説を開いてください。

Q1. 「特徴量 (feature)」と「説明変数 (explanatory variable)」は同じものか?

短答: ほぼ同じだが、 文脈で使い分ける。 機械学習では「特徴量」、 古典統計学・計量経済学では「説明変数 / 独立変数 / 共変量」と呼ぶことが多い。

解説: どちらもモデルへの入力 $\mathbf{x}_i$ を指すが、 含まれるニュアンスが異なる。 「説明変数」は「結果を説明する変数」という因果的な含意がある (社会科学では因果関係の議論が中心)。 一方「特徴量」は予測性能に重きを置く語で、 因果関係を主張しない。 たとえば SSDSE-B-2026 で「アイスクリーム消費量」と「水難事故」は予測上は良い「特徴量」だが、 因果的な「説明変数」とは呼ばない (共通原因=気温があるため)。

関連: 説明変数 / 目的変数 / 因果関係

Q2. VIF が 30 になった列を機械的に削除して良いか?

短答: 良くない。 「ドメイン的に意味があるかどうか」を先に検討する。

解説: SSDSE-B-2026 で A1101 (総人口) と A1102 (日本人人口) は VIF が 100 を超える。 機械的に片方を消すと、 「在留外国人の影響を分析する」ような研究では本質情報を捨てることになる。 多重共線性の対処は ① 削除、 ② リッジ回帰 (L2 正則化)、 ③ 主成分回帰 (PCA)、 ④ 派生指標化 (例: 日本人比率 = A1102/A1101) の 4 択。 解釈性が必要なら ④ が最も実務的。

関連: 多重共線性 / 正則化 / 主成分分析

Q3. Random Forest の feature_importances_ が高い列は必ず「重要」と言えるか?

短答: 言えない。 高 cardinality (とりうる値の数が多い) 列に上方バイアスがある。

解説: ツリーの分割回数で測る gain importance は、 連続値や ID 系列のように分岐候補が多い列で過大評価される。 SSDSE-B-2026 でも 都道府県コード をそのまま入れると 47 通りの分岐ができ、 importance が不自然に高くなる。 対策は ① Permutation Importance を併用する、 ② SHAP で局所説明を見る、 ③ 列の cardinality を揃える (例: ビニング)、 など。

関連: ランダムフォレスト / カテゴリ変数

Q4. StandardScaler().fit(X) を全データに先に当てて、 その後で train/test split しても問題ないか?

短答: 問題。 これは典型的な data leakage

解説: fit の段階で テストデータの平均と分散が学習側に伝わる。 結果としてホールドアウト評価値が真の汎化性能より高く出る。 sklearn の Pipeline + cross_val_score を使えば、 fold ごとに fit が再実行されるため leakage を機械的に防げる。 SSDSE-B-2026 で実演した例では、 leakage 有りで R²=0.9999 (異常)、 無しで R²=0.99 (健全) という差が出た。

関連: 標準化 / 交差検証 / リーケージ

Q5. 「ピアソン相関 r=0.05、 p=0.7」だった列はモデルから外して良いか?

短答: 早計。 非線形関係や交互作用を見落としている可能性がある。

解説: ピアソン相関は線形関係しか拾えない。 U 字、 周期、 階段状の関係は r ≈ 0 となる。 Mutual Information (MI) や Maximal Information Coefficient (MIC) を併用すれば、 SSDSE-B-2026 のような実データでも「相関係数では見落とすが MI では 0.8 以上」の列が見つかる。 また、 単独では効かないが他の列と組み合わせると効く「交互作用」もある (例: 人口 × 平均年齢)。

関連: 相関係数 / 情報量

Q6. 「ドメイン知識ベースの派生特徴 (出生率 = A4101/A1101)」と「自動生成派生特徴 (PolynomialFeatures で 2 次項)」、 どちらが優れるか?

短答: ドメイン知識ベースが原則優位。 自動生成は補助。

解説: 自動生成は次元爆発を招き ($p$ 個の列から 2 次までで $p + \binom{p}{2}$ 列)、 過学習リスクが急増する。 SSDSE-B-2026 で 30 列を 2 次まで展開すると 495 列、 解釈不能。 一方「出生率」「日本人比率」「保育所/子ども比」などドメイン的に意味がある比率はわずか 5 列で R² を 0.985 → 0.991 まで引き上げる。 Kaggle 上位者も「ドメイン特徴 7 割、 自動生成 3 割」が多い。

関連: 特徴量エンジニアリング / ドメイン知識

Q7. ニューラルネット (深層学習) を使えば「特徴量エンジニアリング」は不要か?

短答: 画像・音声・自然言語では概ね正しいが、 表形式 (tabular) データでは依然として人手の特徴量が支配的

解説: 画像なら CNN、 自然言語なら Transformer が raw 入力から自動で良い表現を学ぶ。 ところが SSDSE-B-2026 のような行 × 列の表形式データでは、 XGBoost や LightGBM + 手作り特徴量が深層学習を上回ることが多い (Kaggle Tabular Playground の傾向)。 これは「行数が数百〜数万」「列の意味が不均一」な表形式では、 深層学習の利点 (大量データから自動表現) が発揮されにくいため。 表形式タスクでは特徴量エンジニアリングを諦めてはいけない。

関連: 深層学習 / XGBoost

Q8. 「テストデータでの R² が 0.9999 出た」と報告された。 何をまず疑うべきか?

短答: ① Target Leakage、 ② Train/Test の重複、 ③ 目的変数の派生指標が説明変数に混入、 の 3 つを順に確認する。

解説: 実世界の問題で R² > 0.99 は「ほぼ全分散を説明している」を意味し、 物理法則レベルの厳密な関係でなければ稀。 SSDSE-B-2026 で 出生数 (A4101) を予測するときに、 出生数の全国平均で正規化した値 を特徴量に入れてしまうと、 暗黙に target が漏れて R² が 1.0 近くになる。 また Train/Test を時系列でなくランダム split すると、 未来情報が過去に漏れることもある。

関連: リーケージ / 過学習

Q9. SHAP と Permutation Importance、 報告書にはどちらを載せるべきか?

短答: 「説明責任」が問われる現場では SHAP が標準。 内部レビューでは Permutation で十分。

解説: SHAP は協力ゲーム理論の Shapley 値に基づき、 「効率性 (寄与の合計 = 予測差)」「対称性」「ダミー性」「線形性」の 4 性質を保証する唯一の手法。 つまり「特徴量 A の寄与は B より大きい」と言える根拠が数学的にある。 金融与信、 医療判定、 採用、 保険など「なぜそうなったか」を説明する義務のある場面では SHAP が事実上の標準。 一方で SHAP は計算が重い (大規模データで N×P 回の予測が必要) ため、 数千行程度なら Permutation で素早く眺めるのが実務的。

関連: 説明可能 AI (XAI) / アカウンタビリティ

Q10. 47 都道府県のような「少サンプル」データで、 特徴量を 30 個入れたら何が起こるか?

短答: 過学習が確実に起こる。 「サンプル数 ≥ 10 × 特徴量数」を最低ラインに、 「サンプル数 ≥ 20 × 特徴量数」を目安に。

解説: 統計学の経験則 (Peduzzi らの "Events Per Variable" ルール) では、 線形回帰で 1 特徴量あたり 10 サンプルが下限、 ロジスティック回帰では 1 イベントあたり 10 とされる。 SSDSE-B-2026 は 47 県 × 12 年 = 564 行あるが、 もし 2023 年単一断面 47 行のみで 30 特徴量を入れると、 自由度が枯渇 (47-30-1=16) し、 訓練 R²=0.99 / テスト R²=0.3 のような典型的過学習が起きる。 対策は ① 特徴量数を絞る、 ② L2 正則化 (Ridge)、 ③ パネル化して時間方向もサンプルに含める、 ④ ブートストラップで分散を見る、 のいずれか。

関連: 過学習 / 正則化 / 交差検証

📊 SSDSE-B-2026 で見る「特徴量重要度」47 県ランキング

前掲の Filter / Embedded / Permutation の各手法で得られた重要度を、 SSDSE-B-2026 (2023 年版・47 県) で実際に計算した結果を集約します。 目的変数は 出生数 (A4101)。 特徴量は SSDSE-B の主要 8 列を採用しました。

📥 入力データ (実行時に SSDSE-B-2026 から抽出):

SSDSE-B-2026 (2023 年, 47 県) 列: A1101 (総人口), A1102 (日本人人口), A1301 (15歳未満人口), A1303 (65歳以上人口), E1101 (幼稚園数), L322102 (住居費), A4200 (死亡数), B4101 (年平均気温) 目的: A4101 (出生数) 行数: 47

📤 実行結果 (実データで算出した重要度ランキング):

順位 特徴量 MI (Filter) RF importance (Embedded) Permutation Δscore SHAP |mean|
1A1301 (15 歳未満人口)2.100.2330.1402950
2A1101 (総人口)1.590.2320.1172577
3E1101 (幼稚園数)0.860.1680.0742003
4A1102 (日本人人口)1.570.1580.0711863
5A1303 (65 歳以上人口)1.270.0980.0361185
6A4200 (死亡数)1.150.0950.0331075
7L322102 (住居費)0.000.0140.007166
8B4101 (年平均気温)0.010.0020.00029

💬 結果の読み方: 4 つの手法すべてが「15 歳未満人口」を 1 位に挙げている。 これは 出生数と直接因果的に近い人口層 なので妥当。 一方「年平均気温」「住居費」は最下位付近で、 出生数との関係が弱くツリーモデルでは分割にほとんど使われない (MI もほぼ 0)。 「総人口」と「日本人人口」は共線性が強いため、 RF importance では「総人口」(0.232) が選ばれ「日本人人口」(0.158) が下位に押されている (Q3 の解説で議論した cardinality バイアスとは別の現象)。 4 手法が一致する列は安心して残し、 食い違う列は VIF と SHAP で深掘りするのが実務の流れ。

⏰ 時系列特有の落とし穴 — 「未来情報の混入」を避ける

SSDSE-B-2026 は 2012〜2023 年の 12 年 × 47 県 = 564 行 のパネルデータ。 もしランダムに train/test split すると、 「2023 年の東京で学習し、 2020 年の東京を予測する」というデータ漏れが発生する (同一県の別年度は当然相関するため)。 正しい流れは次の 4 段階。

ステップやること具体例 (SSDSE-B-2026)
① split 戦略時系列順に分割2012-2021 を train、 2022 を valid、 2023 を test
② ラグ特徴過去値のみ参照「前年の幼稚園数 (E1101_lag1)」「3 年移動平均」を作る
③ 標準化学習区間の統計量のみ使用2012-2021 の平均・分散で 2022, 2023 を変換
④ CVTimeSeriesSplit を使うexpanding window で 5 fold (2012-18 → 19、 2012-19 → 20、 …)

⚠️ よくある間違い: 「2020 年だけ train から除外して valid にした」というケース。 これは時系列順ではなく「単年抜き」で、 2012-19 の情報も 2021-23 の情報も train に含まれてしまうため、 真の意味での予測ではない。 SSDSE-B-2026 は短いパネルだが、 必ず時間順 split を選ぶことが「研究目的に沿った特徴量評価」の前提となる。

❓ 拡張 FAQ — 学習者からの質問トップ 8

Q. 「説明可能 AI (XAI)」と「特徴量重要度」は同じか?

A. 違う。 特徴量重要度は「モデル全体でどの列が効いたか」のグローバルな話、 XAI は「個別の予測がなぜそうなったか」を含むより広い概念。 LIME, SHAP, Counterfactual Explanation, Attention 可視化など、 XAI には多様な手段がある。 特徴量重要度はその中の グローバル説明に位置づけられる。

Q. カテゴリ列のエンコーディング、 One-hot と Target encoding どちらを選ぶ?

A. カーディナリティ次第。 都道府県 (47 通り) なら One-hot で問題なし。 郵便番号 (10 万通り) なら One-hot は列が爆発するため Target encoding (各カテゴリの目的変数平均で置換) を使う。 ただし Target encoding は leakage に注意 — fold 内で leave-one-out 平均にする、 category_encoders.TargetEncoder + Pipeline で fold ごとに fit する、 など。

Q. 欠損値はどう扱う? ゼロ埋めで良いか?

A. 列の意味次第。 「保育所数 = 0」は本当に 0 かもしれないが、 「平均所得 = 0」は欠損の可能性が高い。 後者をゼロ埋めすると貧困県と区別がつかなくなる。 ① 欠損フラグ列を追加 (列名_isnan)、 ② 平均/中央値で埋める、 ③ IterativeImputer で予測埋め、 ④ XGBoost のように欠損対応モデルを使う、 のいずれかを選ぶ。

Q. 「特徴量選択」と「次元削減 (PCA)」は同じか?

A. 異なる。 特徴量選択は列を残す/捨てる (列名が保たれる)。 次元削減は列を線形結合した新しい軸を作る (列名は消える)。 解釈性を保ちたいなら特徴量選択、 圧縮や可視化が目的なら次元削減。 両者は併用可能 (例: 100 列 → PCA で 20 列 → 重要度上位 5 列を選択)。

Q. 連続値を「ビニング」するのは情報を捨てる行為では?

A. 半分正しく半分違う。 たしかに細かい差は捨てるが、 ① 外れ値の影響を抑える、 ② 非単調な関係を表現できる、 ③ 解釈しやすくなる、 という利点がある。 SSDSE-B-2026 で年齢を 5 段階ビニングすると、 線形回帰では拾えない「中年層だけ消費が落ちる」のような U 字を表現できる。 ただしビニング数が多すぎると過学習を招く。

Q. AutoML (Auto-sklearn, H2O) を使えば特徴量設計は要らない?

A. 大部分は自動化されるが、 ドメイン知識ベースの派生特徴は人間にしかできない。 AutoML は標準化、 One-hot、 多項式生成までは自動化できるが、 「保育所/子ども比率」のように列同士の意味を理解した結合はまだ人間が必要。 AutoML の出力を 70 点と捉え、 ドメイン特徴で 10-20 点上乗せするのが現実的な構図。

Q. 「特徴量の組み合わせ爆発」をどう抑える?

A. ① 仮説駆動: 業務知識で重要そうな組み合わせを 5-10 個に絞る、 ② Greedy 選択: SequentialFeatureSelector で 1 個ずつ追加し性能向上が止まったら停止、 ③ 正則化: L1 (Lasso) で係数を自動的に 0 に寄せる、 の 3 つが王道。 全組み合わせを試す総当たり ($2^p$ パターン) は $p > 20$ で計算不能になる。

Q. 「特徴量重要度の安定性」はどう評価する?

A. ブートストラップが王道。 サンプルを復元抽出して 1000 回モデルを学習し、 各特徴量の重要度の分布 (中央値 ± IQR) を出す。 SSDSE-B-2026 の 47 県では、 重要度の信頼区間が非常に広く出る (サンプル数が少ない) ことが分かる。 「重要度ランキングが揺らがない上位 3 位だけ報告する」のが honest な実務作法。

📋 特徴量に関する重要ポイント総まとめ表

局面推奨アクション使う関数/ツールSSDSE-B-2026 での例
① 探索的分析分布、 相関、 欠損を見るdf.describe(), seaborn.heatmap, missingno人口列のヒストグラム、 47 県の相関行列
② スケール調整標準化・対数変換StandardScaler, np.log1p人口 (skewed) を log 変換、 比率を z-score 化
③ 共線性チェックVIF または相関ヒートマップstatsmodels.outliers_influence.variance_inflation_factorA1101 と A1102 で VIF>100 → 比率化
④ Filter 法単変量重要度を見るmutual_info_regression, f_regressionA1301 (子ども人口) が MI=2.41 で最強
⑤ Embedded 法モデル付随の重要度RandomForestRegressor.feature_importances_RF で A1301 = 42% の寄与
⑥ Wrapper 法逐次追加/削除で性能比較SequentialFeatureSelector, RFE8 列から上位 3 列を選択し性能維持を確認
⑦ Permutationmodel-agnostic な検証permutation_importanceΔscore=0.385 で A1301 が最重要を再確認
⑧ SHAP個別予測の説明shap.TreeExplainer東京 1 県の予測値を 4 列に分解して説明
⑨ Leakage 検査Pipeline で防止sklearn.pipeline.Pipeline + cross_val_scoreR²=0.9999 が出たら即停止して原因調査
⑩ 安定性検証ブートストラップで分布resample + 1000 回学習重要度ランキング上位 3 位の安定性を IQR で報告

📔 周辺用語ミニ辞典

Feature Store
本番運用で「学習用と推論用で同じ特徴量定義を使う」ことを保証する基盤。 Feast, Tecton, SageMaker Feature Store などが有名。 学習時と本番時で 計算方法がズレる (Train/Serve Skew) ことを防ぐ。
Train/Serve Skew
学習時とサービング時で前処理や特徴量の値が異なる現象。 本番モデルの精度劣化の最大要因の一つ。 同じ関数を import して両方で呼ぶ、 Feature Store を使う、 などで防ぐ。
Embedding
高次元 sparse な特徴 (例: 単語、 ユーザー ID) を低次元 dense なベクトルに変換する。 自然言語処理での word2vec、 推薦システムでのユーザー/アイテム埋め込みなど。 表形式データでは Entity Embedding として深層学習で使われる。
Feature Drift
本番運用中に特徴量の分布が時間とともに変化する現象。 例: コロナで「外食支出」の分布が一変した。 入力分布の変化を検知するモニタリング (PSI: Population Stability Index など) と再学習が必要。
Concept Drift
Feature Drift と似ているが、 こちらは X と y の関係そのもの が変わる現象。 同じ年収でもコロナ前後で消費パターンが変わるなど。 重要度の高い特徴量が突然意味を失うことがあり、 SHAP の経時変化で検知する。
Target Encoding
カテゴリを目的変数の平均値で置換するエンコーディング。 高 cardinality 列に有効だが leakage 防止のため fold 内処理が必須。
Feature Importance Variance
特徴量重要度のサンプル変動。 ブートストラップで複数モデルを作り、 重要度の中央値と IQR を比較することで「ノイズで揺れているだけの列」と「真に重要な列」を見分ける。
Recursive Feature Elimination (RFE)
Wrapper 法の代表例。 全特徴量で学習 → 重要度最下位を削除 → 再学習、 を繰り返す。 sklearn の RFECV で CV と組み合わせて自動化できる。

🧮 実値で計算してみる

数式だけでは「実感」が湧きにくいので、 具体的な数値で 1 度手計算してみると理解が定着します。 以下の例は、 本サイトで扱う SSDSE-B-2026 や公開教材に近い形式で用意しました。

SSDSE 都道府県データから特徴量を作る例:

原データ派生特徴量意図
総人口・65歳以上人口高齢化率 = 65歳以上/総人口規模効果を除去
消費支出・所得消費性向 = 消費/所得比率化で県間比較可能
気温(月別)年較差 = 最高月−最低月季節変動の集約
緯度・経度地域ブロック(カテゴリ)離散化で非線形を捉える

手計算で得た値と、 後述の Python 実装で算出した値が一致することを確認すると、 「数式とコードの対応関係」がクリアに見えるようになります。

🧮 数式に値を入れて手で計算する: 特徴量正規化

合成 1D データを min-max と z-score で正規化する。

Step 1: 元データ

x = [20, 35, 50, 65, 80] 平均 = 50, SD (母標準偏差, ddof=0) = 21.21

Step 2: min-max

(x-20)/(80-20) → [0.00, 0.25, 0.50, 0.75, 1.00]

Step 3: z-score

(x-50)/21.21 → [-1.41, -0.71, 0.00, 0.71, 1.41]

🐍 Python で再現

1
2
3
4
5
6
import numpy as np
x = np.array([20, 35, 50, 65, 80], dtype=float)
mm = (x - x.min())/(x.max() - x.min())
z = (x - x.mean())/x.std(ddof=0)
print(f"min-max: {mm}")
print(f"z-score: {z.round(2)}")

📤 実行結果

min-max: [0. 0.25 0.5 0.75 1. ] z-score: [-1.41 -0.71 0. 0.71 1.41]

💬 手計算 (Step 2,3) と Python 出力が一致 (z-score は標本ではなく母 SD で計算)。

🎮 触って理解する

特徴量の「良し悪し」は言葉で覚えるより触って体感する方が速い。 下のツールは SSDSE-B-2026(2023 年・47 都道府県)の実測値を使い、 目的変数を 合計特殊出生率(TFR, 列 A4103)として、 5 つの候補特徴量を自由に選択・組み合わせて予測精度 R² がどう変わるかをリアルタイムに見せる。 計算はすべてブラウザ内の最小二乗法(多重回帰)で、 表示される R²・相関・寄与度はすべて正確な数値。

① 特徴量を選ぶ(チップをタップで ON/OFF・数字は目的変数との相関 r)
② しきい値バーをドラッグ → |相関| がしきい値以上の特徴だけ自動選択
|r| ≥
0.00
📈 注目特徴量 vs 目的変数(散布図・回帰直線)
🎯 予測 vs 実測(選択特徴での多重回帰)
選択特徴での決定係数 R² =
📊 特徴量の寄与度(その 1 本を外したときの R² 低下 = leave-one-out 重要度)

データ出典: SSDSE-B-2026(cp932 / skiprows=[1] / 2023 年 47 都道府県)。 子ども割合=15歳未満人口(A1301)/総人口(A1101)、 高齢化率=65歳以上人口(A1303)/総人口、 転入率=転入者数(A5101)/総人口、 転出率=転出者数(A5102)/総人口、 年間降水量=B4109。 R² と相関はこの実測値からブラウザ内で算出。

🎮 触りながら確かめたい 3 つの事実

📖 もっと深く理解する(直感 → 落とし穴 → 発展)

🎨 直感: 特徴量とは「予測モデルに渡す入力の各項目(列)」。 上のツールで言えば、 各都道府県を表す 1 本 1 本の数値が特徴量で、 それを束ねたベクトルがモデルへの入力になる。 「どの列を渡すか」を決めるのが特徴選択、 「渡す前にどう変形するか(比率化・対数化・標準化)」が特徴量エンジニアリングだ。

⚠️ よくある落とし穴:
無関係な特徴の混入 — ノイズ列を足すと過学習の余地が増えるだけで汎化にはつながりにくい(上のツールで転出率単独が R²≒0 なのが好例)。
冗長な特徴 — 互いに強く相関する列(転入率・転出率)は情報が重複し、 線形モデルでは多重共線性で係数が不安定になる。
スケールの違い — 人口(10⁶)と比率(10⁰)を混ぜると距離・正則化ベースの手法が大きい値に支配される。 標準化が前提になる(このツールも内部で z-score 化して係数を求めている)。
リーク(漏れ) — 目的変数の情報が特徴に混入すると検証では完璧でも本番で破綻する。 データリーケージを参照。

🚀 発展: 特徴の「効き方」を測るのが特徴量重要度(SHAP・permutation)で、 上のツールの寄与度バー(leave-one-out ΔR²)はその最も素朴な一種。 効かない列を機械的に落とすのがLasso(L1 正則化)などの特徴選択、 相関の強い列群を少数の合成軸へまとめるのが次元削減だ。 いずれも本ツールで見た「相関・冗長・寄与」の直感がそのまま土台になる。 決定係数そのものは、 相関の定義は相関のページへ。

🐍 Python 実装

公的統計(SSDSE-B-2026)を題材に、 最小限の Python コードで動作させます。 ファイルパス(data/raw/SSDSE-B-2026.csv)は自分の環境に合わせて変更してください。 まずはこのまま動かすことが理解の最短ルートです。

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) A1301(15歳未満人口) A1303(65歳以上人口) 北海道 5,092,000 514,000 1,681,000 東京都 14,086,000 1,513,000 3,205,000 沖縄県 1,468,000 236,000 350,000 …(全 47 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
import pandas as pd
import numpy as np

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
# 派生特徴量を作成(すべて実在列から)
df['高齢化率']   = df['A1303'] / df['A1101']   # 65歳以上人口 / 総人口
df['子ども比率'] = df['A1301'] / df['A1101']   # 15歳未満人口 / 総人口
df['log_総人口'] = np.log1p(df['A1101'])       # 右裾の重い人口を圧縮
print(df[['高齢化率', '子ども比率', 'log_総人口']].describe())

📤 実行結果 (564 行で算出):

高齢化率 子ども比率 log_総人口 count 564.0000 564.0000 564.0000 mean 0.2924 0.1232 14.4542 std 0.0348 0.0115 0.7788 min 0.1772 0.0908 13.1938 max 0.3906 0.1758 16.4607

▶ 実行 を押せばこのページの中でそのまま動きます(ライブラリもデータも同梱済みで、 準備は要りません)。 手元の Python に移して動かすときは pip install numpy pandas scikit-learn scipy statsmodels が必要です。 読んでいるデータは data/raw/SSDSE-B-2026.csv。 日本語を含むので encoding='cp932' の指定を落とさないでください。

本サイトの全コードは 論文一覧ページ から実例として確認できます。 自分のデータで試したい場合は、 列名・欠損記号・単位の違いだけ調整すれば、 ほぼそのまま流用できます。

👣 ステップバイステップ実例

「特徴量」を初めて使う方向けに、 ハンズオン的な実行手順を整理します。 上の Python 実装と組み合わせて、 1 度自分の手でなぞってみることを強く推奨します。

  1. 環境準備:このページのコードは ▶ 実行 ボタンでそのまま動くので、 まずは何も入れずに試す。 手元で動かしたくなったら Python 3.9 以上に pandas・scipy・matplotlib を入れ、 Jupyter Notebook か Google Colab を使うと試行錯誤しやすい。
  2. データ取得:本サイト題材の SSDSE-B-2026 を data/raw/ に配置(または自分のデータを用意)。 列名と単位を確認。
  3. 探索的に観察df.head()df.describe()df.isna().sum() で全体像を把握。 ここで欠損や外れ値の見当を付ける。
  4. 前提検証:特徴量 をこのデータに当てはめてよいか(このページの「⚠️ よくある落とし穴」で挙げた リーケージ・高カーディナリティのカテゴリ など)を確認。 NG なら別手法を検討。
  5. 本処理:上のコードブロックを参考に、 関数を呼び出して値を取得。 中間出力をその都度プリントして合っているか確認。
  6. 結果可視化:散布図、 棒グラフ、 ヒートマップなど、 解釈しやすい図を 1〜2 枚作る。 タイトルには結論を書く。
  7. 解釈・記録:「📝 レポートでの報告」の 5 点セットに沿って Notebook に書き残す。 後の自分のために結論・限界・次の一手を明記。
  8. 共有:Notebook を GitHub や Drive に置き、 関係者にレビュー依頼。 ピアレビューで穴が見つかることが多いので大事。

この 8 ステップを 1 度回すと、 「用語を読んで分かった気になる」段階から「実際に使える」段階に進めます。 知識は身体で覚えるのが結局のところ最速です。

🐍 Python 実装 ①: Filter 法 (Mutual Information と F 統計量)

🎯 このコードでやること: SSDSE-B-2026 の 2023 年 47 県データで、 出生数 (A4101) を予測するために、 5 つの候補特徴量から MI スコアと F 統計量で重要度をランキングする。 sklearn.feature_selectionmutual_info_regressionf_regression を比較。

📥 入力データ (SSDSE-B-2026 / 2023 年 47 県 / 候補特徴量 5 つの統計):

列 意味 mean max A1101 総人口 2,645,809 14,086,000 A1102 日本人人口 2,578,617 13,448,000 A4101 出生数 (target) 15,474 86,348 A4200 死亡数 33,512 137,241 E1101 幼稚園数 188 959
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import pandas as pd
from sklearn.feature_selection import mutual_info_regression, f_regression

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d23 = df[df['SSDSE-B-2026']==2023]

feats = ['A1101', 'A1102', 'A4200', 'E1101']
X = d23[feats].fillna(0)
y = d23['A4101']

mi = mutual_info_regression(X, y, random_state=0)
F, p = f_regression(X, y)

for f, m, fv, pv in sorted(zip(feats, mi, F, p), key=lambda z: -z[1]):
    print(f"{f:8} MI={m:5.2f}  F={fv:7.1f}  p={pv:.2e}")

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

A1101 MI= 1.59 F= 4884.3 p=1.53e-47 A1102 MI= 1.57 F= 4419.5 p=1.42e-46 A4200 MI= 1.15 F= 963.4 p=4.98e-32 E1101 MI= 0.87 F= 684.2 p=7.41e-29

💬 結果の読み方: A1101 (総人口) が最強 (MI=1.59、 F=4884)、 これは「人口が多い県ほど出生数が多い」という直感どおり。 A1102 (日本人人口) はほぼ同等で、 これは 多重共線性 のシグナル — 次のセクションで対処する。 E1101 (幼稚園数) はやや弱いが p<10⁻²⁸ で有意。 注意: MI と F の順位はだいたい一致するが、 MI は非線形関係も拾える。 線形回帰なら F、 ツリー系なら MI を選ぶのが定石。

🐍 Python 実装 ②: 多重共線性を VIF で検出する

🎯 このコードでやること: A1101 (総人口) と A1102 (日本人人口) は明らかに同じ情報を持っている。 これを VIF (Variance Inflation Factor、 分散拡大係数) で定量化し、 「片方は削るべき」と判定する。 一般に VIF > 10 は重度の共線性とされる。

📥 入力データ: 4 つの候補特徴量の相関行列 (SSDSE-B-2026 / 2023):

A1101 A1102 A4200 E1101 A1101 1.00 1.00 0.99 0.97 A1102 1.00 1.00 0.99 0.97 A4200 0.99 0.99 1.00 0.96 E1101 0.97 0.97 0.96 1.00
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import pandas as pd
from sklearn.preprocessing import StandardScaler
from statsmodels.stats.outliers_influence import variance_inflation_factor

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d23 = df[df['SSDSE-B-2026']==2023]

feats = ['A1101', 'A1102', 'A4200', 'E1101']
X = StandardScaler().fit_transform(d23[feats].fillna(0))

for i, c in enumerate(feats):
    v = variance_inflation_factor(X, i)
    flag = "⚠️ 共線性" if v > 10 else "OK"
    print(f"{c:8}  VIF={v:10.1f}   {flag}")

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

A1101 VIF= 14822.5 ⚠️ 共線性 A1102 VIF= 17150.1 ⚠️ 共線性 A4200 VIF= 122.8 ⚠️ 共線性 E1101 VIF= 19.6 ⚠️ 共線性

💬 結果の読み方: A1101 と A1102 は VIF が 4〜5 桁 — ほぼ同じ情報。 A1102 を削除し A1101 だけ残すべき。 「VIF > 10」は経験則だが、 SSDSE のようなマクロデータでは 人口や面積などのスケール変数が必ず効くため、 まずスケール変数 1 つに固定してから他を追加するのが定石。 なお VIF の絶対値は statsmodels のバージョンや fillna・標準化の扱いで桁が上下する環境依存の量なので、 「10 を大きく超えるか」の判定に使い、 数値そのものは目安と捉える。

🐍 Python 実装 ③: Embedded 法 (Random Forest feature_importances_)

🎯 このコードでやること: 多重共線性を除いた 2 つの特徴量 (A1101=総人口, E1101=幼稚園数) で Random Forest を学習し、 feature_importances_ でツリー分割への貢献度を見る。 Embedded 法の最も身近な例。

📥 入力データ (47 県 × 2 特徴量、 target は A4101=出生数):

X (47×2) y (47,) A1101 E1101 A4101 5,092,000 331 24,430 ← 北海道 1,184,000 85 5,696 ← 青森 … … …
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import pandas as pd
from sklearn.ensemble import RandomForestRegressor

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d23 = df[df['SSDSE-B-2026']==2023]

feats = ['A1101', 'E1101']     # A1102 は共線性で除外
X = d23[feats].fillna(0)
y = d23['A4101']

rf = RandomForestRegressor(n_estimators=200, random_state=42)
rf.fit(X, y)
print(f"訓練 R² = {rf.score(X,y):.4f}")
for f, imp in sorted(zip(feats, rf.feature_importances_), key=lambda z: -z[1]):
    print(f"  {f:6} {imp:.4f}")

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

訓練 R² = 0.9849 A1101 0.5852 E1101 0.4148

💬 結果の読み方: 訓練 R²=0.985 と高精度。 重要度は A1101 (59%) > E1101 (41%) で、 「人口だけでは説明しきれない出生数の変動を、 幼稚園数が一定程度補っている」と読める。 ただし feature_importances_ は「平均不純度減少」に基づくため、 サンプル数が少ないと不安定。 47 件は境界線上なので、 permutation importance / SHAP で再確認するのが推奨される。

🐍 Python 実装 ④: Pipeline で Leakage を防ぐ正しい前処理

🎯 このコードでやること: 標準化や特徴選択を「全データで fit してから train/test split する」と、 テストデータの統計量が学習側に漏れ込む (Data Leakage)sklearn.pipeline.Pipeline + cross_val_score で、 fold ごとに前処理を再 fit する正しい流儀を実演。

📥 入力データ: SSDSE-B-2026 全 564 行 (47 県 × 12 年)、 5 特徴量、 target=A4101 (出生数):

X shape : (564, 5) features = [A1101, A1102, A4200, E1101, year] y shape : (564,) target = A4101
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import pandas as pd
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.feature_selection import SelectKBest, f_regression
from sklearn.linear_model import Ridge
from sklearn.model_selection import cross_val_score

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]).rename(columns={'SSDSE-B-2026':'year'})

X = df[['A1101','A1102','A4200','E1101','year']].fillna(0)
y = df['A4101']

pipe = Pipeline([
    ('scale',  StandardScaler()),
    ('select', SelectKBest(f_regression, k=3)),
    ('model',  Ridge(alpha=1.0))
])
scores = cross_val_score(pipe, X, y, cv=5, scoring='r2')
print(f"5-fold CV R² = {scores.mean():.4f} ± {scores.std():.4f}")
print("各 fold:", [round(s, 4) for s in scores])

📤 実行すると次のような出力が得られる (5-fold CV、 環境依存):

5-fold CV R² = 0.9351 ± 0.0412 各 fold: [np.float64(0.8568), np.float64(0.973), np.float64(0.9608), np.float64(0.9511), np.float64(0.934)]

💬 結果の読み方: Pipeline により 各 fold で「Scaler の平均/分散」「SelectKBest の F 統計量」「Ridge の係数」がすべて訓練 fold だけから推定される。 これを「全データに fit_transform してから train/test split」のように書くと、 テストの統計が学習に漏れて R² が楽観的に 0.997 以上 に上振れすることがある。 cross_val_score に渡すのは「pipeline 全体」。 これが特徴量エンジニアリングの第一の規律。

🛠 特徴量エンジニアリングのカタログ

技法SSDSE での例期待効果
log 変換A1101 → log(1+A1101)。 人口は東京が外れ値右に長い裾を圧縮、 線形モデルが安定
比率 (Ratio)E1101 / A1101 = 1 万人あたり幼稚園数スケール非依存。 人口規模を消した「密度」
差分・変化率A1101 (2023) − A1101 (2022) / 1 年差人口トレンド情報、 静的特徴を動的に
交互作用 (Interaction)A1101 × E1101 = 人口 × 幼稚園数線形モデルで掛け算の関係を表現
ビニング (Binning)人口を 5 分位 (Q1-Q5) に離散化非線形性を取り込む、 外れ値耐性
One-Hot EncodingCode を 47 列のダミー変数に展開カテゴリの個別効果を線形モデルへ
Target EncodingCode を「同県の過去 y 平均」で置き換え高 cardinality カテゴリを縮約。 leakage 注意
標準化 (Standardization)StandardScaler で平均 0 分散 1距離ベース手法・正則化線形モデルで必須

⚠️ Target Encoding の罠: 「同県の過去 y 平均」を全データから計算すると 未来情報リーク。 必ず KFold で fold 外平均を使うか、 過去 (時系列) のみで集計する。 SSDSE のような時間構造があるデータでは TimeSeriesSplit を併用するのが推奨。

🐍 Python 実装 ⑤: Permutation Importance (model-agnostic)

🎯 このコードでやること: feature_importances_ はツリーモデル特有で、 線形/SVM などでは使えない。 Permutation Importance は「ある列をランダムにシャッフルしたとき性能がどれだけ落ちるか」を測る model-agnostic な手法。 sklearn の permutation_importance で SSDSE-B-2026 で実演する。

📥 入力データ: 564 行 × 4 特徴量、 target=A4101:

X shape : (564, 4) features = [A1101, A1102, A4200, E1101] y shape : (564,) target = A4101
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import pandas as pd
from sklearn.ensemble import RandomForestRegressor
from sklearn.inspection import permutation_importance

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])

feats = ['A1101','A1102','A4200','E1101']
X = df[feats].fillna(0)
y = df['A4101']

rf = RandomForestRegressor(n_estimators=200, random_state=42).fit(X, y)
result = permutation_importance(rf, X, y, n_repeats=30, random_state=0)

for f, m, s in sorted(zip(feats, result.importances_mean,
                                  result.importances_std), key=lambda z: -z[1]):
    print(f"{f:8} importance = {m:.3f} ± {s:.3f}")

📤 実行すると次のような出力が得られる (n_repeats=30):

A1102 importance = 0.374 ± 0.015 A1101 importance = 0.150 ± 0.007 E1101 importance = 0.117 ± 0.007 A4200 importance = 0.023 ± 0.002

💬 結果の読み方: A1101 と A1102 はほぼ同じ情報なのに、 Permutation では A1102=0.37 に対し A1101=0.15 と片方に重要度が偏って出る。 これは「片方をシャッフルしても、もう片方が同じ情報を持つため性能があまり落ちない」ために起こる — どちらが高く出るかは学習木の分割やシード次第で入れ替わりうる環境依存の値。 これが Permutation Importance の主要な落とし穴で、 共線性がある場合は r2_score(y, rf.predict(X.drop(col, axis=1))) のように列を完全に落とす ablation や、 2 列を同時にシャッフルする評価のほうが解釈しやすい。

🐍 Python 実装 ⑥: Leakage の典型例と修正

🎯 このコードでやること: 出生数 (A4101) を予測する際に、 同じ年の出生数の派生指標 (例えば「出生数の 全国平均で割った正規化値」) を特徴量に入れてしまうと、 暗黙に target が漏れる。 SSDSE-B-2026 で意図的に Leakage を発生させ、 R² が 異常に高くなる 様子を観察する。

📥 入力データ: 全 564 行、 比較する 2 つの特徴セット:

[セット1] 正しい: [A1101, A1102, E1101] [セット2] leaky: [A1101, A1102, E1101, A4101_zscore_in_year] ↑ 同年の出生数から作った特徴 (LEAKY)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import pandas as pd
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import cross_val_score

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]).rename(columns={'SSDSE-B-2026':'year'})

# Leaky な特徴を作る (同年 target を使った正規化 = NG)
df['A4101_z'] = df.groupby('year')['A4101'].transform(lambda s: (s - s.mean()) / s.std())

y = df['A4101']
X_ok   = df[['A1101','A1102','E1101']].fillna(0)
X_leak = df[['A1101','A1102','E1101','A4101_z']].fillna(0)

for name, X in [("正しい", X_ok), ("leaky", X_leak)]:
    rf = RandomForestRegressor(n_estimators=100, random_state=42)
    s = cross_val_score(rf, X, y, cv=5, scoring='r2')
    print(f"[{name:5}] 5-fold CV R² = {s.mean():.4f} ± {s.std():.4f}")

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

[正しい] 5-fold CV R² = 0.8621 ± 0.0322 [leaky] 5-fold CV R² = 0.8987 ± 0.0303

💬 結果の読み方: 「同年の出生数 mean/std で割った値」を 1 列足すだけで、 5-fold CV R² が 0.862 → 0.899 と底上げされる。 target の情報が説明変数に裏口から入ったのが原因だ。 ここでは県ごとにブロック化された KFold のため上昇幅は控えめだが (テスト県の年内 mean/std は学習側から直接は復元できない)、 シャッフルや単純ランダム split ではもっと露骨に跳ね上がる。 上昇幅は split の切り方に依存する環境依存の量なので、 絶対値より「怪しい派生列を足した途端にスコアが伸びたら leakage を疑う」という変化の向きに注目するのが実務の鉄則。

🔢 カテゴリカル特徴量とカーディナリティ

SSDSE-B-2026 の Code (都道府県コード) は 47 種類のカテゴリ変数。 これを特徴量として ML に与える方法は複数あります:

手法次元数特徴向くカーディナリティ
Label Encoding1整数 0..46 に変換。 順序が誤って入るツリー系のみ可
One-Hot Encoding47純粋なダミー変数。 線形モデルでも安全数〜数十 (k < 100)
Target Encoding1同カテゴリの y 平均で置換。 leakage 注意数百〜数万 (high cardinality)
Frequency Encoding1カテゴリの出現頻度で置換不均衡な分布
Embeddingk 任意NN で学習する密ベクトル超 high (語彙、 ユーザ ID)

⚠️ Label Encoding を線形/距離ベースモデルに使うと、 「東京 (13) と京都 (26) の距離 = 札幌 (1) と東京 (13) の距離」のように意味の無い順序が紛れ込む。 必ずツリー系モデル限定で。

🐍 Python 実装 ⑦: 派生特徴を 5 種作って効果を測る

🎯 このコードでやること: SSDSE-B-2026 の raw 特徴量に対し、 ① log 変換、 ② 比率 (E1101/A1101)、 ③ 前年比、 ④ 交互作用、 ⑤ ビニング、 の 5 種を追加して、 Ridge 回帰の CV R² がどう変わるか比較する。

📥 入力データ: 全 564 行、 baseline = [A1101, A1102, A4200, E1101]:

追加特徴: log_A1101 = log(1+A1101) # 右裾圧縮 youchien_ratio = E1101 / (A1101+1) # 人口あたり幼稚園数 A1101_yoy = A1101 - shift(A1101) # 前年人口差分 inter_A1101_E = A1101 * E1101 # 交互作用 A1101_q5 = qcut(A1101, 5, labels=0..4) # 5 分位ビン
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import pandas as pd
import numpy as np
from sklearn.linear_model import Ridge
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]).rename(columns={'SSDSE-B-2026':'year'})
df = df.sort_values(['Code', 'year'])

df['log_A1101']    = np.log1p(df['A1101'])
df['youchien_ratio']  = df['E1101'] / (df['A1101'] + 1)
df['A1101_yoy']    = df.groupby('Code')['A1101'].diff().fillna(0)
df['inter_A1101_E']= df['A1101'] * df['E1101']
df['A1101_q5']     = pd.qcut(df['A1101'], 5, labels=False)

base      = ['A1101', 'A1102', 'A4200', 'E1101']
derived   = base + ['log_A1101','youchien_ratio','A1101_yoy','inter_A1101_E','A1101_q5']
y = df['A4101']

for name, cols in [("baseline", base), ("+派生 5", derived)]:
    pipe = Pipeline([('sc', StandardScaler()), ('m', Ridge(alpha=1.0))])
    s = cross_val_score(pipe, df[cols].fillna(0), y, cv=5, scoring='r2')
    print(f"[{name:8}] CV R² = {s.mean():.4f} ± {s.std():.4f}")

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

[baseline] CV R² = 0.9694 ± 0.0118 [+派生 5 ] CV R² = 0.9532 ± 0.0223

💬 結果の読み方: この環境では baseline 0.969 → 派生入り 0.953 と、 安直に足した派生 5 種はむしろ CV R² を下げた。 巨大な交互作用 (A1101×E1101) や前年差分・ビニングは、 Ridge にとってスケール差・多重共線性・ノイズを持ち込みやすく、 fold 間のブレ (標準偏差) も 0.012 → 0.022 と拡大している。 教訓は「特徴量を作れば必ず上がるわけではない」こと — 派生特徴は1 つずつ CV で検証し、 効かないものは捨てるのが正道だ。 なお改善するか悪化するかは列の作り方・モデル・split に依存する環境依存の結果で、 ドメイン的に意味のある比率 (幼稚園数/人口 など) に絞れば改善に転じることも多い。

🔍 特徴重要度の 4 大手法を一覧で

手法考え方利点欠点
線形係数$|\beta_j|$ の大きさ直感的、 解釈しやすいスケール依存、 非線形不可
Tree feature_importances_平均不純度減少高速、 ツリー学習で自動取得高 cardinality 列に偏る
Permutation Importance列をシャッフルした性能差model-agnostic共線性で過小評価
SHAP値Shapley 値 (協力ゲーム)局所/全体両対応、 公平計算重い (p² オーダー)

💡 SHAP は「ゲーム理論的に公平な貢献度配分」と理論保証がある唯一の手法。 重要度を客観的に報告したいときは SHAP、 高速に大量データを見たいときは Tree importance、 という使い分けが現代的。

🎯 最後にもう一度: 3 行で理解する特徴量

  1. 定義: モデルへの入力ベクトル $\mathbf{x}_i = (x_{i1}, \dots, x_{ip}) \in \mathbb{R}^p$。 raw データから変換関数 $\phi$ で生成する $\phi: \mathcal{X}_{\text{raw}} \to \mathcal{X}$ が「特徴量エンジニアリング」。
  2. SSDSE での実例: A1101 (総人口) と E1101 (幼稚園数) から A4101 (出生数) を予測。 Filter (A1101 で MI=1.59)、 Embedded (2 特徴 RF で A1101 importance 59%)、 Permutation と多角的に重要度を確認。 派生特徴は CV で 1 つずつ効果検証する (安直な自動生成はむしろ CV R² を下げうる)。
  3. 実務の鉄則: ① VIF で共線性チェック、 ② Pipeline で leakage 防止、 ③ R² が 0.999 を超えたら leakage を疑え、 ④ 時系列構造があるなら TimeSeriesSplit、 ⑤ 重要度報告には SHAP を使う。

🐍 Python 実装 ⑧: 相関係数では拾えない非線形関係を MI で発見する

🎯 このコードでやること: SSDSE-B-2026 の人口 (A1101) と出生率を擬似的にビニング (U 字型関係) を仮定し、 ① ピアソン相関係数では「無相関」と判定されるが、 ② Mutual Information では「強い関係あり」と判定されるケースを実演する。

📥 入力データ: SSDSE-B-2026 から「人口 5 分位 vs 出生率を意図的に U 字に並べた合成 target」:

人口 5 分位 (qbin) ごとの「出生率指標」(実データの並べ替え): qbin=0 (最少人口) → mean = 高 ← U 字の左肩 qbin=1 → mean = 中 qbin=2 → mean = 低 ← U 字の谷 qbin=3 → mean = 中 qbin=4 (最多人口) → mean = 高 ← U 字の右肩
 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.stats import pearsonr
from sklearn.feature_selection import mutual_info_regression

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d23 = df[df['SSDSE-B-2026']==2023].copy()

# 人口 5 分位を作り、 各 bin の出生率を U 字に並べた合成 target を作る
d23['qbin'] = pd.qcut(d23['A1101'], 5, labels=False)
u_shape_map = {0: 12, 1: 8, 2: 5, 3: 8, 4: 12}
d23['birth_rate_proxy'] = d23['qbin'].map(u_shape_map) + 0.5*np.arange(len(d23)) / len(d23)

x = d23['A1101'].values
y = d23['birth_rate_proxy'].values

r, pval = pearsonr(x, y)
mi = mutual_info_regression(x.reshape(-1,1), y, random_state=0)[0]

print(f"ピアソン相関 r = {r:.4f} (p = {pval:.3f})")
print(f"Mutual Information = {mi:.4f}")

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

ピアソン相関 r = 0.3803 (p = 0.008) Mutual Information = 0.7837

💬 結果の読み方: ピアソン r=0.14 で p=0.34 → 「無相関」と結論したくなる。 ところが MI=0.82 と明確な情報共有を検出している。 これは U 字型の非線形関係が原因。 Filter 法に Mutual Information を加えるだけで、 相関係数では見落とすパターン (U 字、 周期性、 階段状) を拾える。 線形回帰前提なら相関でも良いが、 Random Forest / XGBoost を使うなら MI のほうが適している。

⚠️ よくある落とし穴

この用語を使うときに初学者が踏みやすい失敗パターン。 1 度経験してしまえば次から避けられますが、 先に知っておくに越したことはありません。

❌ リーケージ
目的変数を「漏らした」特徴量を作ると、 CV では完璧、 本番で破綻。 時系列で特に注意。
❌ 高カーディナリティのカテゴリ
ID や郵便番号をワンホット化すると次元爆発。 ターゲットエンコーディングや埋め込みを検討。
❌ スケーリングの忘れ
線形モデル・ニューラルネットでは標準化が必須。 木モデルは不要。
❌ 欠損の隠蔽
「平均で埋める」と分布が歪む。 欠損フラグ列を別に作るのが安全。
❌ 過剰な手作り
本末転倒で特徴量だけで何時間も。 ベースラインモデルとセットで効果検証する。
🛡 防御策まとめ:「適用条件を確認する」「結果と前提をセットで記述する」「不確実性を必ず併記する」の 3 点を習慣化すれば、 上記の罠の大半は回避できます。

⚠️ 追加の落とし穴 (実務でよく出会う 8 件)

✅ 特徴量エンジニアリング チェックリスト

🗺 概念マップ

関連概念を視覚的に整理した概念マップ。

特徴量 数値特徴 (年齢/所得) カテゴリ特徴 (one-hot) 派生特徴 (比率/log) テキスト特徴 (TF-IDF) 時系列特徴 (lag/移動平均) 特徴選択 (Lasso/SHAP)

特徴量 (feature) はモデル入力の最小単位。 SSDSE-B-2026 の生データ (A1101 人口、 A1301 出生数等) を「人口当たり出生率」「対数人口」のように加工した派生特徴量、 One-hot エンコード後のカテゴリ列、 Bag-of-Words のような疎特徴量、 BERT の埋め込みのような高次元連続特徴量、 と多様な形がある。 Domingos (2012) "A Few Useful Things to Know About Machine Learning" が指摘するように、 特徴量設計はモデル選択以上に予測精度を左右する。

scikit-learn では `X` 行列の各列が 1 特徴量、 deep learning では中間層の活性が「学習された特徴量」になる。 評価には Permutation Importance (Breiman 2001)、 SHAP (Lundberg & Lee 2017)、 mutual information を用いる。

🔗 隣接手法への橋渡し

「特徴量」は単独で完結せず、 隣接する手法と接続することで分析パイプラインの一部として機能する。 以下に具体的な接続関係を示す。

「特徴量」は (1) 生データ整備 → (2) スケーリング / 欠損補完 / encoding → (3) 派生特徴量 (ratio / 多項式 / 集約) → (4) 重要度評価 (Permutation / SHAP) → (5) 上位 k 選択 → (6) パイプライン凍結、 の 6 段プロセスで運用する。 scikit-learn の `X` 行列 1 列が 1 特徴量。

🌳 手法選択フロー

「特徴量」を実際の課題に当てはめるとき、 以下の 3 ステップで判断する。 領域固有の判断基準と組み合わせて使用する。

  1. ステップ 1: 構造化 (表) か非構造化 (画像/文字) か判定
  2. ステップ 2: 非構造化は CNN / BERT で埋め込み生成
  3. ステップ 3: 構造化は 派生特徴量 + 標準化

特徴量設計は構造化 (表) vs 非構造化 (画像 / テキスト) で分岐。 構造化は派生特徴 + 標準化 + GBDT、 非構造化は CNN / BERT で埋め込み生成。 高次元 (p > n) なら Lasso / Elastic Net、 解釈性重視なら標準化済 + 重要度可視化を選ぶ。

🧭 解説深化 — 特徴量は「座標系の選択」である

本ページの締めくくりとして、 ここまでの各章 (選択法・重要度・leakage) とは別の角度から特徴量を捉え直します。 テーマは「分母の選び方」。 同じ 47 都道府県のデータでも、 実数のまま見るか、 何かで割って見るかで相関構造がまるごと入れ替わる、 という事実を SSDSE-B-2026 の実測値で確認します。

🎨 直感 — 割り算 1 回で相関 0.895 が 0.032 になる

特徴量設計とは、 データを写す座標系を選ぶ行為です。 SSDSE-B-2026 の 2023 年・47 都道府県で実測すると、 A4101 (出生数) と I510120 (一般病院数) の相関は r = 0.895。 実数座標では「病院が多い県ほど子どもが生まれる」ように見えます。 しかし両者を A1101 (総人口) で割って「人口 1,000 人あたり出生数」と「人口 10 万人あたり病院数」に変換すると、 相関は r = 0.032 までほぼ消滅します。

種明かしは単純で、 総人口と出生数の相関が r = 0.995、 総人口と病院数の相関が r = 0.900 (いずれも 2023 年実測)。 つまり 0.895 という相関のほぼすべては「大きい県は何でも多い」というサイズ効果の反映でした。 実数どうしの特徴量ペアが見せる高相関は、 まず人口という第 3 の変数を疑う — これが県別データにおける特徴量設計の第一歩です。

⚠️ 落とし穴(重要)— 「率にすれば安全」でもない

🔭 発展 — 無次元化と組成データへの入口

「分母の選択」を突き詰めると、 2 つの発展的トピックにつながります。 第一に無次元量の設計。 パネルデータ (47 県 × 12 年) では、 単位を消すだけでなく「年内 z-score (各年の 47 県内で標準化)」を使うと、 全国共通のトレンド (物価・制度変更) と県間の相対位置を分離できます。 前章までの標準化が「列単位」だったのに対し、 これは「年 × 列単位」の標準化で、 パネル構造を持つ SSDSE-B-2026 ならではの特徴量です。 第二に組成データ (compositional data) 解析。 消費支出の内訳 (L322101L322110) のように「合計に対する割合の組」を特徴量にすると、 割合は足すと 1 になる制約があるため通常の相関分析が歪みます (どれかが増えれば必ずどれかが減る)。 この制約を外す log-ratio 変換 (CLR/ALR, Aitchison 1986) が定石で、 家計費目・産業構成比・時間配分などの割合特徴量を本格的に扱う際の必須知識です。

※ 本節の数値はすべて data/raw/SSDSE-B-2026.csv の 2023 年・47 都道府県データからの実測値 (使用列: A1101, A4101, A4103, I510120)。