数据变换
正态分布
为了让成绩符合正态分布,出题老师是怎么做的呢?
他们通常可以把考题分成三类
- 第一类:基础题,占总分70%,基本上属于送分题
- 第二类:灵活题,基础范围内+一定的灵活性,占20%
- 第三类:难题,涉及知识面较广的难题,占10%
如果一个出题老师没有按照上面的标准来出题,而是将第三类难题比重占到了70%,也就是我们说的“超纲”
结果会是怎样呢?你会发现,大部分人成绩都“不及格”
最后在大家激烈的讨论声中,老师会将考试成绩做规范化处理,从而让成绩满足正态分布的情况
因为只有这样,成绩才更具有比较性。所以正态分布的成绩,不仅可以让你了解全班整体的情况,还能了解每个人的成绩在全班中的位置
数据变换在数据分析中的角色
假设A考了80分,B也考了80分,但前者是百分制(60分及格),后者500分制(300分及格)
如果我们把从这两个渠道收集上来的数据进行集成、挖掘
就算使用效率再高的算法,结果也不是正确的。因为这两个渠道的分数代表的含义完全不同
所以,在数据挖掘中数据变换比算法选择更重要
如果不进行变换的话,要不就是维数过多,增加了计算的成本,要不就是数据过于集中,很难找到数据之间的特征
在数据变换中,重点是如何将数值进行规范化,有三种常用的规范方法
- Min-Max规范化
- Z-Score规范化
- 小数定标规范化
其中Z-Score规范化可以直接将数据转化为正态分布的情况,当然不是所有自然界的数据都需要正态分布
我们也可以根据实际的情况进行设计,比如取对数log,或者神经网络里采用的激活函数等
常见的变换方法
数据平滑:去除数据中的噪声,将连续数据离散化。这里可以采用分箱、聚类和回归的方式进行数据平滑
数据聚集:对数据进行汇总,在SQL中有一些聚合函数可以供我们操作,比如Max()反馈某个字段的数值最大值,Sum()返回某个字段的数值总和
数据概化:将数据由较低的概念抽象成为较高的概念,减少数据复杂度,即用更高的概念替代更低的概念。比如说上海、杭州、深圳、北京可以概化为中国
数据规范化:使属性数据按比例缩放,这样就将原来的数值映射到一个新的特定区域中。常用的方法有最小—最大规范化、Z—score规范化、按小数定标规范化等
- Min-max规范化方法是将原始数据变换到[0,1]的空间中。用公式表示就是:新数值 =(原数值 - 极小值)/(极大值 - 极小值)
- Z-Score规范化(以上面A、B考试成绩为例,A班平均值80,标准差10;B班平均值400,标准差100)新数值 =(原数值 - 均值)/ 标准差
- 则A、B的新数值分别为:(80-80)/10=0、(80-400)/100=-3.2
- 在Z-Score标准下,A的成绩比B的成绩好
- Z-Score的优点是算法简单,不受数据量级影响,结果易于比较
- Z-Score的缺点是需要数据整体的平均值和方差,而且结果没有实际意义,只是用于比较
- 小数定标规范化,假设属性A的取值范围是-999到88,那么最大绝对值为999,小数点就会移动3位
- 即新数值=原数值/1000。那么A的取值范围就被规范化为-0.999到0.088
属性构造:构造出新的属性并添加到属性集中。这里会用到特征工程的知识,因为通过属性与属性的连接构造新的属性,其实就是特征工程
- 比如说,数据表中统计每个人的英语、语文和数学成绩,你可以构造一个“总和”这个属性,来作为新属性。这样“总和”这个属性就可以用到后续的数据挖掘计算中
Python的SciKit-Learn库使用
SciKit-Learn是Python的重要机器学习库,它帮我们封装了大量的机器学习算法,比如分类、聚类、回归、降维等。此外,它还包括了数据变换模块
Min-max规范化
from sklearn import preprocessing
import numpy as np
x = np.array([
[1, 10, -100],
[99, 666, 999],
[-100, 0.02, 12]
])
minmax_scale = preprocessing.MinMaxScaler()
minmax_x = minmax_scale.fit_transform(x)
print(minmax_x)
Z-Score规范化
from sklearn import preprocessing
import numpy as np
x = np.array([
[1, 10, -100],
[99, 666, 999],
[-100, 0.02, 12]
])
scaled_x = preprocessing.scale(x)
print(scaled_x)
小数定标规范化
import numpy as np
x = np.array([
[1, 10, -100],
[99, 666, 999],
[-100, 0.02, 12]
])
# 利用log向上取整后,得到3
j = np.ceil(np.log10(np.max(abs(x))))
# 10的3次方,即1000
scaled_x = x/(10**j)
print(scaled_x)