描述性统计:差值



差值的本意是两数相减后剩余的数值。略有不同地,这里的差值定义为「度量差异的值」。

如何描述「差异」?

极差

级差指两极之差,即最大值和最小值相减后的值。值越小可以说明样本所有数据间的差异越小(紧密)。但是「值越大,所有数据之间的差异越大」,就有可能说不通了,比如下面这个例子。由于极差仅仅保留了样本最值之间的差异,因此只能粗略地描述数据的变化范围。

最值差距明显而中间数据排列紧凑,极差并不能真实反映样本数据的差异。


四分位差

四分位差保留了上四分位(Q3,百分比排列 75% 位置上的数)与下四分位(Q1,百分比排列 25% 位置上的数)之间的差异,也称作四分位距(IQR)。IQR 计算的是极差最中间的部分,因此可以用来描述中间 50% 数据的差异程度——数值越大中间的数据越分散,越小则越紧密也越靠近中位数。相比极差而言,IQR 不容易受到极端值的影响。


离差

如果说极差总倾向掩盖数值间的真实差异,那么离差(deviation)便毫无保留地呈现了每个数值的差异。离差是观测值距离特定参照的差值,因而一定程度上反映了实际情况与我们预期之间的差异。这里的特定参照数据可以是预测值,也可以是均值、最值等。


方差、标准差

既然离差反映了各个数据与参照之间的差异,那么它的平均值就可用来反映所有数据的平均差异。由于离差可能出现负值,比如选定平均数作为参照时计算的「离均差」,加总离差值容易出现中和。为了避免这样的情况,很自然会想到对离差取绝对值或平方后再求和的做法。方差(Variance)便是这样一种方式计算而来的平均值。因为离差不尽相同,故将每个离差平方求和再取平均,「尽最大努力保证公平」地代表数据间的差异。

有时候方差数值非常大,为了方便衡量常常会开根号,这时称为标准差(Standard Deviation)。



以上类型的差值足以描述一组数据的组内差异,那对于两组数据,是否也有类似的数字呢?


平均绝对误差、均方误差、均方根误差

方差的计算启发我们,在离差不尽相同且可能存在负值的时候,可以采用「化负为正」和「平均化」的思想计算出当前数据的差异。在机器学习中经常要计算预测值和真实值之间的差异,这样的差异称为误差(Error)。误差是模型评估和优化的依据。下面简单列举回归问题中常见的几种误差:

- 平均绝对误差(MAE)利用绝对值将误差「化负为正」,最后求和取平均。

- 均方误差(MSE)利用平方将误差「化负为正」,最后求和取平均,相较于 MAE 要平滑。

- 均方根误差(RMSE)是 MSE 的开方值,实际含义与 MSE 一致。


协方差、相关系数

协方差(Covariance)数值上等于两组数据的离均差乘积的平均值。与方差不同的是,协方差考虑了两组数据的离均差,因此能够描述两组数据间的某种差异——当数值越小时,说明两组数据所呈现的变化趋势的差异就越明显。

同样为了方便衡量,将协方差与标准差乘积的比值构成相关系数(Correlation Coefficient)。


决定系数

决定系数(Coefficient of Determination)能够描述两组数据的相似程度,它的值根据公式1-MSE/方差计算而来。两组数据越接近,MSE就越低,由于方差固定,决定系数就会接近于 1(完全相同)。

如果数据呈现的是一种线性变化时,决定系数恰好等于相关系数的平方值,别名 R 方(R-square)可能就是这样来的。


如何量化「差异」?

从上面可以看出,离差的计算可能是最核心的 —— 方差、协方差、MAE、MSE都依赖于它;把观测值固定为最大值和 Q1,参照值设为最小值和 Q3 就可以计算极差和 IQR。下面我们且看如何用 Python 实现所有类型的差值。


温馨提示:以下内容涉及中文编程的理念,可能引起极度不适。

离差

def 离差(观测值, 参照值): 
  return  观测值 - 参照值
# 下面的X均为向量 
def 离均差(X): 
  平均值 = 平均数(X)      # 平均数已在上一篇文章实现
  离均差 = [离差(x, 平均值) for x in X]
  return  离均差

def 离均差_numpy版本(X):
  平均值 = np.mean(X)
  离均差 = np.asarray(X) - 平均值
  return  离均差


极差

def 极差(X): 
  最大值 = max(X)
  最小值 = min(X)
  return  离差(最大值, 最小值)

def 极差_numpy版本(X): 
  return  np.asarray(X).ptp()      # 或np.ptp(X),ptp=peak-to-peak


四分位差

为了计算方便,这里使用了numpyscipy模块。

def 四分位差(X): 
  上四分位数 = np.quantile(X, 0.75)      # 或使用np.percentile(X, 75)
  下四分位数 = np.quantile(X, 0.25)      # 或使用np.percentile(X, 25)
  return  离差(上四分位数, 下四分位数)

def 四分位差_scipy版本(X):
  from scipy.stats import iqr
  return iqr(X)


方差、标准差

def 方差(X, 自由度=None): 
  差值 = 离均差(X)
  离差平方和 = [差 ** 2 for 差 in 差值]
  自由度 = 自由度 or len(X)
  return sum(离差平方和) / 自由度

def 标准差(X, 自由度=None):
  return 方差(X, 自由度) ** 0.5

def 方差_numpy版本(X, 自由度=None): 
  自由度 = 自由度 or len(X)
  return np.asarray(X).var(ddof=len(X)-自由度)    # 或np.var(X, ddof=len(X)-自由度)

def 标准差_numpy版本(X, 自由度=None):
  自由度 = 自由度 or len(X)
  return np.asarray(X).std(ddof=len(X)-自由度)    # 或np.std(X, ddof=len(X)-自由度)


平均绝对误差、均方误差、均方根误差

def MAE(X, Y, 自由度=None): 
    绝对误差 = [abs(离差(x,y)) for x,y in zip(X,Y)]
    自由度 = 自由度 or len(X)
    return sum(绝对误差) / 自由度

def MSE(X, Y, 自由度=None):
    平方误差 = [离差(x,y)**2 for x,y in zip(X,Y)]
    自由度 = 自由度 or len(X)
    return sum(绝对误差) / 自由度

def RMSE(X, Y, 自由度=None):
    return MSE(X, Y, 自由度) ** 0.5

def MAE_numpy版本(X, Y, 自由度=None):
    自由度 = 自由度 or len(X)
    return sum(np.abs(np.subtract(X,Y))) / 自由度

def MSE_numpy版本(X, Y, 自由度=None): 
    自由度 = 自由度 or len(X)
    return sum(np.subtract(X,Y)**2) / 自由度

def RMSE_numpy版本(X, Y, 自由度=None):
    自由度 = 自由度 or len(X)
    return MSE_numpy版本(X, Y, 自由度) ** 0.5


协方差、相关系数、决定系数

def 协方差(X, Y, 自由度=None): 
    差值X = 离均差(X)
    差值Y = 离均差(Y)
    离差乘积 = [差X*差Y for 差X,差Y in zip(差值X,差值Y)]
    自由度 = 自由度 or len(X)
    return sum(离差乘积) / 自由度

def 相关系数(X, Y, 自由度=None):
    return 协方差(X, Y, 自由度) / (标准差(X, 自由度)*标准差(Y, 自由度))

def 决定系数(X, Y, 自由度=None):
    return 1 - MSE(X, Y, 自由度) / 方差(Y, 自由度)

def 协方差_numpy版本(X, Y, 自由度=None): 
    自由度 = 自由度 or len(X)
    return np.cov(X, Y, ddof=len(X)-自由度)[0][1]   # .cov()得到的是一个矩阵,下同

def 相关系数_numpy版本(X, Y, 自由度=None): 
    自由度 = 自由度 or len(X)
    return np.corrcoef(X, Y, ddof=len(X)-自由度)[0][1]

def 决定系数_numpy版本(X, Y, 自由度=None): 
    # numpy模块中暂无一步到位的方法
    自由度 = 自由度 or len(X)
    return 1 - MSE_numpy版本(X, Y, 自由度) / 方差_numpy版本(X, 自由度)


总结一下

假设离差是一类复合函数F(f),那么

类型 函数 F
1 离差 □ - ■
2 离均差 □ - ■ 平均值
3 极差 F1 最大值 最小值
4 四分位差 F1 Q3 Q1
5 MAE ∑ |F1| / 自由度
6 MSE ∑ (F1)^2 / 自由度
7 RMSE √ F6
8 方差 ∑ (F1)^2 / 自由度
9 标准差 √ F8
10 协方差 ∑ F2*F2 / 自由度
11 相关系数 F10 / F9*F9
12 决定系数 1 - F6 / F8


如何利用「差异」?

识别异常值

分位数和 IQR 的概念让我们学会怎么画箱线图(Boxplot),同时也教会我们怎样识别异常数据。

箱线图有箱有线——箱的边界是上、下四分位数,长度则由 IQR 决定;箱里的中线表示中位数,箱外的上线和下线各距离箱的边界 1.5 倍 IQR,两线以外标记异常数据。

箱线图



我们把上面的 IQR 倍率设为可调整参数,可以这样实现异常数据的识别:

def 识别异常数据(X, IQR倍率=1.5):
    下四分位数 = np.percentile(X, 25)      # 或np.quantile(X, 0.25)
    上四分位数 = np.percentile(X, 75)      # 或np.quantile(X, 0.75)
    IQR= 上四分位数-下四分位数
    异常数据 = X[np.less(X, 下四分位数-IQR倍率*IQR) | np.greater(X, 上四分位数+IQR倍率*IQR)]
    return 异常数据

如果只是想知道每一行数据是否存在异常,停用第5行的索引(即只保留X[·]中的代码)即可。


标准化

数据的标准化(Standardization)很常见于指标的计算中,例如相关系数就可看作是经过标准化的协方差。

有时也称作缩放(Scaling)或归一化(Normalization),目的是将数据从原始空间转换到新的有限空间内。归一化特指将数据缩放到[0, 1]的范围,此时归一化后的数值的和为 1。

标准化可以消除量纲差异,便于不同数据之间的比较和运算,有时也能加快模型的收敛。

常见的标准化方法有 Min-max 缩放、平均归一化、z分数标准化等等,这些都用到了离差的计算。例如,

def min_max缩放(X):
    最小值 = min(X)
    最值差 = 极差(X)
    结果 = [离差(x, 最小值)/最值差 for x in X]
    return 结果

def min_max缩放_numpy版本(X):
    最小值 = min(X)
    最值差 = np.asarray(X).ptp()
    结果 = (X - 最小值) / 最值差
    return 结果

def min_max缩放_sklearn版本(X):
    return minmax_scale(X)


特征选择

差值还可以用来选择预测能力较强的特征(变量)。应该如何量化预测能力呢?简而有效的做法是,假设某个特征与目标变量越相关,那么它的预测能力越强。这样一来就可以根据相关系数的大小来筛选特征,比如剔除相关性较弱的特征。

def 剔除相关性较弱特征(X, y, 阈值=0.2):
    特征集 = np.asarray(X)      # 避免直接修改原数据
    相关特征 = [相关系数(特征,y)>=阈值 for 特征 in 特征集]
    return 特征集[相关特征]


模型评估和优化

损失函数在模型评估和优化中的地位非常重要。从某个角度看,机器学习就像是不断求解损失函数最优化的过程。MAE、MSE、RMSE 都可以作为回归模型的损失函数,例如线性回归的最小二乘法和逻辑回归的 L2 正则项。

from sklearn.linear_model import LogisticRegression
线性回归 = LinearRegression()
逻辑回归 = LogisticRegression(penalty='l2')


模型选择

在《机器学习》书中,周志华老师认为误差的期望值 ≈ 预测值相对真实值的偏差 + 模型预测值的方差 + 样本噪声的方差

偏差度量了模型的预测与真实结果的偏离程度,刻画的是算法本身的拟合能力;方差度量了同样大小训练集的变动所导致的算法能力的变化,刻画的是数据扰动所造成的影响;噪声表达了任何算法所能达到的期望误差的下界。」

随着训练进程不断推移,模型的拟合能力逐渐变强,偏差也在逐渐缩小,然而方差却增大了。按照偏差-方差权衡准则(Bias-variance Tradeoff),因为实际上很难获得偏差和方差都很小的模型,我们因此可以选择偏差和方差适中的模型。

训练过程 模型复杂度 偏差 方差 效果
T1 欠拟合
T2 刚刚好
T3 过拟合


进一步阅读

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352

推荐阅读更多精彩内容