[6일째] 분류 변수를 인코딩합니다[2021 추가 달력]


2021년 1인 advent 달력(기계학습), 6일째 보도.
https://qiita.com/advent-calendar/2021/solo_advent_calendar
테마는 분류 변수의 인코딩입니다.
대략적으로 말하면, 이것은 수치가 아닌 데이터를 기계 학습으로 처리하는 방법이다.
상세한 상황은 아래와 같다.
분류 변수란 키와 나이처럼 수치로 나타내는 변수가 아니라 조합, 속성(색상, 국가 등)을 분류하는 데 쓰이는 변수를 말한다.또한 분류 변수는 명목 변수와 순서 변수로 나눌 수 있다.
변수 이름
개요
변수 예
디지털 변수
수치로 구성된 변수
신장/나이
명목 변수
정렬하거나 정렬할 수 없는 분류 변수
/색상 (빨간색, 파란색, 녹색)/국가 (일본, 미국, 중국)
정렬 변수
정렬 또는 정렬할 수 있는 분류 변수
・티셔츠 사이즈(S, M, L)
https://di-acc2.com/programming/python/3737/
여기서 카테고리 변수의 항목 수에 따른 교부 시퀀스 번호를 처리하는 Ordinal Encoding과 카테고리 변수의 항목 내역을 가상 변수로 변환하는 One Hot Encoding을 다룹니다.
가상 변수는 무엇입니까?
0이나 1의 값을 취하는 변수.
https://plaza.umin.ac.jp/~health-stat/faq/faq17/
Colab의 코드는 여기.Open In Colab입니다.

모든 OrdinalEnceoding


scikit-learn의 Ordinal Enceoding은 결손 값이 있어도 처리할 수 있지만 인코딩이 없기 때문에'missing'이라는 문자열로 결손 값을 대체합니다.
(missing'을 만드는 것은 알기 쉽고 필연성이 없기 때문이다.)
또한 인코딩 처리 후 numby의ary형이 됩니다.
OrdinalEnceoding의 매개 변수인handleunknown에 있어요.encoded_value를 드리겠습니다. unknown value가 설정한 수치로 미지수를 바꿀 수 있습니다.
설정. - 2는 이따가 나올 Category.Encorders의 Ordienal Enceoding은 자동으로 알 수 없는 숫자를 -1로 설정하고 1부터 번호를 매기기 때문에 -2를 지정하여 매칭합니다.
  • Category_첫 번째 시퀀스부터 시작
  • scikit-learn의OrdianalEnceoding 번호는 0에서 시작하기 때문에 미지수를 -2+1로 설정하면CategoryEncorders의 Ordinal Enceoding과 같은 처리를 사용할 수 있습니다.
  • 그러나 분류의 변환 법칙을 지정하지 않으면 양자의 처리가 일치하지 않을 수 있다.
    # 数値データとカテゴリーデータに分ける
    X_train_number = X_train.select_dtypes(include="number")
    X_test_number = X_test.select_dtypes(include="number")
    
    X_train_category = X_train.select_dtypes(include="object")
    X_test_category = X_test.select_dtypes(include="object")
    
    # index をリセット
    X_train_number = X_train_number.reset_index(drop=True)
    X_test_number = X_test_number.reset_index(drop=True)
    
    X_train_category = X_train_category.reset_index(drop=True)
    X_test_category = X_test_category.reset_index(drop=True)
    
    # カテゴリーのエンコーディング法則を指定する
    ordinal_all_cols_mapping = []
    
    for column in X_train_category.columns:
        ordinal_one_cols_mapping = []
        for category in natsorted(X_train_category[column].unique()):
            ordinal_one_cols_mapping.append(category)
    
        ordinal_all_cols_mapping.append(ordinal_one_cols_mapping)
    
    from sklearn.preprocessing import OrdinalEncoder
    
    # エンコーディング設定
    ode = OrdinalEncoder(
        handle_unknown = 'use_encoded_value', # 未知数をunknown valueに置き換える設定
        unknown_value = -2,
        dtype = np.float64,
        categories = ordinal_all_cols_mapping
    )
    
    # OrdinalEncoderは欠損値があっても処理できるが、エンコーディングしないので欠損値を missing に置き換える
    X_train_category = X_train_category.fillna("missing")
    X_test_category = X_test_category.fillna("missing")
    
    # エンコーディング
    # trainデータは学習と変換、testデータは変換のみを実施。trainの学習パターン通りに変換するため
    X_train_labels = ode.fit_transform(X_train_category)
    X_test_labels = ode.transform(X_test_category)
    
    # OrdinalEncoder は np.array型に変換してしまうため、DataFrame型で再構築する
    X_train_oe = pd.DataFrame(
        X_train_labels,
        columns=X_train_category.columns
    )
    
    X_test_oe = pd.DataFrame(
        X_test_labels,
        columns=X_test_category.columns
    )
    
    # 数値データを結合
    X_train_oe = pd.concat([X_train_oe, X_train_number ], axis=1)
    X_test_oe = pd.concat([X_test_oe, X_test_number ], axis=1)
    

    분류 변수의 세부 항목이 적은 항목은 OneHotEnceoding이고, 많은 항목은 OrdinalEnceoding이다


    분류 변수의 내역수가 많은 변수를 OneHot Encoding 처리할 때 열 수가 너무 많으면 메모리 오류가 발생할 수 있으므로 분류 변수의 세목 수가 많은 경우 Ordinal Enceoding을, 적은 경우 OneHot Enceoding을 수행해야 한다.
    (원래 변수의 성질에 따라 OneHot이 좋은지 Ordinal이 좋은지 연구해야 한다)
    OrdinalEnceoding과 달리 OnehotEnceoding은 결손 값이 있을 때 인코딩 처리를 하지 않기 때문에 결손 값 처리가 필요하다.
    Ordinal Enceoding과 마찬가지로 One Hot Enceoding도 코딩 처리하면 numby의 aray형으로 변한다.
    OneHotEncoding 처리 후의 열 이름은 get입니다feature_names_out () 방법을 사용하면 얻을 수 있습니다.
    # カテゴリー変数の内訳の数に応じてカラムを分割する
    category_unique_num = df.drop(["Global_Sales",  "NA_Sales", "PAL_Sales", "JP_Sales", "Other_Sales"], axis=1).select_dtypes(include="object").nunique()
    few_kinds_category_columns = category_unique_num[category_unique_num < 10].index
    many_kinds_category_columns = category_unique_num[category_unique_num >= 10].index
    
    from sklearn.preprocessing import OneHotEncoder
    
    # エンコーディング設定
    ode = OrdinalEncoder(
        handle_unknown = 'use_encoded_value', # 未知数をunknown valueに置き換える設定
        unknown_value = -2,
        dtype = np.float64,
        categories = ordinal_all_cols_mapping_en
    )
    
    ohe = OneHotEncoder(
        handle_unknown = 'ignore',
        sparse = False,
        dtype = np.int64,
        )
    
    # OneHotEncoderは欠損値があっても処理できるが、エンコーディングしないので欠損値を missing に置き換える
    X_train_category = X_train_category.fillna("missing")
    X_test_category = X_test_category.fillna("missing")
    
    # エンコーディング
    # trainデータは学習と変換、testデータは変換のみを実施。trainの学習パターン通りに変換するため
    
    # OneHotEncoder
    X_train_ohe_labels = ohe.fit_transform(X_train_category[few_kinds_category_columns])
    X_test_ohe_labels = ohe.transform(X_test_category[few_kinds_category_columns ])
    
    # OrdinalEncoder
    X_train_ode_labels = ode.fit_transform(X_train_category[many_kinds_category_columns]) + 1
    X_test_ode_labels = ode.transform(X_test_category[many_kinds_category_columns ]) + 1
    
    # np.array型になってしまうため、DataFrame型で再構築する
    # trainデータ
    X_train_ode = pd.DataFrame(
        X_train_ode_labels,
        columns=X_train_category[many_kinds_category_columns].columns
    )
    X_train_ohe = pd.DataFrame(
        X_train_ohe_labels,
        columns=ohe.get_feature_names_out(few_kinds_category_columns)
    )
    X_train_en = pd.concat([X_train_ohe, X_train_ode], axis=1)
    
    # testデータ
    X_test_ode = pd.DataFrame(
        X_test_ode_labels,
        columns=X_test_category[many_kinds_category_columns].columns
    )
    X_test_ohe = pd.DataFrame(
        X_test_ohe_labels,
        columns=ohe.get_feature_names_out(few_kinds_category_columns)
    )
    X_test_en = pd.concat([X_test_ohe, X_test_ode], axis=1)
    
    
    # 数値データを結合
    X_train_en = pd.concat([X_train_en, X_train_number ], axis=1)
    X_test_en = pd.concat([X_test_en, X_test_number ], axis=1)
    

    Category_Encorders 사용


    분류 변수 인코딩을 위한 라이브러리, CategoryEncorders를 사용합니다.
    인코딩 처리 후 되돌아오는 값은 DataFrame형이 될 수도 있고 인코딩 처리를 할 열을 지정할 수도 있어 매우 쉽다.
    # カテゴリーのエンコーディング法則を指定する
    ordinal_all_cols_mapping_ce = []
    
    for i, column in enumerate(many_kinds_category_columns):
        ordinal_one_cols_mapping = {}
        ordinal_one_cols_mapping_breakdown = {}
        for j, category in enumerate(natsorted(X_train[column].unique())):
            ordinal_one_cols_mapping_breakdown[category] = j
    
        ordinal_one_cols_mapping["col"] = column
        ordinal_one_cols_mapping["mapping"] = ordinal_one_cols_mapping_breakdown
        ordinal_all_cols_mapping_ce.append(ordinal_one_cols_mapping)
    
    # エンコーディング設定
    ode = ce.OrdinalEncoder(
        mapping = ordinal_all_cols_mapping_ce,
        cols = many_kinds_category_columns
    )
    
    ohe = ce.OneHotEncoder(
        use_cat_names=True,
        cols = few_kinds_category_columns
    )
    
    # 元データを壊さないようにコピーする
    X_train_ce = X_train.copy()
    X_test_ce = X_test.copy()
    
    # 欠損値処理
    category_columns = category_unique_num.index
    
    X_train_ce[category_columns] = X_train_ce[category_columns].fillna("missing")
    X_test_ce[category_columns] = X_test_ce[category_columns].fillna("missing")
    
    # OneHotEncoder
    X_train_ce = ohe.fit_transform(X_train_ce)
    X_test_ce = ohe.transform(X_test_ce)
    
    # OrdinalHotEncoder
    X_train_ce = ode.fit_transform(X_train_ce)
    X_test_ce = ode.transform(X_test_ce)
    
    # 正規化
    sc = StandardScaler()
    X_train_ce = pd.DataFrame(
                                sc.fit_transform(X_train_ce),
                                columns=X_train_ce.columns
                                )
    
    X_test_ce = pd.DataFrame(
                                sc.transform(X_test_ce),
                                columns=X_test_ce.columns
                                )
    
    OrdinalEnceoding만: 0.235.19774193
    sklearn에서 OneHot+Ordinal Enceoding: 0.22288307344096592
    Category Encorders One Hot + Ordinal Enceoding: 0.222648763368118405
    6일째 되는 날 여기까지 읽어주셔서 감사합니다.
    https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OrdinalEncoder.html
    https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html
    https://contrib.scikit-learn.org/category_encoders/

    좋은 웹페이지 즐겨찾기