前言
在实际问题中,我们获得的数据会包含非数值型的特征,这种非数值型的无法进入模型进行训练,因此需要进行编码。编码的方式常用的两种:
- 数字编码
- One-Hot编码
数字编码
每个特征用不同的数字表示。例如,“汽车皮牌”={路虎,吉利,奥迪,大众,奔驰},经过数字编码后为“汽车品牌”={0,1,2,3,4}。
- 缺点 : 在模型中,有计算距离的,这种编码方式扭曲描述两种品牌之间的距离远近。
OneHot编码
将K个取值的离散型特征转换成K个二元特征(0或者1),上节我们讨论的五种品牌用五种特征表示,f1,f2,f3,f4,f5.
一个普通标题 | 一个普通标题 | 一个普通标题 | 一个普通标题 | 一个普通标题 | 一个普通标题 |
---|---|---|---|---|---|
路虎 | 1 | 0 | 0 | 0 | 0 |
吉利 | 0 | 1 | 0 | 0 | 0 |
奥迪 | 0 | 0 | 1 | 0 | 0 |
大众 | 0 | 0 | 0 | 1 | 0 |
奔驰 | 0 | 0 | 0 | 0 | 1 |
- 优点:
- 不会人为的引入次序关系,使特征之间保持原有的距离
- 缺点:
- 引入维度,2的指数此增长
- 增加相关性,注意上面的满足线性关系:
f1+f2+f3+f4+f5=1
代码实现
1、pandas自带的get_dummies()【适合含有字符串类型的数据】
好处: * 1.本身就是 pandas 的模块,所以对 DataFrame 类型兼容很好.
* 2.无论你的列是字符型还是数字型都可以进行二值编码.
* 3.能根据用户指定,自动生成二值编码后的变量名.
问题:get_dummies 没有sklearn 的 transformer方法,所以一旦测试集中出现了训练集未曾出现过的特征取值,简单地对测试集、训练集都用 get_dummies 方法将导致数据错误。 也无法像 sklearn 的transformer一样可以输入到pipeline中 进行流程化地机器学习过程。
2、sklearn的OneHotEncoder()【适合只含数值型的数据】
通过 OneHotEncoder() 自带的 feature_indices_ 可以知道哪几列对应哪个原来的特征
使用 numpy.hstack() 将多次结果拼接起来得到变换后的结果
问题:不能直接编码字符串类型数据(LabelEncoder() + OneHotEncoder() 可实现,但需数据格式转换)
python sklearn 实现方式
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.preprocessing import OneHotEncoder,LabelEncoder
data = pd.read_csv("E:\\算法类\\young-people-survey\\responses.csv")
#Label标记 和Onehot编码对象
enc = OneHotEncoder(handle_unknown='ignore')
lenc = LabelEncoder()
X =[['s'],['a'],['a'],['s']]
column = data["Smoking"]
res =column.values.tolist()
#符号标签化
lenc.fit(res)
z = np.array(lenc.transform(res))
#出来的是一个(n,)对象,现在要变为(n,1)对象
z = z.reshape(len(z),1)
#编码
enc.fit(z)
result = enc.transform(z)
#结果最后转成list
rr = result.toarray()
#整理函数形式
def MyOneHot(Series): #输入的是pandas里面的series
res = Series.values.tolist()
lenc.fit(res)
z = np.array(lenc.transform(res))
z = z.reshape(len(z),1)
enc.fit(z)
result = enc.transform(z).toarray()
return result #返回的是np.array