Deep Learning 4 Feature Engineering 几种编码整合
[TOC]
Feature Engineering–拼接、拆分数据
1、直接根据数据量拼接、拆分
df = pd.concat([train, test])
用:
来分割,:num
表示num之前的所有,num:
num之后的所有,:
就是没有界限,所有的
train = df[:len_of_train]
test = df[len_of_test:]
2、提前添加属性拼接、利用属性拆分
train['type'] = 'train'
test['type'] = 'test'
df = pd.concat([train, test])
train = df[df['type'] == 'train']
test = df[df['type'] == 'test']
最后需要把拼接的时候,造成的test多了一个结果(也就是要预测的那个属性)属性给去掉
test.drop(['Ans_Attr'], axis=1)
Feature Engineering–Delete Duplicated attribute
用loc提取对应的列(那么行的位置不提取的话,就要用:
来全部替代),那就是df.loc[:,~df.colums.duplicated()]
。(简化过程,先提取多余属性,df.columns.duplicated()
,然后取反表示非多余的留下,用~
进行筛选)
df = df.loc[:, ~df.columns.duplicated()]
用iloc的意思就是通过索引index来作为参数,提取的依据。
Feature Engineering–Extract some valid info from other Attr
典型例子:
- titanic 中的用户名中,可以拆出Mrs, Mr……等,作为一个新的属性
- Predict Feature Sale中,可以从Shop表中的shop_name属性中拆出城市的名字作为一个新的属性,可以从Category表中的type等,拆除新的属性来。
直接一句话搞定,split分割、map映射、lambda进行填入
shops['newAttr'] = shops['oriAttr'].str.split(' ').map(lambda x: x[0])
shops['newAttr1'] = shops['oriAttr'].str.split(' ').map(lambda x: x[1])
Feature Engineering–几种编码形式
One-hot Encoding
1、手动提取
one_hot_encoding = ['Attr1', 'Attr2']
2、自动提取要进行独热编码的属性
one_hot_encoding = [col for col in df.columns if df[col].unique() < 4 and. col is not 'Ans_Attr']
然后进行独热编码:
- 获取新产生的属性
- 把新产生的拼接进去
- 然后把原来的旧的属性给删去
1、通过pandas的get_dummies()
方法
for col in one_hot_encoding:
new = pd.get_dummies(df[col], prefix=col)
df = pd.concat([df, new], axis=1)
df.drop([col], axis=1, index=True)
简化【三换一,但是就不能再选定one_hot_encoding数组来圈定了,只能把整个df丢进去】:
df = pd.get_dummies(df).reset_index(drop=True)
2、通过sklearn.preprocessing
下的OneHotEncoder
方法。(这个方法的使用类似于LabelEncoder的使用,同样也是sklearn,preprocessing下的方法)
3、通过to_categorical
方法
[一般都是对label进行独热编码]
from keras.utils import to_cateogorical
y = to_categorical(y)
LabelEncoder
然后通过LabelEncoder()
中的fit_transform
方法进行编码(是对属性中的同一类值编一样的码值)
# 导入 LabelEncoder()
from sklearn.preprocessing import LabelEncoder
for df in [train, test]:
for feature in ['newAttr', 'newAttr1']:
df[feature] = LabelEncoder().fit_transform(df[feature])
方法2:通过自己写一个字典【更丰富,二级映射】,然后来进行映射,
# 先写好字典 dict
titleDict = {
"Capt": "Officer",
"Col": "Officer"
}
# then to map, 数据集新的属性也可以通过.Attr_Name直接索引
df.Name = df.Name.apply(lambda x: x.split(',')[1].split('.')[0].strip()) # 这里直接替换,只提取了名字其中的头衔,所以名字中头衔的其他模块就直接被抹去了(替换了)
df.Name = df.Name.map(titleDict)
# 由于是非线性的(见下面的应用场景区分),所以要进行one-hot encoding
title = pd.get_dummies(df.Name, prefix='title')
df = pd.concat([df, title], axis=1)
df.drop(['Name'], axis=1, inplace=True)
# 暂时留着name的version => 考虑后续还有用到name的其他情况
df.tem_title = df.Name.apply(lambda x: x.split(',')[1].split('.')[0].strip()) # 这里新开了一个tem_title列来承接割裂出来的内容,并没有直接占用Name属性
df.tem_title = df.tem_title.map(titleDict)
区分 OHE(One-Hot Encoding) 和 标签编码(LabelEncoder ) 的应用场景
两种模型:
-
基于树的模型:梯度增强决策树(DecisionTree)、随机森林(Random Forest)
- 【cart回归树】xgboost、其他Boosting Tree => 只接受数值型特征输入,不接受类别型特征。(eg:这也就是feature sale中,使用xgboost的时候,所有属性都是用LabelEncoder进行编码,而没有用一次one-hot编码的原因)
-
基于非树的模型:基于线性、KNN或者神经网络
基于树的方法就不需要特征的归一化了,例如随机森林,bagging,boosting等。对于树模型来说,one-hot就是增加树模型的深度,树模型是没有特征大小的概念的,本质上就是不停地做选择,特征更偏向哪一块的概念。
然后一般在非树的模型中进行OHE one-hot encoding 或者标签编码LabelEncoder。
对于能否拆成OHE独立的属性还是LabelEncoder标签编码还在一个属性中 => 主要看属性之间的相关性
-
LabelEncoder
- 线性数据 // 数值型数据「Numerical Data」(无论是离散型还是连续型,连续型也可以通过区间合并) => 能在图形中的一条线内体现 (体积由小到大,衣物S,M,L,XL=>都是可以在坐标系中体现)
- 当某个属性的values种类过多时,如果用OHE直接属性爆炸。
-
OHE One-Hot Encoding
- 非线性数据 // 类别型数据「Categorical Data」 => 不能在图形中的一条线内体现
- 分类特征不是序数/相关性不大的属性的各种值(猫、狗、老鼠)