类别变量
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) 收藏 举报
浙公网安备 33010602011771号