0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

カテゴリ値を含むデータでのLightGBMを使った分析(2本目:One-hot Encoding編)

Posted at

はじめに

前回の投稿ではKaggleのデータセット1を使って二値分類問題にチャレンジしました。
その際、カテゴリ値の取扱い方法としては、Label Encodingを採用しました。

が、他の方法もあるので、後学のために本稿ではOne-hot Encodingにチャレンジします(LightGBMを利用するなど問題設定は同じ)。

本稿で紹介すること

  • データの収集および整形
  • 予測モデルの作成
  • 予測精度の確認
  • 特徴量重要度の確認(可視化)

前回の投稿記事からの変更部分を中心に、説明します。

本稿で紹介しないこと

  • 特徴量設計
  • ハイパーパラメータのチューニング

分析環境の各種情報

筆者は、いつもながらDockerコンテナとしてJupyterを起動しています。

  • Python 3.8.8
  • pip 21.3.1
  • pandas 1.4.0
  • numpy 1.22.1
  • scikit-learn 1.0.2
  • lightgbm 3.3.2

データの収集

前回に同じです。

データの整形

Nullレコードを除去するところまでは前回に同じです。

前回からの変更部分は、今回の主題となるカテゴリ値の処理です。以下を参考に、カテゴリ値はOne-hot化しました。

元データが15カラム(含む目的変数)だったのに対し、処理後は105カラム(含む目的変数)になりました。

各カラム内の1つのカテゴリ値が、1カラムとして独立するので、カラム数が大きく増えるのは納得でした。
(対象データは、母国語をカラムが含まれており、これが40カテゴリだったことが一因。)

例えば、整形処理はこんな感じ。説明変数の計8カラムを整形しました。

columns_cat = [
    'workclass',
    'education',
    'marital-status',
    'occupation',
    'relationship',
    'race',
    'gender',
    'native-country',
    #'income',
]
:
#!pip install category_encoders
import category_encoders as ce

# One-hot Encodingしたい列をリストで指定
ce_ohe = ce.OneHotEncoder(cols=columns_cat, handle_unknown='impute')

# DataFrameを渡してOne-hot Encodingを適用
df = ce_ohe.fit_transform(df)
df.head(10)

後々の特徴量重要度を確認する際に必要になるので、変換処理での対応関係も確認しました。
変換前のカラム名に対し、変換後のカラム名_${Index値}のIndex値を教えてくれました。

# 変換前:文字列と変換後:数値の対応関係を確認
ce_ohe.category_mapping
:
 {'col': 'marital-status',
  'mapping': Never-married            1
  Married-civ-spouse       2
  Widowed                  3
  Separated                4
  Divorced                 5
  Married-spouse-absent    6
  Married-AF-spouse        7
  NaN                     -2
  dtype: int64,
  'data_type': dtype('O')},
:

予測モデルの作成

こちらも、前回に同じです。
こちらのサイトで公開されているPythonコード2を参考にしました。

# LightGBM のハイパーパラメータ
params = {
    # 二値分類問題
    'objective': 'binary',
    # AUC の最大化を目指す
    'metric': 'auc',
    # Fatal の場合出力
    'verbosity': -1,
    # 乱数シード
    'seed': 31,
    # 学習率
    'learning_rate': 0.02,
}

# 上記のパラメータでモデルを学習する
model = lgb.train(params, lgb_train, valid_sets=lgb_valid,
                  verbose_eval=50,  # 50イテレーション毎に学習結果出力
                  num_boost_round=10000,  # 最大イテレーション回数指定
                  early_stopping_rounds=100
                 )
Training until validation scores don't improve for 100 rounds
[50]	valid_0's auc: 0.913351
[100]	valid_0's auc: 0.917335
/opt/conda/lib/python3.8/site-packages/lightgbm/engine.py:181: UserWarning: 'early_stopping_rounds' argument is deprecated and will be removed in a future release of LightGBM. Pass 'early_stopping()' callback via 'callbacks' argument instead.
  _log_warning("'early_stopping_rounds' argument is deprecated and will be removed in a future release of LightGBM. "
/opt/conda/lib/python3.8/site-packages/lightgbm/engine.py:239: UserWarning: 'verbose_eval' argument is deprecated and will be removed in a future release of LightGBM. Pass 'log_evaluation()' callback via 'callbacks' argument instead.
  _log_warning("'verbose_eval' argument is deprecated and will be removed in a future release of LightGBM. "
[150]	valid_0's auc: 0.922076
[200]	valid_0's auc: 0.924902
[250]	valid_0's auc: 0.926122
[300]	valid_0's auc: 0.92682
[350]	valid_0's auc: 0.92731
[400]	valid_0's auc: 0.9276
[450]	valid_0's auc: 0.927851
[500]	valid_0's auc: 0.928042
[550]	valid_0's auc: 0.928216
[600]	valid_0's auc: 0.928317
[650]	valid_0's auc: 0.928426
[700]	valid_0's auc: 0.928446
[750]	valid_0's auc: 0.928452
[800]	valid_0's auc: 0.928403
Early stopping, best iteration is:
[710]	valid_0's auc: 0.928479

予測精度の確認

こちらも、前回に同じです。
こちらのサイトで公開されているPythonコード3を参考にしました。

実行すると、こんな感じ。想像以上に精度が良かった。
前回に比較すると、精度自体はほんの少し下がりました。
が、有意な差ではなく、乱数シードの差異かなというレベルでした。

image.png

特徴量重要度の確認(可視化)

こちらも、前回に同じです。
特徴量重要度の確認ですが、lightgbm.plot_importanceを使いました。
こちらのサイトで公開されているPythonコード4を参考にしました。

実行すると、こんな感じ。特徴量重要度の上位銘柄はあまり変わらず、順位が変動した印象でした。
が、One-hot化によりカテゴリ値を扱うカラムに対して、予測精度に貢献した具体的なカテゴリ値を知ることができ、より予測結果に対して理解を深められました。

importance_type='split'として可視化した結果。
image.png

importance_type='gain'として可視化した結果。
image.png

特に、2つ目の方式、gainの方をもう少し詳しく確認しました4
image.png

結果について少し考察

特徴量重要度についてです。
特徴量重要度のTopは「Married-civ-spouse」であり、個人の婚姻歴として現在進行形(既婚で配偶者あり)だったことが判明しました。つまり、収入が高いから家庭(≒配偶者)をもてたのだろうな、、、という意味付けですね。

relationship: Wife, Own-child, Husband, Not-in-family, Other-relative, Unmarried.
marital-status: Married-civ-spouse, Divorced, Never-married, Separated, Widowed, Married-spouse-absent, Married-AF-spouse.

Notebook(Pythonコード)

githubで公開しました。このタイミングですが、参考サイトの方々に感謝申し上げます。

まとめ

カテゴリ値を含むデータをOne-hot EncodingしてLightGBMを使った分析の例をご紹介。

category_encodersというPythonライブラリ、非常に便利でした。
One-hot Encodingにより対象データのカラム数こそ増えはしますが、Label Encodingでの分析結果に対して更に理解を深められた、というのが1つの成果だと思いました。

  1. Adult Data Set | https://archive.ics.uci.edu/ml/datasets/adult

  2. コード | https://qiita.com/d_desuyon/items/807e01311ad08570ee78#%E3%82%B3%E3%83%BC%E3%83%89

  3. モデルの評価 | https://qiita.com/kt38k/items/3c0ee4251475b6407007#%E3%83%A2%E3%83%87%E3%83%AB%E3%81%AE%E8%A9%95%E4%BE%A1

  4. 特徴量重要度の算出 (2値分類編) | https://mathmatical22.xyz/2020/04/12/%E3%80%90%E5%88%9D%E5%BF%83%E8%80%85%E5%90%91%E3%81%91%E3%80%91%E7%89%B9%E5%BE%B4%E9%87%8F%E9%87%8D%E8%A6%81%E5%BA%A6%E3%81%AE%E7%AE%97%E5%87%BA-lightgbm-%E3%80%90python%E3%80%91%E3%80%90%E6%A9%9F/ 2

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?