[python]稳健回归(Robustness regression)

### 最小二乘法的弊端

之前文章里的关于线性回归的模型,都是基于最小二乘法来实现的。但是,当数据样本点出现很多的异常点(outliers),这些异常点对回归模型的影响会非常的大,传统的基于最小二乘的回归方法将不适用。

比如下图中所示,数据中存在一个异常点,如果不剔除改点,适用OLS方法来做回归的话,那么就会得到途中红色的那条线;如果将这个异常点剔除掉的话,那么就可以得到图中蓝色的那条线。显然,蓝色的线比红色的线对数据有更强的解释性,这就是OLS在做回归分析时候的弊端。

![在这里插入图片描述](https://img-blog.csdnimg.cn/20201206170619229.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2RvbW9kbzIwMTI=,size_16,color_FFFFFF,t_70#pic_center)

当然,可以考虑在做回归分析之前,对数据做预处理,剔除掉那些异常点。但是,在实际的数据中,存在两个问题:

异常点并不能很好的确定,并没有一个很好的标准用于确定哪些点是异常点

即便确定了异常点,但这些被确定为异常的点,真的是错误的数据吗?很有可能这看似异常的点,就是原始模型的数据,如果是这样的话,那么这些异常的点就会带有大量的原始模型的信息,剔除之后就会丢失大量的信息。

再比如下面这幅图,其中红色的都是异常点,但是很难从数据中剔除出去。

![在这里插入图片描述](https://img-blog.csdnimg.cn/20201206170641217.png#pic_center)

### 稳健回归

稳健回归(Robust regression),就是当最小二乘法遇到上述的,数据样本点存在异常点的时候,用于代替最小二乘法的一个算法。当然,稳健回归还可以用于异常点检测,或者是找出那些对模型影响最大的样本点。

##### Breakdown point

关于稳健回归,有一个名词需要做解释:Breakdown point,这个名词我并不想翻译,我也没找到一个很好的中文翻译。对于一个估计器而言,原始数据中混入了脏数据,那么,Breakdown point 指的就是在这个估计器给出错误的模型估计之前,脏数据最大的比例 α,Breakdown point 代表的是一个估计器对脏数据的最大容忍度。

举个简单的例子:有 n 个随机变量,(X1,X2,…,Xn), 其对应的数据为(x1,x2,…,xn),那么,我么可以求出这 n 个随机变量的均值:

X_bar =(X1 + X2 + ⋯ + Xn)  / n

这个均值估计器的Breakdown point 为0,因为使任意一个xi变成足够大的脏数据之后,上面估计出来的均值,就不再正确了。

毫无疑问,Breakdown point越大,估计器就越稳健。

Breakdown point 是不可能达到 50% 的,因为如果总体样本中超过一半的数据是脏数据了,那么从统计上来说,就无法将样本中的隐藏分布和脏数据的分布给区分开来。

本文主要介绍两种稳健回归模型:RANSAC(RANdom SAmple Consensus 随机采样一致性)和Theil-Sen estimator。

##### RANSAC随机采样一致性算法

RANSAC算法的输入是一组观测数据(往往含有较大的噪声或无效点),它是一种重采样技术(resampling technique),通过估计模型参数所需的最小的样本点数,来得到备选模型集合,然后在不断的对集合进行扩充,其算法步骤为:

随机的选择估计模型参数所需的最少的样本点。

估计出模型的参数。

找出在误差 ϵ 内,有多少点适合当前这个模型,并将这些点标记为模型内点

如果内点的数目占总样本点的比例达到了事先设定的阈值 τ,那么基于这些内点重新估计模型的参数,并以此为最终模型, 终止程序。

否则重复执行1到4步。

RANSAC算法是从输入样本集合的内点的随机子集中学习模型。

RANSAC算法是一个非确定性算法(non-deterministic algorithm),这个算法只能得以一定的概率得到一个还不错的结果,在基本模型已定的情况下,结果的好坏程度主要取决于算法最大的迭代次数。

RANSAC算法在线性和非线性回归中都得到了广泛的应用,而其最典型也是最成功的应用,莫过于在图像处理中处理图像拼接问题,这部分在Opencv中有相关的实现。

从总体上来讲,RANSAC算法将输入样本分成了两个大的子集:内点(inliers)和外点(outliers)。其中内点的数据分布会受到噪声的影响;而外点主要来自于错误的测量手段或者是对数据错误的假设。而RANSAC算法最终的结果是基于算法所确定的内点集合得到的。

下面这份代码是RANSAC的适用实例:

```

# -*- coding: utf-8 -*-

"""

author : duanxxnj@163.com

time : 2016-07-07-15-36

"""

import numpy as np

import time

from sklearn import linear_model,datasets

import matplotlib.pyplot as plt

# 产生数据样本点集合

# 样本点的特征X维度为1维,输出y的维度也为1维

# 输出是在输入的基础上加入了高斯噪声N(0,10)

# 产生的样本点数目为1000个

n_samples = 1000

X, y, coef = datasets.make_regression(n_samples=n_samples,

                                      n_features=1,

                                      n_informative=1,

                                      noise=10,

                                      coef=True,

                                      random_state=0)

# 将上面产生的样本点中的前50个设为异常点(外点)

# 即:让前50个点偏离原来的位置,模拟错误的测量带来的误差

n_outliers = 50

np.random.seed(int(time.time()) % 100)

X[:n_outliers] = 3 + 0.5 * np.random.normal(size=(n_outliers, 1))

y[:n_outliers] = -3 + 0.5 * np.random.normal(size=n_outliers)

# 用普通线性模型拟合X,y

model = linear_model.LinearRegression()

model.fit(X, y)

# 使用RANSAC算法拟合X,y

model_ransac = linear_model.RANSACRegressor(linear_model.LinearRegression())

model_ransac.fit(X, y)

inlier_mask = model_ransac.inlier_mask_

outlier_mask = np.logical_not(inlier_mask)

# 使用一般回归模型和RANSAC算法分别对测试数据做预测

line_X = np.arange(-5, 5)

line_y = model.predict(line_X[:, np.newaxis])

line_y_ransac = model_ransac.predict(line_X[:, np.newaxis])

print "真实数据参数:", coef

print "线性回归模型参数:", model.coef_

print "RANSAC算法参数: ", model_ransac.estimator_.coef_

plt.plot(X[inlier_mask], y[inlier_mask], '.g', label='Inliers')

plt.plot(X[outlier_mask], y[outlier_mask], '.r', label='Outliers')

plt.plot(line_X, line_y, '-k', label='Linear Regression')

plt.plot(line_X, line_y_ransac, '-b', label="RANSAC Regression")

plt.legend(loc='upper left')

plt.show()

```

![在这里插入图片描述](https://img-blog.csdnimg.cn/20201206170931273.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2RvbW9kbzIwMTI=,size_16,color_FFFFFF,t_70#pic_center)

运行结果为:

```

真实数据参数: 82.1903908408

线性回归模型参数: [ 55.19291974]

RANSAC算法参数:  [ 82.08533159]

```

##### Theil-Sen Regression 泰尔森回归

Theil-Sen回归是一个参数中值估计器,它适用泛化中值,对多维数据进行估计,因此其对多维的异常点(outliers 外点)有很强的稳健性。

一般的回归模型为:

y = α + βx + ϵ

其中,α,β 模型的参数,而 ϵ 为模型的随机误差。

Theil-Sen回归则是这么处理的:

β = Median{(yi − yj) / (xi − xj): xi ≠ xj, i < j = 1,…, n}

在实践中发现,随着数据特征维度的提升,Theil-Sen回归的效果不断的下降,在高维数据中,Theil-Sen回归的效果有时甚至还不如OLS(最小二乘)。

在之间的文章《线性回归》中讨论过,OLS方法是渐进无偏的,Theil-Sen方法在渐进无偏方面和OLS性能相似。和OLS方法不同的是,Theil-Sen方法是一种非参数方法,其对数据的潜在分布不做任何的假设。Theil-Sen方法是一种基于中值的估计其,所以其对异常点有更强的稳健性。

在单变量回归问题中,Theil-Sen方法的Breakdown point为29.3%,也就是说,Theil-Sen方法可以容忍29.3%的数据是outliers。

```

# -*- coding: utf-8 -*-

"""

@author : duanxxnj@163.com

@time ;2016-07-08_08-50

Theil-Sen 回归

本例生成一个数据集,然后在该数据集上测试Theil-Sen回归

"""

print __doc__

import time

import numpy as np

import matplotlib.pyplot as plt

from sklearn.linear_model import LinearRegression, TheilSenRegressor,\

                                RANSACRegressor

estimators = [('OLS', LinearRegression()),

              ('Theil-Sen', TheilSenRegressor())]

# 异常值仅仅出现在y轴

np.random.seed((int)(time.time() % 100))

n_samples = 200

# 线性模型的函数形式为: y = 3 * x + N(2, .1 ** 2)

x = np.random.randn(n_samples)

w = 3.

c = 2.

noise = c + 0.1 * np.random.randn(n_samples)

y = w * x + noise

# 加入10%的异常值,最后20个值称为异常值

y[-20:] += -20 * x[-20:]

X = x[:, np.newaxis]

plt.plot(X, y, 'k+', mew=2, ms=8)

line_x = np.array([-3, 3])

for name, estimator in estimators:

    t0 = time.time()

    estimator.fit(X, y)

    elapsed_time = time.time() - t0

    y_pred = estimator.predict(line_x.reshape(2, 1))

    plt.plot(line_x, y_pred, label='%s (fit time: %.2fs)'

            %(name, elapsed_time))

plt.axis('tight')

plt.legend(loc='upper left')

plt.show()

```

![在这里插入图片描述](https://img-blog.csdnimg.cn/20201206171133330.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2RvbW9kbzIwMTI=,size_16,color_FFFFFF,t_70#pic_center)

转载自:

https://blog.csdn.net/daunxx/article/details/51858208

### 补充

1、[稳健回归的补充](https://blog.csdn.net/shenziheng1/article/details/72979683)

2、稳健回归的拟合优度计算

直接调用 statsmodel 里的稳健回归算法,结果不包括R方,如果想得到它,可以根据R方的定义手动计算得到:

```

r_sqr = 1. - np.sum((estimator.predict(x) - y) ** 2) / np.sum((y - np.mean(y)) ** 2)

# 或者

r_sqr = np.sum((estimator.predict(x) - np.mean(y)) ** 2) / np.sum((y - np.mean(y)) ** 2)

```

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

推荐阅读更多精彩内容