Kaggleを頑張って始めていますが、チュートリアルをほぼコピペになってしまうかもしれませんが見ていきます。概要は、
https://www.kaggle.com/learn/feature-engineering
- 相互情報を使用して、どの特徴が最も重要かを判断する
- いくつかの実世界の問題領域で新しい特徴を発明する
- ターゲットエンコーディングで高次元のカテゴリカルをエンコードする
- k-meansクラスタリングでセグメンテーション特徴を作成する
- 主成分分析でデータセットの変動を特徴に分解する
特徴量エンジニアリングの目的
特徴量エンジニアリングの目的は、単純にデータを手元の問題により適合させることです。特徴量エンジニアリングを行う理由は以下のとおりです:
- モデルの予測性能を向上させるため
- 計算やデータのニーズを減少させるため
- 結果の解釈性を向上させるため
特徴量エンジニアリングの指針
特徴量が有用であるためには、モデルが学習可能なターゲットとの関係を持つ必要があります。例えば、線形モデルは線形の関係しか学習することができません。したがって、線形モデルを使用する場合、目標は特徴量を変換して、ターゲットとの関係を線形にすることです。
ここでのキーとなる考え方は、特徴量に適用する変換は、本質的にモデルの一部となるということです。例えば、片側の長さから正方形の土地の価格を予測しようとする場合、線形モデルを直接長さにフィットさせると結果が悪くなります:関係は線形ではありません。
Length特徴量を二乗して'Area'(面積)を得ると、我々は線形の関係を作り出します。特徴セットにAreaを追加することで、この線形モデルは今、放物線をフィットすることができます。言い換えれば、特徴量を二乗することで、線形モデルは二乗された特徴量をフィットする能力を得ました。
これにより、特徴量エンジニアリングに投資した時間のリターンが非常に高い理由がわかるはずです。モデルが学習できない関係性は、変換を通じて自ら提供することができます。特徴量セットを開発する際には、モデルが最高の性能を達成するためにどのような情報を使用できるかを考えてください。
相互情報量
新しいデータセットに初めて触れると、時に圧倒されることがあります。説明すらないまま、数百や数千の特徴量が提示されることもあるでしょう。どこから手をつければいいのでしょうか?
最初のステップは、特徴量の有用性を測る指標を用いてランキングを構築することです。これは、特徴量と目的変数との間の関連性を測定する関数です。そうすることで、初めに開発する最も有用な特徴量の小さなセットを選ぶことができ、時間を有効に使うことができると自信を持つことができます。
私たちが使用する指標は「相互情報量」と呼ばれます。相互情報量は、2つの量の間の関係を測定する点で相関に似ています。相互情報量の利点は、任意の種類の関係を検出できるのに対し、相関は線形の関係しか検出できないという点です。
相互情報量は、以下のような特徴を持つため、特にモデルの選定がまだ決まっていない特徴開発の初期に非常に有用な汎用指標となります。
- 使用や解釈が簡単
- 計算効率が良い
- 理論的にしっかりしている
- 過学習に対して耐性がある
- 任意の種類の関係を検出できる
相互情報量とそれが測定するもの
相互情報量は、不確実性の観点から関係を説明します。2つの量の間の相互情報量(MI)は、一方の量の知識が他方の不確実性をどれだけ減少させるかを測定するものです。
以下は、Ames Housingのデータからの例です。図は、家の外装の品質とそれが売られた価格との関係を示しています。各点は家を表しています。
図から、外装の品質の値を知っていることで、対応するSalePriceに対してより確信を持てることがわかります。ExterQualの各カテゴリは、SalePriceをある範囲内に集中させる傾向があります。ExterQualとSalePriceの間の相互情報量は、ExterQualの4つの値にわたるSalePriceの不確実性の平均的な減少です。例えば、FairはTypicalよりも頻繁には発生しないので、FairはMIスコアでの重みが少なくなります。
相互情報量スコアの解釈
2つの量の間の相互情報量が取りうる最小の値は0.0です。MIがゼロの場合、その2つの量は独立しており、どちらももう一方についての情報を持っていません。逆に、理論的にはMIが取りうる上限はありません。しかし、実際には2.0以上の値は珍しいです。(相互情報量は対数的な量なので、非常にゆっくりと増加します。)
次の図は、特徴量がターゲットと持つ関連性の種類と度合いがMIの値とどのように対応するかを示してくれます。
左:特徴量とターゲットの間の依存関係が強くなると、相互情報量が増加します。右:相互情報量は任意の種類の関連性を捉えることができます(相関のように線形だけでなく)。
相互情報量を適用する際に覚えておくべきことは以下の通りです:
1. MIは、特徴量がそれ自体としてターゲットの予測因子としての相対的な潜在能力を理解するのに役立ちます。
2. 特徴量が他の特徴量と相互作用する際に非常に有益である可能性がある一方で、単独ではそれほど有益でない場合があります。MIは特徴量間の相互作用を検出することはできません。それは一変量の指標です。
3. 特徴量の実際の有用性は、それを使用するモデルに依存します。特徴量が有用であるのは、その特徴量とターゲットとの関係がモデルが学習できるものである限りです。特徴量が高いMIスコアを持っているからといって、モデルがその情報を利用できるとは限りません。関連性を明らかにするために、まず特徴量を変換する必要があるかもしれません。
例 - 1985年の自動車
Automobileデータセットは、1985年モデルの193台の車から構成されています。このデータセットの目的は、車のmake(メーカー)、body_style(車体スタイル)、horsepower(馬力)などの23の特徴から、車の価格(ターゲット)を予測することです。この例では、相互情報量で特徴をランキングし、データの可視化によって結果を調査します。
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
plt.style.use("seaborn-whitegrid")
df = pd.read_csv("../input/fe-course-data/autos.csv")
df.head()
MIのscikit-learnアルゴリズムは、離散的な特徴と連続的な特徴を異なる方法で扱います。その結果、どれがどれであるかを指定する必要があります。経験則として、float dtypeでなければならないものは離散的ではありません。カテゴリカル(objectまたはcategorial dtype)は、ラベルエンコーディングを与えることで離散的として扱うことができます。
X = df.copy()
y = X.pop("price")
Label encoding for categoricals
for colname in X.select_dtypes("object"):
X[colname], _ = X[colname].factorize()
All discrete features should now have integer dtypes (double-check this before using MI!)
discrete_features = X.dtypes == int
Scikit-learnには、feature_selectionモジュールに2つの相互情報量メトリックスがあります:実数値のターゲット用のもの(mutual_info_regression)と、カテゴリカルターゲット用のもの(mutual_info_classif)。私たちのターゲットである価格は実数値です。次のセルは、特徴量のMIスコアを計算し、それを整理したデータフレームにまとめます。
from sklearn.feature_selection import mutual_info_regression
def make_mi_scores(X, y, discrete_features):
mi_scores = mutual_info_regression(X, y, discrete_features=discrete_features)
mi_scores = pd.Series(mi_scores, name="MI Scores", index=X.columns)
mi_scores = mi_scores.sort_values(ascending=False)
return mi_scores
mi_scores = make_mi_scores(X, y, discrete_features)
mi_scores[::3] # show a few features with their MI scores
curb_weight 1.540126
highway_mpg 0.951700
length 0.621566
fuel_system 0.485085
stroke 0.389321
num_of_cylinders 0.330988
compression_ratio 0.133927
fuel_type 0.048139
Name: MI Scores, dtype: float64
次にバープロット
def plot_mi_scores(scores):
scores = scores.sort_values(ascending=True)
width = np.arange(len(scores))
ticks = list(scores.index)
plt.barh(width, scores)
plt.yticks(width, ticks)
plt.title("Mutual Information Scores")
plt.figure(dpi=100, figsize=(8, 5))
plot_mi_scores(mi_scores)
sns.relplot(x="curb_weight", y="price", data=df);
fuel_typeの特徴は、MIスコアが比較的低いですが、図からわかるように、horsepowerの特徴内で異なるトレンドを持つ2つの価格集団を明確に分けています。これは、fuel_typeが相互作用の効果を持っていることを示しており、結局のところ重要でない可能性は低いかもしれません。MIスコアから特徴が重要でないと判断する前に、可能な相互作用の効果を調査することが良いでしょう。この点で、専門知識が非常に役立ちます。
sns.lmplot(x="horsepower", y="price", hue="fuel_type", data=df);
データの可視化は、特徴量エンジニアリングのツールボックスに素晴らしい追加です。相互情報量のような有用性メトリクスとともに、これらの可視化はデータ内の重要な関係を発見するのに役立ちます。