为什么要用onehot:

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

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

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

3.将离散型特征使用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).即每两个工作之间的距离是一样的,显得更合理。

4.对离散型特征进行one-hot编码是为了让距离的计算显得更加合理。

5.将离散型特征进行one-hot编码的作用,是为了让距离计算更合理,但如果特征是离散的,并且不用one-hot编码就可以很合理的计算出距离,那么就没必要进行one-hot编码,比如,该离散特征共有1000个取值,我们分成两组,分别是400和600,两个小组之间的距离有合适的定义,组内的距离也有合适的定义,那就没必要用one-hot 编码
离散特征进行one-hot编码后,编码后的特征,其实每一维度的特征都可以看做是连续的特征。就可以跟对连续型特征的归一化方法一样,对每一维特征进行归一化。比如归一化到[-1,1]或归一化到均值为0,方差为1

 

其他解释:

在分类和聚类运算中我们经常计算两个个体之间的距离,对于连续的数字(Numric)这一点不成问题,但是对于名词性(Norminal)的类别,计算距离很难。即使将类别与数字对应,例如{‘A’,‘B’,‘C’}与[0,1,2]对应,我们也不能认为A与B,B与C距离为1,而A与C距离为2。独热编码正是为了处理这种距离的度量,该方法认为每个类别之间的距离是一样的。该方法将类别与向量对应,例如{‘A’,‘B’,‘C’}分别与[1,0,0],[0,1,0],[0,0,1]对应,注意现在各个类别之间的ß欧式距离是相同的。

独热编码即 One-Hot 编码,又称一位有效编码,其方法是使用N位状态寄存器来对N个状态进行编码,每个状态都由他独立的寄存器位,并且在任意时候,其中只有一位有效。

这样做的好处主要有:

  1. 解决了分类器不好处理属性数据的问题
  2. 在一定程度上也起到了扩充特征的作用

------------------------------------------------------------------------------------------------

关于独热编码和哑变量的区别:

基于sklearn 的one hot encoding

独热编码在数据处理中的作用

独热编码和哑变量的不同作用

 

哑变量与独热编码的区别:

本质上差不多,哑变量常用于回归模型,one-hot在任何模型都可以用

哑变量在pandas的get_dummy方法,one-hot在sklearn,就是不同的库from sklearn.preprocessing import OneHotEncoder

 

最常用的编码:应该还是one-hot用的多,pandas机制问题,它需要在内存中把数据集都读入进来,要是数据量大的话,太消耗资源,one-hot可以读数组,因此大规模数据集很方便

#-*- coding:utf-8 -*-
#onehot
from sklearn import preprocessing  
import pandas as pd
import numpy as np
enc = preprocessing.OneHotEncoder()  #相关onehot的包

#独热编码
def set_OneHotEncoder(data,colname,start_index,end_index):
    '''
    data -- [[1,2,3,4,7],[0,5,6,8,9]]
    start_index -- 起始列位置索引
    end_index -- 结束列位置索引. 如start_index为1,end_index为3,则取出来的为[[2,3,4],[5,6,8]]
    '''
    #if type(data) == pandas.core.frame.DataFrame:
        #data = np.array(data).tolist()
    if type(data) != list:
        return  'Error dataType, expect list but ' + str(type(data))
    _data,_colname =[line[:start_index] for line in data],colname[:start_index]
    data_,colname_ = [line[end_index+1:] for line in data],colname[end_index+1:]
    
    data = [line[start_index:end_index+1] for line in data]
    data = pd.DataFrame(data)
    data.columns = colname[start_index:end_index+1]
    enc.fit(data)
    x_ = enc.transform(data).toarray() #已生成
    x_ = [list(line) for line in x_]
    #加栏目名
    new_columns = []
    for col in data.columns:
        dd = sorted(list(set(list(data[col])))) #去重并根据升序排列
        for line in dd:
            new_columns.append(str(col)+'#'+str(line))

    end_x = list(map(lambda x,y,z:x+y+z,_data,x_,data_))
    end_columns = list(_colname)+new_columns+list(colname_)
    x__ = pd.DataFrame(end_x,columns = end_columns)
    return x__ #返回数据框形式

#哑变量
# 对性别、职业等因子变量,构造其哑变量(虚拟变量)
def set_dummies(data, colname):
    for col in colname:
        data[col] = data[col].astype('category')#转换成数据类别类型,pandas用法
        dummy = pd.get_dummies(data[col])  #get_dummies为pandas里面求哑变量的包
        dummy = dummy.add_prefix('{}#'.format(col)) #add_prefix为加上前缀
        data.drop(col,axis = 1,inplace = True)
        data = data.join(dummy) #index即为userid,所以可以用join
    return data


if __name__ == '__main__':

    xlst = [[0,2,1,3,4,5],[9,1,1,4,5,6],[8,9,2,3,4,6],[8,11,23,56,78,99]]
    x = pd.DataFrame(xlst)
    x.columns = ['a','b','c','d','e','f']
    y = [1,0,1,1,1]
    print('----------------------------以下为onehot----------------------------------')
    print(set_OneHotEncoder(xlst,x.columns,2,4))
    print('----------------------------以下为哑变量----------------------------------')
    print(set_dummies(x,x.columns))