posts - 225, comments - 62, trackbacks - 0, articles - 0
   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理
scikit-learn有如下几个常用的线性回归模型
普通最小二乘法 linear_model.LinearRegression
岭回归 linear_model.Ridge
Lasso回归 linear_model.Lasson
弹性网络 linear_model.ElasticNet
下面分别对这些模型进行讨论,
普通最小二乘法的思想就是让均方误差最小化。
假设X是样本,f是预测值,y是实际值,最小二乘就是找一对 w,b,满足 f(i) = w * x(i)转置 + b 并且,均方误差 = (y-f).dot(y-f) / len(X) 最小化
普通最小二乘法没什么可调整的参数,而且为了让均方误差最小化,w的一些分量可能非常大,这意味着这一特征对预测结果起决定性作用,而这时候训练出来的其他特征的权重可能并不正确,比如应该做正贡献的反而w对应分量是负的。
为了解决这个问题,我们可以通过施加约束,让w的分量都尽量小,这种约束叫正则化。
上面提到普通最小二乘法让使用误差均方来评价模型参数的好坏,这个用来估算模型好坏程度的函数叫损失函数。
所谓施加约束,其实就是在损失函数上做手脚。要限制w的分量也有不同的方法:
L1正则化,对应的模型就是Lasso回归,我简单的理解就是在Sigma|wi|上做手脚去限制
L2正则化,对应的模型就是岭回归(Ridge),我简单的理解就是在w.dot(w)上手脚去限制
至于ElasticNet,是结合了L1正则化和L2正则化
其构造函数有两个主要参数ElasticNet(alpha=1, l1_ratio=0.5)
第一个参数alpha:
其中alpha越大,约束越大,模型越简单,越容易欠拟合。
反之alpha越小,约束越小(alpha=0时退化成普通最小二乘),模型越复杂,越容易过拟合。
通常要在对数尺度上对alpha进行搜索,已确定效果最好的alpha。
第二个参数l1_ratio:
l1_ratio是L1和L2的比例,官方文档上写到 a*L1 + b * L2,alpha = a+b,l1_ratio = a/(a+b)
所以通过控制l1_ratio的比例[0,1],其实可以使模型退化成Lasso或Ridge。
因此,下面的例子就不在对Lasso和Ridge进行测试。
需要补充说明的是Lasso模型有一个用途就是它可以用来发现哪些特征比较有用,哪些特征影响不大,因为Lasso训练出来的模型很多w分量是0,通过训练后的模型.coef_ 可以看到这些系数。
下面我们对KNN、最小二乘、弹性网络的
学习曲线(训练数据集的大小和评分的函数)进行观察
这个例子的数据是用13个特征预测波士顿地区的房价,
可以看到最小二乘法在训练集比较小的时候非常差,要到100以上才比较稳定,当数据足够多之后效果还不错。(用普通最小二乘法预测的不稳定性在后面的例子更明显)
而ElasticNet稳定些,会比较快的可用,但是最终反而比普通最小二乘稍差,也可能是我没有仔细调过参的原因。
对于KNN算法模型的评分随着训练集的增加逐步上升,但最终预测效果差强人意。
下面还是波士顿房价的问题但把这些特征的两两乘积也作为特征,特征增加到了91项(=13+13*12/2)
可以看到普通最小二乘表现得有点奇怪,在训练集小于200之前非常不稳定,一度评分为0,即使训练集大于200也不太稳定。
弹性网络则要稳定的多,最终的评分也是弹性网络最好,这次我稍微调过参数了。
KNN还是一样,随着训练集的增加评分逐步上升,但最终预测效果差强人意。
下面是所使用的代码
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsRegressor
from sklearn.linear_model import LinearRegression
from sklearn.linear_model import ElasticNet
from mglearn.datasets import load_extended_boston
from sklearn.datasets import load_boston

X,y 
= load_extended_boston()

# boston = load_boston()
#
 X,y = boston.data, boston.target

X_train, X_test, y_train, y_test 
= train_test_split(
    X, y, random_state
=0)

regressor_names 
= ["5NN""LinearRegression""ElasticNet"]
line_style
=["-",":","--"]
for i, regressor in enumerate([KNeighborsRegressor(n_neighbors = 5), LinearRegression(), ElasticNet(alpha=0.01, l1_ratio=0.5, max_iter=100000)]):
    p1 
= np.zeros((len(X_train)-102))
    p2 
= np.zeros((len(X_train)-102))
    
for n_samples in range(10, len(X_train)):
        regressor.fit(X_train[0:n_samples], y_train[0:n_samples])
        p1[n_samples
-10= (n_samples, regressor.score(X_train, y_train))
        p2[n_samples
-10= (n_samples, regressor.score(X_test, y_test))

    plt.plot(p1[:,0],p1[:,
1], line_style[i], label = "Training "+regressor_names[i])
    plt.plot(p2[:,0],p2[:,
1], line_style[i], label = "Test "+regressor_names[i])

plt.title(
"learning curve(extended_boston)")
plt.xlabel(
"Training set size")
plt.ylabel(
"Score(R^2)")
plt.ylim(0, 
1)
plt.xlim(0,len(X_train))
plt.legend()
plt.show()
只有注册用户登录后才能发表评论。