数据转换
2021-9-2
| 2023-8-6
0  |  阅读时长 0 分钟
type
status
date
slug
summary
tags
category
icon
password
Property
 
 
有些特征的默认取值比较特殊,一般需要做了处理后才能用于算法。
对于时间原始特征,,比如显示20180519,这样的值一般没办法直接使用,处理方法有很多。 第一种是使用连续的时间差值法,即计算出所有样本的时间到某一个未来时间之间的数值差距,这样这个差距是UTC的时间差,从而将时间特征转化为连续值。第二种方法是根据时间所在的年,月,日,星期几,小时数,将一个时间特征转化为若干个离散特征,这种方法在分析具有明显时间趋势的问题比较好用。第三种是权重法,即根据时间的新旧得到一个权重值。比如对于商品,三个月前购买的设置一个较低的权重,最近三天购买的设置一个中等的权重,在三个月内但是三天前的设置一个较大的权重。
对地理特征,比如“广州市天河区XX街道XX号”,这样的特征应该如何使用呢?处理成离散值和连续值都是可以的。如果是处理成离散值,则需要转化为多个离散特征,比如城市名特征,区县特征,街道特征等。但是如果需要判断用户分布区域,则一般处理成连续值会比较好,这时可以将地址处理成经度和纬度的连续特征。
 

离散特征的连续化处理

有很多机器学习算法只能处理连续值特征,不能处理离散值特征,比如线性回归,逻辑回归等。那么想使用逻辑回归,线性回归时需要将离散特征连续化处理。
最常见的离散特征连续化的处理方法是独热编码one-hot encoding。处理方法其实比较简单,比如某特征的取值是高,中和低,那么可以创建三个取值为0或者1的特征,将高编码为1,0,0这样三个特征,中编码为0,1,0这样三个特征,低编码为0,0,1这样三个特征,之前的一个特征被转化为了三个特征。sklearn的OneHotEncoder可以帮我们做这个处理。
 
独热编码的好处:
  • 解决了分类器不好处理属性数据的问题,让特征之间的距离计算更加合理
    • 比如共有3个类,那么就有3个编码:[1 0 0 ],[0 1 0 ],[0 0 1 ]
      为什么不直接用1,2,3来表示3个类别呢?一个很重要的原因在于计算loss时的问题。loss一般用距离来表示, 如果用1~3来表示,那么1和2的距离时1,而1和3的距离时2,但是按道理1和2、1和3的距离应该一样。 如果用one hot编码表示,那么1和2的距离跟1和3的距离时一样的。
  • 在一定程度上也起到了扩充特征的作用,比如性别本身是一个特征,经过one hot编码以后,就变成了男或女两个特征。
  • 将离散特征的取值扩展到了欧式空间,离散特征的某个取值就对应欧式空间的某个点。
 
什么时候不适合编码呢?
  • 因为编码的目的是使离散数据变得有序,所以如果特征本身有序(可以计算),则不需要编码。
  • Tree Model 没有特征大小的概念,不太需要编码,如GBDT处理高维稀疏矩阵的时候效果并不好,即使是低维的稀疏矩阵也未必比SVM好
 
第二个方法是特征嵌入embedding,一般用于深度学习中。比如对于用户的ID这个特征,如果要使用独热编码,则维度会爆炸,如果使用特征嵌入就维度低很多了。对于每个要嵌入的特征,会有一个特征嵌入矩阵,这个矩阵的行很大,对应该特征的数目。比如用户ID,如果有100万个,那么嵌入的特征矩阵的行就是100万。但是列一般比较小,比如可以取20。这样每个用户ID就转化为了一个20维的特征向量,进而参与深度学习模型。
此外,在自然语言处理中,可以用word2vec将词转化为词向量,进而可以进行一些连续值的后继处理。
 

离散特征的离散化处理

离散特征有时间也不能直接使用,需要先进行转化。比如最常见的,如果特征的取值是高,中和低,那么就算需要的是离散值,也是没法直接使用的。
对于原始的离散值特征,最常用的方法也是独热编码。
第二种方法是虚拟编码dummy coding,它和独热编码类似,但是它的特点是,如果我们的特征有N个取值,它只需要N-1个新的0,1特征来代替,而独热编码会用N个新特征代替。比如一个特征的取值是高,中和低,那么我们只需要两位编码,比如只编码中和低,如果是1,0则是中,0,1则是低。0,0则是高了。目前虚拟编码使用的没有独热编码广,因此一般有需要的话还是使用独热编码比较好。
此外,有时候可以对特征进行研究后做一个更好的处理。比如,研究商品的销量对应的特征。里面有一个原始特征是季节春夏秋冬。可以将其转化为淡季和旺季这样的二值特征,方便建模。当然有时候转化为三值特征或者四值特征也是可以的。
对于分类问题的特征输出,一般需要用sklearn的LabelEncoder将其转化为0,1,2,...这样的类别标签值。
 

连续特征的离散化处理

对于连续特征,有时候也可以将其做离散化处理。这样特征变得高维稀疏,方便一些算法的处理。
对常用的方法是根据阈值进行分组,比如根据连续值特征的分位数,将该特征分为高,中和低三个特征。将分位数从0-0.3的设置为高,0.3-0.7的设置为中,0.7-1的设置为高。
当然还有高级一些的方法。比如使用GBDT。在LR+GBDT的经典模型中,就是使用GDBT来先将连续值转化为离散值。那么如何转化呢?比如我们用训练集的所有连续值和标签输出来训练GBDT,最后得到的GBDT模型有两颗决策树,第一颗决策树有三个叶子节点,第二颗决策树有4个叶子节点。如果某一个样本在第一颗决策树会落在第二个叶子节点,在第二颗决策树落在第4颗叶子节点,那么它的编码就是0,1,0,0,0,0,1,一共七个离散特征,其中会有两个取值为1的位置,分别对应每颗决策树中样本落点的位置。
在sklearn中,可以用GradientBoostingClassifier的 apply方法很方便的得到样本离散化后的特征,然后使用独热编码即可。
 
 
 
 

字典特征抽取

字典特征抽取,就是针对一系列字典中的数据进行抽取
result返回的是一个sparse矩阵,是scipy库中的数据类型。sparse的特点是可以节省内存,因为他只会记录result.toarray()这个列表中哪些位置出现了非0的值,以及具体的值。
常用方法:
  • fit_transform(X):应用并转化列表X
  • inverse_transform:将numpy数组或者sparse矩阵转换成列表。
  • get_feature_names():获取fit_transform后的数组中,每个位置代表的意义。
  • toarray():将sparse矩阵转换成多维数组。
 
One-hot编码:
机器学习的算法是没法针对字符串进行运算的。所以需要将字符串转换成数据类型。比如fruits的数据,转换成One-hot编码就是:
苹果
橘子
菠萝
price
1
0
0
5
0
1
0
5.9
0
0
1
9.9
toarray()返回回来的就是one-hot编码的数组。
 
 
 

文本特征抽取

文本的特征提取应用于很多方面,比如说文档分类、垃圾邮件分类和新闻分类。那么文本分类是通过词是否存在、以及词的概率(重要性)来表示。

文档中词出现的个数

文本特征抽取,使用的是sklearn.feature_extraction.text.CountVectorizer
其中,单个字母比如i是不会被当作一个单词进行抽取的。并且他的抽取规则是按标点符合或者是空格进行划分。因此这种默认的分词方式是不符合中文需求的
 

中文分词

如果想要统计中文中某些词出现的次数,那么先要对中文进行分词,这时候就需要用到一个第三方的开源库jieba分词,用法跟之前是一样的:
 

tf-idf文本抽取

tf-idf(英语:tf(term frequency) idf(inverse document frequency))是一种用于信息检索与文本挖掘的常用加权技术。tf-idf是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。假如现在总共有1000个文档,“共享”这个词在500个文档中出现了,并且A文档中总共有800个词,“共享”出现了12次,那么tf-idf的值为:(12/800)*lg(1000/500)
  • Scikit-Learn
  • 不平衡分类的k折交叉验证编码分类数据
    目录