1.1.数值空间

    所有原始数据转换成数值特征,机器就可识别了。考虑点:

  1. 量级」是正还是负?还是某个粒度上的量级?

  2. 尺度」最大值和最小值多少?是否跨多个数量级?

  3. 分布」分布可以表示出一个特定值出现的概率。

1. 标量、向量、空间

  • 标量:单独的数值型特征称为标量。

  • 向量:标量的有序列表称为向量。

  • 向量空间:向量构成的完整空间为向量空间。

大多数机器学习中模型输入都是数值向量。

    如上图,方向d1d1中向量有一个值1,d2d2中向量中有一个值-1,则坐标轴中vv就是这两个值对应的向量。在数据中,抽象向量和它的特征维度可能相关,如此处的1, -1可表示两个特征维度,于是所有数据集合在特征空间中可表示为点云。

2. 处理计数

2.1. 二值化

    当数据中呈现出极端值时,模型有时候会被异常值带偏,所以原始计数并不是衡量结果的强壮指标。如听音乐的用户喜好:有些人会无限循环听最喜欢的歌曲,有些人只是特定情形下欣赏音乐,不能单纯认为听20次的人喜欢程度是挺10次人的两倍——这就是原始计数的问题。

    更强壮的表示方法是将计数二值化,把所有大于1的值视为1(如上述示例中若设定大于1次就认为用户喜欢,那么count>10count > 10count>20count > 20都是一致的)——所以二值化目标变量是一个简单又强壮的衡量指标。这种方法是在修改模型的目标变量,它不是特征也不是输入,但为了保证最终结果,有时需要修改目标变量。

2.2. 区间量化(分箱)

    例子

# book/feature/source/0202.yelp.py
import pandas as pd
import json

# 加载商家数据
biz_file = open("data/yelp_academic_dataset_business.json")
biz_df = pd.DataFrame([json.loads(x) for x in biz_file.readlines()])
biz_file.close()

import matplotlib.pyplot as plt
import seaborn as sns

sns.set_style("whitegrid")
fig, ax = plt.subplots()
biz_df['review_count'].hist(ax = ax, bins=100)
ax.set_yscale('log')
ax.tick_params(labelsize=14)
ax.set_xlabel('Review Count', fontsize = 14)
ax.set_ylabel('Occurrence', fontsize=14)
plt.show()

    最终绘图:

    如果使用协同过滤方法预测某用户给商家的打分,点评数量是和好的指标,和上个问题一样,是使用原始点评数,还是对其进一步处理?看分布极端化现象依旧比较严重,另外的一种方法就是区间量化。将上述分布中的点评数量分到多个箱子中,去掉实际的计数。——这种方法会将连续型数值映射为离散类型,而这些离散类型是有序分箱,它可测量密度。两种分箱法:

  • 固定跨度分箱(等宽)

  • 自适应分箱(等深)

2.2.1. 固定宽度

    固定宽度分箱,每个分箱中会包含一个具体范围内的数据,这些范围

  • 可人工定义

  • 可让系统自动分段

  • 可是线性的

  • 也可是指数性的

    若数值横跨多个数量级,可以按照10的幂(或其他数量的幂)进行分箱,这种分箱是呈指数增长的,要将计数映射到分箱则需要取计数值的对数。

# book/feature/source/0203.box.py
import numpy as np

# 生成20个随机数,均匀分布0~99之间
small_counts = np.random.randint(0,100,20)
print(small_counts)

# 除法映射到间隔均匀的分布中,每个分箱取值范围都是0~9
ret1 = np.floor_divide(small_counts, 10)
print(ret1)

# 横跨若干数量级的计数值数组
large_counts = [296,8286,64011,80,3,725,867,2215,7689,11495,91897,
                44,28,7971,926,122,22222]
# 通过对数函数映射到指数宽度分箱
ret2 = np.floor(np.log10(large_counts))
print(ret2)

2.2.2. 分位数分箱

    固定宽度分箱有可能导致计数值产生无数据的空箱子!解决该方法可使用分位数分箱——这种方法将数据划分成相等若干等分数值,使用分位数使得数据不会出现偏斜。

# book/feature/source/0204.quantile.py
import pandas as pd
import json

biz_file = open("data/yelp_academic_dataset_business.json")
biz_df = pd.DataFrame([json.loads(x) for x in biz_file.readlines()])
deciles = biz_df['review_count'].quantile([
    .1, .2, .3, .4, .5, .6, .7, .8, .9
])
# 在直方图上绘图
import matplotlib.pyplot as plt
import seaborn as sns

sns.set_style("whitegrid")
fig, ax = plt.subplots()
for pos in deciles:
    handle = plt.axvline(pos, color='r')
    ax.legend([handle], 'deciles', fontsize=14)
biz_df['review_count'].hist(ax=ax, bins=100)
ax.set_xscale('log')
ax.set_yscale('log')
ax.tick_params(labelsize=14)
ax.set_xlabel('Review Count', fontsize=14)
ax.set_ylabel('Occurrence', fontsize=14)
plt.show()

    根据输出信息可以看到自适应分箱的结果(红线)。

2.3. 对数变换

    对数函数是指数函数的反函数,它的定义如:loga(ax)=x\log_a(a^x) = x,其中aa是正常数,xx可以是任意正数。对数函数可以对大数值的范围进行压缩,对小数值的范围进行扩展,xx越大,log(x)\log(x)增长得越慢。

    对具有重尾分布的正数值,对数变换是非常强大的工具,它压缩了分布高端的长尾,使之成为较短的尾部,并将低端扩展为更长的头部。如果使用特征使用对数变换,可以为线性模型在输入特征空间的低端值赢得更多“呼吸空间”。

2.3.1. 指数变换:对数变换推广

    指数变换是一个变换族,对数变换只是它的一种特例,二者都是方差稳定化变换。泊松分布是一种重尾分布,它的方差等于均值,它质心越大,方差就越大,重尾程度也越大。指数变换可以改变变量分布,让它不依赖于均值:X~=X\widetilde{X} = \sqrt{X}趋近常数而不等于均值。

    平方根变换和对数变换都可推广成Box-Cox变换:

x~={xλ1λ,(λ0)ln(x),(λ=0)\widetilde{x} = \left\{ \begin{aligned} & \frac{x^{\lambda} - 1}{\lambda}, (\lambda \neq 0) \\ & \ln{(x)}, (\lambda = 0) \end{aligned} \right.

λ<1,λ>1\lambda < 1 , \lambda > 1

    λ<1\lambda < 1可以压缩高端值,λ>1\lambda > 1则相反。只有数据为正时Box-Cox公式才有效,如果为负数则加上常数进行平移。

概率图(probplot)用来比较数据的实际分布和理论分布,本质上是一种表示实测分位数和理论分位数的关系散点图。

2.4. 特征缩放/归一化

    特征缩放会改变特征的尺度,有些人将它称为归一化。基于距离运算的模型对特征尺度比较敏感,基于树计算的模型对特征尺度不敏感,特征缩放通常会对每个特征独立运行。

2.4.1. Min-Max缩放

    条件:

  • xx是一个独立特征值

  • min(x)\min{(x)}max(x)\max{(x)}分别表示这个特征的最小值和最大值

    Min-Max缩放可以将所有特征值压缩(扩展)到[0,1]的区间,公式如下:

x~=xmin(x)max(x)min(x)\widetilde{x} = \frac{x - \min{(x)}}{\max{(x)} - \min{(x)}}

2.4.2. 标准化/方差缩放

    又称Z-Score标准化,公式:

x~=xxˉvar(x)=xixˉσ(X)\widetilde{x} = \frac{x - \bar{x}}{\sqrt{var(x)}} = \frac{x_i - \bar{x}}{\sigma(X)}

    先减去特征的均值,再除以方差,所以称为方差缩放,缩放后的特征均值为0,方差为1。

不要在稀疏数据中执行Min-Max或Z-Score标准化,这两个方法都会从原始特征中减去一个量:Min-Max中,这个平移量是当前特征中的最小值,Z-Score中,这个平移量是均值;如果平移量不为0,意味着这两种变换会将一个多数元素为0的稀疏特征向量转换成密集向量。——这样做会带来非常大的计算负担,如词袋模型,大部分分类算法针对这部分内容都执行了优化。

2.4.3. l2l^2归一化

    这种归一化操作是将初始特征值除以一个l2l^2范数的量,l2l^2又称为欧几里得范数,定义如下:

x~=xx2\widetilde{x} = \frac{x}{||x||_2}

    l2l^2是坐标空间中向量长度的测量,它可以根据毕达哥拉斯定理导出:

x2=x12+x22+...+xm2)||x||_2 = \sqrt{x_1^2 + x_2^2 + ... + x_m^2)}

    l2l^2先对所有数据点中特征值平方求和,然后计算平方根。经过这种归一化后,特征列的范数就是1,最后注意此处归一化使用的是数据空间,而不是特征空间

缩放是乘以一个常数,归一化可以包含多种操作,注意二者区别,并且特征缩放并不会改变单个特征的分布形状(只改变尺度)。

2.5. 交互特征

    两个特征的乘积可以组成一对简单的交互特征,这种关系可使用逻辑符号AND类比。简单的线性模型使用独立特征来预测结果:

y=w1x1+w2x2+...+wnxny = w_1x_1 + w_2x_2 + ... + w_nx_n

    将该模型推广,使得它包含输入特征的两两组合:

y=w1x1+w2x2+...+wnxn+w1,1x1x1+w1,2x1x2+w1,3x1x3+...y = w_1x_1 + w_2x_2 + ... + w_nx_n + w_{1,1}x_1x_1 + w_{1,2}x_1x_2 + w_{1,3}x_1x_3 + ...

    如此就可以捕获特征之间的交互作用,因此这些特征称为交互特征,如果x1x_1x2x_2是二值特性,那么乘积就是x1&x2x_1 \And x_2。交互特征原理很简单,但计算代价会很高,一旦线性模型出现交互特征,那么训练时间和评分时间会从O(n)O(n)增加到O(n2)O(n^2)

2.6. 特征选择

    精简掉无用特征,降低模型复杂度,最终目的得到一个简约模型,不降低预测准确率或影响不大的前提下提高计算速度。

不是为了减少训练时间,而是为了减少模型评分时间。

    分类:

  • 过滤式:除去那些不太可能对模型有用的特征,成本比较低廉,但不考虑要使用的模型,因此有可能无法为模型选择出正确的特征。

  • 包裹式:成本高昂,但可试验特征的各个子集,不会意外删除本身不提供什么信息但和其他特征组合起来非常有用的特征。

  • 嵌入式:将模型选择作为模型训练的一部分(如决策树和l2l^2正则项)。l1l^1鼓励模型使用更少的特征,所以又称为稀疏性约束,它实现了过滤式和包裹式之间的平衡。

最后更新于

这有帮助吗?