数据噪声(Noise):数据集中的干扰数据(对场景描述不准确的数据),即测量变量中的随机误差或方差。
观测量(Measurement) = 真实数据(True Data) + 噪声 (Noise):而离群点(Outlier)属于观测量,既有可能是真实数据产生的,也有可能是噪声带来的,但是总的来说是和大部分观测量之间有明显不同的观测值。
数据噪声与离群点有很多相同的地方。之间没有太过明确的定义,主要看应用的场景。如在信用卡诈骗中,我们通常会关注那些少量的异常数据,此时数据是具有探索意义的。而在一般的场景下,离群点和噪声都需要剔除,一般使用的方法也有很多相似之处,如3标准差去噪,dbscan去噪,孤立森林等。
同异常值,也有机器因素和人为因素。这里不做过多说明。
对模型训练有影响很多算法,不仅会增加数据量,也会加大计算量,增加计算机内存和计算开销,也会增大计算误差。特别是线性算法,都是通过迭代来获取最优解的,如果数据中含有大量的噪声数据,将会大大的影响数据的收敛速度,甚至对于训练生成模型的准确也会有很大的副作用。
常见的噪声数据的处理方法:
根据业务和对数据本身的理解,人为的进行数据筛选。
对于正态数据,利用3个标准差原则进行去噪,或使用四分位差进行去噪。
对于偏态数据用分箱则效果更好。
分箱方法是一种简单常用的预处理方法,通过考察相邻数据来确定最终值。所谓“分箱”,实际上就是按照属性值划分的子区间,如果一个属性值处于某个子区间范围内,就称把该属性值放进这个子区间所代表的“箱子”内。把待处理的数据(某列属性值)按照一定的规则放进一些箱子中,考察每一个箱子中的数据,采用某种方法分别对各个箱子中的数据进行处理。
在采用分箱技术时,需要确定的两个主要问题就是:
分箱的方法有4种:等深分箱法、等宽分箱法、用户自定义区间法和最小熵法。
例:客户收入属性income排序后的值(人民币元):800 1000 1200 1500 1500 1800 2000 2300 2500 2800 3000 3500 4000 4500 4800 5000。
也称等深分箱法,将数据集按记录行数分箱,每箱具有相同的记录数,每箱记录数称为箱子的深度。这是最简单的一种分箱方法。每个箱子的深度(箱内数据的个数)统一。
统一权重:设定权重(箱子深度)为4,分箱后
箱1:800 1000 1200 1500
箱2:1500 1800 2000 2300
箱3:2500 2800 3000 3500
箱4:4000 4500 4800 5000
也称等宽分箱法,使数据集在整个属性值的区间上平均分布,即每个箱的区间范围是一个常量,称为箱子宽度。
统一区间:设定区间范围(箱子宽度)为1000元人民币,分箱后
箱1:800 1000 1200 1500 1500 1800
箱2:2000 2300 2500 2800 3000
箱3:3500 4000 4500
箱4:4800 5000
用户可以根据需要自定义区间,当用户明确希望观察某些区间范围内的数据分布时,使用这种方法可以方便地帮助用户达到目的。
用户自定义:如将客户收入划分为1000元以下、1000-2000、2000-3000、3000-4000和4000元以上几组,分箱后
箱1:800
箱2:1000 1200 1500 1500 1800 2000
箱3:2300 2500 2800 3000
箱4:3500 4000
箱5:4500 4800 5000
熵是不确定性的度量,最大熵原理的意思就是说我们在对结果进行推测时,要承认我们的无知,所以要最大化不确定性,以得到最客观的结果。而对于最小熵原理,则是要最小化每个分箱内的不确定性。跟下面介绍的聚类方法不一样,这里的无监督模型,是为了更好的分组,进而进行数据平滑处理。而后面的聚类是直接把噪声数据删除。
链接:最小熵原理
数据平滑方法又可以细分为:平均值平滑、边界值平滑和按中值平滑。
排序后的数据:4, 8, 9, 15, 21, 21, 24, 25, 26, 28, 29, 34。以下例子按照等深分箱处理。
对同一箱值中的数据求平均值,用平均值替代该箱子中的所有数据。
可以通过如聚类如k-means来检测离群点。聚类将类似的值组织成群或“簇”。那些落在簇之外的值(孤立点),这些孤立点被视为噪声。同离群点的处理方式。
k均值聚类法将观测值聚为k类,但在聚类过程中需要保证分箱的有序性:第一个分箱中所有观测值都要小于第二个分箱中的观测值,第二个分箱中所有观测值都要小于第三个分箱中的观测值,等等。
可以用一个函数拟合数据来光滑数据。这种技术称之为回归。即让数据适合一个函数来平滑数据,通过建立数学模型来预测下一个数值。通过,包括线性回归和非线性回归。
pandas中的cut(),qcut()用来把一组数据分割成离散的区间。
pd.cut(),按照数据值的大小(从最大值到最小值进行等距划分)进行划分。每个间隔段里的间隔区间都是相同的,统一区间。
pandas.cut(x, bins, right=True, labels=None, retbins=False, precision=3, include_lowest=False, duplicates='raise')
import numpy as np
import pandas as pd
ages = np.array([1,5,10,40,36,12,58,62,77,89,100,18,20,25,30,32]) #年龄数据
# 将ages平分成5个区间,等宽分箱
pd.cut(ages, 5)
[(0.901, 20.8], (0.901, 20.8], (0.901, 20.8], (20.8, 40.6], (20.8, 40.6], ..., (0.901, 20.8], (0.901, 20.8], (20.8, 40.6], (20.8, 40.6], (20.8, 40.6]]
Length: 16
Categories (5, interval[float64]): [(0.901, 20.8] < (20.8, 40.6] < (40.6, 60.4] < (60.4, 80.2] < (80.2, 100.0]]
#将ages平分成5个区间并指定labels
pd.cut(ages, 5, labels=[u"婴儿",u"青年",u"中年",u"壮年",u"老年"])
[婴儿, 婴儿, 婴儿, 青年, 青年, ..., 婴儿, 婴儿, 青年, 青年, 青年]
Length: 16
Categories (5, object): [婴儿 < 青年 < 中年 < 壮年 < 老年]
# 给ages指定区间进行分割
pd.cut(ages, [0,5,20,30,50,100], labels=[u"婴儿",u"青年",u"中年",u"壮年",u"老年"])
[婴儿, 婴儿, 青年, 壮年, 壮年, ..., 青年, 青年, 中年, 中年, 壮年]
Length: 16
Categories (5, object): [婴儿 < 青年 < 中年 < 壮年 < 老年]
#返回分割后的bins,令retbins=True即可
pd.cut(ages, [0,5,20,30,50,100], labels=[u"婴儿",u"青年",u"中年",u"壮年",u"老年"],retbins=True)
([婴儿, 婴儿, 青年, 壮年, 壮年, ..., 青年, 青年, 中年, 中年, 壮年]
Length: 16
Categories (5, object): [婴儿 < 青年 < 中年 < 壮年 < 老年],
array([ 0, 5, 20, 30, 50, 100]))
#只返回x中的数据在哪个bin,令labels=False即可
#第一个0表示1在第0个bin中。
pd.cut(ages, [0,5,20,30,50,100], labels=False)
array([0, 0, 1, 3, 3, 1, 4, 4, 4, 4, 4, 1, 1, 2, 2, 3], dtype=int64)
df_cut['data'] = ages
df_cut['data_分组'] = pd.cut(ages,5)
df_cut['data_标签分组'] = pd.cut(ages,5,labels=[u"婴儿",u"青年",u"中年",u"壮年",u"老年"])
df_cut['data_标签组别'] = pd.cut(ages, [0,5,20,30,50,100], labels=False)
pd.qcut(),按照数据出现频率百分比划分,比如要把数据分为四份,则四段分别是数据的0-25%,25%-50%,50%-75%,75%-100%,每个间隔段里的元素个数都是相同的,统一权重。
pd.qcut(x, q, labels=None, retbins=False, precision=3, duplicates='raise')
# 将ages平分成5个区间
pd.qcut(ages,5)
[(0.999, 12.0], (0.999, 12.0], (0.999, 12.0], (36.0, 62.0], (25.0, 36.0], ..., (12.0, 25.0], (12.0, 25.0], (12.0, 25.0], (25.0, 36.0], (25.0, 36.0]]
Length: 16
Categories (5, interval[float64]): [(0.999, 12.0] < (12.0, 25.0] < (25.0, 36.0] < (36.0, 62.0] < (62.0, 100.0]]
# 查看区间内的数据个数,等深分箱
pd.qcut(ages,5).value_counts()
(0.999, 12.0] 4
(12.0, 25.0] 3
(25.0, 36.0] 3
(36.0, 62.0] 3
(62.0, 100.0] 3
dtype: int64
#将ages平分成5个区间并指定labels
pd.qcut(ages,5,labels=[u"婴儿",u"青年",u"中年",u"壮年",u"老年"])
[婴儿, 婴儿, 婴儿, 壮年, 中年, ..., 青年, 青年, 青年, 中年, 中年]
Length: 16
Categories (5, object): [婴儿 < 青年 < 中年 < 壮年 < 老年]
#返回分割后的bins,令retbins=True即可
pd.qcut(ages,5,labels=[u"婴儿",u"青年",u"中年",u"壮年",u"老年"],retbins=True)
[婴儿, 婴儿, 婴儿, 壮年, 中年, ..., 青年, 青年, 青年, 中年, 中年]
([婴儿, 婴儿, 婴儿, 壮年, 中年, ..., 青年, 青年, 青年, 中年, 中年]
Length: 16
Categories (5, object): [婴儿 < 青年 < 中年 < 壮年 < 老年],
array([ 1., 12., 25., 36., 62., 100.]))
#只返回x中的数据在哪个bin,令labels=False即可
#第一个0表示1在第0个bin中。
pd.cut(ages, 5, labels=False)
array([0, 0, 0, 1, 1, 0, 2, 3, 3, 4, 4, 0, 0, 1, 1, 1], dtype=int64)
df_qcut = pd.DataFrame()
df_qcut['data'] = ages
df_qcut['data_分组'] = pd.qcut(ages,5)
df_qcut['data_标签分组'] = pd.qcut(ages,5,labels=[u"婴儿",u"青年",u"中年",u"壮年",u"老年"])
df_qcut['data_标签组别'] = pd.qcut(ages, 5, labels=False)
噪声和离群点之间有一定的差别,而具体的处理要看应用场景是什么。
存在数据噪声,会增大数据量,影响模型运行速度,并对准确率造成影响。
处理方法有
对于分箱,可先使用pandas中的cut()和qcut(),进行分箱,然后通过mean(),median()编写数据平滑的函数,作为替代值。具体哪种分箱方式,要看应用的场景。如年龄,等宽分箱比较合理。
聚类和回归可使用sklearn中的包实现。其中回归通过对数据拟合预测的方式,来甄别噪声数据。
https://blog.csdn.net/M_WBCG/article/details/79117085
https://blog.csdn.net/poi10086/article/details/82497065
https://blog.csdn.net/qq_32572085/article/details/89704051
https://www.zhihu.com/question/37506766
https://www.cnblogs.com/nicetoseeyou/p/10655422.html
https://www.cnblogs.com/sench/p/10128216.html
https://www.cnblogs.com/nicetoseeyou/p/10655422.html