类别变量

1. Label encoding

Label encoding是使用字典的方式,将每个类别标签与不断增加的整数相关联,即生成一个名为class_的实例数组的索引。

缺点:所有的标签都变成了数字,然后算法模型直接将根据其距离来考虑相似的数字,而不考虑标签的具体含义。

方案一:单列数据

from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()

city_list = ["paris", "paris", "tokyo", "amsterdam"]

le.fit(city_list)
print(le.classes_)  # 输出为:['amsterdam' 'paris' 'tokyo']

city_list_le = le.transform(city_list)  # 进行Encode
print(city_list_le)  # 输出为:[1 1 2 0]

city_list_new = le.inverse_transform(city_list_le)  # 进行decode
print(city_list_new)  # 输出为:['paris' 'paris' 'tokyo' 'amsterdam']

方案二:多列数据

from collections import defaultdict
import pandas as pd

d = defaultdict(LabelEncoder)

df = pd.DataFrame({
    'pets': ['cat', 'dog', 'cat', 'monkey', 'dog', 'dog'],
    'owner': ['Champ', 'Ron', 'Brick', 'Champ', 'Veronica', 'Ron'],
    'location': ['San_Diego', 'New_York', 'New_York', 'San_Diego', 'San_Diego',
                 'New_York']
})

# Encoding the variable
fit = df.apply(lambda x: d[x.name].fit_transform(x))
print("df",df)

# Inverse the encoded
fit.apply(lambda x: d[x.name].inverse_transform(x))
print("fit",fit)
# Using the dictionary to label future data
df.apply(lambda x: d[x.name].transform(x))
print("df",df)

'''
df      pets     owner   location
0     cat     Champ  San_Diego
1     dog       Ron   New_York
2     cat     Brick   New_York
3  monkey     Champ  San_Diego
4     dog  Veronica  San_Diego
5     dog       Ron   New_York
fit    pets  owner  location
0     0      1         1
1     1      2         0
2     0      0         0
3     2      1         1
4     1      3         1
5     1      2         0
'''
fruit_data = pd.DataFrame({
    'fruit': ['apple', 'orange', 'pear', 'orange'],
    'color': ['red', 'orange', 'green', 'green'],
    'weight': [5, 6, 3, 4]
})


class MultiColumnLabelEncoder:
    def __init__(self, columns=None):
        self.columns = columns  # array of column names to encode

    def fit(self, X, y=None):
        return self  # not relevant here

    def transform(self, X):
        '''
        Transforms columns of X specified in self.columns using
        LabelEncoder(). If no columns specified, transforms all
        columns in X.
        '''
        output = X.copy()
        if self.columns is not None:
            for col in self.columns:
                output[col] = LabelEncoder().fit_transform(output[col])
        else:
            for colname, col in output.iteritems():
                output[colname] = LabelEncoder().fit_transform(col)
        return output

    def fit_transform(self, X, y=None):
        return self.fit(X, y).transform(X)

multiColumnLabelEncoder=MultiColumnLabelEncoder()
r1=multiColumnLabelEncoder.fit_transform(fruit_data)
print(r1)

'''
 fruit  color  weight
0      0      2       2
1      1      1       3
2      2      0       0
3      1      0       1

'''

方案三:pd.factorize()

pandas的factorize()可以将Series中的标称型数据映射称为一组数字,相同的标称型映射为相同的数字。

factorize函数的返回值是一个tuple(元组),元组中包含两个元素。

第一个元素是一个array,其中的元素是标称型元素映射为的数字;第二个元素是Index类型,其中的元素是所有标称型元素,没有重复。

2. One hot encoding

为什么能使用One-Hot Encoding?

使用one-hot编码,将离散特征的取值扩展到了欧式空间,离散特征的某个取值就对应欧式空间的某个点。在回归,分类,聚类等机器学习算法中,特征之间距离的计算或相似度的计算是非常重要的,而我们常用的距离或相似度的计算都是在欧式空间的相似度计算,计算余弦相似性,也是基于的欧式空间。

将离散型特征使用one-hot编码,可以会让特征之间的距离计算更加合理。比如,有一个离散型特征,代表工作类型,该离散型特征,共有三个取值,不使用one-hot编码,计算出来的特征的距离是不合理。那如果使用one-hot编码,显得更合理。

独热编码优缺点

优点:独热编码解决了分类器不好处理属性数据的问题,在一定程度上也起到了扩充特征的作用。它的值只有0和1,不同的类型存储在垂直的空间。

缺点:当类别的数量很多时,特征空间会变得非常大。在这种情况下,一般可以用PCA(主成分分析)来减少维度。而且One-Hot Encoding+PCA这种组合在实际中也非常有用。

One-Hot Encoding的使用场景

独热编码用来解决类别型数据的离散值问题。将离散型特征进行one-hot编码的作用,是为了让距离计算更合理,但如果特征是离散的,并且不用one-hot编码就可以很合理的计算出距离,那么就没必要进行one-hot编码,比如,该离散特征共有1000个取值,我们分成两组,分别是400和600,两个小组之间的距离有合适的定义,组内的距离也有合适的定义,那就没必要用one-hot 编码。

基于树的方法是不需要进行特征的归一化,例如随机森林,bagging 和 boosting等。对于决策树来说,one-hot的本质是增加树的深度,决策树是没有特征大小的概念的,只有特征处于他分布的哪一部分的概念。

2.1 LabelBinarizer

from sklearn.preprocessing import LabelBinarizer
 
lb = LabelBinarizer()
 
city_list = ["paris", "paris", "tokyo", "amsterdam"]
 
lb.fit(city_list)
print(lb.classes_)  # 输出为:['amsterdam' 'paris' 'tokyo']
 
city_list_le = lb.transform(city_list)  # 进行Encode
print(city_list_le)  # 输出为:
# [[0 1 0]
#  [0 1 0]
#  [0 0 1]
#  [1 0 0]]
 
city_list_new = lb.inverse_transform(city_list_le)  # 进行decode
print(city_list_new)  # 输出为:['paris' 'paris' 'tokyo' 'amsterdam']

2.2 DictVectorizer

from sklearn.feature_extraction import DictVectorizer
 
measurements = [
    {'city': 'Dubai', 'temperature': 33.},
    {'city': 'London', 'temperature': 12.},
    {'city': 'San Fransisco', 'temperature': 18.},
]
 
vec = DictVectorizer()
measurements_vec = vec.fit_transform(measurements)
print(measurements_vec)
  # 输出内容:
  # (0, 0)    1.0
  # (0, 3)    33.0
  # (1, 1)    1.0
  # (1, 3)    12.0
  # (2, 2)    1.0
  # (2, 3)    18.0
print(measurements_vec.toarray())
# 输出内容
# [[ 1.  0.  0. 33.]
#  [ 0.  1.  0. 12.]
#  [ 0.  0.  1. 18.]]
 
feature_names = vec.get_feature_names()
print(feature_names)  # 输出:['city=Dubai', 'city=London', 'city=San Fransisco', 'temperature']

2.3 基于sklearn 的one hot encoding

import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder
 
df = pd.DataFrame([
    ['green', 'Chevrolet', 2017],
    ['blue', 'BMW', 2015],
    ['yellow', 'Lexus', 2018],
])
df.columns = ['color', 'make', 'year']
 
le_color = LabelEncoder()
le_make = LabelEncoder()
df['color_encoded'] = le_color.fit_transform(df.color)
df['make_encoded'] = le_make.fit_transform(df.make)
 
color_ohe = OneHotEncoder()
make_ohe = OneHotEncoder()
X = color_ohe.fit_transform(df.color_encoded.values.reshape(-1, 1)).toarray()
Xm = make_ohe.fit_transform(df.make_encoded.values.reshape(-1, 1)).toarray()
 
dfOneHot = pd.DataFrame(X, columns=["Color_" + str(int(i)) for i in range(X.shape[1])])
df = pd.concat([df, dfOneHot], axis=1)
 
dfOneHot = pd.DataFrame(Xm, columns=["Make" + str(int(i)) for i in range(X.shape[1])])
df = pd.concat([df, dfOneHot], axis=1)

2.4 基于pandas的one hot encoding

get_dummies的优势在于:

    本身就是 pandas 的模块,所以对 DataFrame 类型兼容很好

    不管你列是数值型还是字符串型,都可以进行二值化编码

    能够根据指令,自动生成二值化编码后的变量名:

缺点:不是 sklearn 里的transformer类型,所以得到的结果得手动输入到 sklearn 里的相应模块,也无法像 sklearn 的transformer一样可以输入到pipeline中进行流程化地机器学习过程。

import pandas as pd
 
df = pd.DataFrame([
    ['green', 'Chevrolet', 2017],
    ['blue', 'BMW', 2015],
    ['yellow', 'Lexus', 2018],
])
df.columns = ['color', 'make', 'year']
 
 
df_processed = pd.get_dummies(df, prefix_sep="_", columns=df.columns[:-1])
print(df_processed)

3. 利用神经网络的Embedding层处理类别特征

 

posted on 2020-10-17 15:42  happygril3  阅读(547)  评论(0)    收藏  举报

导航