继续回归.
(正交匹配追踪算法(OMP)与贝叶斯回归完全没接触过,先略过。。。)
逻辑回归
如果忽略名称的话,逻辑回归更像是一个分类模型而不是回归模型。一般还被称为最大熵分类模型或者对数线性分类器。在该模型中,通过对数函数求得概率,然后用来描述样本更可能分到某一类。
sklearn中实现逻辑回归的函数是LogisticRegression。可以用于二分类问题也可以是多分类,并且可以选择添加L1或者L2惩罚项。
逻辑回归中需要优化的目标函数如下:
带有L2惩罚项:
带有L1惩罚项:
函数使用的求解算法有C++库liblinear封装而成的(使用了坐标下降法),还有共轭梯度法(newton-cg)和拟牛顿法。后两种方法只支持L2正则,并且在高维数据下收敛速度相对更快。
liblinear中的坐标下降法并不能真正的解决多分类问题,因此sklearn中采取了对所有的分类都进行A和非A这种的二分类方式,来实现多分类。
使用newton-cg和LBFGS,则是能够实现真正的多分类的。所以,理论上,在多分类问题上,应当是比liblinear效果要好一些。
LogisticRegression是通过LogisticRegressionCV来对参数做交叉选择的。
随机梯度下降
随机梯度下降法是个拟合线性模型非常简单有效的办法,尤其是数据量较大的时候,使用它的partial_fit方法能够允许电脑处理超出自己内存的数据量
sklearn中主要相关的两个函数是SGDClassifier和SGDRegressor。可以设置参数使用不同的损失函数和不同的惩罚项。比如如果设置loss=”log”,就得到了一个逻辑回归函数,设置loss=”hinge”, 就得到了一个线性支持向量机模型
感知机算法
处理大数据量的另一种方法。
Passive Aggressive Algorithms
“Online Passive-Aggressive Algorithms” K. Crammer, O. Dekel, J. Keshat, S. Shalev-Shwartz, Y. Singer JMLR 7 (2006)
回归的稳定性:异常值和模型误差
我们的数据中有时会存在一些被污染的数据,可能是异常值,可能是误差。这时候我们就会非常关心模型的稳定性,也就是会不会被这些噪声点影响
在这里会对三个模型在不同情境下的表现做个对比。这三个模型为OLS(最小二乘),Theil-Sen,和RANSAC.
RANSAC:随机样本一致性
RANSAC的拟合方式是从完整的数据集中的正常数据点随机选取一个子集进行拟合。
RANSAC是一个非确定性算法,只会依据当时的概率分布产生一个合理的结果。这个结果是依赖于迭代次数的。该算法经常用于线性和非线性的龟龟问题中,并且在计算机视觉领域很流行。
该算法把数据集分成两部分,一部分是可能带有一点噪声的正常值。另一部分就是那些由于错误的测量或是无效的假设而产生的异常值。最终模型只会用正常值去拟合。
算法的步骤如下:
- 选择一个随机小样本min_samples,并且检查数据集是否有效(is_data_valid)
- 用这个随机子集拟合模型(base_estimator.fit),检查估计出来的模型是否有效(is_model_valid)
- 通过计算数据点到估计模型的残差来把所有数据点分为正常值和异常值两部分(base_estimator.predict(X) - y),比较基准是事先设定的一个residual_threshold.
- 当正常值样本数量达到最大时,就把模型定义为最终的模型。
这个步骤可以设定一个最大循环次数,也可以定义一个停止条件(参考stop_n_inliers 和 stop_score).
Theil_Sen estimator:
TheilSenRegressor估计量,是通过取任意p个子样本点拟合线性模型,将计算出的范围和截距取均值这种方式来消除异常点的影响,p必须大于或等于特征的数量加1。它的一个临界值是29.3%,就是说在二维情况下用这种回归方式能忍受29.3%的异常值的影响。
import time
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression, TheilSenRegressor
from sklearn.linear_model import RANSACRegressor
estimators = [('OLS', LinearRegression()),
('Theil-Sen', TheilSenRegressor(random_state=42)),
('RANSAC', RANSACRegressor(random_state=42))]
np.random.seed(0)
n_samples = 200
x = np.random.randn(n_samples)
w = 3.
c = 2.
noise = 0.1 * np.random.randn(n_samples)
y = w * x + c + noise
#制造异常点
y[-20:] += -20 * x[-20:]
X = x[:, np.newaxis]
plt.plot(x, y, 'k+', mew=2, ms=8)
line_x = no.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')
np.random.seed(0)
x = np.random.randn(n_samples)
noise = 0.1 * np.random.randn(n_samples)
y = 3 * x + 2 + noise
x[-20:] = 9.9
y[-20:] += 22
X = x[:, np.newaxis]
plt.figure()
plt.plot(x, y, 'k+', mew=2, ms=8)
line_x = np.array([-3, 10])
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()
多项式回归:线性回归的扩展
有一种机器学习中常用的套路,就是用线性模型来训练非线性的数据。因为用线性方法性能会更好,这样就可以拟合更大范围的数据。
比如,我们可以通过构建多项式的特征来扩展线性回归。标准的线性回归如下式:
如果我们想要拟合一个抛物面而不是平面。那么我们可以通过特征组合来增加二阶特征。模型就变成了以下的形式:
从观察值的角度,这居然还是可以看成一个线性模型,想象一下, 令:
那么我们的问题就可以重新表示成:
线性模型的样子就已经出来了。在实际求解到时候也可以使用线性模型相同的技术,而且模型可以灵活的去拟合更大范围的数据。
我们可以用预处理函数PolynomialFeatures来实现这种功能。为了比较,我们还可以引入Pipeline函数。
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline
import numpy as np
# fit一个3阶的多项式回归函数
model = Pipeline([('poly', PolynominalFeatures(degree=3)),
('linear', LinearRegression(fit_intercept=False))])
x = np.arange(5)
y = 3 - 2*x + x**2 - x**3
model = model.fit(x[:, np.newaxis], y)
print(model.named_steps['linear'].coef_)
打印出来可以看到用多阶特征训练出来的线性模型的系数和输入的多项式的系数是正好符合的。
有些时候,我们只想要特征的交叉相乘项,而不想要它自身的高阶项,也就是对于二阶的,只需要 x1x2 ,这时候就可以把PolynominalFeatures的interaction_only设为True。比如在处理一个0,1矩阵时, xn 和它自身是一样的,并没有什么意义。但 x1x2 可以体现出这两个特征的关系,比如是否同时发生。