💡 30秒で分かる結論
🍰 まずはやさしく
データの料理のような作業です。
予測の精度を上げるために使います。
テストの点数を分析する時に役立ちます。
結論と使いどころについて読みましょう。
特徴量エンジニアリング (Feature Engineering):予測に有用な特徴量を設計・抽出する作業。 ML の精度を最も左右する
位置づけ :機械学習・データ分析の中核概念 のひとつ
キーアイデア :本ページでは数式・実コード・落とし穴の 3 点セットで学ぶ
使い所 :実データ(SSDSE-B 都道府県データ等)で 47 サンプルでも体験できる
落とし穴 :詳細は ⚠️ 落とし穴 章へ
関連 :🔗 前提・並列・発展 をたどると体系が見える
📍 あなたが今見ているもの
🍰 まずはやさしく
この用語の解説ページです。
機械学習の基礎を学ぶために使います。
都道府県のデータを使って練習します。
おすすめの読み方について説明します。
このページは「特徴量エンジニアリング(Feature Engineering)」 の用語解説です。 機械学習の基礎カテゴリにおける重要概念で、
機械学習の基礎 グループ教材の中で繰り返し登場します。
数式・実コード・落とし穴を 1 ページに集約し、 SSDSE-B-2026 都道府県データ(47 件 × 112 列)を題材に
手を動かしながら理解できるよう構成しています。
別称:特徴量設計。 まず 💡 30秒結論 で全体像を、 次に
🎨 直感 → 📐 数式 → 🧮 実値 →
🐍 Python の順で読むのがおすすめ。
🎨 直感で掴む
🍰 まずはやさしく
データの形を整える作業です。
AIが学びやすくするために使います。
スマホの利用時間を整理する時に似ています。
具体的なやり方と考え方を読みましょう。
特徴量エンジニアリング は、 「与えられた生データから、 ML が学びやすい形へ作り直す」工程です。 業界の常識(ドメイン知識)と統計の知識を組み合わせる、 もっとも クリエイティブで効果の大きい 工程です。
代表的な手法:(1) 対数変換 (裾の長い分布を圧縮)、 (2) 比率・差分 (人口あたり、 前年比)、 (3) Binning (連続値を区分)、 (4) カテゴリエンコーディング (OneHot, Target)、 (5) 時系列ラグ 。 「kaggle の上位は 90% が特徴量勝負」とよく言われます。
🎨 直感の深掘り — もう一段の理解
特徴量エンジニアリング を 30 秒で言えば「生データから「学習に使いやすい特徴量」を設計・抽出する作業。 モデル性能の半分以上はここで決まる。」ですが、 実務で迷わないためにはもう一段深い理解が必要です。 ここでは「何が分かれば自信を持って使えるか」を、 3 つの観点で整理します。
観点 問い 答え方の指針
定義の根拠 なぜこの式・この定義になったのか? 「何を最小化/最大化したいか」から逆算する
境界条件 いつ使える/使えないのか? 「データの形」「分布の前提」を確認する
他との関係 隣接概念とは何が違うのか? 「共通点」と「分かれ目」を 1 つずつ挙げる
💡 暗黙の前提 :特徴量エンジニアリング が「うまく機能する」には、 データに対する暗黙の仮定(独立同分布、 適切な前処理、 十分なサンプル数)があります。 これを言語化できるかどうかで、 失敗時のデバッグ力が大きく変わります。
身近な例え:料理の下ごしらえ
特徴量エンジニアリングは「料理の下ごしらえ」と同じ。 同じレシピ(ML モデル)でも、 玉ねぎを「みじん切り」にするか「輪切り」にするかで味は劇的に変わる。 生データを「モデルが食べやすい形」に切り直すのが特徴量エンジニアリングだ。 もし君がプロのシェフなら、 まな板に乗った素材をそのまま炒めるだろうか? まず洗い、 皮をむき、 サイズを揃え、 必要なら下茹で・マリネする。 ML も全く同じで、 「生 CSV をそのまま fit」は素人の調理だ。
SSDSE-B-2026 で「出生率予測」の特徴量設計例
生データ そのまま使う 特徴量エンジニアリング後
総人口(百万) 0.54〜14.1 (分散大) log(人口): -0.62〜2.65 (圧縮)
20-34歳女性人口 絶対数 女性比率 = 20-34歳女性 / 総人口
保育所定員(絶対数) 東京偏重 定員 / 0-5歳児 (人口あたり)
平均通勤時間 連続値 Bin: <30/30-50/50-70/>70分
都道府県(47カテゴリ) — OneHot 47 列 or Target Encoding
右列の特徴量を使うと、 同じ線形回帰モデルでも R² が 0.62 → 0.81 に跳ね上がる経験は珍しくない。 モデルを変える前に「特徴量を見直す」が鉄則。
特徴量エンジニアリングの 3 つの罠
Data Leakage : 予測時に手に入らない情報(未来の値)を訓練特徴量に混入させる
Target Encoding の過学習 : 全データの平均で encode → 訓練データ汚染 → CV 内で fit すべし
過剰な交互作用項 : 100 列から $\binom{100}{2}=4950$ 交互作用 → 次元爆発、 正則化必須
🔬 数式を言葉で読み解く
記号と意味を逐一突き合わせて読みます。 慣れないうちは式を「日本語で読む」ことが理解の近道です。
$\phi_j$ :$j$ 番目の特徴量変換関数
$\phi_j(x)$ :元のサンプル $x$ から生成された $j$ 番目の新特徴量
$X'$ :新しい特徴量行列。 列数 $m$ は増減する
$\phi$ の例 :$\log(x)$, $\frac{x_1}{x_2}$, $x_1\times x_2$, OneHot($x$), Bin($x$)
方針 :ドメイン知識で仮説 → 検証 → 残す/捨てる の反復
🧮 SSDSE-B 実値で計算してみる
SSDSE-B から 派生特徴を 4 つ作り 、 元の列だけ使った場合と R² を比較して効果を確認します。
データ出典:SSDSE-B-2026(独立行政法人統計センター) 。 47 都道府県 × 複数年(最新 2023)の社会統計データ。
📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行)
都道府県 A1101(総人口) A1301(15歳未満人口) A1302(15~64歳人口) A1303(65歳以上人口) A4101(出生数)
北海道 5,092,000 514,000 2,897,000 1,681,000 24,430
東京都 14,086,000 1,513,000 9,368,000 3,205,000 86,348
沖縄県 1,468,000 236,000 882,000 350,000 12,549
…(全 47 行)
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import pandas as pd
import numpy as np
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 ])
df = df [ df [ 'SSDSE-B-2026' ] == 2023 ] . reset_index ( drop = True ) # 2023 年の 47 都道府県
y = df [ 'A4101' ] . values # A4101 = 出生数
# A) 元の列のみ(総人口・生産年齢人口・高齢人口)
X_raw = df [[ 'A1101' , 'A1302' , 'A1303' ]] . values
print ( 'raw ' , cross_val_score ( Ridge (), X_raw , y , cv = 5 ) . mean ())
# B) 派生特徴を追加
df [ '若年比率' ] = df [ 'A1301' ] / df [ 'A1101' ]
df [ '高齢比率' ] = df [ 'A1303' ] / df [ 'A1101' ]
df [ '生産年齢比率' ] = df [ 'A1302' ] / df [ 'A1101' ]
df [ 'log総人口' ] = np . log10 ( df [ 'A1101' ])
X_eng = df [[ 'A1101' , 'A1302' , 'A1303' ,
'若年比率' , '高齢比率' , '生産年齢比率' , 'log総人口' ]] . values
print ( 'eng ' , cross_val_score ( Ridge (), X_eng , y , cv = 5 ) . mean ())
実行結果の要約 (出力は環境依存。 概算値):
項目 値
raw R² (5-CV) 0.992
engineered R² (5-CV) 0.993
追加特徴量数 +4
R² 改善幅 +0.001
最重要派生特徴 若年比率
作業時間目安 数時間〜数日
🧮 SSDSE-B-2026 で派生変数を作って予測精度比較
🎯 このコードでやること : SSDSE-B-2026 の生の人口カウント特徴量で予測した場合と、 「若年比率」「高齢化率」「生産年齢比率」「log 総人口」の 4 派生変数を加えた場合で、 線形回帰の CV R² を比較する。 率・対数への変換で予測精度が大きく変わる。
📥 入力 : SSDSE-B-2026、 47 都道府県、 ターゲットは「合計特殊出生率」(A4103)。
📋 コピー 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 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 , KFold
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 )
y = df [ 'A4103' ] # A4103 = 合計特殊出生率(率=ターゲット)
# (1) 生の特徴量だけ(人口カウント+消費支出)
X_raw = df [[ 'A1101' , 'A1301' , 'A1302' , 'A1303' , 'L3221' ]]
# (2) 派生変数を追加(カウントを比率・対数に変換)
df [ '若年比率' ] = df [ 'A1301' ] / df [ 'A1101' ]
df [ '高齢化率' ] = df [ 'A1303' ] / df [ 'A1101' ]
df [ '生産年齢比率' ] = df [ 'A1302' ] / df [ 'A1101' ]
df [ 'log総人口' ] = np . log10 ( df [ 'A1101' ])
X_aug = pd . concat ([ X_raw , df [[ '若年比率' , '高齢化率' , '生産年齢比率' , 'log総人口' ]]], axis = 1 )
pipe = Pipeline ([( 'sc' , StandardScaler ()), ( 'rd' , Ridge ( alpha = 1.0 ))])
cv = KFold ( 5 , shuffle = True , random_state = 42 )
r2_raw = cross_val_score ( pipe , X_raw , y , cv = cv , scoring = 'r2' )
r2_aug = cross_val_score ( pipe , X_aug , y , cv = cv , scoring = 'r2' )
print ( f '生特徴量のみ R² = { r2_raw . mean () : .4f } ± { r2_raw . std () : .4f } ' )
print ( f '+ 4 派生変数 R² = { r2_aug . mean () : .4f } ± { r2_aug . std () : .4f } ' )
print ( f '改善幅 ΔR² = { r2_aug . mean () - r2_raw . mean () : +.4f } ' )
📤 実行例 :
生特徴量のみ R² = 0.3496 ±0.2628
+ 4 派生変数 R² = 0.8250 ±0.0516
改善幅 ΔR² = +0.4754
💬 結果の読み方 : 生の人口カウントだけでは R² = 0.35 と低い(出生率という「率」を絶対数から当てるのは無理がある)。 だが若年比率・高齢化率などの派生を加えると R² = 0.83 まで跳ね上がる(ΔR² ≈ +0.48)。 CV 分散も大きく縮む(汎化が安定)。 47 県という小サンプルでも、 ドメイン知識(率・対数)を反映した派生は絶大な効果を生む。 これが「特徴量設計が ML の 80% を占める」と言われる所以。
🧮 数式に値を入れて手で計算する: 特徴量追加による精度向上
合成データで特徴量数増加に伴うモデル R² を計算する。
Step 1: 特徴量数 vs R²
特徴数 R² 調整 R²
1 0.50 0.49 3 0.70 0.69 5 0.80 0.78 10 0.85 0.81 20 0.86 0.78
※ n=100 サンプル
Step 2: 調整 R² の式
adj R² = 1 - (1-R²)·(n-1)/(n-k-1)
特徴 5 個: adj = 1 - 0.20·99/94 = 1 - 0.2106 ≈ 0.789
特徴 20 個: adj = 1 - 0.14·99/79 = 1 - 0.175 ≈ 0.825 (実際は過学習で下がる)
🐍 Python で再現
📋 コピー import numpy as np
n = 100
k = np . array ([ 1 , 3 , 5 , 10 , 20 ])
r2 = np . array ([ 0.50 , 0.70 , 0.80 , 0.85 , 0.86 ])
adj = 1 - ( 1 - r2 ) * ( n - 1 ) / ( n - k - 1 )
print ( f "adj R²: { adj . round ( 3 ) } " )
print ( f "最大 adj index: { adj . argmax () } " )
📤 実行結果
adj R²: [0.495 0.691 0.789 0.833 0.825]
最大 adj index: 3
💬 手計算 (Step 2) と Python 出力が一致。 特徴 10 個で adj R² 最大。
🐍 Python 実装
scikit-learn / pandas を使った最小実装パターン。 上の SSDSE-B 計算と同じスタイルですが、 ここでは「読み込み→前処理→学習→評価」のテンプレを 4 つのスニペットに分けます。
① データ読み込み & 概観
📥 入力例(SSDSE-B-2026 全体:564 行 × 112 列 = 47 都道府県 × 2012〜2023 年)
年度 地域コード 都道府県 A1101(総人口) A1303(65歳以上人口) A4101(出生数) …
2023 R01000 北海道 5,092,000 1,681,000 24,430 …
2023 R13000 東京都 14,086,000 3,205,000 86,348 …
2023 R47000 沖縄県 1,468,000 350,000 12,549 …
…(残り 112 列は住宅・家計・教育・医療など)
📋 コピー import pandas as pd
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 )
print ( df . shape , df . columns . tolist ()[: 8 ])
② 特徴量と目的変数
📋 コピー X = df [[ 'A1101' , 'A1303' ]] . values # 総人口・高齢人口
y = df [ 'A1301' ] . values # 15歳未満人口を予測
print ( 'X shape =' , X . shape , ', y shape =' , y . shape )
③ 訓練/テスト分割 + モデル学習
📋 コピー from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
X_tr , X_te , y_tr , y_te = train_test_split ( X , y , test_size = 0.3 , random_state = 0 )
model = RandomForestRegressor ( n_estimators = 300 , random_state = 0 ) . fit ( X_tr , y_tr )
print ( 'R^2 (test) =' , model . score ( X_te , y_te ))
④ 評価と可視化
📋 コピー import matplotlib.pyplot as plt
pred = model . predict ( X_te )
plt . scatter ( y_te , pred )
plt . plot ([ y_te . min (), y_te . max ()], [ y_te . min (), y_te . max ()], 'r--' )
plt . xlabel ( '実測' ); plt . ylabel ( '予測' ); plt . title ( '「特徴量エンジニアリング」関連モデルの予測精度' )
plt . tight_layout (); plt . savefig ( 'out.png' , dpi = 150 )
※ 「特徴量エンジニアリング」固有の本格コードは上の 🧮 SSDSE-B 実値計算 節を参照。
🐍 応用コード — 人口カウントから「若年比率」「高齢化率」を派生させる
SSDSE 公的データを題材に、 特徴量エンジニアリング を実際に動かす最小コードです。 paths は引数に直書きで、 初心者がコピペで動かせる形を優先しています。
📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行)
都道府県 A1101(総人口) A1303(65歳以上人口) A4103(合計特殊出生率) L3221(消費支出(二人以上の世帯))
北海道 5,092,000 1,681,000 1.06 296,888
東京都 14,086,000 3,205,000 0.99 341,320
沖縄県 1,468,000 350,000 1.6 251,222
…(全 47 行)
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12 import pandas as pd
import numpy as np
# データ読み込み(SSDSE-B 都道府県・47 県 × 112 列)
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 )
print ( 'shape:' , df . shape )
print ( '列コードの先頭:' , df . columns . tolist ()[: 6 ])
# 使う列(A1101=総人口, A1303=高齢人口, L3221=消費支出, A4103=出生率)
features = [ 'A1101' , 'A1303' , 'L3221' , 'A4103' ]
print ( df [ features ] . describe ())
次に、 特徴量エンジニアリング に固有の処理を加えます。 ここがページごとの「肝」になる部分。
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error , r2_score
# 比率特徴量を作る(カウントそのままより率が効く)
df [ '若年比率' ] = df [ 'A1301' ] / df [ 'A1101' ]
df [ '高齢化率' ] = df [ 'A1303' ] / df [ 'A1101' ]
df [ '生産年齢比率' ] = df [ 'A1302' ] / df [ 'A1101' ]
X = df [[ '若年比率' , '高齢化率' , '生産年齢比率' , 'B4101' , 'L3221' ]] . values
y = df [ 'A4103' ] . values # A4103 = 合計特殊出生率
X_tr , X_te , y_tr , y_te = train_test_split ( X , y , test_size = 0.3 , random_state = 0 )
model = RandomForestRegressor ( n_estimators = 200 , max_depth = 4 , random_state = 0 ) . fit ( X_tr , y_tr )
pred_tr = model . predict ( X_tr )
pred_te = model . predict ( X_te )
print ( f 'train R^2 = { r2_score ( y_tr , pred_tr ) : .3f } ' )
print ( f 'test R^2 = { r2_score ( y_te , pred_te ) : .3f } ' )
print ( f 'test RMSE = { np . sqrt ( mean_squared_error ( y_te , pred_te )) : .4f } ' )
さらに可視化を加えると、 学んだ内容が「眼で」確認できます。
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12 import matplotlib.pyplot as plt
plt . figure ( figsize = ( 7 , 5 ))
plt . scatter ( y_te , pred_te , alpha = 0.7 , edgecolor = 'k' )
lims = [ min ( y_te . min (), pred_te . min ()), max ( y_te . max (), pred_te . max ())]
plt . plot ( lims , lims , 'r--' , linewidth = 2 , label = '完全予測ライン' )
plt . xlabel ( '実測 出生率' )
plt . ylabel ( '予測 出生率' )
plt . title ( '特徴量エンジニアリング を使ったモデルの予測精度(SSDSE-B-2026)' )
plt . legend ()
plt . tight_layout ()
plt . savefig ( 'out_feature-engineering.png' , dpi = 150 )
最後に、 同じ問題を別の角度から見る「クロスバリデーション版」も用意します。
📋 コピー from sklearn.model_selection import cross_val_score
scores = cross_val_score (
RandomForestRegressor ( n_estimators = 200 , max_depth = 4 , random_state = 0 ),
X , y , cv = 5 , scoring = 'r2'
)
print ( f '5-fold CV R^2 = { scores . mean () : .3f } (± { scores . std () : .3f } )' )
print ( '各 fold:' , np . round ( scores , 3 ))
🐍 実装パターン集 — 状況別レシピ
同じ「特徴量エンジニアリング」を使うにも、 データの形・規模・目的によって書き方が変わります。 4 つの典型パターンを示します。
パターン A:探索的・最小構成
📥 入力例(SSDSE-B-2026 全体:564 行 × 112 列 = 47 都道府県 × 2012〜2023 年)
年度 地域コード 都道府県 A1101(総人口) A1303(65歳以上人口) A4101(出生数) …
2023 R01000 北海道 5,092,000 1,681,000 24,430 …
2023 R13000 東京都 14,086,000 3,205,000 86,348 …
2023 R47000 沖縄県 1,468,000 350,000 12,549 …
…(残り 112 列は住宅・家計・教育・医療など)
📋 コピー import pandas as pd
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 )
print ( df . shape , df . head ( 3 ))
パターン B:パイプライン化(前処理+モデル)
📋 コピー from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import Ridge
pipe = Pipeline ([
( 'scaler' , StandardScaler ()),
( 'model' , Ridge ( alpha = 1.0 )),
])
pipe . fit ( X_tr , y_tr )
print ( 'R^2 =' , pipe . score ( X_te , y_te ))
パターン C:交差検証+ハイパーパラメータ探索
📋 コピー from sklearn.model_selection import GridSearchCV
params = { 'model__alpha' : [ 0.01 , 0.1 , 1.0 , 10.0 , 100.0 ]}
gs = GridSearchCV ( pipe , params , cv = 5 , scoring = 'r2' , n_jobs =- 1 )
gs . fit ( X , y )
print ( 'best:' , gs . best_params_ , 'score:' , gs . best_score_ )
パターン D:可視化付きの結果保存
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14 import matplotlib.pyplot as plt
import json
pred = gs . predict ( X_te )
plt . figure ( figsize = ( 7 , 5 ))
plt . scatter ( y_te , pred , alpha = 0.7 , edgecolor = 'k' )
plt . plot ([ y_te . min (), y_te . max ()], [ y_te . min (), y_te . max ()], 'r--' )
plt . xlabel ( '実測' ); plt . ylabel ( '予測' ); plt . title ( '特徴量エンジニアリング 結果' )
plt . tight_layout (); plt . savefig ( 'result_feature-engineering.png' , dpi = 150 )
with open ( 'result_feature-engineering.json' , 'w' , encoding = 'utf-8' ) as f :
json . dump ({ 'best_params' : gs . best_params_ ,
'cv_score' : gs . best_score_ ,
'test_score' : gs . score ( X_te , y_te )}, f , ensure_ascii = False , indent = 2 )
🐍 多項式特徴量と交互作用項
🎯 このコードでやること : PolynomialFeatures で 2〜3 次の多項式・交互作用項を一括生成し、 元の 5 特徴量が 20・55 特徴量へ膨張する様子を見る。 過学習リスクと精度のトレードオフを Ridge で評価する。
📥 入力 : SSDSE-B-2026、 X=5 特徴量(比率+気温+消費)、 y=合計特殊出生率。
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import pandas as pd
import numpy as np
from sklearn.linear_model import Ridge
from sklearn.preprocessing import StandardScaler , PolynomialFeatures
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score , KFold
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 )
df [ '若年比率' ] = df [ 'A1301' ] / df [ 'A1101' ]
df [ '高齢化率' ] = df [ 'A1303' ] / df [ 'A1101' ]
df [ '生産年齢比率' ] = df [ 'A1302' ] / df [ 'A1101' ]
y = df [ 'A4103' ] # 合計特殊出生率
X = df [[ '若年比率' , '高齢化率' , '生産年齢比率' , 'B4101' , 'L3221' ]]
cv = KFold ( 5 , shuffle = True , random_state = 42 )
for deg in [ 1 , 2 , 3 ]:
pipe = Pipeline ([
( 'sc' , StandardScaler ()),
( 'poly' , PolynomialFeatures ( degree = deg , include_bias = False , interaction_only = False )),
( 'rd' , Ridge ( alpha = 1.0 )),
])
r2 = cross_val_score ( pipe , X , y , cv = cv , scoring = 'r2' )
n_feat = PolynomialFeatures ( degree = deg , include_bias = False ) . fit ( X ) . n_output_features_
print ( f 'degree= { deg } 特徴量数= { n_feat : 3d } CV R² = { r2 . mean () : .4f } ± { r2 . std () : .4f } ' )
📤 実行例 :
degree=1 特徴量数= 5 CV R² = 0.8083 ±0.0432
degree=2 特徴量数= 20 CV R² = 0.1399 ±1.3087
degree=3 特徴量数= 55 CV R² = -3.9389 ±6.2699
💬 結果の読み方 : degree=1(5 特徴量)が最良で CV R² = 0.81。 次数を上げると特徴量が 20 → 55 個 へ急増し、 サンプル数 47 を上回るあたりで Ridge の正則化があっても CV R² が急落・分散も激増する(degree=3 では負に転落)。 典型的な curse of dimensionality。 多項式特徴量を入れるときは「次数を上げすぎない」「正則化を強める」「サンプル数とのバランスを見る」の 3 原則を守ること。
数式を言葉で読み解く: 多項式の次元爆発
$p$ 個の特徴量で degree $d$ の多項式(交互作用込み)を作ると、 特徴量数は
$$ \binom{p+d}{d} - 1 $$
になる。 $p=5, d=2$ なら $\binom{7}{2}-1 = 20$、 $p=5, d=3$ なら $\binom{8}{3}-1 = 55$。 サンプル数 $n=47$ より多くなると線形代数的に「優決定系」となり、 解が存在しない or 数値的に不安定になる。 これを避けるのが Ridge の役割($X^\top X + \alpha I$ で常に正則化)。
🐍 ビニング(離散化)の効果
🎯 このコードでやること : 連続変数「年平均気温」を 4 分位で離散化し、 元の連続値モデルと CV R² で比較する。 ビニングは非線形効果を線形モデルで吸収できる場合に有効だが、 情報損失とのトレードオフ。
📥 入力 : SSDSE-B-2026、 X=比率 3 種+年平均気温、 y=合計特殊出生率。
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 import pandas as pd
import numpy as np
from sklearn.linear_model import Ridge
from sklearn.preprocessing import StandardScaler , KBinsDiscretizer
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.model_selection import cross_val_score , KFold
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 )
df [ '若年比率' ] = df [ 'A1301' ] / df [ 'A1101' ]
df [ '高齢化率' ] = df [ 'A1303' ] / df [ 'A1101' ]
df [ '生産年齢比率' ] = df [ 'A1302' ] / df [ 'A1101' ]
y = df [ 'A4103' ] # 合計特殊出生率
X = df [[ '若年比率' , '高齢化率' , '生産年齢比率' , 'B4101' ]] # B4101 = 年平均気温
cv = KFold ( 5 , shuffle = True , random_state = 42 )
# (1) 連続値のまま
pipe1 = Pipeline ([( 'sc' , StandardScaler ()), ( 'rd' , Ridge ())])
r2_a = cross_val_score ( pipe1 , X , y , cv = cv , scoring = 'r2' ) . mean ()
# (2) 年平均気温だけ 4 分位ビニング
ct = ColumnTransformer ([
( 'temp_bin' , KBinsDiscretizer ( n_bins = 4 , encode = 'onehot-dense' , strategy = 'quantile' ),
[ 'B4101' ]),
( 'rest' , StandardScaler (), [ '若年比率' , '高齢化率' , '生産年齢比率' ]),
])
pipe2 = Pipeline ([( 'ct' , ct ), ( 'rd' , Ridge ())])
r2_b = cross_val_score ( pipe2 , X , y , cv = cv , scoring = 'r2' ) . mean ()
print ( f '連続のまま R² = { r2_a : .4f } ' )
print ( f '年平均気温を 4 分位 R² = { r2_b : .4f } ' )
print ( f '差 ΔR²= { r2_b - r2_a : +.4f } ' )
📤 実行例 :
連続のまま R² = 0.8097
年平均気温を 4 分位 R² = 0.8380
差 ΔR²= +0.0283
💬 結果の読み方 : 年平均気温は 4 分位ビニングした方が R² が僅かに上がる(ΔR² ≈ +0.03)。 気温と出生率の関係が非線形(暖かい地方ほど出生率が高い傾向)なため、 One-Hot 化で階段状の効果を線形モデルが捉えられる。 逆に線形関係が強い変数では連続値のままが勝つ。 ビニングは「順序情報を捨てる」代わりに「非線形効果を One-Hot で扱える」という交換であり、 効くかはドメイン次第。
🐍 自動特徴量生成(feature-engine)
🎯 このコードでやること : feature-engine ライブラリの MathFeatures を使って 6 特徴量から「合計」「平均」「最大」「分散」を自動生成し、 R² への寄与を見る。 ドメイン知識なしでも一定の派生が作れるのが自動特徴量の魅力。
📥 入力 : SSDSE-B-2026、 X=6 特徴量(人口カウント+気温+消費)、 y=合計特殊出生率。
📋 コピー 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 feature_engine.creation import MathFeatures
from sklearn.linear_model import Ridge
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score , KFold
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 )
y = df [ 'A4103' ] # 合計特殊出生率
cols = [ 'A1101' , 'A1301' , 'A1302' , 'A1303' , 'B4101' , 'L3221' ]
X = df [ cols ]
mf = MathFeatures ( variables = cols , func = [ 'sum' , 'mean' , 'max' , 'std' ])
X_new = mf . fit_transform ( X )
print ( '元の特徴量数:' , X . shape [ 1 ], '→ 拡張後:' , X_new . shape [ 1 ])
cv = KFold ( 5 , shuffle = True , random_state = 42 )
pipe = Pipeline ([( 'sc' , StandardScaler ()), ( 'rd' , Ridge ( alpha = 1.0 ))])
print ( '元のみ R²:' , cross_val_score ( pipe , X , y , cv = cv , scoring = 'r2' ) . mean () . round ( 4 ))
print ( '元+自動生成 R²:' , cross_val_score ( pipe , X_new , y , cv = cv , scoring = 'r2' ) . mean () . round ( 4 ))
📤 実行例 :
元の特徴量数: 6 → 拡張後: 10
元のみ R²: 0.6366
元+自動生成 R²: 0.6378
💬 結果の読み方 : 自動生成された統計量(合計・平均・最大・分散)はごく僅かの改善(+0.0012)に留まる。 ドメイン知識ベースの派生(若年比率・高齢化率など)が生んだ ΔR² ≈ +0.48(前掲)と比べると桁違いに小さい。 自動特徴量はベースラインを底上げするのに有効だが、 ドメイン知識の代替にはならない。
数式を言葉で読み解く: なぜ自動生成だけでは足りないか
自動生成は「与えられた変数集合に対する非情報的な統計量」を吐き出す。 一方ドメイン知識ベースの派生(例: 「15歳未満人口 / 総人口 = 若年比率」)は 意味的に解釈可能な比 を生む。 後者は次元解析的にも妥当で、 線形モデルが直接捉えられない「分母正規化」を含意する。 数式で書けば: $f(\text{15歳未満人口}, \text{総人口}) = \text{15歳未満人口}/\text{総人口}$ は単純な交互作用や和では表せず、 ドメイン知識でしか思いつかない関数形である。
⚠️ よくある落とし穴(5 つ)
❌ 目的変数を使った特徴量(リーケージ)
Target Encoding を fold 外で計算しないと未来情報が混入。 必ず CV 内で。
❌ 派生特徴を闇雲に大量生成
次元の呪い + 多重共線性 + 過学習。 仮説駆動で作り、 importance や mRMR で選別。
❌ ドメイン知識を軽視
「総人口 ÷ 県面積 = 人口密度」のような重要派生は機械的探索より人間の方が見つけやすい。
❌ 全データで fit してリーク
StandardScaler や Target Encoder を全データで fit してから CV すると未来情報が漏れる。 Pipeline で fold 毎に fit。
❌ テスト時に派生特徴を再現できない
本番では訓練と完全に同じ変換を再現できる仕組み(Pipeline 永続化)を整える。
⚠️ さらに 5 つの落とし穴 — 実務で痛い目を見るパターン
❌ デフォルト設定をそのまま信じる
ライブラリのデフォルト引数は「平均的なケース」向け。 あなたのデータが平均的でなければ、 必ず設定を再検討する必要があります。 公式 docstring を読む癖をつけましょう。
❌ スケーリングを忘れる
「総人口」(数百万) と「出生率」(0.0〜2.0) では値域が 10⁶ 倍違う。 距離ベースの手法では、 必ず StandardScaler / MinMaxScaler でスケールを揃えること。
❌ 訓練データでの前処理パラメータをテストに使わない
StandardScaler の fit は訓練データだけ に対して行い、 テストには transform のみを適用。 これを混同するとデータリーケージになる。
❌ メトリクスの単位を見落とす
RMSE を「絶対値で 100」と聞いて大きいか小さいかは、 目的変数のスケールによる。 「出生率」(0〜2) で RMSE=100 はあり得ない、 などのサニティチェックを必ず。
❌ 「精度が高い = 良いモデル」と短絡
precision/recall の不均衡、 ラベルの偏り、 ベースラインとの比較を見ないと、 「高精度」は単に多数派を予測しているだけかもしれません。
🕰 歴史的経緯と現代的意味
特徴量エンジニアリング は、 統計学と計算機科学の流れの中から生まれました。 下の年表はこの分野全体の流れ で、 特徴量エンジニアリング 固有の年表ではありません。 この用語がどの時代の産物かを掴むために置いています。
時期 出来事 この時代に起きたこと
前史 統計学・情報理論の基盤整備 数式的な土台
古典期 機械学習の黎明(1960〜80 年代) 「特徴量エンジニアリング」の原型が登場
展開期 scikit-learn / TensorFlow など実装の普及(2010〜) 誰でも 1 行で使える時代に
現代 大規模モデル時代(2020〜) 「特徴量エンジニアリング」の意味が再解釈される
現代の文脈では、 古典的な定義のままでは説明しきれない使い方も出てきています。 教科書の定義を出発点としつつ、 実務での「変奏」も知っておくとよいでしょう。
❓ よくある質問
Q1. なぜこの定義になっているの? 別の式じゃダメ? 理論的には別定義も可能ですが、 「数学的に扱いやすい」「経験的に良い結果が出る」「歴史的経緯」の 3 拍子で現在の定義が標準化されています。 学術論文では別定義を「変種」として議論することもよくあります。
Q2. データが少ない(47 県)でも意味ある分析になる? 教育用途・探索的分析では十分。 ただし「統計的有意」を主張するには n=47 は不足することが多いので、 解釈は慎重に。 ブートストラップで信頼区間を出すと頑健性が確かめられます。
Q3. scikit-learn 以外でも実装はある? PyTorch / TensorFlow / XGBoost / LightGBM など多数。 ただし基本的な動作確認は scikit-learn が一番速いので、 まず sklearn で動かしてから他に移植するのがおすすめ。
Q4. 大規模データ(百万行)でも同じ方法でいける? 計算量・メモリの観点でアルゴリズムを切り替える必要があります。 mini-batch 版、 サブサンプリング、 近似アルゴリズムの利用を検討します。 47 県スケールで本質を理解した後の応用課題です。
Q5. 論文を書くとき、 この概念をどう引用すべき? 古典的な定義は原典(教科書や著名論文)、 実装は使用ライブラリのバージョン情報を併記するのが標準。 「Murphy 2012」「Hastie et al. 2009」あたりが定番引用です。
Q6. 関連用語との学習順序は? 下の「📚 関連グループ教材」セクションのリストが、 推奨される学習順序の一つです。 上位概念から入って詳細に降りる「トップダウン」と、 1 つの具体例から始めて他に広げる「ボトムアップ」、 どちらも一長一短。 自分の学び方に合わせて。
⚠️ 特徴量設計の 8 つの落とし穴
落とし穴 何が起きるか 対策
target leakage target encoding で fold をまたぐ out-of-fold で集計
test 漏洩 test 統計量で train を標準化 Pipeline で fit は train のみ
多重共線性 「人口」と「15-64+65以上」を両方入れる VIF 確認、 PCA、 削除
過学習 特徴量数 > サンプル数 正則化、 次元削減
過剰なビニング 情報損失 連続値と比較
スケール混在 勾配が偏り収束遅延 StandardScaler、 RobustScaler
カテゴリ高カーディナリティ One-Hot で次元爆発 target encoding、 hashing
時系列で未来情報混入 将来値で past を符号化 expanding window で集計
特に target leakage はコンペで上位入賞者の typical なミス。 「リーダーボードでは強かったが本番で全く効かない」モデルは大体これが原因。
📚 関連グループ教材
この用語の全体像を学ぶには、 まず横断的な教材で文脈を掴むのが効率的です:
✅ 学習チェックリスト
□ 「特徴量エンジニアリング」の 30 秒結論を 1 文で言える
□ 数式の記号と意味の対応を全て口頭で説明できる
□ SSDSE-B コードを自分の環境で動かし、 表の値を再現できた
□ 5 つの落とし穴をそれぞれ「自分のプロジェクト」の文脈で言い換えられる
□ 前提・並列・発展の用語を 4 つずつ列挙できる
□ 機械学習の基礎 グループ教材で文脈を確認した
📚 参考文献 — 次に読むもの
Hastie, T., Tibshirani, R., & Friedman, J. (2009). The Elements of Statistical Learning (2nd ed.). Springer. — ML の標準教科書、 「特徴量エンジニアリング」も網羅
Murphy, K. P. (2012). Machine Learning: A Probabilistic Perspective . MIT Press. — 確率論的視点
Bishop, C. M. (2006). Pattern Recognition and Machine Learning . Springer. — 直感と数式のバランスがよい
Goodfellow, I., Bengio, Y., & Courville, A. (2016). Deep Learning . MIT Press. — 深層学習文脈での特徴量エンジニアリング
scikit-learn User Guide — 実装と例題
SSDSE 公式(独立行政法人統計センター) — 本ページのデータ出典
グループ教材:機械学習の基礎 — 全体像
🧭 これからの学習ルート
「特徴量エンジニアリング」を理解した次に何を学ぶか、 5 ステップで提案します。 順序は厳密ではなく、 興味のあるところから飛び入りで OK。
ステップ 1 :上の「🐍 応用コード」を自分の環境で動かす(コピペで OK)
ステップ 2 :データを別のもの(自分の興味のあるテーマ)に差し替えて再実行
ステップ 3 :上の「🌐 比較」表の類似手法を 1 つ選んで、 同じデータで比較
ステップ 4 :「📋 前提」セクションのリンクを 1 つずつ巡って、 関連用語を固める
ステップ 5 :機械学習の基礎 グループ教材で、 体系全体を俯瞰する
📋 1 枚チートシート
項目 内容
用語 特徴量エンジニアリング(Feature Engineering)
1 行定義 生データから「学習に使いやすい特徴量」を設計・抽出する作業。 モデル性能の半分以上はここで決まる。
数式 $x' = \phi(x_{raw}), \quad \hat y = f(x')$
SSDSE 適用例 総人口や面積から「人口密度」「高齢化率」を派生させる
主要ライブラリ scikit-learn, pandas, numpy
典型的な落とし穴 スケーリング忘れ・データリーケージ・前提分布
次に学ぶ 機械学習の基礎 グループ教材
※ このチートシートは「30 秒で復習」用。 詳しくは各セクションへ。
📂 ケーススタディ — 過去論文での使われ方
統計データ解析コンペティション過去論文で「特徴量エンジニアリング」がどのように登場し、 どんな問題を解決したかを見てみます。 論文ページからリンクして本ページに来た方も、 ぜひもう一度自分の関心ある論文を見直してみてください。
論文の方向性 「特徴量エンジニアリング」の役割 学べる点
人口動態の予測 将来予測モデルの構成要素として 時系列との組み合わせ方
地域格差の分析 都道府県をクラスタリング・分類する基盤 教師なし/教師ありの切り替え
経済指標の関係性 特徴量間の関係を可視化・解釈 解釈可能性とのトレードオフ
健康・福祉データ 少数派ラベルに対する頑健性 不均衡データの扱い方
テキスト解析 前処理・後処理の枢要 NLP との接続
💡 論文を読むときのコツ :「この論文では『特徴量エンジニアリング』を何のために使っているか?」「もし使わなかったら何が問題だったか?」を意識すると、 技術選定の判断軸 が身に付きます。
📚 グループ教材の中での位置
「特徴量エンジニアリング」は単独で学ぶよりも、 関連する複数の用語をセットで学ぶ方が効率的です。 関連グループ教材へのリンクを整理します。
グループ教材 含まれる主な用語 「特徴量エンジニアリング」の位置
機械学習の基礎 教師あり/なし、 損失、 汎化、 過学習 中核
モデル選択 CV、 ハイパーパラメータ、 交差検証 関連
評価指標 R²、 RMSE、 ROC-AUC、 confusion matrix 関連
決定木 情報利得、 エントロピー、 ジニ 特定の応用
分類 2 値・多値・不均衡 タスク
クラスタリング K-means、 階層型、 DBSCAN 教師なし側
💡 勧めの学習スタイル :1 つのグループ教材を読破してから次へ、 ではなく、 「気になる用語を起点に近所を巡る」スタイルが、 ジャストインタイム学習のコツです。 興味の連鎖に従って深掘りしましょう。
📚 参考文献・推薦リソース
Zheng, A. & Casari, A. (2018) Feature Engineering for Machine Learning. O'Reilly. — 全体像を学ぶ定番
Kuhn, M. & Johnson, K. (2019) Feature Engineering and Selection. CRC. — 統計家向けの体系書(無料 web 版あり)
Galli, S. (2023) Python Feature Engineering Cookbook, 2nd ed. Packt. — feature-engine 開発者による実装本
Micci-Barreca, D. (2001) A Preprocessing Scheme for High-Cardinality Categorical Attributes. — target encoding の原典
Kaggle Notebooks: feature engineering tutorials — 実践的なテクニック集
最後に: 特徴量設計の心得
「データを変える」のではなく「データに新しい 視点 を与える」のが特徴量設計の本質。 同じ生データでも、 適切な派生・変換・エンコードを通すことで、 線形モデルが非線形パターンを捉え、 NN が学習可能になる。 SSDSE-B-2026 の 47 県 × 7 変数という小さなデータでも、 派生変数の有無で R² が 0.4 ポイント動く。 これがデータ分析者の腕の見せ所である。
🎯 補遺: Target Encoding と leakage 対策 — CV out-of-fold mean encoding
高基数カテゴリ変数(zip code、 ユーザー ID、 市町村コード)に One-Hot を当てると次元爆発を起こす。 Target encoding (mean encoding) は各カテゴリを 目的変数の平均値 で置き換える手法で、 木モデルとの相性が良い。 しかし素朴に train 全体で平均を取ると target leakage が発生し、 train スコアは異常に高くなるが汎化性能は劣化する。 ここでは leakage を防ぐ out-of-fold (OOF) target encoding と、 平滑化 (smoothing) の式を SSDSE-B-2026 で実装する。
📐 数式を言葉で読み解く — Bayesian smoothing
$$ \hat{y}_c = \frac{n_c \bar{y}_c + m \bar{y}_{\text{global}}}{n_c + m} $$
記号の意味 : $\bar{y}_c$ はカテゴリ $c$ 内の目的変数平均、 $n_c$ は出現回数、 $\bar{y}_{\text{global}}$ は全体平均、 $m$ は平滑化パラメータ(先験的サンプル数)。 $n_c$ が小さいほど global 平均に引き寄せられ、 $n_c$ が大きいほどカテゴリ固有平均に近づく。 これは「観測が少ないカテゴリは過信しない」というベイズ的事前情報を表す。
🐍 Python 実装: category_encoders + CV split で leakage 防止
🎯 このコードでやること : SSDSE-B-2026 の都道府県を地方ブロック(北海道・東北・関東・中部・近畿・中国・四国・九州沖縄)にマッピングし、 目的変数 = 合計特殊出生率 に対して target encoding を施す。 KFold で OOF 推定し、 train データ自身の値が leak しないようにする。
📥 入力例 :
Prefecture Region 合計特殊出生率
北海道 北海道 1.06
青森県 東北 1.23
東京都 関東 0.99
沖縄県 その他 1.60
📋 コピー 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 import pandas as pd
import numpy as np
from sklearn.model_selection import KFold
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 )
region_map = {
'北海道' : '北海道' ,
'青森県' : '東北' , '岩手県' : '東北' , '宮城県' : '東北' , '秋田県' : '東北' , '山形県' : '東北' , '福島県' : '東北' ,
'東京都' : '関東' , '茨城県' : '関東' , '栃木県' : '関東' , '群馬県' : '関東' , '埼玉県' : '関東' , '千葉県' : '関東' , '神奈川県' : '関東' ,
}
df [ 'Region' ] = df [ 'Prefecture' ] . map ( region_map ) . fillna ( 'その他' )
y = df [ 'A4103' ] # A4103 = 合計特殊出生率
global_mean = y . mean ()
m = 10 # smoothing prior
# OOF target encoding
encoded = np . zeros ( len ( df ))
kf = KFold ( n_splits = 5 , shuffle = True , random_state = 42 )
for tr , va in kf . split ( df ):
stats = df . iloc [ tr ] . groupby ( 'Region' )[ 'A4103' ] . agg ([ 'mean' , 'count' ])
smooth = ( stats [ 'count' ] * stats [ 'mean' ] + m * global_mean ) / ( stats [ 'count' ] + m )
encoded [ va ] = df . iloc [ va ][ 'Region' ] . map ( smooth ) . fillna ( global_mean )
df [ 'Region_enc' ] = encoded
print ( df [[ 'Prefecture' , 'Region' , 'Region_enc' ]] . head ( 8 ))
📤 実行結果 :
Prefecture Region Region_enc
0 北海道 北海道 1.293
1 青森県 東北 1.252
2 岩手県 東北 1.252
3 宮城県 東北 1.260
4 秋田県 東北 1.255
5 山形県 東北 1.247
6 福島県 東北 1.260
7 茨城県 関東 1.235
💬 結果の読み方 : 北海道は単独カテゴリ($n_c=1$)なので smoothing で global 平均 1.293 に強く引き寄せられている(≈1.293)。 一方、 関東は複数県あるため固有平均 1.151 が(平滑化されつつ)反映され、 全国平均より低い出生率が現れる。 OOF 分割により、 fold 内の自身の y は除外されているので、 train スコアと validation スコアの乖離が縮む。
⚠️ Target Encoding の落とし穴
未知カテゴリ問題 : test に train で見ていないカテゴリが出ると NaN になる。 fillna(global_mean) を必ず仕込む。
時系列 leakage : 時系列データでは KFold ではなく TimeSeriesSplit を使う。 過去から未来は OK、 未来から過去は厳禁。
m の決め方 : $m$ が小さすぎると leakage 寄り、 大きすぎると情報損失。 経験則は カテゴリ平均出現数 前後。
分類問題への適用 : 二値分類なら $\bar{y}_c$ は単純な陽性率。 多クラスは class ごとに encoding 列を増やす。
関連: One-Hot エンコーディング / leakage / 交差検証 / カテゴリ変数
🖼 図解で深掘り:特徴量エンジニアリングの3つの視点
特徴量エンジニアリング(feature engineering, 略 FE)は 「モデルが学びやすい形にデータを翻訳する作業」 である。 ここでは SSDSE-B-2026 の都道府県データを題材に、 散布図・ヒストグラム・箱ひげ図 の 3 枚の図を通じて、 特徴量変換が予測精度・解釈・誤差分布にどう効くかを徹底的に観察する。 「数値を眺める」だけでは見えない構造が、 図にすると一気に立ち上がるのが FE の醍醐味である。
🔍 視点 1:散布図で「対数変換」の効果を確認する
人口と出生数の関係を生スケールで散布図にすると、 東京・神奈川・大阪などの大都市圏が右上の隅に固まり、 残り 40 県前後が左下に密集してしまう。 これは「べき乗則的な分布 」の典型で、 線形回帰の前提(誤差の等分散性)を破る。 そこで両軸に常用対数(log10)を取ると、 ほぼ直線状に並び、 相関係数 0.99 が「ノイズの少ない強い線形関係」として可視化される。 これが FE の最も基本的かつ強力な操作 = 対数変換 の威力である。
図1: SSDSE-B-2026 都道府県データ(横軸: 人口、 縦軸: 出生数)。 大都市圏が右上に張り付くため、 対数変換が必要となる典型例。
変換 相関係数 r(模式値) 線形回帰 R²(模式値) 残差の歪度(模式値) 推奨用途
生スケール 0.972 0.944 +2.1(右に長い裾) 概観・粗い比較
log10 変換 0.991 0.982 +0.2(ほぼ対称) 線形回帰・距離計算
平方根変換 0.983 0.967 +0.9 カウントデータ向け
Box-Cox(λ=0.1) 0.993 0.986 +0.05 最適変換を機械的に探索
Yeo-Johnson 0.993 0.986 +0.04 負値・0 を含むデータ
💬 表の数値は「右裾の重いデータで対数変換が効く」という一般的傾向を示す模式例(架空値) である。 より正確な分析:SSDSE-B-2026(2023 年)の「総人口 × 出生数」を実測すると、 生スケールでも r = 0.995(R² = 0.991)と極めて高く、 log10 変換後は r = 0.990 とむしろ僅かに下がる (この 2 変数はほぼ比例関係にあるため)。 対数変換が効くのは「裾の重さが線形関係を歪めている」場合であり、 効果の有無は 必ず交差検証で確認 すること。 Box-Cox や Yeo-Johnson は λ パラメータを最尤推定で決めてくれる「自動対数変換」とも呼べる手法で、 試行錯誤を減らせる。
🔍 視点 2:ヒストグラムで「正規化・標準化」の前後を比べる
多くのアルゴリズム(線形回帰、 ロジスティック回帰、 k-NN、 ニューラルネット、 SVM)は 入力スケールが揃っていることを暗黙に仮定 する。 人口(百万単位)と年平均気温(数十単位)を同じモデルに突っ込むと、 数値の大きい人口にだけ係数が偏り、 気温の効果が消えてしまう。 ヒストグラムで「変換前」「Min-Max 正規化後」「Z スコア標準化後」を並べると、 形状は保ったまま値域だけが [0,1] や平均 0・分散 1 に揃うことが視覚的に確認できる。
図2: SSDSE-B-2026 人口分布のヒストグラム。 形状そのものは変換で変わらないことに注目(ビンの位置だけがシフト/スケール変更される)。
変換手法 式 変換後の範囲 外れ値耐性 適する場面
Min-Max 正規化 $x' = (x - \min)/(\max - \min)$ [0, 1] 弱い ニューラルネット入力
Z スコア標準化 $x' = (x - \mu)/\sigma$ 平均0・分散1 弱い 線形モデル・SVM
Robust Scaler $x' = (x - \text{median})/\text{IQR}$ 中央値0付近 強い 外れ値が多い実データ
MaxAbs Scaler $x' = x / \max(|x|)$ [-1, 1] 弱い スパース行列(符号維持)
Quantile Transformer 累積分布で順位化 [0,1] 一様 or 正規 非常に強い 分布形状を強制したい時
💬 SSDSE-B-2026 のような 東京の外れ値が極端 なデータでは、 Min-Max 正規化は東京を 1.0 とする一方、 大半の県(人口 200 万人未満の約 40 県)を 0.11 以下に押し込めてしまい、 多くの県が「ゼロ近傍」に潰れる。 こうした場合は Robust Scaler (中央値と IQR を使う)が第一選択肢になる。 「データの形」を見ずに無闇に StandardScaler を当てるのは典型的な初学者ミスである。
🔍 視点 3:箱ひげ図で「カテゴリ × 数値」の特徴量を発掘する
都道府県を地域ブロック(北海道・東北・関東・中部・近畿・中国・四国・九州沖縄)に分けて箱ひげ図を描くと、 単純な「人口」という 1 変数からは見えなかった 地域差 がくっきり浮かび上がる。 関東は中央値が突出して高く、 ひげも長い。 四国は箱が小さく、 ばらつきも小さい。 ここから「地域ダミー変数」「地域×人口の交互作用項」といった 新しい特徴量 を作るアイデアが湧く。 これが FE における 「カテゴリと数値の組み合わせ」 の発想法である。
図3: 地域ブロック別の人口分布。 箱の高さ・中央線・ひげ・外れ値を通じて、 グループ間の中心と散らばりの違いが一目で読める。
FE 技法 入力 出力 適用例 注意点
One-Hot エンコード 地域(8 カテゴリ) 8 列のバイナリ 線形・木モデル両対応 カテゴリ数が多いと次元爆発
Target エンコード 地域 + 目的変数 1 列の数値 高カーディナリティ leakage に厳重注意
Frequency エンコード 地域 出現頻度 「珍しい地域」を強調 情報量が限定的
交互作用項 地域 × 人口 8 列の連続値 地域ごとに傾きが違うとき 多重共線性に注意
グループ統計量 地域 → 数値の平均・分散 2〜4 列の数値 「自県は地域平均より大きいか」 同じく leakage 注意
💬 「箱ひげ図で差が見える ⇒ それを表現する特徴量を作る」という流れは、 FE の最も生産的なルーチンである。 統計検定(ANOVA)で有意差を確認してから特徴量化するのが理想だが、 探索段階では「目で見て差がありそう ⇒ 試してみる」で十分。 効くか効かないかは交差検証で答えが出る。
🛠 実践チェックリスト:FE を始める前に必ず確認する 10 項目
# 確認項目 理由 具体策
1 欠損値の分布を確認 欠損自体が特徴量になることがある df.isna().mean() + missingno で可視化
2 外れ値の位置を確認 変換手法の選択を左右する 箱ひげ図 + IQR 法で同定
3 分布の歪度 対数/Box-Cox の要否判断 df.skew() > 1 なら検討
4 カテゴリ変数のカーディナリティ One-Hot か Target か選ぶ df.nunique()
5 数値変数のスケール差 標準化が必要な手法かを判定 df.describe() で max/min を比較
6 相関の有無 多重共線性の予兆 相関行列ヒートマップ
7 時系列要素の有無 leakage 防止のため KFold ではなく TimeSeriesSplit を使う 日付列の存在を確認
8 目的変数の分布 回帰なら対数 y、 分類なら不均衡対策 ヒストグラム or 出現頻度表
9 テキスト/画像/音声の有無 専門的な FE が別途必要 型と内容を目視確認
10 ドメイン知識 最強の特徴量は専門家から来る 業務担当者・統計指標定義書を確認
💬 機械学習プロジェクトの 70% の時間は FE と前処理に費やされる、 という業界の経験則がある。 上記 10 項目はその「最初の 1 日」で確認すべき最低限のチェック項目。 ここを飛ばして PyTorch を書き始めると、 後から「データが汚かった」「leakage していた」「スケールが揃っていなかった」と全てやり直しになる。
📊 ケーススタディ:SSDSE-B-2026 で人口予測モデルを段階的に改善する
都道府県の「人口」を、 他の社会指標(出生率、 高齢化率、 若年比率、 年平均気温、 消費支出 等)から予測する回帰タスクを想定する(下表は改善曲線を示す代表的な模式例)。 何の前処理もせず線形回帰に投入すると、 RMSE は非常に大きく、 R² も低い。 そこに 1 つずつ FE を積み重ねるごとに性能が改善していくのを確認する。 「1 つ加えるごとに何 % 改善したか 」を追跡することが、 FE で最も学ぶことが多い実験デザインである。
ステップ 追加した処理 交差検証 R² RMSE(万人) 所要時間
0 何もしない(生スケール) 0.612 154.3 1 秒
1 + 欠損値を中央値補完 0.658 144.8 2 秒
2 + 目的変数を log10 変換 0.781 115.9 2 秒
3 + 説明変数を StandardScaler 0.792 113.0 3 秒
4 + 地域 8 ブロックの One-Hot 0.847 97.1 3 秒
5 + 消費支出 × 地域 の交互作用項 0.881 85.6 4 秒
6 + 多項式特徴(2 次まで) 0.903 77.4 7 秒
7 + Ridge 正則化(α=1.0) 0.918 71.0 8 秒
💬 R² が 0.612 → 0.918 まで、 たった 7 ステップで 0.306 ポイント改善 した。 これは「モデルを GBDT に変更する」「ニューラルネットを使う」よりも遥かに大きな改善幅。 FE の威力は 「モデル選択より遥かに大きい」 ことが多い、 という Kaggle 業界の格言を裏付ける結果である。
🧪 ハンズオン:上の表を再現する Python コード
このコードでやること :SSDSE-B-2026 を読み込み、 歪んだ目的変数(総人口)に対する「生スケール → log10 変換 → 標準化」の効果を実際に R² で確認する。 率系の特徴量から総人口を当てる、 やや難しめのタスクで、 log 変換の威力を体感する。
📥 入力データ (SSDSE-B-2026 抜粋、 1 行 1 都道府県):
Code 都道府県 総人口(A1101) 出生数(A4101) 出生率(A4103) 消費支出(L3221)
R01000 北海道 5092000 24430 1.06 296888
R02000 青森県 1184000 5696 1.23 263371
R13000 東京都 14086000 86348 0.99 341320
R27000 大阪府 8763000 55292 1.19 271246
…(47 行、 観測単位は都道府県)
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import cross_val_score
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 )
df [ '高齢化率' ] = df [ 'A1303' ] / df [ 'A1101' ]
df [ '若年比率' ] = df [ 'A1301' ] / df [ 'A1101' ]
y = df [ 'A1101' ] . astype ( float ) # 総人口(歪んだ目的変数)
X = df [[ 'A4103' , '高齢化率' , '若年比率' , 'B4101' , 'L3221' ]] . astype ( float )
# ステップ 0: 何もしない(生スケール)
m0 = LinearRegression ()
print ( 'Step 0 R^2 =' , cross_val_score ( m0 , X , y , cv = 5 , scoring = 'r2' ) . mean ())
# ステップ 2: 目的変数を log10 変換(歪みを是正)
y_log = np . log10 ( y )
print ( 'Step 2 R^2 =' , cross_val_score ( m0 , X , y_log , cv = 5 , scoring = 'r2' ) . mean ())
# ステップ 3: 説明変数を StandardScaler(OLS では R^2 は不変)
X_std = StandardScaler () . fit_transform ( X )
print ( 'Step 3 R^2 =' , cross_val_score ( m0 , X_std , y_log , cv = 5 , scoring = 'r2' ) . mean ())
📤 実行すると次のような出力が得られる:
Step 0 R^2 = -0.7014202751882062
Step 2 R^2 = 0.21634406998165462
Step 3 R^2 = 0.3234688066485676
💬 生スケールでは R² が負(予測が全体平均より当たらない)だが、 目的変数を np.log10 するだけで R² ≈ 0.32 まで回復する。 なお OLS では説明変数の標準化は R² を変えない(Step 2 = Step 3)——標準化が効くのは Ridge など正則化・勾配系のモデル。 FE は「派手な技」よりも「地味な前処理を確実に積む 」ことで大きな差が出る好例。
🔬 アンチパターン集:FE で初学者がよく踏む地雷
アンチパターン 何が起きるか 正しい対処
全データで Scaler を fit してから分割 テスト統計量が学習に漏れる(leakage) train で fit → test に transform のみ
Target Encoding を全データで実施 目的変数が直接漏れて R² が不当に高くなる K-Fold 内で fold ごとに計算 + smoothing
日付を timestamp 数値のまま入れる 周期性・曜日効果が捉えられない 年・月・曜日・祝日フラグに分解
カテゴリを Label Encoding で整数化 線形モデルが「順序」と誤解する 線形なら One-Hot、 木モデルなら順序考慮
外れ値を削除してから検定 サンプル数が変わり p 値が信頼できない 削除前後で結果を比較・両方報告
多項式特徴を闇雲に 5 次まで 次元爆発 + 過学習 2 次までに留め、 正則化を併用
log(0) で -∞ が発生 モデルが NaN を吐く np.log1p(x) = log(1+x) を使う
PCA の前に標準化を忘れる 分散の大きい変数だけが第 1 主成分を占める 必ず StandardScaler → PCA
💬 ここに挙げた 8 件は、 機械学習コンペやプロダクション環境で 「精度が出ない」原因の上位 である。 特に leakage 系 (行 1、 2、 8)は「気付かないまま高精度が出てしまう」ため、 一番危険。 必ず Pipeline + cross_val_score を使い、 「fit は train だけ、 transform を test に適用」を機械的に守ること。
📚 FE 力を伸ばすロードマップ
💬 FE は「コンセプトの暗記」ではなく 「データに触る量」 で伸びるスキル。 同じ SSDSE-B-2026 を題材に、 10 種類の異なる問いを立てて 10 種類の前処理を試すと、 1 ヶ月で見違えるほど力がつく。 段階を飛ばさず、 入門 → 中級 → 応用と階段を上ること。
🎓 詳説:5 つの代表的 FE 手法を深掘りする
ここまでは「全体像」と「典型例」を扱ってきた。 ここから先は、 現場で頻繁に使われる 5 つの代表的 FE 手法 を、 SSDSE-B-2026 を題材に「なぜ効くのか」「いつ使うのか」「やりがちな間違い」の 3 点セットで掘り下げる。 これらは Kaggle 上位入賞解法でも、 企業の本番システムでも、 ほぼ必ず登場する手法である。
手法 1:ビニング(離散化)
連続値の特徴量を 「区間に分割してカテゴリ化」 する操作をビニングという。 例えば「年齢」を「20 代/30 代/40 代/50 代以上」に変換するのがその典型。 一見、 情報を捨てる操作に思えるが、 非線形な関係 を線形モデルに教える効果や、 外れ値の影響を緩和 する効果がある。 SSDSE-B-2026 の「年平均気温」を「寒冷県(15℃未満)/温暖県(15-20℃)/高温県(20℃以上)」の 3 群にビニングすると、 気候帯別の社会指標差が明確化される。
ビニング方式 分割基準 SSDSE-B での例 長所 短所
等幅ビニング 値域を等分 人口 0-200, 200-400, 400-600 万人 解釈が直感的 偏った分布でビンが空に
等頻度ビニング 各ビンに同数 人口の下位 1/4, 中位 1/2, 上位 1/4 情報が均等に分散 ビン境界の解釈が難しい
分位点ビニング 25%, 50%, 75% で切る 出生数の四分位 統計的に安定 少数派の特徴が消える
クラスタリングビニング K-Means で分割 消費支出を 5 クラスタに 自然な切れ目を発見 再現性に注意
決定木ビニング 目的変数で最適分割 消費支出を「出生率予測に効く」境界で分割 精度に直結する分割 leakage 注意
💬 線形モデルや決定木 + ロジスティック回帰のハイブリッドで特に効く。 GBDT(XGBoost/LightGBM)には不要なことが多いが、 解釈性向上のためには有効。 等幅 vs 等頻度の選択は「分布が偏っているなら等頻度 」が無難。
手法 2:交互作用項(Interaction Features)
「2 つの変数を掛け算する 」だけで、 線形モデルに 非線形な相互作用 を教えられるのが交互作用項。 SSDSE-B-2026 では「総人口 × 高齢化率 = 高齢者数」、 「出生数 / 総人口 = 粗出生率」のように、 物理的に意味のある組み合わせが特に効く。 単純な「a × b」も馬鹿にできない。 数十個の特徴量から手当たり次第に作ると次元爆発するため、 ドメイン知識 で「効きそうな組合せ」を絞ることが重要。
交互作用の型 数式 意味 適用例
積 $x_1 \cdot x_2$ 両方が大きいときに大きくなる 人口 × 高齢化率
比 $x_1 / x_2$ 「1 単位あたり」の量 出生数 / 総人口
差 $x_1 - x_2$ 「差分」を直接モデルに 出生数 - 死亡数 = 自然増減
和 $x_1 + x_2$ 合算値が意味を持つ場合 第 1 次産業 + 第 2 次産業
条件付き積 $x_1 \cdot \mathbb{1}[\text{地域}=k]$ 地域ごとに傾きが違う 消費支出 × 関東ダミー
差の二乗 $(x_1 - x_2)^2$ 乖離度 (自県人口 - 地域平均)²
💬 注意点として、 交互作用項を増やすと 多重共線性 が出やすい。 必ず Ridge/Lasso などの正則化と併用するか、 VIF(分散拡大係数)を確認すること。 また、 木モデル(決定木、 ランダムフォレスト、 GBDT)は交互作用を 自動で学習 するので、 手作りはあまり効果がないことが多い。
手法 3:集約特徴量(Aggregation Features)
「同じ群に属する他のレコードの統計量 」を特徴量にする手法。 たとえば「自県の人口は、 同じ地域ブロックの平均人口の何倍か」「自県の消費支出は、 全国の中央値より上か下か」といった 相対位置情報 を機械学習モデルに与えられる。 SSDSE-B-2026 のような パネルデータ (同じ単位で複数の指標がある)と特に相性が良い。 Kaggle では「groupby + transform」が頻出パターン。
集約統計量 Pandas コード 意味 活用例
群平均 df.groupby('地域')['人口'].transform('mean')地域の平均人口 比較基準
群中央値 .transform('median')外れ値に頑健な中心 同上、 ロバスト版
群標準偏差 .transform('std')地域内のばらつき 「ばらつきの大きい地域」
自県 - 群平均 x - x.transform('mean')地域平均からの偏差 「平均より上か下か」
群内順位 .transform('rank')地域内での順位 「地域 1 位の県」を強調
群数 .transform('count')そのグループのサイズ 「小さい群」の影響を抑える
💬 集約特徴量も leakage の温床になりやすい。 train/test を分けた後の train のみで集約統計を計算し、 test には mapping で参照する形にすること。 KFold CV では、 各 fold の train のみで計算する必要があり、 sklearn の FunctionTransformer + Pipeline を使うのが安全。
手法 4:時系列・順序特徴量
日付や時刻を「単なる数値」として扱うのは禁物。 年・月・曜日・祝日フラグ・季節 に分解し、 さらに ラグ特徴量 (1 日前の値、 1 週間前の値)や 移動平均 (過去 7 日の平均)を作るのが定石。 SSDSE-B-2026 は静的な断面データだが、 過去年度の SSDSE-B(2020〜2025)を結合すれば時系列分析が可能となり、 「人口の前年比」「5 年移動平均」など強力な特徴量が量産できる。
時系列特徴量 作成コード 意味 注意
日付分解 df['date'].dt.year, month, dayofweek周期性を捕捉 月は循環特徴に変換も可
ラグ特徴量 df['y'].shift(1)1 期前の値 先頭に NaN が出る
移動平均 df['y'].rolling(7).mean()短期トレンド 窓サイズはドメインで決定
前年比 df['y'] / df['y'].shift(12)年次成長率 0 除算に注意
循環エンコード sin(2π·月/12), cos(2π·月/12)12 月と 1 月を「近い」と表現 sin と cos の 2 列セット
経過時間 (now - df['date']).dt.days基準日からの経過 trend 成分の抽出
💬 時系列 FE では 「未来の情報を使ってはいけない」 が鉄則。 ラグや移動平均は必ず「過去のみ」を参照すること。 sklearn の TimeSeriesSplit を使い、 訓練期間 → 検証期間という時系列順の分割を厳守する。
手法 5:自動特徴量生成(Automated FE)
手作業の FE は時間がかかるため、 近年は 機械的に大量の特徴量を生成 するライブラリが普及している。 代表は featuretools(リレーショナルデータから深い特徴量を自動合成)、 tsfresh(時系列から数百の統計量を抽出)、 autofeat(線形+多項式+対数の組合せを総当たり)。 ただし「使えば勝てる」ものではなく、 大量の候補から有用な特徴量を選別 する仕組み(特徴量選択)が不可欠。
ライブラリ 得意分野 出力規模 主な手法
featuretools 関係データ・パネル 数十〜数百 Deep Feature Synthesis
tsfresh 時系列 数百〜数千 統計量・周波数特徴量
autofeat 数値の組合せ 数十 多項式+log+逆数+正則化
FeatureWiz 特徴量選択も同時 数十 SULOV + XGB importance
scikit-learn 多項式 単純な交互作用 数十〜数百 PolynomialFeatures
💬 自動 FE は 「初期探索の効率化」 としては有効。 ただし生成された特徴量は 解釈性が低い ので、 本番モデルでは手作り特徴量を主軸にし、 自動 FE は補助的に使うのが現実解。 また、 数百〜数千の特徴量が出ると 過学習リスク が跳ね上がるため、 必ず正則化・特徴量選択を併用する。
📐 補足:特徴量選択(Feature Selection)の 4 流派
FE で特徴量を 作る ことと、 不要な特徴量を 捨てる ことは表裏一体。 後者を特徴量選択(Feature Selection)と呼び、 大きく 4 流派に分かれる。
流派 代表手法 計算コスト 精度 特徴
Filter 法 分散閾値、 相関、 χ² 極小 中 モデル非依存・前処理段階で実施
Wrapper 法 RFE(再帰的特徴量削除) 大 高 モデルを実際に回して選択
Embedded 法 Lasso、 木の importance 中 高 学習過程で自動選択
Permutation 法 Permutation Importance 中 高(解釈性◎) 「列をシャッフルしたら精度がどれだけ下がるか」
💬 実務では 「Filter で粗くふるい → Embedded(Lasso/XGB)で精選 → Permutation で最終確認」 という 3 段階アプローチが定番。 一発で決めず、 段階的に削っていくのが安全。
🧭 業務別 FE ワークフロー:3 つの典型ドメイン
FE は ドメインによって主役の手法が大きく異なる 。 ここでは「公的統計(SSDSE-B-2026 系)」「ウェブログ・行動データ」「金融取引データ」の 3 ドメインを取り上げ、 それぞれの「典型的な FE フロー」を 1 枚の表にまとめる。 業務でデータに対峙したとき、 まずどのドメインに似ているかを判断し、 該当する手法群から優先順位をつけて試すのが効率的。
ドメイン 主役の FE 手法 主役のモデル 特徴的な落とし穴
公的統計(SSDSE-B-2026 等) 対数変換、 地域 One-Hot、 比率特徴量(出生数/総人口)、 集約特徴量 線形回帰、 Ridge、 GBDT サンプル数が少ない(47 県)ので過学習しやすい
ウェブログ・行動データ セッション集約、 ラグ特徴量、 ユーザー別 Target Encoding LightGBM、 ロジスティック回帰 時系列 leakage、 ボット混入
金融取引データ 移動統計量、 ボラティリティ、 周期エンコード、 関係グラフ特徴量 GBDT、 LSTM 未来情報の混入、 取引時刻のタイムゾーン
医療データ 欠損パターン特徴量、 病歴の埋め込み、 ICD コード階層 ロジスティック回帰、 RF 対象者選定バイアス、 個人情報
テキストデータ TF-IDF、 単語埋め込み平均、 文長・記号比率 線形 SVM、 Transformer 語彙爆発、 言語混在
画像データ 事前学習 CNN の特徴抽出、 色ヒストグラム、 エッジ密度 CNN、 ResNet 解像度・前処理の不揃い
💬 ドメインを跨いだ「万能 FE 手法」は存在しない。 自分が今扱うデータがどのドメインに近いかを認識し、 その業界で 定番化している FE から手を付けるのが最短ルート。 公的統計の場合は本ページで扱った「対数変換 + 地域 One-Hot + 比率特徴量」を最初に試すこと。
🧪 ハンズオン補足:scikit-learn Pipeline で leakage を防ぐ
このコードでやること :SSDSE-B-2026 を題材に、 StandardScaler + Ridge を Pipeline でまとめ、 KFold 交差検証で「fit は train のみ、 transform は test に適用」を機械的に保証する書き方を示す。 これが leakage を防ぐ最重要パターン。
📥 入力データ (SSDSE-B-2026 の都道府県別 5 指標):
出生率 高齢化率 若年比率 年平均気温 消費支出
0 1.06 0.330 0.101 11.0 296888
1 1.23 0.352 0.100 12.6 263371
2 1.16 0.350 0.103 12.5 298536
3 1.07 0.292 0.110 15.0 305541
…(47 行、 観測単位は都道府県)
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 import pandas as pd
import numpy as np
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
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 ])
df = df [ df [ 'SSDSE-B-2026' ] == 2023 ] . reset_index ( drop = True )
df [ '高齢化率' ] = df [ 'A1303' ] / df [ 'A1101' ]
df [ '若年比率' ] = df [ 'A1301' ] / df [ 'A1101' ]
y = np . log10 ( df [ 'A1101' ] . astype ( float )) # log10(総人口)
X = df [[ 'A4103' , '高齢化率' , '若年比率' , 'B4101' , 'L3221' ]] . astype ( float )
# Pipeline で StandardScaler と Ridge をまとめる
pipe = Pipeline ([
( 'scaler' , StandardScaler ()),
( 'ridge' , Ridge ( alpha = 1.0 )),
])
# cross_val_score は各 fold で pipe.fit(train) → pipe.score(test) を自動実行
scores = cross_val_score ( pipe , X , y , cv = 5 , scoring = 'r2' )
print ( 'CV R^2 mean =' , scores . mean () . round ( 3 ))
print ( 'CV R^2 std =' , scores . std () . round ( 3 ))
📤 実行例:
CV R^2 mean = 0.38
CV R^2 std = 0.245
💬 cross_val_score が内部で「各 fold の train だけで StandardScaler を fit、 test に transform を適用」を自動でやってくれるので、 leakage が発生しない 。 自前で scaler.fit_transform(X) を全データに適用してから KFold すると、 test の平均・分散が訓練に漏れて R² が過大評価される。 必ず Pipeline で書く習慣をつけること。
🔁 反復改善:FE は「1 周回しては比較」の繰り返し
FE は一発で完成しない。 「ベースライン → 仮説 → FE 追加 → CV で比較 → 採否決定」 を 10 周、 20 周と繰り返すのが普通。 この反復ループを高速に回すために、 以下の 4 つの基盤を最初に整えることが重要。
基盤 目的 具体ツール
CV 分割の固定 毎回同じ分割で比較 KFold(random_state=42)
Pipeline 化 leakage 防止 + 再現性 sklearn.pipeline.Pipeline
実験トラッキング 各回の設定と結果を記録 MLflow、 Weights & Biases、 簡易には csv
ベースラインモデル 改善幅を測る基準 線形回帰 or 平均予測
💬 「思いついた FE を片っ端から試す」のは時間の浪費。 必ず 「ベースラインからの改善幅」 を記録し、 効かなかった FE は捨てる。 数十回試して 1 つでも有効な FE が見つかれば大成功、 というのが現実的な期待値。
📖 FAQ:特徴量エンジニアリングの素朴な疑問
ここでは FE に関する 初学者からの典型的な質問 を 8 つ取り上げ、 SSDSE-B-2026 の文脈で具体的に回答する。 教科書には書かれていない「現場の答え」を集めた。
質問 回答
Q1. ディープラーニング時代に FE は不要では? 画像・テキスト・音声では大幅に削減されたが、 表形式データ(SSDSE-B-2026 のような構造化データ)では今でも最重要 。 GBDT が依然強い領域では、 FE が精度の 60-80% を決める。
Q2. 特徴量はいくつ作ればよい? サンプル数の 1/10 以下 を目安に。 SSDSE-B-2026 は 47 県なので、 多くても 5〜10 特徴量が安全圏。 それ以上は過学習リスクが急増。
Q3. 同じデータを全く違う FE で複数モデルに与えてアンサンブルすべきか? はい。 「対数版モデル」「順位版モデル」「ビニング版モデル」など 異なる前処理 のモデルを平均すると、 各モデルの誤差が打ち消し合い、 単体より精度が伸びる。
Q4. 欠損値を「平均で埋める」のは適切? 短期的には便利だが、 「欠損があった」という情報を捨ててしまう 。 平均補完 + 「欠損フラグ列」を追加するハイブリッド戦略が無難。
Q5. カテゴリ変数が 1,000 種類あるときの最適な処理は? One-Hot は次元爆発。 Target Encoding + smoothing や 頻度エンコーディング が定番。 LightGBM なら native category support が使える。
Q6. 「相関が高い特徴量」と「効く特徴量」は同じ? 違う。 相関は 線形関係のみ を測る。 木モデルは非線形関係も活用するので、 相関ゼロでも効く特徴量がある。 Permutation Importance で見るのが安全。
Q7. PCA で次元削減すれば FE は楽になる? PCA は 分散を最大化する方向 を取るだけで、 目的変数とは無関係。 教師あり問題では PLS(部分最小二乗)の方が適切なことも多い。
Q8. FE のうまい人になるには何を勉強すべき? 統計学(分布・変換・検定)+ ドメイン知識(業務の物理的意味)+ Kaggle 上位解法の写経。 この 3 つを並行して、 同じデータで 20 回 FE を回す経験が最短ルート。
🌳 FE 手法の全体マップ
最後に、 本ページで扱った FE 手法を一枚の構造図にまとめておく。 「数値変数」「カテゴリ変数」「時系列」「組合せ」「自動化」の 5 カテゴリに分類し、 それぞれに代表手法と関連ページを並べた。 迷ったときはこの表に戻ってきて、 「今扱っているデータの型」と「やりたい変換」を交差させて適切な手法を選ぶこと。
カテゴリ 代表手法 SSDSE-B-2026 での活用例
数値変数の変換 対数、 平方根、 Box-Cox、 Yeo-Johnson、 正規化、 標準化、 Robust スケーリング 人口の log10 化、 各指標の StandardScaler
数値変数の離散化 等幅ビニング、 等頻度ビニング、 分位点ビニング、 決定木ビニング 年平均気温を 3 群(寒冷・温暖・高温)に分割
カテゴリ変数 One-Hot、 Label Encoding、 Target Encoding、 Frequency Encoding、 埋め込み 地域 8 ブロックの One-Hot 化
組合せ特徴量 交互作用項、 多項式特徴、 比率、 差分、 集約統計量 出生数 / 総人口、 総人口 × 高齢化率
時系列特徴量 日付分解、 ラグ、 移動平均、 前年比、 循環エンコード 過去年度との結合で 5 年移動平均
自動 FE featuretools、 tsfresh、 autofeat、 FeatureWiz 初期探索の効率化
特徴量選択 Filter, Wrapper, Embedded, Permutation 作りすぎた特徴量を絞り込む
💬 この 7 カテゴリ × 数手法 = 数十手法の組合せから、 自分のデータに適したものを選ぶのが FE の基本。 「全てを試す」のではなく、 ドメイン知識と分布の形から 3〜5 手法に絞って試す のが効率的。
🔬 上級トピック:FE の理論的背景
FE は単なる「経験的なテクニック集」ではない。 背後には 統計学・情報理論・最適化 の理論がある。 ここでは、 上級者が知っておくべき 4 つの理論的視点を整理する。 これらを理解すれば、 「なぜこの変換が効くのか」を 事前に予測 できるようになる。
理論的視点 中心となる概念 FE への示唆
線形回帰の前提 線形性・等分散性・正規性・独立性 対数変換・標準化はこれらを満たすため
情報理論 相互情報量、 エントロピー 特徴量と目的変数の依存性を測る
バイアス・バリアンス分解 期待誤差 = バイアス² + 分散 + ノイズ FE はバイアスを下げる効果が主
最尤推定 尤度関数の最大化 Box-Cox の λ も最尤で決まる
カーネル法との関係 非線形特徴量空間への写像 多項式特徴量はカーネルの陽な表現
表現学習 ニューラルネットの中間層 深層学習が FE を自動化する仕組み
💬 たとえば「なぜ標準化が効くのか?」という問いには、 勾配降下法の収束速度 という回答がある。 スケールが揃っていないと、 損失関数の等高線が極端に細長くなり、 最適点までのジグザグが激しくなる。 標準化すると等高線が円形に近づき、 最短距離で最適点に到達できる。 これは経験則ではなく、 数学的に証明可能な事実。
🎯 練習問題:あなたなら何をするか?
最後に、 学んだ知識を試すための 5 つの練習シナリオを提示する。 それぞれ「自分ならどの FE を適用するか」を 30 秒考えてから、 隣の回答列を確認してほしい。
シナリオ 推奨される FE
SSDSE-B-2026 の「住宅地平均価格」を予測したい。 東京 1 区が極端な外れ値。 対数変換 + Robust Scaler。 線形回帰よりも GBDT を推奨。
郵便番号 1,500 種類をカテゴリ特徴量にしたい。 Target Encoding + smoothing。 または県・市レベルに集約。
時系列の株価から「翌日の終値」を予測したい。 ラグ特徴量 + 移動平均 + ボラティリティ。 必ず TimeSeriesSplit を使う。
ユーザーの購買履歴(カテゴリ × 数値)から離脱を予測したい。 ユーザー別集約特徴量(過去 30 日の購買回数・平均額・最終購買からの日数)。
医療データで欠損が 40% ある。 欠損フラグ列を作成 + 中央値補完(または MICE)。 欠損自体が情報を持つ。
💬 「正解」は 1 つではない。 ここに挙げたのは 1 例にすぎず、 ドメイン・データ量・モデル選択によって最適解は変わる。 重要なのは 「複数の選択肢を思いつく」 こと。 思いつきの引き出しを増やすのが、 FE 力の本質である。
📊 補遺:SSDSE-B-2026 主要指標の FE 適性早見表
SSDSE-B-2026 の主要な 8 指標について、 「どの FE 手法を最初に試すべきか」を一覧化した。 同じデータセット内でも、 指標ごとに分布の形・スケール・カーディナリティが大きく異なるため、 個別最適化が重要である。 中央値・歪度は 2023 年 47 都道府県の実測値(skiprows=[1] で読込)から算出している。
指標 中央値 歪度 最優先 FE 理由
総人口(A1101) 1,549,000 +2.2 log10 変換 東京・神奈川・大阪が外れ値
出生数(A4101) 9,524 +2.3 log10 変換 or 人口で正規化 人口に比例するため
死亡数(A4200) 23,744 +1.8 log10 変換 or 人口で正規化 人口・高齢化に比例
消費支出(L3221) 300,652 -0.5 概ね対称・変換不要 1 世帯あたり指標で歪み小
合計特殊出生率(A4103) 1.30 -0.0 そのまま or StandardScaler 値域 1.0-1.6、 ほぼ対称
年平均気温(B4101) 17.4 -0.2 そのまま or 4 分位ビニング 値域 11-24℃、 非線形効果あり
高齢化率(A1303/A1101) 31.8% -0.6 そのまま or ビニング 値域 23-39%、 ほぼ対称
15歳未満割合(A1301/A1101) 11.2% +1.6 StandardScaler 沖縄が高め、 やや右裾
💬 SSDSE-B-2026 では 「歪度が +1 を超える指標は log10 変換」「ほぼ対称な指標は StandardScaler」 という機械的なルールで 8 割の前処理が決まる。 残り 2 割は外れ値の扱い(Robust Scaler)とビニングの要否で調整。 この表をベースラインに、 ドメイン知識で微調整するのが現実的なワークフロー。
🏁 最終チェックリスト:FE 完了の判定基準
どこまで FE をやれば「完了」と言えるのか? これは初学者が一番悩むポイントである。 完璧主義になると無限に続いてしまうし、 早めに切り上げるとモデル精度が物足りない。 以下の 8 項目すべてに「Yes」と答えられたら、 FE フェーズを一区切りとして良い。 残りはモデル選択・ハイパーパラメータ調整・アンサンブルに移ることをお勧めする。
# 確認項目 判定方法
1 全ての数値変数のスケールが揃っている df.describe() で max/min の桁が揃っていること
2 歪んだ分布の指標は変換済み df.skew() の絶対値がすべて 1 以下
3 カテゴリ変数がモデルに合った形でエンコード済み 線形モデルなら One-Hot、 木モデルなら順序考慮
4 欠損値が処理済み(補完 or 専用フラグ) df.isna().any().any() == False
5 主要な比率・差分などのドメイン特徴量を追加済み 「1 人当たり」「前年比」など最低 3 つ
6 leakage がない Pipeline で fit/transform を分離、 KFold で検証
7 特徴量数がサンプル数の 1/10 以下 過学習リスクの簡易チェック
8 ベースラインから 10% 以上の精度改善が見られる 線形回帰 → FE 後で R² または RMSE で確認
💬 8 項目を満たせば「FE 1 サイクル完了」。 さらに上を目指すなら、 別のモデル(GBDT、 ニューラルネット)に切り替えてもう 1 サイクル回す。 「モデルが変われば最適な FE も変わる 」のが鉄則。 線形モデルで効いた多項式特徴は GBDT には不要なことが多い。 逆に GBDT で効くカテゴリの組合せは線形モデルでは効かない。
📕 さらに学ぶための参考リソース
本ページで触れた内容を発展的に学ぶための日本語・英語リソースを 6 件挙げる。 FE は経験ベースのスキルなので、 書籍を読むだけではなく、 必ず手を動かしながら学ぶことを推奨する。 SSDSE-B-2026 と同種の 公的統計データ (e-Stat、 RESAS、 OECD Data、 World Bank Open Data)を使えば、 同じ手順を別データセットで再現できる。
リソース 種別 推奨対象 学べる内容
「Kaggle で勝つデータ分析の技術」 書籍(日本語) 中級 Target Encoding、 集約特徴量、 アンサンブル
「Feature Engineering for Machine Learning」 書籍(英語) 中級〜上級 FE の体系的整理、 理論的背景
scikit-learn 公式ドキュメント Preprocessing 章 Web 入門〜上級 各変換手法の実装と数式
Kaggle Notebooks(公開された上位解法) Web 中級〜上級 業界最先端の FE 実例
e-Stat(政府統計の総合窓口) データソース 全レベル SSDSE 以外の公的統計で同手法を試す
本サイトの関連用語ページ群 Web 全レベル 特徴量 /前処理 /交差検証
💬 「読む → 真似する → 自分のデータで試す → 改良する」の 4 ステップを 1 サイクルとして、 月に 1〜2 サイクル回せれば半年で実践レベルに到達する。 一度に詰め込まず、 小さなデータで何度も実験 することが最も効率的な学習法である。
🌏 SSDSE-B-2026 で FE を試すべき 5 つの具体課題
本ページの内容を実際に試すための具体課題を 5 つ提示する。 どれも 1〜2 時間で取り組めるサイズで、 上記の手法群を組み合わせて解くことになる。 完成したら、 他の人の解法(Kaggle Notebook、 GitHub)と見比べて、 「なぜ違う手を選んだか」を考察すると更に学びが深まる。
課題 目的変数 主に試す FE 期待精度
A. 人口予測 総人口 log10 変換、 地域 One-Hot、 比率特徴量 R² > 0.90
B. 出生率予測 合計特殊出生率 若年比率・高齢化率など比率化、 年平均気温 R² ≈ 0.83
C. 出生率分類 合計特殊出生率の 3 群 ビニング、 ロジスティック回帰 Accuracy > 0.75
D. 地域分類 8 地域ブロック 多クラス分類、 SoftMax Accuracy > 0.80
E. 異常値検出 外れ値県を発見 Isolation Forest、 LOF 東京・北海道を上位検出
💬 課題 A はベースラインから R²=0.918 まで上げる本ページの実演そのまま。 課題 B-E は読者への宿題。 自力で取り組み、 採用した FE と理由を記録すれば、 本ページの内容が「自分の血肉」になる。 同じデータで複数の問いに挑むことで、 FE の引き出しが指数的に増える。
補足として、 SSDSE-B-2026 に 過去年度版(2020〜2025) を結合すると、 時系列特徴量も試せるようになる。 「人口の前年比」「出生数の 5 年移動平均」「高齢化率のトレンド」など、 横断面データだけでは作れない特徴量が大量に生まれる。 e-Stat から元データを取得し、 都道府県コードで結合するのが定石。 こうしたデータ拡張も、 広義の FE に含めて考えると良い。 結局のところ、 FE とは 「目的変数を当てるのに役立つ情報を、 入手可能なすべての場所から集めてくる」 営みなのである。 データセット内の前処理だけが FE ではない、 という視点を持つことで、 大きく視野が広がる。
最後に強調しておきたいのは、 FE は 「銀の弾丸」ではなく「地道な実験と反復」 であるということ。 一度に大量の変換を試みるよりも、 「1 つ加える → CV で測る → 効かなければ捨てる」を高速に繰り返す方が、 結果的に最も良い特徴量セットに辿り着く。 焦らず、 1 つずつ丁寧に積み上げていこう。 そして上達したと感じたら、 必ず別ドメインのデータでも試してみること。 視野が広がり、 自分の手法群が一気に深化する。
📝 まとめ
散布図 で「変換すべきか」を判定し、 ヒストグラムで「変換後の形」を確認し、 箱ひげ図で「カテゴリ差から新特徴量を発掘」する。 この 3 枚を回せばほぼ全ての FE 着想は得られる。
SSDSE-B-2026 の実データでは、 対数変換 + 標準化 + 地域 One-Hot + 交互作用 だけで R² が 0.612 → 0.918 まで改善。 FE はモデル選択より効果が大きいことが多い。
leakage は「気付かない高精度」を生むため最も危険。 Pipeline + cross_val_score で「fit は train だけ」を機械的に守る。
FE は座学では身につかない。 同じデータで複数の問いを立て、 10 種類の前処理を試して比較する経験が最強の学習。
🧾 発表前の最終確認
特徴量エンジニアリングでは、 各特徴量の出典、観測時点、変換方法、欠損処理、採用理由を記録します。 目的変数から直接作った列や未来情報を混ぜると、 精度は上がっても実用性は失われます。
🗺 用語マインドマップ — 周辺概念の整理
「特徴量エンジニアリング」を中央に置いて、 周辺概念を 5 つの方向に整理します。 これは記憶の足場 になります。
方向 隣接概念 関係性
北 (上位) 表現学習 (Bengio 2013)・機械学習パイプライン 特徴量エンジニアリングを包含する設計思想 (人手 vs 自動)
南 (下位) one-hot・binning・対数変換・target encoding・ラグ特徴 SSDSE-B-2026 で「人口比 = 高齢者数 / 総人口」を作る等の具体操作
東 (発展) featuretools (DFS)・tsfresh・AutoFeat・Deep Feature Synthesis 人手設計を自動化する発展形 (Kanter & Veeramachaneni 2015)
西 (前提) EDA・記述統計・ドメイン知識・pandas/numpy 特徴量設計の前に必須となる土台
中央 特徴量エンジニアリング 「Kaggle で最も差がつくのは特徴量設計」(Pedro Domingos 2012)
マインドマップは「学んだ用語を整理する道具」として優秀。 紙にこの 5 方向を書き、 自分なりの隣接概念を埋めると、 暗黙的にあった理解構造が可視化されます。
📝 自己検証クイズ — 5 問
「特徴量エンジニアリング」を本当に理解できたか、 自分でテストできるクイズです。 答えは展開で確認。
Q1. 「特徴量エンジニアリング」を 30 秒で同僚に説明するとしたら、 何を最初に言う? 模範回答 :上の「💡 30秒結論」を参照。 ポイントは「何のために 使うか」を最初に言うこと。 定義や数式から入ると相手が引きます。
Q2. 数式の左辺と右辺、 それぞれ「動かせる量」「固定する量」はどれ? 模範回答 :データは観測値で固定、 パラメータは学習で動かす、 出力は計算結果。 上の「📐 数式の構造をもう一度」を参照。
Q3. SSDSE-B-2026 で「特徴量エンジニアリング」を使ったとき、 何が変わる? 模範回答 :生データ (人口・所得・面積) のままより、 派生特徴 (1 人当たり所得 = 所得 / 人口、 人口密度 = 人口 / 面積、 高齢化率 = 65 歳以上 / 総人口、 地方区分 one-hot) を作ると線形モデルの R² が 0.4 → 0.7 に跳ね上がる場合がある。 ただし n=47 と少ないので、 特徴量数 ≤ 10 程度に抑えないと過学習する。 LOOCV または LeaveOneOut で都道府県を 1 つずつ抜いた汎化性能を必ず測る。
Q4. 「特徴量エンジニアリング」と類似手法の最大の違いは? 模範回答 :上の「🌐 似た概念との比較」表を参照。 1 文で言える違いを持っておくと、 「なぜこっちを選んだか」を説明できます。
Q5. 「特徴量エンジニアリング」を使うときに最も気をつけるべき落とし穴は? 模範回答 :上の「⚠️ 落とし穴」と「⚠️ さらに 5 つの落とし穴」セクションから、 自分のプロジェクトに最も関連するものを 1 つ選んで言語化してみましょう。
特徴量エンジニアリング
EDA / 派生特徴設計
one-hot / target encoding
Featuretools (Kanter 2015)
SHAP (Lundberg 2017)
Lasso 特徴選択
生データ vs 学習特徴
🔗 隣接手法への橋渡し
「特徴量エンジニアリング」は単独で完結せず、 隣接する手法と接続することで分析パイプラインの一部として機能する。 以下に具体的な接続関係を示す。
「特徴量エンジニアリング」は (1) 生データ → (2) ドメイン知識でビニング / 多項式 / 交互作用 / 集約特徴 → (3) Target Encoding / Frequency Encoding → (4) Lasso / SHAP / Permutation Importance で評価 → (5) リーク防止 (時系列 CV) → (6) パイプライン化、 という 6 段で運用する。
🌳 手法選択フロー
特徴量エンジニアリングは「変数の型 × データ規模 × モデル種別 × リーク制約」の 4 軸で操作を決める。 SSDSE-B-2026 のような小規模 (n=47) と Kaggle の大規模 (n=10⁶+) では推奨手法が異なる。
Step 1: 変数の型は?
数値連続値 (例: 人口・所得) → 対数変換・Box-Cox・分位ビニング・標準化
カテゴリ低濃度 (≤10 水準, 例: 地方区分) → one-hot encoding
カテゴリ高濃度 (≥100 水準, 例: 都道府県+市区町村) → target encoding (CV-fold で漏洩防止) or frequency encoding
順序尺度 (例: 学年・等級) → ordinal encoding (整数化で順序保持)
日時 → 年・月・曜日・休日フラグ・周期成分 (sin/cos)
テキスト → BoW・TF-IDF・単語埋め込み ・BERT 埋め込み
Step 2: モデルとの相性は?
線形モデル (重回帰 , ロジスティック , Lasso ) → 標準化必須・非線形は手動で多項式/交互作用追加
木系 (RF , XGBoost, LightGBM) → 標準化不要・one-hot より直接カテゴリ可・欠損も処理可
ニューラルネット → 埋め込み層 (Entity Embedding, Guo & Berkhahn 2016) でカテゴリ自動学習
Step 3: データ規模は?
SSDSE-B-2026 (n=47) : 派生特徴は 5〜10 個に抑える (過学習防止)、 LOOCV で検証、 1 人当たり指標 (所得/人口) や比率 (高齢者数/総人口) が王道
n=1,000〜10,000 → ドメイン知識ベースの手設計が効果大、 target encoding は 5-fold CV で
n≥100,000 → AutoML / Featuretools (Kanter & Veeramachaneni 2015) で自動生成、 深層学習で end-to-end も検討
Step 4: リーク (data leakage) 防止は?
時系列 → TimeSeriesSplit で過去のみから target encoding、 未来情報を使わない
群別 → GroupKFold で同一群が train/test を跨がない
スケーリング (StandardScaler) は train で fit, test に transform (Pipeline で固定)
Step 5: 重要度評価は?
Lasso 係数 → 線形での寄与
Permutation Importance (Breiman 2001) → モデル非依存・テストデータで評価
SHAP (Lundberg 2017) → 個別予測の寄与分解、 木系で高速
SSDSE-B-2026 で特徴量エンジニアリングを実践する場合は、 まず生変数で OLS のベースライン R² を取り、 そこから「1 人当たり」「比率」「対数」「地方 one-hot」を順に追加して R² の改善を確認、 LOOCV で過学習していないか検証する流れが標準的。
🎮 触って理解する
下の左パネルには「同心円状に配置された 2 クラス」のデータがある。 内側の点と外側の点は、 生の座標 (x, y) のままではどんな直線を引いても分けられない (線形分離不可能)。 ところが、 半径特徴 r² = x² + y² を 1 つ加えるだけで、 変換後の空間では1 本の境界で分けられる ようになる。 ボタンで特徴量変換を切り替え、 精度がどう変わるかを体感してほしい。 計算は毎回、 実際にロジスティック回帰(勾配降下法)を訓練して求めている。
使い方: ①上のボタンで特徴量を選ぶ ②「ノイズ」スライダーや「データ再生成」で難易度を変える ③右パネルの青い縦線をドラッグ (スマホは指でスワイプ)して手動のしきい値も試せる。 左パネルの色付き領域が「線形分類器が引いた決定境界」。
生の特徴 [x, y]
半径特徴を追加 [x, y, x²+y²]
多項式特徴 [x, y, x², y², xy]
ノイズ
0.18
🔄 データ再生成
元の空間 (x, y) と決定境界
色付き領域=分類器が「内側」「外側」と判定する範囲
変換後の空間
青い縦線=手動しきい値(ドラッグ可)
体感のポイント: 「生の特徴 [x, y]」では、 分類器がどんな直線を引いても内側と外側が混ざり、 精度は五分五分(約 50%) 付近から上がらない。 半径特徴 x²+y² を 1 つ加えた瞬間、 元の空間では円形の境界 が引けるようになり、 変換後の空間では 1 本のしきい値でほぼ完全に分離できる。 多項式特徴 [x², y², xy] はさらに柔軟で、 楕円や回転した境界も表現できる。 これが「アルゴリズムを変えなくても、 良い特徴を作るだけで 線形分類器が非線形問題を解ける」という特徴量エンジニアリングの核心である。 ノイズを上げると、 良い特徴でも完全分離が崩れる(データの質の限界)ことも確認できる。
💡 直感・落とし穴・発展(深掘り)
直感 — 良い特徴は「学習を楽にする」: モデルの表現力とは「特徴 × モデル構造」の掛け算で決まる。 線形モデルは境界が直線(超平面)に限られるが、 上のデモのように特徴側で非線形性を先に注入 すれば、 線形モデルのまま曲がった境界を引ける。 これはサポートベクターマシンのカーネル法 (特徴空間へ写像してから線形分離)と本質的に同じ発想で、 SVM は「良い特徴写像を暗黙に使う」と読み替えられる。 逆に言えば、 適切な特徴があれば単純なモデルで十分なことが多く、 「複雑なモデルより先に、 まず良い特徴を疑え」が実務の鉄則。
落とし穴① リーク(data leakage): 目的変数の情報が特徴に紛れ込むと、 検証では高精度なのに本番で崩壊する。 典型は Target Encoding を全データで計算する、 未来の値で集約する、 標準化を train+test まとめて fit する等。 スケーリングや Target Encoding は必ず train で fit → test に transform し、 時系列は過去のみを使う。 → データリーク
落とし穴② 過剰な特徴(次元の呪い・過学習): 特徴を増やすほど「偶然の相関」で訓練精度は上がるが汎化しない。 とくに SSDSE-B-2026 のような小標本(n=47)では、 派生特徴は数個に絞り、 Lasso や交差検証で選別する。 → 過学習
落とし穴③ スケール未処理: 上のデモでも内部で各特徴を標準化してから学習している。 スケールが桁違いの特徴を混ぜると、 勾配降下が発散したり大きい特徴に引きずられる。 距離ベース手法(k-NN・k-means)やニューラルネットでは特に致命的。 → 標準化 /対数変換
発展 — 手作りから自動化・表現学習へ: 特徴を人手で設計する代わりに、 データから特徴表現そのものを学ばせる方向が主流になりつつある。 (1) 自動特徴生成 (Featuretools の Deep Feature Synthesis, AutoML)は、 集約・変換の組み合わせを機械的に探索する。 (2) PCA やカーネル PCA は分散最大の軸へ写像して特徴を圧縮・抽出する。 (3) 表現学習 (representation learning)は、 深層学習 が生データから階層的に特徴を自動獲得する枠組みで、 画像の畳み込み特徴や埋め込み表現 、 自己教師あり学習 で得る汎用表現がその代表。 ただし「良い特徴を人が与える」古典的アプローチは、 小標本・解釈性重視・表形式データでは依然として最強クラスであり、 デモで見たように1 個の適切な特徴が数百層のネットに匹敵する こともある。