기계 학습 모델 및 결과 해석 (Feature Importance)

Abstract: 기계 학습 모델과 결과를 해석하는 방법



1. 어떤 특징량이 중요한가: 모델이 중요시하고 있는 요인을 알 수 있다
  • feature importance

  • 2. 각 특징량이 예측에 어떻게 영향을 미치는지: 특징량을 변화시켰을 때의 예측으로부터 경향을 잡는다
  • partial dependence
  • permutation importance

  • 3. 예측 결과가 나왔을 때의 특징량의 기여: 근사한 모델을 만들어, 각 특징의 기여를 산출
  • LIME (Local Interpretable Model-agnostic Explainations)
  • SHAP (SHapley Additive exPlanations)

  • Introduction : 기계 학습의 해석성의 중요성이 증가하고 있습니다.



    현재, 고정밀도를 두드린 기계 학습은, 블랙 박스가 되기 쉽고 근거의 설명을 인간에게 제시하지 않는다

    예를 들어, 가까운 장래에 의사가 기계 학습 모델에서 유도 한 모델에서 진단 할 시대가되었을 때
    お医者さん「あなたは糖尿病に今後5年以内になりますよ。」
    患者さん「どうしてわかったんですか? 何が原因なんですか!?」
    お医者さん「...。 AIがそう判断したからですよ...。」
    患者さん「納得できません!」
    

    라고 되어 버린다.
    기계 학습 모델이 예측 결과에 대해 왜 그 예측을 한지에 대한 설명이 필요하다.

    Environment:



    실험 환경



    Python==3.6.8
    matplotlib==3.0.3
    jupyter notebook
    import re
    import sklearn
    import numpy as np
    import pandas as pd
    import seaborn as sns
    import matplotlib.pyplot as plt
    import matplotlib
    %matplotlib inline
    
    import warnings
    warnings.filterwarnings('ignore')
    
    from IPython.core.interactiveshell import InteractiveShell
    InteractiveShell.ast_node_interactivity = 'all'
    
    %reload_ext autoreload
    %autoreload 2
    

    데이터



    Kaggle titanic를 사용.
    적당한 데이터수, 카디널리티의 적음, 해석의 용이성, 모두에게 인식되고 있는 3점으로부터 채용.

    Titanic: Machine Learning from Disaster

    이 대회는 타이타닉호에 승선한 각 승객이 구입한 티켓의 클래스(Pclass1, 2, 3의 순서로 높은 클래스)나 요금(Fare), 연령(Age), 성별(Sex), 출항지( Embarked), 방 번호(Cabin), 티켓 번호(Tichket), 승선하고 있던 형제 또는 배우자의 수(SibSp), 승선하고 있던 부모 또는 아이의 수(Parch) 등 정보가 있으며, 거기에서 타이타닉호 빙산에 충돌하여 침몰했을 때 생존했는지(Survived)를 예측한다.
    PassengerId – 乗客識別ユニークID
    Survived – 生存フラグ(0=死亡、1=生存)
    Pclass – チケットクラス
    Name – 乗客の名前
    Sex – 性別(male=男性、female=女性)
    Age – 年齢
    SibSp – タイタニックに同乗している兄弟/配偶者の数
    parch – タイタニックに同乗している親/子供の数
    ticket – チケット番号
    fare – 料金
    cabin – 客室番号
    Embarked – 出港地(タイタニックへ乗った港)
    
    train.head()
    



    전처리



    Python에서 앙상블 (스태킹) 학습 & 기계 학습 자습서 in Kaggle
    ↑전처리가 간결하고, 데이터를별로 괴롭히지 않으므로 참고로 했습니다. 감사합니다.

    기본적으로는 전처리에 의해 이하의 용으로 빈 분할하였다. (빈 분할한 이유는 결과를 인간이 해석하기 쉬워지기 때문)


     Value
    Age(나이)


    0
    16세 이하

    1
    32세 이하

    2
    48세 이하

    3
    64세 이하

    4
    그 이상



     Value
    Fare(요금)


    0
    굉장히 낮은

    1
    낮은

    2
    높은

    3
    굉장히 높은



     Value
    Embarked(출항지)


    0
    S 사람이 많다.

    1
    C 부자가 많다.

    2
    Q 빈곤이 많다



     Value
    Title(경칭)


    0
    Mr

    1
    Miss

    2
    Mrs

    3
    마스터

    4
    Rare



     Value
    Sex(성별)


    0
    female 여자

    1
    male 남성



     Value
    Pclass(티켓 클래스)


    0
    럭셔리

    1
    중급

    2
    하급



     Value
    IsAlone (가족 유무)


    0
    가족 없음

    1
    가족 있음

    full_data = [train, test]
    
    # 客室番号データがあるなら1を、欠損値なら0
    train['Has_Cabin'] = train["Cabin"].apply(lambda x: 0 if type(x) == float else 1)
    test['Has_Cabin'] = test["Cabin"].apply(lambda x: 0 if type(x) == float else 1)
    
    # 家族の大きさを"タイタニックに同乗している兄弟/配偶者の数"と
    # "タイタニックに同乗している親/子供の数"から定義
    for dataset in full_data:
        dataset['FamilySize'] = dataset['SibSp'] + dataset['Parch'] + 1
    
    # 家族の有無 0なら家族なし、1なら家族あり
    for dataset in full_data:
        dataset['IsAlone'] = 0
        dataset.loc[dataset['FamilySize'] == 1, 'IsAlone'] = 1
    
    # 出港地の欠損値を一番多い"S"としておく
    for dataset in full_data:
        dataset['Embarked'] = dataset['Embarked'].fillna('S')
    
    # 料金の欠損値を中央値としておく
    # 料金の4グループに分ける
    for dataset in full_data:
        dataset['Fare'] = dataset['Fare'].fillna(train['Fare'].median())
    train['CategoricalFare'] = pd.qcut(train['Fare'], 4)
    
    # 年齢を5グループに分ける
    for dataset in full_data:
        age_avg = dataset['Age'].mean()
        age_std = dataset['Age'].std()
        age_null_count = dataset['Age'].isnull().sum()
        age_null_random_list = np.random.randint(age_avg - age_std, age_avg + age_std, size=age_null_count)
        dataset['Age'][np.isnan(dataset['Age'])] = age_null_random_list
        dataset['Age'] = dataset['Age'].astype(int)
    train['CategoricalAge'] = pd.cut(train['Age'], 5)
    
    # 正規表現で姓名を取り出す
    def get_title(name):
        title_search = re.search(' ([A-Za-z]+)\.', name)
        if title_search:
            return title_search.group(1)
        return ""
    
    for dataset in full_data:
        dataset['Title'] = dataset['Name'].apply(get_title)
    
    # 誤字修正
        dataset['Title'] = dataset['Title'].replace(['Lady', 'Countess','Capt', 'Col','Don', 'Dr', 'Major', 'Rev', 'Sir', 'Jonkheer', 'Dona'], 'Rare')
    
        dataset['Title'] = dataset['Title'].replace('Mlle', 'Miss')
        dataset['Title'] = dataset['Title'].replace('Ms', 'Miss')
        dataset['Title'] = dataset['Title'].replace('Mme', 'Mrs')
    
    for dataset in full_data:
        # 性別を2種類にラベル付 女なら0、男なら1
        dataset['Sex'] = dataset['Sex'].map( {'female': 0, 'male': 1} ).astype(int)
    
        # 敬称を5種類にラベル付
        title_mapping = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Rare": 5}
        dataset['Title'] = dataset['Title'].map(title_mapping)
        dataset['Title'] = dataset['Title'].fillna(0)
    
        # 出港地の3種類にラベル付
        dataset['Embarked'] = dataset['Embarked'].map( {'S': 0, 'C': 1, 'Q': 2} ).astype(int)
    
        # 料金を4グループに分ける
        dataset.loc[ dataset['Fare'] <= 7.91, 'Fare']                               = 0
        dataset.loc[(dataset['Fare'] > 7.91) & (dataset['Fare'] <= 14.454), 'Fare'] = 1
        dataset.loc[(dataset['Fare'] > 14.454) & (dataset['Fare'] <= 31), 'Fare']   = 2
        dataset.loc[ dataset['Fare'] > 31, 'Fare']                                  = 3
        dataset['Fare'] = dataset['Fare'].astype(int)
    
        # 年齢を5グループに分ける
        dataset.loc[ dataset['Age'] <= 16, 'Age']                          = 0
        dataset.loc[(dataset['Age'] > 16) & (dataset['Age'] <= 32), 'Age'] = 1
        dataset.loc[(dataset['Age'] > 32) & (dataset['Age'] <= 48), 'Age'] = 2
        dataset.loc[(dataset['Age'] > 48) & (dataset['Age'] <= 64), 'Age'] = 3
        dataset.loc[ dataset['Age'] > 64, 'Age'] = 4 ;
    
    # 必要ない特徴を削除
    drop_elements = ['PassengerId', 'Name', 'Ticket', 'Cabin', 'SibSp']
    train = train.drop(drop_elements, axis = 1)
    train = train.drop(['CategoricalAge', 'CategoricalFare'], axis = 1)
    test  = test.drop(drop_elements, axis = 1)
    

    데이터를 읽고 학습하고 싶은 데이터와 정답 라벨로 나누기
    y_train = train['Survived'].ravel()
    x_train = train.drop(['Survived'], axis=1)
    x_test = test.values
    

    모델링



    Gradient Boosting Decision Tree의 LightGBM에서 모델을 만듭니다.
    import lightgbm as lgbm
    model = lgbm.LGBMClassifier()
    model.fit(x_train, y_train)
    y_pred = model.predict(x_test)
    prediction = np.round(y_pred).astype(int)
    

    Method: Feature Importance



    x축이 중요도를 나타내고 y축이 위에서부터 순서대로 중요한 특징을 표시합니다.
    plot_importance(booster, ax=None, height=0.2,
                        xlim=None, ylim=None, title='Feature importance',
                        xlabel='Feature importance', ylabel='Features',
                        importance_type='split', max_num_features=None,
                        ignore_zero=True, figsize=None, grid=True,
                        precision=None, **kwargs):
    

    Result:


    lgbm.plot_importance(model, figsize=(12, 6))
    plt.show()
    



    Discussion:



    교사가있는 학습 모델을 사용하여 개별 기능의 중요성을 계산합니다. 모델이 학습시 자동으로 산출해 주므로 손쉽게 사용할 수 있다.

    References:



    htps // gghtgbm. Red d. cs. 이오 / 엔 / ㅁ st / _ 모즈 ぇ s / ぃghtgbm / p ぉ チン g. HTML
    htps : // 코 m / 호쿠토 _ 히라 노 / ms / 2c35 아 81fbc95f0에 4b7c1 # 세콘 d ぇょPut

    좋은 웹페이지 즐겨찾기