特徴量エンジニアリング

データ処理・分析 | IT用語集

この用語をシェア

概要

特徴量エンジニアリング(Feature Engineering)は、機械学習において生データから有用な特徴量(Features)を作成・選択・変換する重要なプロセスです。モデルの性能を左右する最も重要な要素の一つとして位置づけられており、「データから価値のある情報を抽出し、機械学習アルゴリズムが理解できる形に変換する」技術です。

良い特徴量エンジニアリングは、シンプルなモデルでも高性能を実現できる一方、不適切な特徴量は複雑なモデルを使っても十分な性能を得られません。データサイエンティストや機械学習エンジニアが最も時間を費やす作業の一つでもあり、ドメイン知識と統計的理解の両方が求められる高度なスキルです。

特徴量エンジニアリングの主要プロセス

1. 特徴量作成(Feature Creation)

既存のデータから新しい特徴量を生成するプロセスです。ドメイン知識と創造性が最も重要な段階です。

  • 数学的変換:対数変換、平方根、指数変換による分布正規化
  • 交互作用特徴量:複数の特徴量の掛け算、割り算による相関関係の表現
  • 集約特徴量:グループ化による統計値(平均、分散、最大値、最小値)の算出
  • 時系列特徴量:移動平均、差分、ラグ特徴量、季節性の抽出
  • テキスト特徴量:文字数、単語数、TF-IDF、n-gram、感情分析スコア

2. 特徴量変換(Feature Transformation)

既存の特徴量を機械学習アルゴリズムに適した形に変換するプロセスです。

  • スケーリング(正規化):標準化(Z-score)、最小最大正規化、頑健スケーリング
  • エンコーディング:カテゴリカル変数の数値変換(One-Hot、Label、Target Encoding)
  • ビニング(離散化):連続値を区間に分割してカテゴリ化
  • 次元削減:PCA、t-SNE、UMAPによる高次元データの圧縮

3. 特徴量選択(Feature Selection)

多くの特徴量から最も重要で有用なものを選択するプロセスです。

  • フィルター法:統計的指標(相関係数、χ²検定、互換情報量)による選択
  • ラッパー法:再帰的特徴除去(RFE)、前進選択、後退除去
  • 組み込み法:L1正則化(Lasso)、ランダムフォレストの特徴量重要度
  • ハイブリッド法:複数手法の組み合わせによる総合的評価

カテゴリカル変数の処理技術

基本的なエンコーディング手法

  • One-Hot Encoding:カテゴリを0/1のダミー変数に変換
  • Label Encoding:カテゴリを順序数値に変換(順序がある場合)
  • Binary Encoding:二進数表現による効率的なエンコーディング
  • Frequency Encoding:出現頻度による数値変換

高度なエンコーディング手法

  • Target Encoding:目的変数の平均値による変換(リークage対策必要)
  • Bayesian Target Encoding:ベイズ統計を用いた安定化されたTarget Encoding
  • Leave-One-Out Encoding:現在の行を除いた Target Encoding
  • CatBoost Encoding:時系列データに適した順序統計ベースの変換

実用的なコード例

基本的な特徴量作成

import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler, OneHotEncoder, LabelEncoder
from sklearn.model_selection import train_test_split

# サンプルデータの作成
df = pd.DataFrame({
    'age': [25, 35, 45, 22, 55, 33, 41, 28],
    'income': [50000, 75000, 95000, 35000, 120000, 65000, 80000, 48000],
    'education': ['高校', '大学', '大学院', '高校', '大学院', '大学', '大学', '大学'],
    'city': ['東京', '大阪', '名古屋', '東京', '大阪', '東京', '名古屋', '東京'],
    'purchase': [0, 1, 1, 0, 1, 1, 1, 0]  # 目的変数
})

# 1. 数学的変換による特徴量作成
df['log_income'] = np.log(df['income'])  # 対数変換
df['age_squared'] = df['age'] ** 2  # 二乗
df['income_per_age'] = df['income'] / df['age']  # 交互作用特徴量

# 2. ビニング(離散化)
df['age_group'] = pd.cut(df['age'], 
                        bins=[0, 30, 40, 100], 
                        labels=['若年層', '中年層', '高年層'])

# 3. カテゴリカル変数のエンコーディング
# One-Hot Encoding
education_encoded = pd.get_dummies(df['education'], prefix='education')
df = pd.concat([df, education_encoded], axis=1)

# Target Encoding(教育レベル別の購入率)
education_target_mean = df.groupby('education')['purchase'].mean()
df['education_target_encoding'] = df['education'].map(education_target_mean)

# 4. 集約特徴量(都市別統計)
city_stats = df.groupby('city').agg({
    'income': ['mean', 'std'],
    'age': 'mean'
}).reset_index()
city_stats.columns = ['city', 'city_income_mean', 'city_income_std', 'city_age_mean']
df = df.merge(city_stats, on='city', how='left')

print(df[['age', 'income', 'log_income', 'age_squared', 'income_per_age', 
          'education_target_encoding', 'city_income_mean']].head())

スケーリングと前処理パイプライン

from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer

# 特徴量の分類
numerical_features = ['age', 'income', 'log_income', 'income_per_age']
categorical_features = ['education', 'city']

# 数値特徴量の前処理パイプライン
numerical_pipeline = Pipeline([
    ('scaler', StandardScaler())  # 標準化
])

# カテゴリカル特徴量の前処理パイプライン
categorical_pipeline = Pipeline([
    ('onehot', OneHotEncoder(drop='first', sparse_output=False))
])

# 総合的な前処理パイプライン
preprocessor = ColumnTransformer([
    ('num', numerical_pipeline, numerical_features),
    ('cat', categorical_pipeline, categorical_features)
])

# データ分割
X = df[numerical_features + categorical_features]
y = df['purchase']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 前処理の適用
X_train_processed = preprocessor.fit_transform(X_train)
X_test_processed = preprocessor.transform(X_test)

# 多項式特徴量の生成
poly = PolynomialFeatures(degree=2, interaction_only=True, include_bias=False)
X_train_poly = poly.fit_transform(X_train_processed)
X_test_poly = poly.transform(X_test_processed)

print(f"元の特徴量数: {X_train_processed.shape[1]}")
print(f"多項式特徴量後: {X_train_poly.shape[1]}")

特徴量選択の実装

from sklearn.feature_selection import SelectKBest, f_classif, RFE
from sklearn.feature_selection import RFECV, SelectFromModel
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression

# より多くの特徴量を持つサンプルデータ生成
np.random.seed(42)
n_samples, n_features = 1000, 20
X_sample = np.random.randn(n_samples, n_features)
# 最初の5つの特徴量のみが目的変数と関連
y_sample = (X_sample[:, 0] + X_sample[:, 1] + X_sample[:, 2] + 
           X_sample[:, 3] + X_sample[:, 4] + np.random.randn(n_samples) > 0).astype(int)

# 1. フィルター法:統計的検定による選択
selector_filter = SelectKBest(score_func=f_classif, k=10)
X_selected_filter = selector_filter.fit_transform(X_sample, y_sample)
print(f"フィルター法で選択された特徴量: {selector_filter.get_support(indices=True)}")

# 2. ラッパー法:再帰的特徴除去
estimator = LogisticRegression(random_state=42)
selector_rfe = RFE(estimator, n_features_to_select=10)
X_selected_rfe = selector_rfe.fit_transform(X_sample, y_sample)
print(f"RFEで選択された特徴量: {selector_rfe.get_support(indices=True)}")

# 3. 組み込み法:ランダムフォレストの特徴量重要度
rf = RandomForestClassifier(n_estimators=100, random_state=42)
selector_rf = SelectFromModel(rf, threshold='median')
X_selected_rf = selector_rf.fit_transform(X_sample, y_sample)
print(f"ランダムフォレストで選択された特徴量: {selector_rf.get_support(indices=True)}")

# 4. 交差検証付きRFE
selector_rfecv = RFECV(estimator, step=1, cv=5, scoring='accuracy')
X_selected_rfecv = selector_rfecv.fit_transform(X_sample, y_sample)
print(f"RFECVで選択された特徴量数: {selector_rfecv.n_features_}")
print(f"最適スコア: {selector_rfecv.score(X_sample, y_sample):.3f}")

# 特徴量重要度の可視化
rf.fit(X_sample, y_sample)
feature_importance = rf.feature_importances_
print("特徴量重要度(上位10位):")
for i in np.argsort(feature_importance)[::-1][:10]:
    print(f"Feature {i}: {feature_importance[i]:.4f}")

時系列データの特徴量エンジニアリング

主要な時系列特徴量

  • ラグ特徴量:過去の値(1期前、7期前、30期前等)
  • 移動統計量:移動平均、移動分散、移動最大・最小値
  • 差分特徴量:前期差、前年同期差、季節差分
  • 季節性特徴量:月、曜日、四半期、祝日フラグ
  • 技術指標:RSI、MACD、ボリンジャーバンド等(金融データ)

時系列特徴量の実装例

import pandas as pd
import numpy as np
from datetime import datetime, timedelta

# 時系列データの作成
dates = pd.date_range('2020-01-01', periods=730, freq='D')
np.random.seed(42)
values = 100 + np.random.randn(730).cumsum() + 10 * np.sin(np.arange(730) * 2 * np.pi / 365)

ts_df = pd.DataFrame({
    'date': dates,
    'value': values
})
ts_df.set_index('date', inplace=True)

# 1. ラグ特徴量の作成
for lag in [1, 7, 30]:
    ts_df[f'lag_{lag}'] = ts_df['value'].shift(lag)

# 2. 移動統計量の作成
for window in [7, 30, 90]:
    ts_df[f'ma_{window}'] = ts_df['value'].rolling(window=window).mean()
    ts_df[f'std_{window}'] = ts_df['value'].rolling(window=window).std()
    ts_df[f'max_{window}'] = ts_df['value'].rolling(window=window).max()
    ts_df[f'min_{window}'] = ts_df['value'].rolling(window=window).min()

# 3. 差分特徴量の作成
ts_df['diff_1'] = ts_df['value'].diff(1)  # 前期差
ts_df['diff_7'] = ts_df['value'].diff(7)  # 7期前との差
ts_df['pct_change_1'] = ts_df['value'].pct_change(1)  # 変化率

# 4. 日時特徴量の作成
ts_df['year'] = ts_df.index.year
ts_df['month'] = ts_df.index.month
ts_df['day'] = ts_df.index.day
ts_df['dayofweek'] = ts_df.index.dayofweek
ts_df['quarter'] = ts_df.index.quarter
ts_df['is_weekend'] = ts_df['dayofweek'].isin([5, 6]).astype(int)

# 5. 季節性の循環エンコーディング
ts_df['month_sin'] = np.sin(2 * np.pi * ts_df['month'] / 12)
ts_df['month_cos'] = np.cos(2 * np.pi * ts_df['month'] / 12)
ts_df['dayofyear_sin'] = np.sin(2 * np.pi * ts_df.index.dayofyear / 365)
ts_df['dayofyear_cos'] = np.cos(2 * np.pi * ts_df.index.dayofyear / 365)

# 6. 技術指標の計算(金融データ向け)
def calculate_rsi(prices, window=14):
    delta = prices.diff()
    gain = (delta.where(delta > 0, 0)).rolling(window=window).mean()
    loss = (-delta.where(delta < 0, 0)).rolling(window=window).mean()
    rs = gain / loss
    return 100 - (100 / (1 + rs))

ts_df['rsi_14'] = calculate_rsi(ts_df['value'])

# 欠損値を除去して確認
print("作成された時系列特徴量:")
print(ts_df.dropna().head())
print(f"\n特徴量数: {ts_df.shape[1]}")

自動特徴量エンジニアリング

主要なライブラリとツール

  • Featuretools:階層データからの自動特徴量生成
  • AutoFeat:数学的変換による特徴量自動生成
  • tsfresh:時系列データ専用の自動特徴量抽出
  • AutoML tools:H2O AutoML、Auto-sklearn、TPOT

Deep Feature Synthesis

Featuretoolsで利用されている自動特徴量生成の手法で、関連するテーブルから階層的に特徴量を生成します。

  • プリミティブ関数を組み合わせた複雑な特徴量の自動生成
  • 関係データベースの外部キー関係を活用した集約特徴量
  • 時間窓を考慮した時系列特徴量の自動作成

ドメイン特化型特徴量エンジニアリング

自然言語処理(NLP)

  • 基本特徴量:文字数、単語数、文数、平均文長
  • TF-IDF:単語の重要度を表現する数値特徴量
  • N-gram:連続する単語の組み合わせパターン
  • 感情分析:ポジティブ・ネガティブスコア
  • エンベッディング:Word2Vec、BERT、GPT等による密ベクトル表現

画像データ

  • 基本特徴量:サイズ、アスペクト比、ファイルサイズ
  • 色彩特徴量:ヒストグラム、平均RGB値、色相分布
  • テクスチャ特徴量:GLCM、LBP、Gabor フィルター
  • エッジ検出:Canny、Sobel、Laplacian
  • 深層特徴量:CNN(ResNet、EfficientNet)の中間層出力

ベストプラクティスと注意点

データリークage(情報漏洩)の防止

  • 時系列での情報漏洩:未来の情報を使った特徴量を避ける
  • Target Leakage:目的変数と直接的に関連する特徴量の除外
  • Train-Test分割後の処理:スケーリング、エンコーディングは学習データのみで学習
  • 交差検証での一貫性:fold間での処理の一貫性確保

計算効率性の考慮

  • 特徴量数の管理:curse of dimensionalityを避けるため適切な数に制限
  • 計算コスト:推論時間を考慮した特徴量の選択
  • メモリ使用量:大規模データでのメモリ効率的な処理
  • 再現性:random seedの設定と処理の文書化

検証と評価

  • 単変量解析:各特徴量と目的変数の関係性確認
  • 多重共線性チェック:VIF(分散拡大要因)による相関確認
  • A/Bテスト:特徴量追加前後でのモデル性能比較
  • SHAP/LIME:特徴量の寄与度分析による解釈可能性確認

最新トレンドと技術動向

AutoML と特徴量エンジニアリング

2024年現在、AutoMLツールは特徴量エンジニアリングの自動化において大きな進歩を遂げています:

  • H2O Driverless AI:ドメイン知識を組み込んだ自動特徴量生成
  • DataRobot:業界特化型の特徴量テンプレート
  • Google Cloud AutoML Tables:大規模データでの自動前処理
  • Amazon SageMaker Autopilot:エンドツーエンドの自動化

Neural Feature Engineering

深層学習による特徴量エンジニアリングの新しいアプローチです:

  • Representation Learning:生データから自動的な特徴量抽出
  • Graph Neural Networks:グラフ構造データからの特徴量学習
  • Transformer-based Features:注意機構による動的特徴量生成
  • Meta-learning for FE:過去の経験から最適な特徴量生成手法を学習

実用的な活用場面

  • Eコマース:購買行動分析、レコメンデーション、価格最適化
  • 金融業界:信用スコアリング、不正検知、アルゴリズミックトレーディング
  • 医療・ヘルスケア:診断支援、薬物発見、個別化医療
  • マーケティング:顧客セグメンテーション、キャンペーン最適化、LTV予測
  • 製造業:品質管理、予知保全、工程最適化
  • IoT・センサーデータ:異常検知、パターン認識、状態監視

学習リソースと参考文献

この用語についてもっと詳しく

特徴量エンジニアリングに関するご質問や、システム導入のご相談など、お気軽にお問い合わせください。