上一期我们实战了归一化的两种方法:线性函数归一化(Min-Max Scaling)和零均值归一化(z-score Normalization)。这一期我们从实数型型特征转到类别性特征去回应如下问题:
Q: 在进行数据预处理时,应该怎么处理类别性特征?(难度:2⭐)
我们常用三种方法处理类别型特征:
- 序号编码(Ordinal Encoding)
是将n种类别从0到n-1或1到n的整数排序,主要是可以保留不同等级(例如空气质量等级1到6级,分别对应"优"到"重污染")。
- 独热编码(Ordinal Encoding)
将一个类别变量中多种类按照每个种类的有(1)无(0)去分类。输出是:
需要注意如下问题:
(1)使用稀疏向量来节省空间。因此可以利用向量的稀疏表示有效地节省空间,并且目前大部分的算法均接受稀疏向量形式的输入。
(2)配合特征选择采降低维度。高维度特征会带来几方面的问题:
一是在K 近邻算法中,高维空间下两点之间的距离很难得到高效的衡量;
二是在逻幅回归模型中,参数的数量会随着维度的增高而增加,易引
起过拟合问题;
三是通常只有高部分维度是对台类、预测有帮助,因此可以考虑配合特征选择来降低维度。
- 二进制编码(Binary Encoding)
序号编码的二进制数版本。好处是比独热编码更省空间,空间复杂度是
其中N是单个类别变量中类别个数,M为样本长度。
接下来咱们进入实战吧!
同样,我们需要的是葡萄酒数据(以下代码块均用python3)。这次追加一个包是为后面的对数运算做准备:
import urllib.request
import numpy as np
url = "http://archive.ics.uci.edu//ml//machine-learning-databases//wine//wine.data"
raw_data = urllib.request.urlopen(url)
data0 = np.loadtxt(raw_data, delimiter=",")
用numpy硬干模式:
# arr 的 独特函数,输入一维数组,双指针算法时间复杂度为O(n)
def unique(arr):
arrs = arr.copy()
j = 0
for i in range(len(arrs)):
if (not i) or (arrs[i] not in arrs[0 : j]):
arrs[j] = arrs[i]
j += 1
return arrs[0 : j]
# a[0] ~ a[j - 1] 所有a中不重复的数
# 标签编码
def label(arr,a):
arrs = np.zeros_like(arr)
for i in range(len(arr)):
arrs[i] = list(a).index(arr[i])
return arrs
# 独热编码
def onehot(arr,a):
arrs = np.zeros((len(arr),len(a)))
for i in range(len(arr)):
arrs[i,list(a).index(arr[i])] = 1
return arrs
# 二进制编码
def binary(arr,a):
arrs = np.zeros((len(arr),int(math.log(len(a)-1,2))+1),dtype = int)
for i in range(len(arr)):
q = list(a).index(arr[i])
cnt = -1
if q == 0:
continue
while q > 0:
q,m = q // 2, q % 2
arrs[i,cnt] = m
cnt -= 1
return arrs
# 总函数
encoders_func = {'label': label, 'onehot': onehot, 'binary': binary}
def categotical_encoders(arr, encode_type):
a = unique(arr)
return encoders_func[encode_type](arr,a)
# 注意输入数组是一维的,不是n*1的二维
data1 = categotical_encoders(data0[:,0], 'label')
data2 = categotical_encoders(data0[:,0], 'onehot')
data2 = categotical_encoders(data0[:,0], 'binary')
优雅的sklearn模式:
from sklearn import preprocessing
from sklearn.preprocessing import OneHotEncoder
le = preprocessing.LabelEncoder()
ohe = OneHotEncoder(handle_unknown='ignore')
# 求unique 函数
le.fit(data0[:,0])
data1 = le.transform(data0[:,0])
ohe.fit(data0[:,0:1])
data2 = ohe.transform(data0[:,0:1])
二进制编码省空间但是耗时,是因为他的时间复杂度为
上一期代码耗时也是按重复1000次来计算的。
各位敬请期待下一期:
[Hulu百面机器学习]python实战系列(1.3-1.4)——(高维)组合特征
最后欢迎大家关注我们的微信公众号哦(科罗娜气候狂热者):
http://weixin.qq.com/r/AS4RCXPEli7prTdq93sT (二维码自动识别)