Python机器学习基础教程学习笔记(5)——线性模型(回归)

Python机器学习基础教程学习笔记(5)——线性模型(回归)

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import mglearn

1 线性回归处理wave数据集

1.1 wave数据集

mglearn.plots.plot_linear_regression_wave()
w[0]: 0.393906  b: -0.031804
output_3_1

1.2 线性回归

  • 线性回归,或者普通最小二乘法(ordinary least squairs ,OLS),回归总是最简单也是最经典的线性方法
  • 寻找参数w和b,使得对训练集的预测值与真实的回归目标值y之间的均方误差(预测值与真实值之差的平方各除以样本数)最小。
  • 没有参数,但无法控制模型的复杂度
from sklearn.linear_model import LinearRegression
X,y = mglearn.datasets.make_wave(n_samples=60)
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=42)

lr = LinearRegression().fit(X_train,y_train)
# "斜率"参数(w,也叫做权重或系统),被保存到coef_属性中
print("lr.coef_:{}".format(lr.coef_))
# 偏移或者截距(b),被保存到intercept_属性中
print("lr.intercept_:{}".format(lr.intercept_))
lr.coef_:[0.39390555]
lr.intercept_:-0.031804343026759746
print("Train set score:{:.2f}".format(lr.score(X_train,y_train)))
print("Test set score:{:.2f}".format(lr.score(X_test,y_test)))
Train set score:0.67
Test set score:0.66
  • R^2分数约为0.66,结果不是很好
  • 训练集和测试集的分数非常接近,可能存在欠拟合
  • 一维数据来说,过拟合的风险很小,因为模型非常简单(或受限)
  • 高维数据来说,线性模型变得更加强大,过拟合的可能性也会变大

2 线性回归处理波士顿房价数据集

2.1 波士顿房价数据集

from sklearn.datasets import load_boston
boston = load_boston()
# boston是Bunch类型数据
print("boston.keys :{}".format(boston.keys()))
boston.keys :dict_keys(['data', 'target', 'feature_names', 'DESCR', 'filename'])
# 数据集包括506个数据点,13个特征
print("data shape :{}".format(boston.data.shape))
data shape :(506, 13)

扩展数据集:

  • 输入特征不仅包括这13个测量结果
  • 还包括这些特征的乘积(也叫交互项
  • 像这样包含导出特征的方法叫作特征工程(feature engineering)
# 通过load_extended_boston函数加载导出的数据集
X,y = mglearn.datasets.load_extended_boston()
# 最初的13个特征加上这13个特征两两组合(有放回)得到的91个特征,一共有104个特征
print("X.shape:{}".format(X.shape))
X.shape:(506, 104)

2.2 用线性回归处理

X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=0)
lr = LinearRegression().fit(X_train,y_train)
print("Train set score:{:.2f}".format(lr.score(X_train,y_train)))
print("Test set score:{:.2f}".format(lr.score(X_test,y_test)))
Train set score:0.95
Test set score:0.61
  • 训练集和测试集之间的性能差异是过拟合(训练集0.95,测试集0.61)的明显标志
  • 线性回归没有参数,不可以控制模型复杂度。

3 岭回归(Ridge regression)

  • 一种用于回归的线性模型
  • 预测公式与普通最小二乘法相同
  • 对系数(w)的选择不仅要在训练集数据上得到好的预测结果
  • 还要拟合附加约束
  • 系统尽可能小——w的所有元素都应接近于0
  • 意味着,每个特征对输出的影响应尽可能小(即斜率很小),同时仍给出很好的预测结果 。这种约束是所谓的正则化的一个例子
  • 正则化是指对模型做的显示约束,以避免过拟合
  • 岭回归用的是L2正则化
from sklearn.linear_model import Ridge
ridge = Ridge().fit(X_train,y_train)
print("Train set score:{:.2f}".format(ridge.score(X_train,y_train)))
print("Test set score:{:.2f}".format(ridge.score(X_test,y_test)))
Train set score:0.89
Test set score:0.75
  • ridge的训练集分数0.89低于linear的训练集分数0.95

  • ridge的测试集分数0.75高于linear的训练集分数0.61

  • linear过拟合

  • rigde约束性更强,更不容易过拟合

  • riged复杂度更小,在训练集性能更差,泛化性能更好

  • 我们对泛化性能感兴趣,应选择ridge,而不选择linear

  • ridge在模型的简单性(系数都接近于0)与训练集之间做出权衡

  • 通过alpha参数来指定

  • 默认alpha=0

  • alpha的最佳设定值取决于用到的具体的数据集

  • alpha越大,模型约束性越强,系数越趋向于0,训练集性能越低,泛化能力越强

  • alpha非常小,系数几乎没有限制,结果与linear类似

ridge10=Ridge(alpha=10).fit(X_train,y_train)
print("Train set score:{:.2f}".format(ridge10.score(X_train,y_train)))
print("Test set score:{:.2f}".format(ridge10.score(X_test,y_test)))
Train set score:0.79
Test set score:0.64
ridge01=Ridge(alpha=0.1).fit(X_train,y_train)
print("Train set score:{:.2f}".format(ridge01.score(X_train,y_train)))
print("Test set score:{:.2f}".format(ridge01.score(X_test,y_test)))
Train set score:0.93
Test set score:0.77
ridge0001=Ridge(alpha=0.001).fit(X_train,y_train)
print("Train set score:{:.2f}".format(ridge0001.score(X_train,y_train)))
print("Test set score:{:.2f}".format(ridge0001.score(X_test,y_test)))
Train set score:0.95
Test set score:0.63
# 约束越强,y值越趋向于0
# 约束强
plt.plot(ridge10.coef_,"^",label="alpha=10")
# 约束中
plt.plot(ridge.coef_,"s",label="alpha=1")
# 约束弱
plt.plot(ridge01.coef_,"v",label="alpha=0.1")
# 无约束
plt.plot(lr.coef_,"o",label="linear")

plt.xlabel("Coefficient index")
plt.ylabel("Coefficient magnitude")
plt.hlines(0,0,len(lr.coef_))
plt.ylim(-25,25)
plt.legend()
plt.show()
output_31_0
  • 固定alpha的值,改变训练集数据量
  • 将模型性能作为数据集大小的函数进行绘图,这样的图像叫作学习曲线
mglearn.plots.plot_ridge_n_samples()
output_33_0.png
  • 训练集分数高于测试集分数
  • ridge训练集分数低于linear训练集分数
  • ridge测试集分数高于linear测试集分数
  • 数据越多,性能越好
  • 如果数据量足够多,正则化不再重要,rideg与linear会得到同样的性能
  • 数据越多,linear将更加难以过拟合或记住所有的数据

4 lasso

  • 约束系数使其接近于0
  • 使用L1正则化
  • 使某些系数刚好为0,说明某些特征被模型完全忽略,更容易解释,呈现模型最重要的特征
  • 自动化特征选择
from sklearn.linear_model import Lasso
lasso = Lasso().fit(X_train,y_train)
print("Train set score:{:.2f}".format(lasso.score(X_train,y_train)))
print("Test set score:{:.2f}".format(lasso.score(X_test,y_test)))
print("Number of features used:{}".format(np.sum(lasso.coef_!=0)))
Train set score:0.29
Test set score:0.21
Number of features used:4
  • 训练集和测试集的性能都很差,欠拟合
  • 只用到了104个特征中的4个
  • 正则化参数alpha,默认是1
  • 为降低欠拟合,尝试减小alpha,同时增加max_iter
  • alpha越小,模型越复杂,越不容易欠拟合
  • alpha极小,结果与linear类似
lasso001 = Lasso(alpha=0.01,max_iter=100000).fit(X_train,y_train)
print("Train set score:{:.2f}".format(lasso001.score(X_train,y_train)))
print("Test set score:{:.2f}".format(lasso001.score(X_test,y_test)))
# 模型用了33个特征,性能好了些
print("Number of features used:{}".format(np.sum(lasso001.coef_!=0)))
Train set score:0.90
Test set score:0.77
Number of features used:33
lasso00001 = Lasso(alpha=0.0001,max_iter=100000).fit(X_train,y_train)
print("Train set score:{:.2f}".format(lasso00001.score(X_train,y_train)))
print("Test set score:{:.2f}".format(lasso00001.score(X_test,y_test)))
# 模型用了96个特征,类似linear,过拟合
print("Number of features used:{}".format(np.sum(lasso00001.coef_!=0)))
Train set score:0.95
Test set score:0.64
Number of features used:96
plt.plot(lasso.coef_, 's', label="Lasso alpha=1")
plt.plot(lasso001.coef_, '^', label="Lasso alpha=0.01")
plt.plot(lasso00001.coef_, 'v', label="Lasso alpha=0.0001")

plt.plot(ridge01.coef_, 'o', label="Ridge alpha=0.1")
plt.legend(ncol=2, loc=(0, 1.05))
plt.ylim(-25, 25)
plt.xlabel("Coefficient index")
plt.ylabel("Coefficient magnitude")
plt.show()
output_41_0.png
  • alpha=1,只用到了104个特征中的4个,大部分系数都为0,而且系数比较小
  • alpha=0.01,用了33个特征
  • alpha=0.0001,用了96个特征,大不分系数不为0,而且系数比较大
  • ridge(alpha=0.1)性能与lasso(alpha=0.01)性能类似,但是ridge的所有系数都不为0

实践中:

  • 首先ridge
  • 特征多,认为只有其中几个是重要的,选择lasso
  • 想更容易解释,选择lasso
  • scikit-learn提供了ElasticNet,结合了ridge和lasso的惩罚项,效果最好,需要调节l1正则化参数和l2正则化参数,共2个参数

你可能感兴趣的:(Python机器学习基础教程学习笔记(5)——线性模型(回归))