pop-ketle
すみません、文字数の制限なのかどうしても該当のフォーラムのコメント欄に書き込めなかったので、わざわざ新しくトピックを開いて質問させていただきます。ご迷惑ご容赦ください。
Target Encodingを初めて使ってみようと、以下のフォーラムの実装を参考にコードを書いたのですが、この例だと各行のTarget Encodingをかけた列が全て同じ値になってしまい、特徴量が消えてしまっている気がするのですが、これは実装としてうまくいっているのでしょうか?
https://prob.space/competitions/game_winner/discussions/Oregin-Post344b005eb605a8777141
import pandas as pd
import numpy as np
import re
import matplotlib.pyplot as plt
import seaborn as sns
import lightgbm as lgb
from sklearn.model_selection import train_test_split
from sklearn.model_selection import KFold
from sklearn.metrics import accuracy_score
import warnings
warnings.filterwarnings('ignore')
# データの読込
train = pd.read_csv("./features/train_data.csv")
test = pd.read_csv('./features/test_data.csv')
# 欠損値は、全て「-1」とする。
def fill_all_null(df):
for col_name in df.columns[df.isnull().sum()!=0]:
df[col_name] = df[col_name].fillna(-1)
# 訓練データ、テストデータの欠損値を補完
fill_all_null(train)
fill_all_null(test)
# ターゲットエンコーディングの関数定義
def change_to_target2(train_df,test_df,input_column_name,output_column_name):
from sklearn.model_selection import KFold
# nan埋め処理
train[input_column_name] = train[input_column_name].fillna('-1').isnull().sum()
test[input_column_name] = test[input_column_name].fillna('-1').isnull().sum()
kf = KFold(n_splits=5, shuffle=True, random_state=71)
#=========================================================#
c=input_column_name
# 学習データ全体で各カテゴリにおけるyの平均を計算
data_tmp = pd.DataFrame({c: train_df[c],'target':train_df['y']})
target_mean = data_tmp.groupby(c)['target'].mean()
#テストデータのカテゴリを置換
test_df[output_column_name] = test_df[c].map(target_mean)
# 変換後の値を格納する配列を準備
tmp = np.repeat(np.nan, train_df.shape[0])
for i, (train_index, test_index) in enumerate(kf.split(train_df)): # NFOLDS回まわる
#学習データについて、各カテゴリにおける目的変数の平均を計算
target_mean = data_tmp.iloc[train_index].groupby(c)['target'].mean()
#バリデーションデータについて、変換後の値を一時配列に格納
tmp[test_index] = train_df[c].iloc[test_index].map(target_mean)
#変換後のデータで元の変数を置換
train_df[output_column_name] = tmp
#========================================================#
# オブジェクトの列のリストを作成
object_col_list = train.select_dtypes(include=object).columns
# オブジェクトの列は全てターゲットエンコーディング実施
for col in object_col_list:
change_to_target2(train,test,col,"enc_"+col)
# 変換前の列を削除
train = train.drop(object_col_list,axis=1)
test = test.drop(object_col_list,axis=1)
# 'id'の列を削除
train = train.drop('id',axis=1)
test = test.drop('id',axis=1)
enc_obj_list = ['enc_'+s for s in object_col_list.tolist()]
print(train[enc_obj_list].head())
enc_period enc_game-ver enc_lobby-mode enc_lobby enc_mode enc_stage \ 0 0.525161 0.525161 0.525161 0.525161 0.525161 0.525161 1 0.524499 0.524499 0.524499 0.524499 0.524499 0.524499 2 0.525747 0.525747 0.525747 0.525747 0.525747 0.525747 3 0.523781 0.523781 0.523781 0.523781 0.523781 0.523781 4 0.524329 0.524329 0.524329 0.524329 0.524329 0.524329 enc_A1-weapon enc_A1-rank enc_A2-weapon enc_A2-rank ... \ 0 0.525161 0.525161 0.525161 0.525161 ... 1 0.524499 0.524499 0.524499 0.524499 ... 2 0.525747 0.525747 0.525747 0.525747 ... 3 0.523781 0.523781 0.523781 0.523781 ... 4 0.524329 0.524329 0.524329 0.524329 ... enc_A4-weapon enc_A4-rank enc_B1-weapon enc_B1-rank enc_B2-weapon \ 0 0.525161 0.525161 0.525161 0.525161 0.525161 1 0.524499 0.524499 0.524499 0.524499 0.524499 2 0.525747 0.525747 0.525747 0.525747 0.525747 3 0.523781 0.523781 0.523781 0.523781 0.523781 4 0.524329 0.524329 0.524329 0.524329 0.524329 enc_B2-rank enc_B3-weapon enc_B3-rank enc_B4-weapon enc_B4-rank 0 0.525161 0.525161 0.525161 0.525161 0.525161 1 0.524499 0.524499 0.524499 0.524499 0.524499 2 0.525747 0.525747 0.525747 0.525747 0.525747 3 0.523781 0.523781 0.523781 0.523781 0.523781 4 0.524329 0.524329 0.524329 0.524329 0.524329 [5 rows x 22 columns]
cha_kabu
関数の途中にある、「# nan埋め処理」がプログラムミスと思われます。
元のカテゴリ変数の値を、target encodingの前にすべて0に置き換えてしまっています。
※「# 変換前の列を削除」の処理を実行せずに関数を適用したデータフレームを確認すると分かるかと思います。
関数外で「# 欠損値は、全て「-1」とする。」処理をしているので、「# nan埋め処理」のプログラムは削除して良いかと思います。