目录
- Target Encoding
- Ordinal Encoding
- One-Hot Encoding
简介
在很多机器学习任务中,特征并不总是连续值,而有可能是分类值。
离散特征的编码分为两种情况:
1、离散特征的取值之间没有大小的意义,比如color:[red,blue],那么就使用one-hot编码
2、离散特征的取值有大小的意义,比如size:[X,XL,XXL],那么就使用数值的映射{X:1,XL:2,XXL:3}
One-Hot和Ordinal两种比较常见,接下来着重讲的是 目标编码(target encoding
)是特征工程中一种非常强大的技术,在机器学习竞赛中广泛应用并取得了良好的效果。近年来,出现了多种目标编码的方法和变体。本文将探讨并实现一种常见的目标编码方法,即k-fold
目标编码。
1Target Encoding
目标编码(Target Encoding)是一种用于处理分类特征的技术,它将类别特征映射为目标变量的相关性。在目标编码中,每个类别的特征值被替换为该类别在目标变量上的统计指标,通常是平均值、频率或其他相关性度量。
具体的话是将下面转变成按照类别分类,填为target的平均值
1具体步骤
- 代码
- 首先的话使用model_selection.KFold,分成5个fold,再把kfold值写回去,通过kfold值划分xtrain和xvalid,通过groupby(col)将含objec的列的里面值分组然后计算
xtrain的target
的平均值,最后将值转为字典通过map将xvalid[col]
的object值转换target的平均值
,test集的话是将5个fold的值加起来然后取平均。
py
#这里用把fold填进去是为了方便查看
kf = model_selection.KFold(n_splits=5,shuffle = True,random_state= 42)
for fold,(train_indicies,valid_indicies) in enumerate(kf.split(X=df_train)):
df_train.loc[valid_indicies,"kfold"] = fold
#object_cols 含有object的列
for col in object_cols:
temp_df = []
temp_test_feat = None
#这里的话是有5个fold
for fold in range(5):
xtrain = df[df.kfold != fold].reset_index(drop=True)
xvalid = df[df.kfold == fold].reset_index(drop=True)
#这里的话是根据col列的值分组 比如A一组,B一组,然后计算每一组的平均值
feat = xtrain.groupby(col)['target'].agg("mean")
#转为字典
feat = feat.to_dict()
#将原值转为平均值
xvalid[col] = xvalid[col].map(feat)
temp_df.append(xvalid)
if temp_test_feat is None:
temp_test_feat = df_test[col].map(feat)
else:
temp_test_feat += df_test[col].map(feat)
temp_test_feat /= 5
df_test.loc[col] = temp_test_feat
df = pd.concat(temp_df)
- groupby()功能查看
py
for key,values in df.groupby(col):
print(pd.DataFrame([values[col],values['target']]).T)
css
cat9 target
31 A 6.847814
32 A 8.023149
33 A 6.975083
34 A 5.858966
48 A 7.732898
... ... ...
299835 A 7.65375
299894 A 8.060798
299909 A 6.427984
299925 A 4.821355
299974 A 7.584323
[13408 rows x 2 columns]
cat9 target
5 B 7.060652
35 B 8.563246
97 B 7.691082
239 B 8.3303
277 B 7.18416
... ... ...
299748 B 6.823052
299773 B 6.975738
299848 B 8.113872
299935 B 5.561943
299979 B 8.342594
2对比原数据和修改数据
py
df2 = df1.groupby('kfold')['cat0'].unique()
df3 = df.groupby('kfold')['cat0'].unique()#原数据
df4 = pd.merge(df3,df2,on = 'kfold',how = 'left')
df4
左边是原有的数据值,右边是转换成的target平均值
kfold | cat0(原本) | cat0(target encoding之后) |
---|---|---|
0 | [A, B] | [7.468670297726988, 7.270407090697891] |
1 | [A, B] | [7.469791725132474, 7.269712615159259] |
2 | [B, A] | [7.271782291227367, 7.468671480124456] |
3 | [A, B] | [7.46870305956268, 7.26862208495064] |
4 | [A, B] | [7.467050068804046, 7.265260691611668] |
3最终效果
2 Ordinal Encoding
使用sklearn导包,并查看原本是Object的数据
py
#找出有object的列,也可以用DataFrame.select_dtypes(include=None, exclude=None)找出来
object_cols = [col for col in useful_features if col.startswith("cat")]
df[object_cols]
使用 Ordinal Encoding
py
from sklearn.preprocessing import OrdinalEncoder
# Apply ordinal encoder
ordinal_encoder = OrdinalEncoder()
df[object_cols] = ordinal_encoder.fit_transform(df[object_cols])
3 One-Hot Encoding
单热编码创建新列,指示原始数据中每个可能值的存在(或不存在)。
方法 1pandas 的独热编码
py
df = pd.get_dummies(df)
- 查看结果
- 数据太多,单独查看有object的列查看
py
df1 = df[object_cols]
df1 = pd.get_dummies(df1)
- 原数据
- 查看新列名列表,下面是结果
py
df1.columns
py
Index(['cat0_A', 'cat0_B', 'cat1_A', 'cat1_B', 'cat2_A', 'cat2_B', 'cat3_A',
'cat3_B', 'cat3_C', 'cat3_D', 'cat4_A', 'cat4_B', 'cat4_C', 'cat4_D',
'cat5_A', 'cat5_B', 'cat5_C', 'cat5_D', 'cat6_A', 'cat6_B', 'cat6_C',
'cat6_D', 'cat6_E', 'cat6_G', 'cat6_H', 'cat6_I', 'cat7_A', 'cat7_B',
'cat7_C', 'cat7_D', 'cat7_E', 'cat7_F', 'cat7_G', 'cat7_I', 'cat8_A',
'cat8_B', 'cat8_C', 'cat8_D', 'cat8_E', 'cat8_F', 'cat8_G', 'cat9_A',
'cat9_B', 'cat9_C', 'cat9_D', 'cat9_E', 'cat9_F', 'cat9_G', 'cat9_H',
'cat9_I', 'cat9_J', 'cat9_K', 'cat9_L', 'cat9_M', 'cat9_N', 'cat9_O'],
dtype='object')
方法2使用sklearn
- 具体步骤就是创造OneHotEncoder,然后fit_transform,有object的列,然后通过pd.concat,再将原数据drop掉了有object的列,再拼接独热编码好的列,如OH_cols_train
py
# Apply one-hot encoder to each column with categorical data
OH_encoder = OneHotEncoder(handle_unknown='ignore', sparse=False)
OH_cols_train = pd.DataFrame(OH_encoder.fit_transform(X_train[low_cardinality_cols]))
OH_cols_valid = pd.DataFrame(OH_encoder.transform(X_valid[low_cardinality_cols]))
# One-hot encoding removed index; put it back
OH_cols_train.index = X_train.index
OH_cols_valid.index = X_valid.index
# Remove categorical columns (will replace with one-hot encoding)
num_X_train = X_train.drop(object_cols, axis=1)
num_X_valid = X_valid.drop(object_cols, axis=1)
# Add one-hot encoded columns to numerical features
OH_X_train = pd.concat([num_X_train, OH_cols_train], axis=1)
OH_X_valid = pd.concat([num_X_valid, OH_cols_valid], axis=1)
# Ensure all columns have string type
OH_X_train.columns = OH_X_train.columns.astype(str)
OH_X_valid.columns = OH_X_valid.columns.astype(str)