python使用H265格式编码 python onehot编码_python使用H265格式编码


在半研墨:数据分析思考笔记(1):用特征选择方法优化模型|python数据挖掘一文中有说到在数据建模过程中,关于特征工程中特征选择的一些思考。

今天,我们再来聊聊关于特征处理中数据编码问题的一些思考。

某些机器学习算法和模型只能接受定量特征的输入,需要将定性特征转换为定量特征。 sklearn中的数据预处理preproccessing库提供了相关的处理方法:

OneHotEncoder(),

LabelEncoder(),

LabelBinarizer(),

MultiLabelBinarizer()

Binarizer

OneHotEncoder(独热编码)

为什么能使用one hot?

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

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

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

比如,有一个离散型特征,代表工作类型,该离散型特征,共有三个取值,不使用one-hot编码,其表示分别是x_1 = (1), x_2 = (2), x_3 = (3)。两个工作之间的距离是,d(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 编码的优点:

1.能够处理非连续型数值特征。

2.在一定程度上也扩充了特征。比如性别本身是一个特征,经过one hot编码以后,就变成了男或女两个特征。


#使用onehot编码
import pandas as pd 
df2 = pd.DataFrame({'id': [3566841, 6541227, 3512441],
                    'sex': [1, 2, 2],
                    'level': [3, 1, 2]})


#输出df2
	id	level	sex
0	3566841	3	1
1	6541227	1	2
2	3512441	2	2

from sklearn.preprocessing import OneHotEncoder #导入OneHotEncoder
id_data = df2.values[:, :1]  # 获得ID列
transform_data = df2.values[:, 1:]  # 指定要转换的列
enc = OneHotEncoder()  # 建立模型对象
df2_new = enc.fit_transform(transform_data).toarray()  # 转换

# 查看df2_new
array([[ 0.,  0.,  1.,  1.,  0.],
       [ 1.,  0.,  0.,  0.,  1.],
       [ 0.,  1.,  0.,  0.,  1.]])

df2_all = pd.concat((pd.DataFrame(id_data),pd.DataFrame(df2_new)),axis=1)#组合数据帧

# 输出df2_all,可以看到特征由原来的3个变成了现在的6个
	0	0	1	2	3	4
0	3566841	0.0	0.0	1.0	1.0	0.0
1	6541227	1.0	0.0	0.0	0.0	1.0
2	3512441	0.0	1.0	0.0	0.0	1.0


# 再来看下不使用onehot编码,使用自定义转
import pandas as pd
df = pd.DataFrame({'id': [3566841, 6541227, 3512441],
                   'sex': ['male', 'Female', 'Female'],
                   'level': ['high', 'low', 'middle']})

# 输出df
	id	level	sex
0	3566841	high	male
1	6541227	low	Female
2	3512441	middle	Female


df_new = df.copy() #复制新的一份数据框用来存储转换结构
for col_num, col_name in enumerate(df):  # 循环读出每个列的索引值和列名
    col_data = df[col_name]  # 获得每列数据
    col_dtype = col_data.dtype  # 获得每列dtype类型
    if col_dtype == 'object':  # 如果dtype类型是object(非数值型),执行条件
        df_new = df_new.drop(col_name, axis=1)  # 删除df数据框中要进行标志转换的列
        value_sets = col_data.unique()  # 获取分类和顺序变量的唯一值域
        for value_unique in value_sets:  # 读取分类和顺序变量中的每个值
            col_name_new = col_name + '_' + value_unique  # 创建新的列名,使用原标题+值的方式命名
            col_tmp = df.iloc[:, col_num]  # 获取原始数据列
            new_col = (col_tmp == value_unique)  # 将原始数据列与每个值进行比较,相同为True,否则为False
            df_new[col_name_new] = new_col  # 为最终结果集增加新列值

# 输出df_new,可以看到level,sex分别都由1个特征变成了3个特征
        id  level_high  level_low  level_middle  sex_male  sex_Female
0  3566841        True      False         False      True       False
1  6541227       False       True         False     False        True
2  3512441       False      False          True     False        True


使用one hot 编码注意点:

a,OneHotEncoder 的输入必须是 2-D array


from sklearn.preprocessing import OneHotEncoder
#data.cloumn1 返回的 Series 本质上是 1-D array
#所以要改成data[['cloumn1']] 2-D array再传入
OneHotEncoder(sparse = False).fit_transform( data[['cloumn1']])


b,OneHotEncoder无法直接对字符串型的类别变量编码。

OneHotEncoder无法直接对字符串型的类别变量编码,所以如果想利用OneHotEncoder对字符串型类别变量的支持,所以一般都采用曲线救国的方式:


from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import LabelEncoder
#先用 LabelEncoder() 转换成连续的数值型变量
a = LabelEncoder().fit_transform(data['cloumn'])
#再用 OneHotEncoder() 二值化
OneHotEncoder( sparse=False ).fit_transform(a.reshape(-1,1)) # 注意: 这里把 a 用 reshape 转换成 2-D array


c,离散特征如果是数值型变量,则数值变量的取值之间没有大小的意义,如果是分类变量,则是无序变量。

d,对于每一个特征,如果它有m个可能值,那么经过独热编码后,就变成了m个二元特征。并且,这些特征互斥,每次只有一个激活。因此,数据会变成稀疏的。


#示例
>>> data=np.array([[1,0,3.25],
               [0,0,5.2],
               [2,1,3.6]])
>>> enc=OneHotEncoder(categorical_features=np.array([0,1]),n_values=[3,2])
>>> enc.fit(data)
>>> enc.transform(data).toarray()
array([[ 0.  ,  1.  ,  0.  ,  1.  ,  0.  ,  3.25],
       [ 1.  ,  0.  ,  0.  ,  1.  ,  0.  ,  5.2 ],
       [ 0.  ,  0.  ,  1.  ,  0.  ,  1.  ,  3.6 ]])


categorical_features是需要独热编码的列索引,

n_values是对应categorical_features中各列下类别的数目,

注意这里两个值可以不指定,直接使用fit_transform函数也可以,程序将统计各列中类别的多少。但是只对整数有效,对浮点数会转换为整数之后再统计,也就是对于3.5和3.6默认都是3,也就是同一类。

如果指定了这两个参数,就要对未转换的数据提出要求,各列必须是以{0,1,2,3,4......}来编码,而不能以{1,10,100,200.........}这种随意的方式来编码。 否则会出现数组越界的错误。

LabelEncode(标签编码)

LabelEncoder是一个可以用来将标签规范化的工具类,它可以将标签的编码值范围限定在[0,n_classes-1]. 当然,它也可以用于非数值型标签的编码转换成数值标签(只要它们是可哈希并且可比较的):


#示例
>>> le = preprocessing.LabelEncoder()
>>> le.fit(["paris", "paris", "tokyo", "amsterdam"])
LabelEncoder()
>>> list(le.classes_)
['amsterdam', 'paris', 'tokyo']
>>> le.transform(["tokyo", "tokyo", "paris"])
array([2, 2, 1])
>>> list(le.inverse_transform([2, 2, 1]))
['tokyo', 'tokyo', 'paris']


注:示例来源于官方文档

LabelEncoder设计为只支持 1-D array,也使得它无法像上面 OneHotEncoder 那样批量接受多列输入。

LabelBinarizer(标签二值化)

LabelBinarizer是一个用来从多类别列表创建标签矩阵的工具类:


>>> from sklearn import preprocessing
>>> lb = preprocessing.LabelBinarizer()
>>> lb.fit([1, 2, 6, 4, 2])
LabelBinarizer(neg_label=0, pos_label=1, sparse_output=False)
>>> lb.classes_
array([1, 2, 4, 6])
>>> lb.transform([1, 6])
array([[1, 0, 0, 0],
       [0, 0, 0, 1]])


注:示例来源于官方文档

无论 LabelEncoder() 还是 LabelBinarizer(),他们在 sklearn 中的设计初衷,都是为了解决标签 y 的离散化,而非输入 X。

所以他们的输入被限定为 1-D array,这恰恰跟 OneHotEncoder() 要求输入 2-D array 相左。因此我们使用的时候要格外小心。

Binarization(特征二值化)

特征二值化将数值特征用阈值过滤得到布尔值

公式表达如下:


python使用H265格式编码 python onehot编码_python数据预处理_02


>>> X = [[ 1., -1.,  2.],
...      [ 2.,  0.,  0.],
...      [ 0.,  1., -1.]]

>>> binarizer = preprocessing.Binarizer().fit(X)  # fit does nothing
>>> binarizer
Binarizer(copy=True, threshold=0.0)

>>> binarizer = preprocessing.Binarizer(threshold=1.1)
>>> binarizer.transform(X)
array([[ 0.,  0.,  1.],
       [ 1.,  0.,  0.],
       [ 0.,  0.,  0.]])


注:示例来源于官方文档