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」 => 不能在图形中的一条线内体现
    • 分类特征不是序数/相关性不大的属性的各种值(猫、狗、老鼠)
Posted on Jan 28, 2020