精华内容
下载资源
问答
  • 下面将给出两种预测onehot编码方法,其中模型用LinearRegression。 汽车数据 密码:7izi 2.训练+预测 2.1.get_dummies方法 import pandas as pd df = pd.read_csv('carprices.csv') dummies = pd.get_dummies(df['Car...
  • 编码2.1 序号编码(Ordinal Encoding)2.2独热编码(One-hot Encoding)2.3 标签编码 (Label Encoding)2.4 频数编码(Frequency Encoding/Count Encoding)2.5 目标编码(Target Encoding) 一. 常见的特征类型 ...

    一. 常见的特征类型

    一般特征可以分为两大类特征,连续型离散型特征。而离散型特征既有是数值型的,也有类别型特征。例如性别(男、女)、成绩等级(A、B、C)等等。连续型特征的原始形态就可以作为模型的输入,无论是LR、神经网络,还是SVM、GBDT、xgboost等等。但是除了决策树等少数模型能直接处理字符串形式的类别型特征输入,逻辑回归、支持向量机等模型的输入必须是数值型特征才能正确工作。因此就需要将离散型特征中的类别型特征转换成数值型的。
    在这里插入图片描述

    二. 编码

    2.1 序号编码(Ordinal Encoding)

    序号编码通常用于处理类别间具有内在大小顺序关系的数据,对于一个具有m个类别的特征,我们将其对应地映射到 [0,m-1] 的整数。例如对于”学历”这样的类别,”学士”、”硕士”、”博士” 可以很自然地编码成 [0,2],因为它们内在就含有这样的逻辑顺序。但如果对于“颜色”这样的类别,“蓝色”、“绿色”、“红色”分别编码成[0,2]是不合理的,因为我们并没有理由认为“蓝色”和“绿色”的差距比“蓝色”和“红色”的差距对于特征的影响是不同的。

    sklearn.preprocessing中的OrdinalEncoder进行处理,可以通过两种方式进行编码:

    • 方法1:先将数据categorical_df载入encoder中,再将载入的数据进行OrdinalEncoder编码
    • 方法2: 直接载入encoder并编码
    import pandas as pd
    from sklearn.preprocessing import OrdinalEncoder
    
    categorical_df = pd.DataFrame({'my_id': ['101', '102', '103', '104'],
                                   'name': ['allen', 'bob', 'chartten', 'dory'], 
                                   'place': ['third', 'second', 'first', 'second']})
    print(categorical_df)
    print('--'*20)
    
    encoder = OrdinalEncoder() #创建OrdinalEncoder对象
    
    # 方法1
    encoder.fit(categorical_df) #将数据categorical_df载入encoder中
    categorical_df = encoder.transform(categorical_df) #将载入的数据进行OrdinalEncoder
    
    # 方法2
    categorical_df = encoder.fit_transform(categorical_df) #代替上面的fit()和transform(),一步到位
    
    print(categorical_df)
    

    输出:
    在这里插入图片描述
    我们发现将三列特征全部按照升序的方式编码,比如name这一列,按照首字母前后顺序排序:allen为0,bob为1,chartten为2,dory为3,其余两行也是如此。如果我们想自定义排列顺序呢?比如name列,想按照这样的方式编码:dory为0, bob为1, chartten为2, allen为3
    方法很简单,就是先自定义标签序列name_categoriesplace_categories,然后在创建OrdinalEncoder对象时,categories变量中传入自定义标签列即可。

    import pandas as pd
    from sklearn.preprocessing import OrdinalEncoder
    
    categorical_df = pd.DataFrame({'my_id': ['101', '102', '103', '104'],
                                   'name': ['allen', 'bob', 'chartten', 'dory'], 
                                   'place': ['third', 'second', 'first', 'second']})
    
    # In the 'name' column, I want 'dory' to be 0, 'bob' to be 1, 'chartten' to be 2, and 'allen' to be 3
    # In the 'place' column, I want 'first' to be 0, 'second' to be 1, and 'third' to be 2
    name_categories = ['dory', 'bob', 'chartten', 'allen']
    place_categories = ['first', 'second', 'third']
    
    encoder = OrdinalEncoder(categories=[name_categories, place_categories])
    
    categorical_df[['name', 'place']]= encoder.fit_transform(categorical_df[['name', 'place']])
    
    categorical_df
    

    输出:
    在这里插入图片描述
    如图中所示,dory现在排在编码后name列的0,以此类推。

    2.2独热编码(One-hot Encoding)

    独热编码:通常用于处理类别间不具有大小关系的特征。
    可以通过导入sklearn.preprocessing中的OneHotEncoder,创建哑变量进行处理。

    import pandas as pd
    from sklearn.preprocessing import OneHotEncoder
    
    categorical_df = pd.DataFrame({'my_id': ['101', '102', '103', '104'],
                                   'name': ['allen', 'bob', 'chartten', 'dory'], 
                                   'place': ['third', 'second', 'first', 'second']})
    print(categorical_df)
    print('--'*20)
    
    encoder = OneHotEncoder()
    encoder.fit_transform(categorical_df[['name']]).toarray()
    

    输出:
    在这里插入图片描述
    我们对name进行onehot编码后,第一列表示allen: [1,0,0,0],第二列表示bob: [0,1,0,0],以此类推。

    同理也可以自定义编码顺序:

    import pandas as pd
    from sklearn.preprocessing import OneHotEncoder
    
    categorical_df = pd.DataFrame({'my_id': ['101', '102', '103', '104'],
                                   'name': ['allen', 'bob', 'chartten', 'dory'], 
                                   'place': ['third', 'second', 'first', 'second']})
    print(categorical_df)
    print('--'*20)
    
    encoder = OneHotEncoder(categories=[['dory', 'bob', 'chartten', 'allen']])
    encoder.fit_transform(categorical_df[['name']]).toarray()
    

    输出:
    在这里插入图片描述

    我们自定义的编码顺序是['dory', 'bob', 'chartten', 'allen'],dory=[1,0,0,0],bob=[0,1,0,0],chartten=[0,0,1,0],allen=[0,0,0,1], 在输出结果的第一列中表示allen,即为[0,0,0,1],第二列表示bob,即为[0,1,0,0],以此类推。

    2.3 标签编码 (Label Encoding)

    Label Encoding是给某一列数据编码,而Ordinal Encoding是给所有的特征编码。因此Label Encoding常用于给标签(label)编码,而Ordinal Encoding常用于给数据集中的特征编码。

    代码举例:

    import pandas as pd
    from sklearn.preprocessing import LabelEncoder
    
    categorical_df = pd.DataFrame({'my_id': ['101', '102', '103', '104'],
                                   'name': ['allen', 'bob', 'chartten', 'dory'], 
                                   'place': ['third', 'second', 'first', 'second'],
                                   })
    print(categorical_df)
    print('--'*20)
    
    encoder = LabelEncoder()
    categorical_df['place']=encoder.fit_transform(categorical_df['place'])
    categorical_df
    

    输出:
    在这里插入图片描述
    我们可以从上面的例子中看到place列已被编码,与上文Ordinal Encoding中的例子做对比可以发现,Label Encoding是给某一列数据编码,而Ordinal Encoding是给所有的特征编码

    我们知道Ordinal Encoding用于有序特征的数据编码,OneHot Encoding用于无序特征的数据编码,而LabelEncoder与OneHotEncoder又存在什么样的区别呢?

    表面区别:
    在这里插入图片描述
    用途区别:
    有些模型的损失函数对数值大小是敏感的,即变量间的数值大小本身是有比较意义的,如逻辑回归,SVM等,我们暂将其称为A类模型;有些模型本身对数值变化不敏感,数值存在的意义更多的是为了排序,即0.1,0.2,0.3与10,20,30是没有区别的,这部分模型绝大部分是树模型,暂将其称为B类模型。比如用label encoding将某列特征 [dog,cat,dog,mouse,cat],转换为[1,2,1,3,2]。这里就产生了一个奇怪的现象:dog和mouse的平均值是cat,所以label encoding最直观的缺点就是赋值难以解释,适用场景更窄。

    • 特征数据类型
      对于定类类型的数据,建议使用one-hot encoding。定类类型就是纯分类,不排序,没有逻辑关系。比如性别分男和女,男女不存在任何逻辑关系,我们不能说男就比女好,或者相反。再者,中国各省市分类也可以用独热编码,同样各省不存在逻辑关系,这时候使用one-hot encoding会合适些。但注意,一般会舍去一个变量,比如男的对立面肯定是女,那么女就是重复信息,所以保留其中一个变量即可。
      对于定序类型的数据,建议使用label encoding。定序类型也是分类,但有排序逻辑关系,等级上高于定类。比如,学历分小学,初中,高中,本科,研究生,各个类别之间存在一定的逻辑,显然研究生学历是最高的,小学最低。这时候使用Label encoding会显得更合适,因为自定义的数字顺序可以不破坏原有逻辑,并与这个逻辑相对应。

    • 所使用的模型
      数值大小敏感的模型必须使用one-hot encoding。典型的例子就是LR和SVM。二者的损失函数对数值大小是敏感的,并且变量间的数值大小是有比较意义的。而Label encoding的数字编码没有数值大小的含义,只是一种排序,因此对于这些模型都使用one-hot encoding。
      数值大小不敏感的模型(如树模型)不建议使用one-hot encoding。一般这类模型为树模型。如果分类类别特别多,那么one-hot encoding会分裂出很多特征变量。这时候,如果我们限制了树模型的深度而不能向下分裂的话,一些特征变量可能就因为模型无法继续分裂而被舍弃损失掉了。因此,此种情况下可以考虑使用Label encoding。

    2.4 频数编码(Frequency Encoding/Count Encoding)

    将类别特征替换为训练集中的计数(一般是根据训练集来进行计数,属于统计编码的一种,统计编码,就是用类别的统计特征来代替原始类别,比如类别A在训练集中出现了100次则编码为100)。这个方法对离群值很敏感,所以结果可以归一化或者转换一下(例如使用对数变换)。未知类别可以替换为1。

    频数编码使用频次替换类别。有些变量的频次可能是一样的,这将导致碰撞。尽管可能性不是非常大,没法说这是否会导致模型退化,不过原则上我们不希望出现这种情况。

    比如某个分类中’Peking’出现了10次,那么’Peking’就会被替换为10. 我们可以用categorical-encodings包中的CountEncoder实现。

    import category_encoders as ce
    features = ['Peking', 'Peking', 'Shanghai', 'Peking', 'Guangzhou', 'Shanghai']
    count_enc = ce.CountEncoder()
    count_enc.fit_transform(features)
    

    2.5 目标编码(Target Encoding)

    等待更新。。。

    展开全文
  • 机器学习Author:louwillMachine Learning Lab 在做结构化数据训练时,类别特征是一个非常常见的变量类型。机器学习中有多种类别变量编码方式,各种编码...

     机器学习

    Author:louwill

    Machine Learning Lab

         在做结构化数据训练时,类别特征是一个非常常见的变量类型。机器学习中有多种类别变量编码方式,各种编码方法都有各自的适用场景和特点。本文就对机器学习中常见的类别编码方式做一个简单的总结。

    硬编码:Label Encoding

         所谓硬编码,即直接对类别特征进行数值映射,有多少类别取值就映射多少数值。这种硬编码方式简单粗暴,方便快捷。但其仅在类别特征内部取值是有序的情况才好使用,即类别特征取值存在明显的顺序性,比如说学历特征取值为高中、本科、硕士和博士,各学历之间存在明显的顺序关系。

         Sklearn提供了Label Encoding的实现方式,示例代码如下:

    from sklearn import preprocessing
    le = preprocessing.LabelEncoder()
    le.fit(['undergraduate', 'master', 'PhD', 'Postdoc'])
    le.transform(['undergraduate', 'master', 'PhD', 'Postdoc'])
    
    array([3, 2, 0, 1], dtype=int64)
    

    独热编码:One-hot Encoding

         One-hot编码应该是应用最广泛的类别特征编码方式了。假设一个类别特征有m个类别取值,通过One-hot编码我们可以将其转换为m个二元特征,每个特征对应该取值类别。

         对于类别特征内部取值不存在明显的内在顺序时,即直接的硬编码不适用时,One-hot编码的作用就凸显出来了。但当类别特征取值过多时,One-hot编码很容易造成维度灾难,特别是对于文本类的特征,如果使用One-hot编码对其进行编码,基本上都是茫茫零海。所以,在类别特征取值无序,且特征取值数量少于5个时,可使用One-hot方法进行类别编码。有朋友可能会问,一定得是5个吗,6个行不行,当然也可以,这里并没有固定标准,但差不多就是这个数据左右。数量再多就不建议使用One-hot了。

         Pandas和Sklearn都提供了One-hot编码的实现方式,示例代码如下。

    import pandas as pd
    df = pd.DataFrame({'f1':['A','B','C'], 
    'f2':['Male','Female','Male']})
    df = pd.get_dummies(df, columns=['f1', 'f2'])
    df
    

    from sklearn.preprocessing import OneHotEncoder
    enc = OneHotEncoder(handle_unknown='ignore')
    X = [['Male', 1], ['Female', 3], ['Female', 2]]
    enc.fit(X)
    enc.transform([['Female', 1], ['Male', 4]]).toarray()
    
    array([[1., 0., 1., 0., 0.],
    [0., 1., 0., 0., 0.]])
    

    目标变量编码:Target Encoding

         Target Encoding就是用目标变量的类别均值来给类别特征做编码。CatBoost中就大量使用目标变量统计的方法来对类别特征编码。但在实际操作时,直接用类别均值替换类别特征的话,会造成一定程度的标签信息泄露的情况,主流方法是使用两层的交叉验证来计算目标均值。Target Encoding一般适用于类别特征无序且类别取值数量大于5个的情形。

         参考代码如下:

    ### 该代码来自知乎专栏:
    ### https://zhuanlan.zhihu.com/p/40231966
    from sklearn.model_selection import KFold
    n_folds = 20
    n_inner_folds = 10
    likelihood_encoded = pd.Series()
    likelihood_coding_map = {}
    # global prior mean
    oof_default_mean = train[target].mean()      
    kf = KFold(n_splits=n_folds, shuffle=True)
    oof_mean_cv = pd.DataFrame()
    split = 0
    for infold, oof in kf.split(train[feature]):
    print ('==============level 1 encoding..., fold %s ============' % split)
    inner_kf = KFold(n_splits=n_inner_folds, shuffle=True)
    inner_oof_default_mean = train.iloc[infold][target].mean()
    inner_split = 0
    inner_oof_mean_cv = pd.DataFrame()
    likelihood_encoded_cv = pd.Series()
    for inner_infold, inner_oof in inner_kf.split(train.iloc[infold]):
    print ('==============level 2 encoding..., inner fold %s ============' % inner_split)
            # inner out of fold mean
    oof_mean = train.iloc[inner_infold].groupby(by=feature)[target].mean()
            # assign oof_mean to the infold
    likelihood_encoded_cv = likelihood_encoded_cv.append(train.iloc[infold].apply(
    lambda x : oof_mean[x[feature]]
    if x[feature] in oof_mean.index
    else inner_oof_default_mean, axis = 1))
    inner_oof_mean_cv = inner_oof_mean_cv.join(pd.DataFrame(oof_mean), rsuffix=inner_split, how='outer')
    inner_oof_mean_cv.fillna(inner_oof_default_mean, inplace=True)
    inner_split += 1
    oof_mean_cv = oof_mean_cv.join(pd.DataFrame(inner_oof_mean_cv), rsuffix=split, how='outer')
    oof_mean_cv.fillna(value=oof_default_mean, inplace=True)
    split += 1
    print ('============final mapping...===========')
    likelihood_encoded = likelihood_encoded.append(train.iloc[oof].apply(
    lambda x: np.mean(inner_oof_mean_cv.loc[x[feature]].values)
    if x[feature] in inner_oof_mean_cv.index
    else oof_default_mean, axis=1))
    

    模型自动编码

         在LightGBM和CatBoost等算法中,模型可以直接对类别特征进行编码,实际使用时直接将类别特征标记后传入对应的api即可。一个示例代码如下:

    lgb_train = lgb.Dataset(train2[features], train2['total_cost'], 
                           categorical_feature=['sex'])
    

    总结

    根据本文的梳理,可总结机器学习中类别特征的编码方式如下:

    • Label Encoding

      • 类别特征内部有序

    • One-hot Encoding

      • 类别特征内部无序

      • 类别数值<5

    • Target Encoding

      • 类别特征内部无序

      • 类别数值>5

    • 模型自动编码

      • LightGBM

      • CatBoost

    往期精彩:

    【原创首发】机器学习公式推导与代码实现30讲.pdf

    【原创首发】深度学习语义分割理论与实战指南.pdf

    喜欢您就点个在看!

    展开全文
  • 机器学习算法,我们经常会遇到分类特征,例如:人的性别有男女,祖国有中国,美国,法国等。 这些特征值并不是连续的,而是离散的,无序的。通常我们需要对其进行特征数字化。 那什么是特征数字化呢?例子如下...

    一. 什么是独热编码?

    ————————————————————————————————————————

    在机器学习算法中,我们经常会遇到分类特征,例如:人的性别有男女,祖国有中国,美国,法国等。
    这些特征值并不是连续的,而是离散的,无序的。通常我们需要对其进行特征数字化。

    那什么是特征数字化呢?例子如下:

    • 性别特征:["男","女"]

    • 祖国特征:["中国","美国,"法国"]

    • 运动特征:["足球","篮球","羽毛球","乒乓球"]

    假如某个样本(某个人),他的特征是这样的["男","中国","乒乓球"],我们可以用 [0,0,4] 来表示,但是这样的特征处理并不能直接放入机器学习算法中。因为类别之间是无序的(运动数据就是任意排序的)。

     

    什么是独热编码(One-Hot)?

    ————————————————————————————————————————

    One-Hot编码,又称为一位有效编码,主要是采用N位状态寄存器来对N个状态进行编码,每个状态都由他独立的寄存器位,并且在任意时候只有一位有效。

    One-Hot编码是分类变量作为二进制向量的表示。这首先要求将分类值映射到整数值。然后,每个整数值被表示为二进制向量,除了整数的索引之外,它都是零值,它被标记为1。

     

    One-Hot实际案例

    ————————————————————————————————————————

    就拿上面的例子来说吧,性别特征:["男","女"],按照N位状态寄存器来对N个状态进行编码的原理,咱们处理后应该是这样的(这里只有两个特征,所以N=2):

    男  =>  10

    女  =>  01

    祖国特征:["中国","美国,"法国"](这里N=3):

    中国  =>  100

    美国  =>  010

    法国  =>  001

    运动特征:["足球","篮球","羽毛球","乒乓球"](这里N=4):

    足球  =>  1000

    篮球  =>  0100

    羽毛球  =>  0010

    乒乓球  =>  0001

    所以,当一个样本为["男","中国","乒乓球"]的时候,完整的特征数字化的结果为:

    [1,0,1,0,0,0,0,0,1]

    下图可能会更好理解:

    https://img.mukewang.com/5b20f1b90001cc2202550045.jpg

     

    One-Hot在python中的使用

    ————————————————————————————————————————

    1

    2

    3

    4

    5

    6

    7

    8

    from sklearn import preprocessing  

       

    enc = preprocessing.OneHotEncoder()  

    enc.fit([[0,0,3],[1,1,0],[0,2,1],[1,0,2]])  #这里一共有4个数据,3种特征

       

    array = enc.transform([[0,1,3]]).toarray()  #这里使用一个新的数据来测试

       

    print array   # [[ 1  0  0  1  0  0  0  0  1]]

    结果为 1 0 0 1 0 0 0 0 1

     

    为什么使用one-hot编码来处理离散型特征?

    ————————————————————————————————————————

    在回归,分类,聚类等机器学习算法中,特征之间距离的计算或相似度的计算是非常重要的,而我们常用的距离或相似度的计算都是在欧式空间的相似度计算,计算余弦相似性,基于的就是欧式空间。

    而我们使用one-hot编码,将离散特征的取值扩展到了欧式空间,离散特征的某个取值就对应欧式空间的某个点。

    将离散型特征使用one-hot编码,确实会让特征之间的距离计算更加合理。

    比如,有一个离散型特征,代表工作类型,该离散型特征,共有三个取值,不使用one-hot编码,其表示分别是x_1 = (1), x_2 = (2), x_3 = (3)。两个工作之间的距离是,(x_1, x_2) = 1, d(x_2, x_3) = 1, d(x_1, x_3) = 2。那么x_1和x_3工作之间就越不相似吗?显然这样的表示,计算出来的特征的距离是不合理。那如果使用one-hot编码,则得到x_1 = (1, 0, 0), x_2 = (0, 1, 0), x_3 = (0, 0, 1),那么两个工作之间的距离就都是sqrt(2).即每两个工作之间的距离是一样的,显得更合理。

     

    不需要使用one-hot编码来处理的情况

    ————————————————————————————————————————

    将离散型特征进行one-hot编码的作用,是为了让距离计算更合理,但如果特征是离散的,并且不用one-hot编码就可以很合理的计算出距离,那么就没必要进行one-hot编码。

    比如,该离散特征共有1000个取值,我们分成两组,分别是400和600,两个小组之间的距离有合适的定义,组内的距离也有合适的定义,那就没必要用one-hot 编码。

    离散特征进行one-hot编码后,编码后的特征,其实每一维度的特征都可以看做是连续的特征。就可以跟对连续型特征的归一化方法一样,对每一维特征进行归一化。比如归一化到[-1,1]或归一化到均值为0,方差为1。

     

    示例详解:

    假如有三种颜色特征:红、黄、蓝。 在利用机器学习的算法时一般需要进行向量化或者数字化。那么你可能想令 红=1,黄=2,蓝=3. 那么这样其实实现了标签编码,即给不同类别以标签。然而这意味着机器可能会学习到“红<黄<蓝”,但这并不是我们的让机器学习的本意,只是想让机器区分它们,并无大小比较之意。所以这时标签编码是不够的,需要进一步转换。因为有三种颜色状态,所以就有3个比特。即红色:1 0 0 ,黄色: 0 1 0,蓝色:0 0 1 。如此一来每两个向量之间的距离都是根号2,在向量空间距离都相等,所以这样不会出现偏序性,基本不会影响基于向量空间度量算法的效果。

     

    自然状态码为:
    000,001,010,011,100,101
    独热编码为:
    000001,000010,000100,001000,010000,100000
    

    来一个sklearn的例子:

     

    from sklearn import preprocessing  
    enc = preprocessing.OneHotEncoder()  
    enc.fit([[0, 0, 3], [1, 1, 0], [0, 2, 1], [1, 0, 2]])    # fit来学习编码  
    enc.transform([[0, 1, 3]]).toarray()    # 进行编码  
    

    输出:array([[ 1., 0., 0., 1., 0., 0., 0., 0., 1.]])

    数据矩阵是4*3,即4个数据,3个特征维度。

    0 0 3 观察左边的数据矩阵,第一列为第一个特征维度,有两种取值0\1. 所以对应编码方式为10 、01

    1 1 0 同理,第二列为第二个特征维度,有三种取值0\1\2,所以对应编码方式为100、010、001

    0 2 1 同理,第三列为第三个特征维度,有四中取值0\1\2\3,所以对应编码方式为1000、0100、0010、0001

     

    再来看要进行编码的参数[0 , 1, 3], 0作为第一个特征编码为10, 1作为第二个特征编码为010, 3作为第三个特征编码为0001. 故此编码结果为 1 0 0 1 0 0 0 0 1

    二. 为什么要独热编码?

    正如上文所言,独热编码(哑变量 dummy variable)是因为大部分算法是基于向量空间中的度量来进行计算的,为了使非偏序关系的变量取值不具有偏序性,并且到圆点是等距的。使用one-hot编码,将离散特征的取值扩展到了欧式空间,离散特征的某个取值就对应欧式空间的某个点。将离散型特征使用one-hot编码,会让特征之间的距离计算更加合理。离散特征进行one-hot编码后,编码后的特征,其实每一维度的特征都可以看做是连续的特征。就可以跟对连续型特征的归一化方法一样,对每一维特征进行归一化。比如归一化到[-1,1]或归一化到均值为0,方差为1。

    为什么特征向量要映射到欧式空间?

    将离散特征通过one-hot编码映射到欧式空间,是因为,在回归,分类,聚类等机器学习算法中,特征之间距离的计算或相似度的计算是非常重要的,而我们常用的距离或相似度的计算都是在欧式空间的相似度计算,计算余弦相似性,基于的就是欧式空间。

    三 .独热编码优缺点

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

    • 缺点:当类别的数量很多时,特征空间会变得非常大。在这种情况下,一般可以用PCA来减少维度。而且one hot encoding+PCA这种组合在实际中也非常有用。

    四. 什么情况下(不)用独热编码?

    • 用:独热编码用来解决类别型数据的离散值问题,

    • 不用:将离散型特征进行one-hot编码的作用,是为了让距离计算更合理,但如果特征是离散的,并且不用one-hot编码就可以很合理的计算出距离,那么就没必要进行one-hot编码。 有些基于树的算法在处理变量时,并不是基于向量空间度量,数值只是个类别符号,即没有偏序关系,所以不用进行独热编码。 Tree Model不太需要one-hot编码: 对于决策树来说,one-hot的本质是增加树的深度。

    总的来说,要是one hot encoding的类别数目不太多,建议优先考虑。

    五. 什么情况下(不)需要归一化?

    • 需要: 基于参数的模型或基于距离的模型,都是要进行特征的归一化。

    • 不需要:基于树的方法是不需要进行特征的归一化,例如随机森林,bagging 和 boosting等。

    六. 标签编码LabelEncoder

    作用: 利用LabelEncoder() 将转换成连续的数值型变量。即是对不连续的数字或者文本进行编号例如:

     

    from sklearn.preprocessing import LabelEncoder  
    le = LabelEncoder()  
    le.fit([1,5,67,100])  
    le.transform([1,1,100,67,5])  
    

    输出: array([0,0,3,2,1])

     

    >>> le = preprocessing.LabelEncoder()  
    >>> le.fit(["paris", "paris", "tokyo", "amsterdam"])  
    LabelEncoder()  
    >>> list(le.classes_)  
    ['amsterdam', 'paris', 'tokyo']     # 三个类别分别为0 1 2  
    >>> le.transform(["tokyo", "tokyo", "paris"])   
    array([2, 2, 1]...)      
    >>> list(le.inverse_transform([2, 2, 1]))   # 逆过程  
    ['tokyo', 'tokyo', 'paris'] 
    

    限制:上文颜色的例子已经提到标签编码了。Label encoding在某些情况下很有用,但是场景限制很多。再举一例:比如有[dog,cat,dog,mouse,cat],我们把其转换为[1,2,1,3,2]。这里就产生了一个奇怪的现象:dog和mouse的平均值是cat。所以目前还没有发现标签编码的广泛使用。

    附:基本的机器学习过程

     

    我们使用sklearn进行虚线框内的工作(sklearn也可以进行文本特征提取)。通过分析sklearn源码,我们可以看到除训练,预测和评估以外,处理其他工作的类都实现了3个方法:fit、transform和fit_transform。从命名中可以看到,fit_transform方法是先调用fit然后调用transform,我们只需要关注fit方法和transform方法即可。

    transform方法主要用来对特征进行转换。从可利用信息的角度来说,转换分为无信息转换和有信息转换。无信息转换是指不利用任何其他信息进行转换,比如指数、对数函数转换等。有信息转换从是否利用目标值向量又可分为无监督转换和有监督转换。无监督转换指只利用特征的统计信息的转换,统计信息包括均值、标准差、边界等等,比如标准化、PCA法降维等。有监督转换指既利用了特征信息又利用了目标值信息的转换,比如通过模型选择特征、LDA法降维等。通过总结常用的转换类,我们得到下表:

     

    不难看到,只有有信息的转换类的fit方法才实际有用,显然fit方法的主要工作是获取特征信息和目标值信息,在这点上,fit方法和模型训练时的fit方法就能够联系在一起了:都是通过分析特征和目标值,提取有价值的信息,对于转换类来说是某些统计量,对于模型来说可能是特征的权值系数等。另外,只有有监督的转换类的fit和transform方法才需要特征和目标值两个参数。fit方法无用不代表其没实现,而是除合法性校验以外,其并没有对特征和目标值进行任何处理,Normalizer的fit方法实现如下:

     

    def fit(self, X, y=None):  
            """Do nothing and return the estimator unchanged 
            This method is just there to implement the usual API and hence 
            work in pipelines. 
            """  
            X = check_array(X, accept_sparse='csr')  
            return self  

    ==============使用示例: ==================

     

    背景:

    在拿到的数据里,经常有分类型变量的存在,如下:
    球鞋品牌:Nike、adidas、 Vans、PUMA、CONVERSE
    性别:男、女
    颜色:红、黄、蓝、绿
    However,sklearn大佬不能直接分析这类变量呀。在回归,分类,聚类等机器学习算法中,特征之间距离的计算或相似度的计算是算法关键部分,而常用的距离或相似度的计算都是在欧式空间的相似度计算,计算余弦相似性,基于的就是欧式空间。于是,我们要对这些分类变量进行哑变量处理,又或者叫虚拟变量。
    缺点:
    当类别的数量很多时,特征空间会变得非常大。在这种情况下,一般可以用PCA来减少维度。而且one hot encoding+PCA这种组合在实际中也非常有用。有些基于树的算法在处理变量时,并不是基于向量空间度量,数值只是个类别符号,即没有偏序关系,所以不用进行独热编码。Tree Model不太需要one-hot编码: 对于决策树来说,one-hot的本质是增加树的深度。
    In summary,
    要是one hot encoding的类别数目不太多,可优先考虑。

    一.pd.get_dummies()简单&粗暴

    pandas.get_dummies(data, prefix=None, prefix_sep='_', dummy_na=False, columns=None, sparse=False, drop_first=False, dtype=None)
    官网文档:
    http://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.get_dummies.html

    输入:array-like, Series, or DataFrame
    输出:DataFrame
    主要参数说明:
    data : array-like, Series, or DataFrame
    prefix : 给输出的列添加前缀,如prefix="A",输出的列会显示类似
    prefix_sep : 设置前缀跟分类的分隔符sepration,默认是下划线"_"
    一般,我们输入data就够了。如果要专门关注Nan这类东东,可设置dummy_na=True,专门生成一列数据。
    见下面的栗子:(简直不要太容易)

    import numpy as np
    import pandas as pd
    data = pd.DataFrame({"学号":[1001,1002,1003,1004],
                        "性别":["男","女","女","男"],
                        "学历":["本科","硕士","专科","本科"]})
    data
     学历学号性别
    0本科1001
    1硕士1002
    2专科1003
    3本科1004
    pd.get_dummies(data)
     学号学历_专科学历_本科学历_硕士性别_女性别_男
    0100101001
    1100200110
    2100310010
    3100401001
    pd.get_dummies(data,prefix="A")
     学号A_专科A_本科A_硕士A_女A_男
    0100101001
    1100200110
    2100310010
    3100401001
    pd.get_dummies(data,prefix=["A","B"],prefix_sep="+")
     学号A+专科A+本科A+硕士B+女B+男
    0100101001
    1100200110
    2100310010
    3100401001

    二.sklearn的崽一:LabelEncoder 将不连续的数字or文本进行编号

    sklearn.preprocessing.LabelEncoder()
    官方文档:
    https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.LabelEncoder.html

    from sklearn.preprocessing import LabelEncoder
    le = LabelEncoder()
    le.fit([1,5,67,100])
    le.transform([1,1,100,67,5])
    #输出: array([0,0,3,2,1])
    array([0, 0, 3, 2, 1], dtype=int64)
    from sklearn import preprocessing
    le = preprocessing.LabelEncoder()
    le.fit([1, 3, 3, 7])
    LabelEncoder()
    le.transform([1, 1, 3, 7]) 
    #array([0, 0, 1, 2]...)
    le.classes_   #查看分类
    #array([1, 2, 6])
    le.inverse_transform([0, 0, 1, 2])  #transform的逆向
    #array([1, 1, 2, 6])    
    array([1, 1, 3, 7])

    三.sklearn的崽二:OneHotEncoder 对表示分类的数字进行编码,输出跟dummies一样

    sklearn.preprocessing.OneHotEncoder(n_values=None, categorical_features=None, categories=None, sparse=True, dtype=<class ‘numpy.float64’>, handle_unknown=’error’)
    官方文档:
    https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html
    注意:
    输入的应该是表示类别的数字,如果输入文本,会报错的

    from sklearn.preprocessing import OneHotEncoder
    OHE = OneHotEncoder()
    OHE.fit(data)
    
    ValueError: could not convert string to float: '男'

    看到,OneHotEncoder处理不了字符串。要先用

    data3 = le.fit_transform(data["性别"])
    OHE.fit(data3.reshape(-1,1))
    OHE.transform(data3.reshape(-1,1)).toarray()
    array([[ 0.,  1.],
           [ 1.,  0.],
           [ 1.,  0.],
           [ 0.,  1.]])

    对因变量y不能用OneHotEncoder,要用LabelBinarizer。

     

    Spark ML 特征工程之 One-Hot Encoding

    参照:https://blog.csdn.net/u011622631/article/details/81562699

     

    展开全文
  • 什么是类别数据? 类别数据是一种只有标签值而没有数值的变量。 它的值通常属于一个大小固定且有限的集合。 类别变量也常被称为标称值(nominal)。 下面举例说明: 宠物(pet)变量包含以下几种值:狗(dog)、猫...

    什么是类别数据?

    类别数据是一种只有标签值而没有数值的变量。
    它的值通常属于一个大小固定且有限的集合。
    类别变量也常被称为标称值(nominal)。
    下面举例说明:

    • 宠物(pet)变量包含以下几种值:狗(dog)、猫(cat)。
    • 颜色(color)变量包含以下几种值:红(red)、绿(green)、蓝(blue)。
    • 位次(place)变量包含以下几种值:第一(first)、第二(second)和第三(third)。

    以上例子中的每个值都代表着一个不同的类别。
    有些类别彼此间存在一定的自然关系,比如自然的排序关系。
    上述例子中,位次(place)变量的值就有这种自然的排序关系。这种变量被称为序数变量(ordinal variable)。

    类别数据有什么问题?

    有些算法可以直接应用于类别数据。

    比如,你可以不进行任何数据转换,将决策树算法直接应用于类别数据上(取决于具体实现方式)。

    但还有许多机器学习算法并不能直接操作标签数据。这些算法要求所有的输入输出变量都是数值(numeric)。
    通常来说,这种限制主要是因为这些机器学习算法的高效实现造成的,而不是算法本身的限制。

    但这也意味着我们需要把类别数据转换成数值形式。如果输出变量是类别变量,那你可能还得将模型的预测值转换回类别形式,以便在一些应用中展示或使用它们。

    更多信息参考:
    https://juejin.im/post/5d15840e5188255c23553204

    展开全文
  • 机器学习算法,常会遇到分类特征是离散的,无序的。例如:性别有男、女,城市有北京,上海,深圳等。 性别特征: ["男","女"] => 0,1 地区特征: ["北京","上海,"深圳"] => 0,1,2 工作特征: [...
  • onehotencoder(独热编码) # dataset数据集 product_tags需要编码的特征列(假设第一列) product_tags = dataset.iloc[:, :1] from sklearn.preprocessing import OneHotEncoder enc = OneHotEncoder...
  • 机器学习初级篇8——数据的编码方式一.变量的编码方式1.序号编码2.独热编码3.二进制编码3.哑变量编码方式二.哑变量编码与独热编码的区别与联系三.连续值的离散化为什么会提升模型的非线性能力? 类别型特征( ...
  • 机器学习 数据预处理之特征编码(归纳整理版)

    千次阅读 多人点赞 2021-04-23 15:40:51
    由于机器学习算法都是在矩阵上执行线性代数计算,所以参加计算的特征必须是数值型的,对于非数值型的特征需要进行编码处理。对于离散型数据的编码,我们通常会使用两种方式来实现,分别是标签编码和独热编码 import ...
  • Sklearn独热编码one hot 编码,preprocessing.OneHotEncoder()使用
  • 机器学习中的特征工程总结!

    千次阅读 2020-10-17 20:13:44
    机器学习项目,关注点变成了特征表示。也就是说,开发者通过添加和改善特征来调整模型。“Garbage in, garbage out”。对于一个机器学习问题,数据和特征往往决定了结果的上限,而模型、算法的选择及优化则是在...
  • 机器学习编码方式总结

    千次阅读 2019-10-21 13:14:05
    这里讲一下onehot独热编码和labelencoding编码。 先说一下独热编码 实现方式1:pd.get_dummies()函数 官方api: pandas.get_dummies(data,prefix=None,prefix_sep='_',dummy_na=False,columns=None,sparse=False...
  • 数据科学家Rakshith Vasudev简要解释了one hot编码这一机器学习中极为常见的技术。 你可能在有关机器学习的很多文档、文章、论文接触到“one hot编码”这一术语。本文将科普这一概念,介绍one hot编码到底是...
  • 1、独热编码(OneHotEncoder) 有一些特征并不是以连续值的形式给出。例如以下三个特征属性: 人的性别 [“male”, “female”], 来自的国家 [“from Europe”, “from US”, “from Asia”], 使用的浏览器[...
  • 机器学习算法,常会遇到分类特征是离散的,无序的。例如:性别有男、女,城市有北京,上海,深圳等。 性别特征: [“男”,“女”] => 0,1 地区特征: [“北京”,"上海,“深圳”] => 0,1,2 工作特征...
  • 为什么要用独热编码?什么情况下可以用独热编码?以及和其他几种编码方式的区别。 首先了解机器学习中的特征类别:连续型特征和离散型特征 拿到获取的原始特征,必须对每一特征分别进行归一化,比如,特征A的...
  • 一、为什么要独热编码? 独热编码(是因为大部分算法是基于向量空间的度量来进行计算的,为了使非偏序关系的变量取值不具有偏序性,并且到原点是等距的。使用one-hot编码,将离散特征的取值扩展到了欧式空间,离散...
  • One-Hot编码,又称为一位有效编码,主要是采用N位状态寄存器来对N个状态进行编码,每个状态都由他独立的寄存器位,并且在任意时候只有一位有效。 One-Hot编码是分类变量作为二进制向量的表示。这首先要求将分类值...
  • 机器学习 数据预处理之标签编码

    千次阅读 2020-02-13 15:08:37
    1、什么是标签编码 将字符型的特征映射整数(将字符串转换整数)但没有被广泛使用因为求平均值之类的数据会出现问题(不过具体需求具体分析) 有[dog,cat,dog,mouse,cat],我们把其转换[1,2,1,3,2]。这里就...
  • 文章目录独热编码和 LabelEncoder标签编码1、介绍2、代码测试2.1 导入相关库2.2 读取数据2.3 查看缺失值2.4 利用位数填补年龄2.5 删除Embarked的缺失行2.6 查看每个特征的类别2.7 对标签进行LabelEncoder编码2.8 ...
  • 机器是看不懂绝大部分原始数据的,为了让让机器看懂,需要将原始数据进行预处理。 引入模块和数据 import numpy as np from sklearn import preprocessing data = np.array([[3,-1.5,2,-5.4], [0,4,0.3,2.1]...
  • 我们在处理机器学习数据的时候经常会见到离散特征的数据,例如水果的颜色、人名等,离散特征的挑战在于不是连续的方式,这导致很难用数字去描述,所以引入独热编码进行处理。 独热编码,One-Hot编码,又称为一...
  • 特征工程是数据科学模型开发的重要组成部分之一。数据科学家把大部分时间花在数据...什么是独热编码? 独热编码,又称虚拟编码,是一种将分类变量转换数值向量格式的方法。每个类别在数值向量中都有自己的列或特征.
  • 本文转载自 机器学习实战:数据预处理之独热编码(One-Hot Encoding) 问题由来 在很多机器学习任务,特征并不总是连续值,而有可能是分类值。 例如,考虑一下的三个特征: ["male", "...
  •   由于机器学习模型的输入必须是数字类型的数据,所以有必要在数据预处理的过程,完成对非数字类型的数据或者说离散而又无序的数据进行特征编码。在数据的预处理的过程,需要对类别特征进行编码。因为类别特征...
  • 1. 为什么使用 one-hot 编码? 问题: 在机器学习算法,我们经常会遇到分类特征,例如:人的性别有男女,祖国有中国,美国,法国等。 这些特征值并不是连续的,而是离散的,无序的。 目的: 如果要作为...
  • 机器学习标签编码

    2019-09-18 19:15:42
    二值编码独热编码 定义 :One-Hot Encoding即One-Hot 编码,也称独热编码,又称一位有效编码,其方法是使用N位状态...应用场景:由于分类器往往默认数据数据是连续的,并且是有序的,但是在很多机器学习任务,存在...
  • 文章目录一、 Index编码二、 OneHot编码独热编码优缺点什么情况下(不)用独热编码什么情况下(不)需要归一化?三、 Multiple编码如何使用Multiple编码呢?四、 编码比较参考文献 一、 Index编码 用来对离散的类型...
  • 机器学习 数据预处理之独热编码(One-Hot Encoding) 问题由来 在很多机器学习任务,特征并不总是连续值,而有可能是分类值。 例如,考虑一下的三个特征: ["male","female"] ["from Europe","from US".....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 20,380
精华内容 8,152
关键字:

机器学习中为什么热编码