Null Importance를 사용한 피쳐 양 선택

본 보도의 대상


본고는 RandomForest, XGBoost, LightGBM 등 학습기를 사용하는 사람들을 대상으로 한다.

개요


자신이 생성한 몇 가지 특징량에는 소음이 될 수 있는 것이 포함되어 있다.실제로 RandomForest, XGBoost, LightGBM 등 학습기를 사용하여 특징량의 중요도를 표시할 때 중요도가 높은 특징량은 이런 소음을 포함할 수 있다.따라서 이번에는 가짜 교사 데이터로 중요도를 측정해 소음에 묻힌 특징량을 찾아내고 진정으로 중요한 특징량만 선택하는 방법을 소개한다.참고 자료는 여기.

준비


이번에는 scikit-learn의 데이터 집중Breast Cancer을 사용했다.
# 必要なモジュールをインポート
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from sklearn.datasets import load_breast_cancer
from sklearn.ensemble import RandomForestClassifier


# データの取得
cancer = load_breast_cancer()
X = pd.DataFrame(cancer.data, columns=cancer.feature_names)
y = cancer.target

특징량의 중요도를 확인하다


원시 데이터 학습 모델로 특징량의 중요도를 확인한다.
# モデルの学習
clf = RandomForestClassifier(random_state=42)
clf.fit(X, y)

# 特徴量の重要度を含むデータフレームを作成
imp_df = pd.DataFrame()
imp_df["feature"] = X.columns
imp_df["importance"] = clf.feature_importances_
imp_df = imp_df.sort_values("importance")

# 可視化
plt.figure(figsize=(7, 10))
plt.barh(imp_df.feature, imp_df.importance)
plt.xlabel("Feature Importance")
plt.show()

실제 데이터와 허위 데이터로 특징량의 중요도를 얻다


여기서부터 본론이야.방금 전의 특징량의 중요도가 정말 정확한지 검증하다.목표 변수에 대해 카드를 씻는 데이터 학습 모델을 사용하고 이 모델의 특징량 중요도(빈 입력)를 얻는다.
def get_feature_importances(X, y, shuffle=False):
    # 必要ならば目的変数をシャッフル
    if shuffle:
        y = np.random.permutation(y)

    # モデルの学習
    clf = RandomForestClassifier(random_state=42)
    clf.fit(X, y)

    # 特徴量の重要度を含むデータフレームを作成
    imp_df = pd.DataFrame()
    imp_df["feature"] = X.columns
    imp_df["importance"] = clf.feature_importances_
    return imp_df.sort_values("importance", ascending=False)

# 実際の目的変数でモデルを学習し、特徴量の重要度を含むデータフレームを作成
actual_imp_df = get_feature_importances(X, y, shuffle=False)

# 目的変数をシャッフルした状態でモデルを学習し、特徴量の重要度を含むデータフレームを作成
N_RUNS = 100
null_imp_df = pd.DataFrame()
for i in range(N_RUNS):
    imp_df = get_feature_importances(X, y, shuffle=True)
    imp_df["run"] = i + 1
    null_imp_df = pd.concat([null_imp_df, imp_df])

각 데이터에서 얻은 중요도를 비교하다


이어 상술한 각자의 중요도를 비교했다.
def display_distributions(actual_imp_df, null_imp_df, feature):
    # ある特徴量に対する重要度を取得
    actual_imp = actual_imp_df.query(f"feature == '{feature}'")["importance"].mean()
    null_imp = null_imp_df.query(f"feature == '{feature}'")["importance"]

    # 可視化
    fig, ax = plt.subplots(1, 1, figsize=(6, 4))
    a = ax.hist(null_imp, label="Null importances")
    ax.vlines(x=actual_imp, ymin=0, ymax=np.max(a[0]), color='r', linewidth=10, label='Real Target')
    ax.legend(loc="upper right")
    ax.set_title(f"Importance of {feature.upper()}", fontweight='bold')
    plt.xlabel(f"Null Importance Distribution for {feature.upper()}")
    plt.ylabel("Importance")
    plt.show()

# 実データにおいて特徴量の重要度が高かった上位5位を表示
for feature in actual_imp_df["feature"][:5]:
    display_distributions(actual_imp_df, null_imp_df, feature)



본 보도에서 중요도가 높다고 여겨지는 다섯 가지 특징량을 살펴보자.그림에서 가로축은 각 특징량의 중요도를 나타내고, 세로축은 빈 Importance의 주파수를 나타낸다(파란색은 빈 Importance의 직사각형 분포를 나타낸다).소음에 묻힌 특징량의 경우 빨간색 세로선(실제 중요도)이 파란색 블록에 있거나 그 중요도보다 낮다.이번에 사용한 데이터는 중요도가 높은 특징량에서 소음이 되지 않을 것이다(다른 데이터가 있는 경우).

피쳐 양의 선택


중요도가 높은 특징량에 소음이 함유된 상황을 가정하고 이 특징량을 제거하기 위해 설정된 한도값을 초과한 특징량만 얻는 방법을 기재한다.
# 閾値を設定
THRESHOLD = 80

# 閾値を超える特徴量を取得
imp_features = []
for feature in actual_imp_df["feature"]:
    actual_value = actual_imp_df.query(f"feature=='{feature}'")["importance"].values
    null_value = null_imp_df.query(f"feature=='{feature}'")["importance"].values
    percentage = (null_value < actual_value).sum() / null_value.size * 100
    if percentage >= THRESHOLD:
        imp_features.append(feature)

imp_features
# ['worst concave points', 'worst perimeter', 'worst radius', 'mean perimeter', 'worst concavity', 'mean radius', 'mean concavity', 'mean concave points', 'area error', 'worst compactness']
이번에는 상기 도표에서 보여준 소음 분포를 기준으로 80% 이상의 빈 Importance 특징량을 얻었다.그 결과 최초로 구한 특징량의 중요도 도표worst texture 이하의 물건이 소음에 묻혔다.

총결산


특징량에는 소음이 될 수 있는 것이 함유되어 있을 수 있으므로 확인하고 선택해야 한다.그 중에서 이번에 빈 Importance를 사용하는 방법은 비교적 쉽고 그림으로 확인할 수 있기 때문에 개인적으로 추천하는 방법이다.
누군가 더 좋은 방법이 있다고 한다면 평론을 받을 수 있기를 바란다.

좋은 웹페이지 즐겨찾기