机器学习-线性回归

## 一、机器学习评估指标
- 1.机器学习的一些基本概念 有监督、无监督、泛化能力、过拟合、欠拟合(方差和偏差以及各自解决办法)、交叉验证原理
- 2.线性回归的原理
- 3.线性回归损失函数、代价函数、目标函数
- 3.优化方法(梯度下降法、随机梯度下降法、牛顿法、拟牛顿法等)
- 4.机器学习模型评估指标
- 5.Sklearn 线性回归的使用

一、机器学习的基本概念

  • 有监督学习: 训练数据既有特征又有标签,通过训练,让机器可以自己找到特征和标签的联系,在面对只有特征没有标签的数据时,可以判断出标签。

  • 无监督学习: 训练样本的标记信息未知,目标是通过对无标记样本的学习来揭示数据的内在性质和规律。为进一步的数据分析提供基础。此类学习研究最多、应用最广的是“聚类”。其他就是:k均值聚类算法、谱聚类、主成分分析法(PCA)

  • 半监督学习: 训练集同时包含有标记样本数据和未标记样本数据,不需要人工干预,让机器不依赖外界交互,自动地利用未标记样本来提升学习性能,就是半监督学习

  • 泛化能力: 学习到的模型对未知数据的预测能力。

  • ① 什么是欠拟合? 欠拟合是指模型不能在训练集上获得足够低的误差。换句换说,就是模型复杂度低,模型在训练集上就表现很差,没法学习到数据背后的规律
    怎么解决欠拟合? 欠拟合基本上都会发生在训练刚开始的时候,经过不断训练之后欠拟合应该不怎么考虑了。但是如果真的还是存在的话,可以通过增加网络复杂度或者在模型中增加特征,这些都是很好解决欠拟合的方法。

  • 什么是过拟合?
    过拟合是指训练误差和测试误差之间的差距太大。换句换说,就是模型复杂度高于实际问题,模型在训练集上表现很好,但在测试集上却表现很差。模型对训练集"死记硬背"(记住了不适用于测试集的训练集性质或特点),没有理解数据背后的规律,泛化能力差。
    ②为什么会出现过拟合现象?
    造成原因主要有以下几种:1、训练数据集样本单一,样本不足。 如果训练样本只有负样本,然后那生成的模型去预测正样本,这肯定预测不准。所以训练样本要尽可能的全面,覆盖所有的数据类型。
    2、训练数据中噪声干扰过大。 噪声指训练数据中的干扰数据。过多的干扰会导致记录了很多噪声特征,忽略了真实输入和输出之间的关系。
    3、模型过于复杂。 模型太复杂,已经能够“死记硬背”记下了训练数据的信息,但是遇到没有见过的数据的时候不能够变通,泛化能力太差。我们希望模型对不同的模型都有稳定的输出。模型太复杂是过拟合的重要因素。
    ③如何防止过拟合?
    1.获取和使用更多的数据(数据集增强)——解决过拟合的根本性方法
    2.采用合适的模型(控制模型的复杂度)
    3.降低特征的数量
    4.L1 / L2 正则化
    5.Dropout
    6.Early stopping(提前终止)

  • 交叉验证原理
    交叉验证是在机器学习建立模型和验证模型参数时常用的办法。交叉验证,顾名思义,就是重复的使用数据,把得到的样本数据进行切分,组合为不同的训练集和测试集,用训练集来训练模型,用测试集来评估模型预测的好坏。
    三种常用的交叉验证:简单交叉验证、K折交叉验证、留一交叉验证

二、线性回归原理

1.线性回归大家族(有监督)

  • 回归是一种应用非常广泛的预测建模技术,这种技术的核心在于预测的结果是连续型变量
  • 理解线性回归有两种角度:矩阵的角度和代数的角度,本课程会使用矩阵方式(线性代数的方式)为大家展示回归家族

2多元线性回归LinearRegression

2.1多元线性回归的基本原理

  • 多元线性回归指的就是一个样本有多个特征的线性回归问题
    在这里插入图片描述

  • 考虑有m个样本,则m个样本的回归结果可以写为下式:其中y是包含了m个全部的样本的回归结果的列向量
    在这里插入图片描述
    在这里插入图片描述

  • 线性回归的任务:就是构造一个预测函数来映射输入的特征矩阵X和标签值y的线性关系,这个预测函数的本质就是我们需要构建的模型,而构造预测函数的核心就是找出模型的参数向量w(但我们怎样才能够求解出参数向量呢?)

    • 1.先定义损失函数,然后通过最小化损失函数或损失函数的某种变化来求解参数向量,以此将单纯的求解问题转化为一个最优化问题
      在这里插入图片描述
  • 这个式子我们常称为RSS (残差平方和)
    在这里插入图片描述

2.2 最小二乘法求解多元线性回归的参数

  • 求极值也就意味着先求出导数=0,即RRS对w求导:
    在这里插入图片描述
  • 让求导后的一阶导数为0:(但是在这里,逆矩阵的充分必要条件是特征矩阵不存在多重共线性
    在这里插入图片描述
  • 假设矩阵的逆是存在的,此时w就是我们参数的最优解。求解出这个参数向量,我们就解出了我们的Xw,也就能计算出我们的预测值y^。( X T X^T XTX其实是使用奇异值分解SVD来求解的)
  • 使用最小二乘法来求解线性回归的方法是一种“无偏估计”的方法,这种无偏估计要求因变量y,也就是标签的分布必须服从正态分布。因此我们的y必须经由正态化处理。在机器学习中我们会先考虑模型的效果。如果效果不好,那我们可能考虑改变因变量的分布

2.3 linear_model.LinearRegression

class sklearn.linear_model.LinearRegression(fit_intercept=True,normalize=False,copy_X=True,n_jobs=None)

在这里插入图片描述

  • 该算法多半是基于数据本身,而不是可以通过多方式调参或改造来优化性能

在这里插入图片描述

#1.导入需要的模块和库
from sklearn.linear_model import LinearRegression as LR
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_val_score
from sklearn.datasets import fetch_california_housing as fch #加利福尼亚房屋数据集
import pandas as pd

#2.导入数据,探索数据
housevalue = fch() #需要下载
x = pd.DataFrame(housevalue.data) #放入dataframe中便于查看
x.shape
y = housevalue.target
y.shape
x.head()
housevalue.feature_names #特征名字

'''
'MedInc':该街区住户的收入中位数
 'HouseAge':该街区房屋使用年代的中位数
 'AveRooms':该街区平均的房间数目
 'AveBedrms':该街区平均的卧室数目
 'Population':街区人口
 'AveOccup:平均入住率
 'Latitude':街区放入维度
 'Longitude'街区的精度
'''
x.columns = housevalue.feature_names
x.head()

#3.划分训练集和测试集
Xtrain,Xtest,Ytrain,Ytest = train_test_split(x,y,test_size=0.3,random_state=420)
Xtrain.head() #查看是否划分正确

#因为随机生成的Xtrain,Xtest是乱序的,所以恢复索引
for i in [Xtrain,Xtest]:
    i.index = range(i.shape[0])

Xtrain.head()
Xtrain.shape
#如果希望进行数据标准化,还记得应该怎么做嘛?
#先用训练集训练(fit)标准化的类,然后用训练好的类分别转化(transfrom)训练集和测试集

#4.建模
reg = LR().fit(Xtrain,Ytrain) #实例化
yhat = reg.predict(Xtest) #预测我们的yhad
yhat

#5.探索建好的模型
reg.coef_  #w.  系数的向量
[*zip(Xtrain.columns,reg.coef_)]
reg.intercept_  #查看截距

3 回归类的模型评估指标

  • 回归算法中,我们用不同的角度来看待回归效果:
    1、我们是否预测到了正确的数值
    2、我们是否拟合到了足够的信息

3.1我们是否预测到了正确的数值

  • RSS既是我们的损失函数,也是我们回归类模型的迷行评估指标之一,但是有着致命的缺点:它是一个无界的和,可以无限地大。
  • 为了应对这种状况,skearn中使用RSS的变体:均方误差MSE来衡量我们的预测值和真实值的差异:
    在这里插入图片描述
  • 得到每个样本量的平均误差,我们就可以将平均误差和我们的标签的取值范围在一起比较,以此获得一个较为可靠的评估依据。
  • sklearn中,有两种方式调用评估指标
#1.使用sklearn专用的模型评估模块metrics里的类mean_squares_error
from sklearn.metrics import mean_squared_error as MSE
MSE(yhat,Ytest)

Ytest.mean()  #有20%的预测错误
y.max()
y.min()

#2.调用交叉验证的类cross_val_score并使用里面的scoring参数来设置使用均方误差
cross_val_score(reg,x,y,cv=10,scoring="mean_squared_error")

#为什么以上报错了?来试试看
import sklearn
sorted(sklearn.metrics.SCORERS.keys())

cross_val_score(reg,x,y,cv=10,scoring="neg_mean_squared_error")
cross_val_score(reg,x,y,cv=10,scoring="neg_mean_squared_error")*(-1)  #得到均方误差的真实值
cross_val_score(reg,x,y,cv=10,scoring="neg_mean_squared_error").mean()
  • 线性回归的一号大坑:均方误差为负
    (因为sklearn在计算模型评估指标的时候,会考虑指标本身的性质,均方误差本身是一种误差,所以被sklearn划分为模型的一种损失(loss),在sklearn中,所有的损失都使用负数表示,因此均方误差也被显示为负数了)
  • MAE(绝对均值误差),在现实使用中,MSE和MAE选一个使用就好了
    在这里插入图片描述

3.2是否拟合了足够的信息

  • 除了数据本身数值大小,我们还希望能够捕捉到数据的“规律”
    在这里插入图片描述
  • 方差的本质就是任意一个y值和样本均值的差异,差异越大,这些值所带的信息越多。
  • R 2 R^2 R2中,分子是真实值和预测值之间的差值,也就是我们的模型没有捕捉到的信息总量,分母就是真实标签所带的信息量。而1-我们的模型没有捕捉到的信息量占真实标签中所带的信息量的比例。因此 R 2 R^2 R2越接近1 越好
  • R 2 R^2 R2调用的三种方式:
#1.直接从metrics中导入r2_score,输入预测值和真实值后打分
from sklearn.metrics import r2_score
r2_score(yhat,Ytest)

#2.从线性回归LinearRegression的接口score来进行调用
r2 = reg.score(Xtest,Ytest)

#3.在交叉验证中,输入r2来调用
r2
  • 线性回归的二号大坑: 相同的评估指标不同的结果
    R 2 R^2 R2涉及到的计算中对预测值和真实值有极大的区别,必须是预测值在分子,真实值在分母,所以我们在调用metrics模块中的模型评估指标的时候,必须检查清楚,指标的参数中,究竟是要求我们先输入真实值还是先输入预测值。
#使用shift tab键来检查究竟哪个值先进行输入
r2_score(Ytest,yhat)

#或者可以指定参数,就不必在意顺序
r2_score(y_true = Ytest,y_pred =yhat )

cross_val_score(reg,x,y,cv=10,scoring='r2').mean()
  • 在加利福尼亚房屋预测数据集上的MSE不是一个很大的值(0.5),但是 R 2 R^2 R2不高。这说明没能正确拟合的数据分布。可绘图看看我们的结果
import matplotlib.pyplot as plt
sorted(Ytest) #排序

plt.plot(range(len(Ytest)),sorted(Ytest),c="black",label="Data")
plt.plot(range(len(yhat)),sorted(yhat),c="red",label="Predict")
plt.legend()
plt.show()

在这里插入图片描述

  • 在sklearn中,一个与 R 2 R^2 R2非常相似的指标叫做可解释性方差分数(EVS),它也是衡量1-没有捕捉到的信息占总信息的比例,但它与 R 2 R^2 R2略有不同。

看一组有趣的情况

import numpy as np
rng = np.random.RandomState(42)
X = rng.randn(100,80)
y = rng.randn(100)
cross_val_score(LR(),X,y,cv=5,scoring='r2')
  • 线性回归的三号大坑: 负的 R 2 R^2 R2
    当我们的 R 2 R^2 R2显示为负的时候,这就证明模型对数据的拟合非常糟糕,模型完全不能用。如果你检查了所有代码,也确定你的预处理没有问题,但你的 R 2 R^2 R2也还是负的,那就证明,线性回归模型不适合你的数据,试试看其他的算法吧。
    在这里插入图片描述在这里插入图片描述

4.多重回归:岭回归与Lasso

4.1多重共线性

在这里插入图片描述

  • 而逆矩阵存在的充分必要条件: 特征矩阵不存在多重共线性
  • 逆矩阵存在的充分必要条件: 矩阵的行列式不为0,即是| X T X X^TX XTX |不能为0,这是使用最小二乘法求解线性回归的核心条件。
  • 行列式不为0的充分必要条件: 矩阵满秩是矩阵的行列式不为0的充分必要条件
  • 精确相关关系(矩阵秩为0)和高度相关关系(矩阵秩非常接近0)并成为“多重共线性
  • 矩阵满秩的充分必要条件: 一个矩阵如果要满秩,则要求矩阵中每个向量之间不能存在多重共线性。这也构成了线性回归算法对于特征矩阵的要求
    在这里插入图片描述
  • 多重共线性 是一种统计现象,是指线性模型中的特征(解释变量)之间犹豫存在精确相关关系或高度相关关系,多重共线性的存在会使得模型无法建立或者估计失真。
  • 相关性 是衡量两个或多个变量一起波动的程度的指标,通常指线性相关性
  • 三种常见的能够处理多重共线性的方法:
    在这里插入图片描述
  • 处理多重共线性的核心首选是使用改进线性回归:岭回归、Lasso

4.2岭回归

4.2.1岭回归解决多重共线性
  • 岭回归——又称吉洪诺夫正则化,在多元线性回归的损失函数上加上了正则项。岭回归的损失函数的完整表达式为:
    在这里插入图片描述
  • 在线性回归中我们通过在损失函数上对w求导来求解极值,我们依旧使用最小二乘法来求解()
    -在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 以上也就是说,矩阵的逆是永远存在的!
    在这里插入图片描述
  • 正则化系数 a a a就避免了“精确相关关系”带来的影响,这样一来,多重共线性也就被控制住了:最小二乘法一定有解,并且这个解可以通过 a a a来调节,以确保不会偏离太多。在使用中,需要找出 a a a让模型效果变好的最佳取值。
4.2.2 linear_model.Ridge
  • 岭回归模型的调用
class sklearn.linear_model.Ridge(alpha=1.0,fit_intercept=True,nomalize=False,copy_X=True,max_iter=None,tol=0.001,solver='auto',random_state=None)
  • 但是真正的核心参数是我们的正则化系数 a a a 所以大家只需要了解 a a a的用法就好啦
  • 利用模型来判断多重共线性: 在机器学习中,我们可以用模型来判断——如果一个数据集在岭回归中使用各种正则化参数取值下模型表现没有明显上升(比如出现持平或者下降),这说明数据没有多重共线性,顶多就是特征之间的一些相关性。反之则说明数据存在多重共线性。
import numpy as np
import pandas as pd
from sklearn.linear_model import Ridge,LinearRegression,Lasso
from sklearn.model_selection import train_test_split as TTS
from sklearn.model_selection import cross_val_score
from sklearn.datasets import fetch_california_housing as fch
import matplotlib.pyplot as plt

housevalue = fch()
X = pd.DataFrame(housevalue.data)
y = housevalue.target
X.columns = ["住户收入中位数","房屋使用年代的中位数","平均的房间数目","平均的卧室数目","街区人口","平均入住率","街区维度","街区的精度"]
X.head()

Xtrain,Xtest,Ytrain,Ytest = TTS(X,y,test_size=0.3,random_state=420)
Xtrain.head()

#恢复索引
for i in [Xtrain,Xtest]:
    i.index = range(i.shape[0])
Xtrain.head()

#使用岭回归来进行建模
reg = Ridge(alpha=1).fit(Xtrain,Ytrain)
reg.score(Xtest,Ytest) #加利福尼亚州房屋价值数据集中应该不是共线性问题

#在交叉验证下,与线性回归相比,岭回归的结果如何变化?
alpharange = np.arange(1,1001,100)
ridge,lr = [],[]
for alpha in alpharange:
    reg = Ridge(alpha = alpha)
    linear = LinearRegression()
    regs = cross_val_score(reg,X,y,cv=5,scoring = "r2").mean()
    linears = cross_val_score(linear,X,y,cv=5,scoring = "r2").mean()
    ridge.append(regs)
    lr.append(linears)
    
plt.plot(alpharange,ridge,color="red",label="Ridge")
plt.plot(alpharange,lr,color="orange",label="LR")
plt.title("Mean")
plt.legend()
plt.show
#细化一下学习曲线
alpharange = np.arange(1,201,10)
ridge,lr = [],[]
for alpha in alpharange:
    reg = Ridge(alpha = alpha)
    linear = LinearRegression()
    regs = cross_val_score(reg,X,y,cv=5,scoring = "r2").mean()
    linears = cross_val_score(linear,X,y,cv=5,scoring = "r2").mean()
    ridge.append(regs)
    lr.append(linears)
    
plt.plot(alpharange,ridge,color="red",label="Ridge")
plt.plot(alpharange,lr,color="orange",label="LR")
plt.title("Mean")
plt.legend()
plt.show
#使用岭回归来进行建模
reg = Ridge(alpha=80).fit(Xtrain,Ytrain)
reg.score(Xtest,Ytest)

#结果依然没有alpha=1来得高

#模型方差如何变化?描述泛化能力
alpharange = np.arange(1,1001,100)
ridge,lr = [],[]
for alpha in alpharange:
    reg = Ridge(alpha = alpha)
    linear = LinearRegression()
    varR = cross_val_score(reg,X,y,cv=5,scoring = "r2").var()
    varLR = cross_val_score(linear,X,y,cv=5,scoring = "r2").var()
    ridge.append(varR)
    lr.append(varLR)
    
plt.plot(alpharange,ridge,color="red",label="Ridge")
plt.plot(alpharange,lr,color="orange",label="LR")
plt.title("Variance")
plt.legend()
plt.show

  • 可以用波士顿是数据集来对比一下出现的现象
#波士顿房价数据集
from sklearn.datasets import load_boston

X = load_boston().data
y = load_boston().target

Xtrain,Xtest,Ytrain,Ytest = TTS(X,y,test_size=0.3,random_state=420)

X.shape
4.2.3 选取最佳的正则化参数取值
  • 传统方法是通过岭迹图来选取最佳正则化参数的取值 a a a,而菜菜不建议大家使用岭迹图来作为寻找最佳参数的标准。
  • 真正应用来选择正则化系数的技术是交叉验证,并且选择的标准非常明确——选择让交叉验证下的均方误差最小的正则化系数 a a a
  • 带有交叉验证的岭回归来选择最佳的正则化系数
class sklearn.linear_model.RidgeCV(alpha=(0.1,1.0,10.0),fit_intercept=True,normalize=False,scoring=None,cv=None,gcv_mode=None,store_cv_values=False)

在这里插入图片描述
在这里插入图片描述

import numpy as np
import pandas as pd
from sklearn.linear_model import RidgeCV,LinearRegression,Lasso
from sklearn.model_selection import train_test_split as TTS
from sklearn.model_selection import cross_val_score
from sklearn.datasets import fetch_california_housing as fch
import matplotlib.pyplot as plt

housevalue = fch()
X = pd.DataFrame(housevalue.data)
y = housevalue.target
X.columns = ["住户收入中位数","房屋使用年代的中位数","平均的房间数目",
            "平均的卧室数目","街区人口","平均入住率","街区维度","街区的精度"]

Ridge_ = RidgeCV(alphas = np.arange(1,1001,100)
                #,scoring = "neg_mean_squared_error"
                ,store_cv_values = True
                #,cv = 5
                ).fit(X,y)

#无交叉验证的岭回归结果
Ridge_.score(X,y)

#调用所有交叉验证的结果
Ridge_.cv_values_.shape

#进行平均后可以查看每个正则化系数取值下的交叉验证结果
Ridge_.cv_values_.mean(axis=0)

#查看被选择出来的最佳正则化系数
Ridge_.alpha_
  • 总结:以上内容解决了三大问题:
    1岭回归如何解决多重共线性问题
    2如何探索和理解对于不同正则化系数下的泛化误差如何变化
    3以及怎样来选取最佳正则化参数

4.3 Lasso解决多重共线性

4.3.1Lasso与多重共线性
  • Lasso的损失函数表达式
    在这里插入图片描述

  • 依旧对lasso的损失函数求导
    -

  • 以上问题又回到了 X T X X^TX XTX的逆必须存在,因此Lasso无法解决特征之间“精确相关”的问题

  • 岭回归 vs Lasso
    1岭回归可以解决特征间的精确相关关系导致的最小二乘无法使用的问题,而Lasso不行
    2Lasso不是根本上解决多重共线性问题,而是限制多重共线性带来的影响

  • L1和L2正则化的核心差异就是它们对系数 w w w的影响:两个正则化都会压缩系数 w w w的大小,对标签贡献更少的特征的系数会更小,也会更容易压缩。不过L2正则化会将系数压缩到尽量接近0,但L1正则化主导稀疏性,因此会将系数压缩到0.这个性质,让Lasso成为了线性模型中的特征选择工具首选

4.3.2 Lasso的核心作用:特征选择
class sklearn.linear_model.Lasso (alpha=1.0, fit_intercept=True, normalize=False, precompute=False,
copy_X=True, max_iter=1000, tol=0.0001, warm_start=False, positive=False, random_state=None, selection=’cyclic’)
  • 需要注意的是,在sklearn中我们的Lasso使用的损失函数是:
    在这里插入图片描述
  • 看看lasso如何做特征选择
import numpy as np
import pandas as pd
from sklearn.linear_model import Ridge,LinearRegression,Lasso
from sklearn.model_selection import train_test_split as TTS
from sklearn.datasets import fetch_california_housing as fch
import matplotlib.pyplot as plt

housevalue = fch()

X = pd.DataFrame(housevalue.data)
y = housevalue.target
X.columns = ["住户收入中位数","房屋使用年代的中位数","平均的房间数目",
            "平均的卧室数目","街区人口","平均入住率","街区维度","街区的精度"]

X.head()

Xtrain,Xtest,Ytrain,Ytest = TTS(X,y,test_size=0.3,random_state=420)

#恢复索引
for i in [Xtrain,Xtest]:
    i.index = range(i.shape[0])

#线性回归进行拟合
reg = LinearRegression().fit(Xtrain,Ytrain)
(reg.coef_*100).tolist()

#岭回归进行拟合
Ridge_ = Ridge(alpha=0).fit(Xtrain,Ytrain)
(Ridge_.coef_*100).tolist()

#Lasso进行拟合
lasso_ = Lasso(alpha=0).fit(Xtrain,Ytrain)
(lasso_.coef_*100).tolist()
  • 虽然结果差别不大,但是运行结果只有Lasso报错
    1.正则化系数为0,这样算法不可收敛!如果你想让正则化系数为0,请使用线性回归吧
    2.没有正则项的坐标下降法可能会导致意外的结果,不鼓励这样做
    3.目标函数没有收敛,你也许想要增加迭代次数,使用一个非常小心的alpha来拟合模型可能会造成精确度问题
<ipython-input-12-76c577e38589>:2: UserWarning: With alpha=0, this algorithm does not converge well. You are advised to use the LinearRegression estimator
  lasso_ = Lasso(alpha=0).fit(Xtrain,Ytrain)
D:\Anaconda\lib\site-packages\sklearn\linear_model\_coordinate_descent.py:529: UserWarning: Coordinate descent with no regularization may lead to unexpected results and is discouraged.
  model = cd_fast.enet_coordinate_descent(
D:\Anaconda\lib\site-packages\sklearn\linear_model\_coordinate_descent.py:529: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations. Duality gap: 3769.8607714139102, tolerance: 1.917255476913148
  model = cd_fast.enet_coordinate_descent(

-Debug tips: 在sklearn中的Lasso类不是使用最小二乘法来进行求解,而是使用坐标下降。有了序偶表下降,就有迭代和收敛问题,因此sklearn不推荐我们使用0这样的正则化系数。但是我们的确希望取到0,那我们就可以使用一个比较小的数字,比如0.001。这样就不会报错了

#Lasso进行拟合
lasso_ = Lasso(alpha=0.01).fit(Xtrain,Ytrain)
(lasso_.coef_*100).tolist()
  • 但是结果就有较大的差别
#加大正则项系数,观察模型的系数发生了什么变化
Ridge_ = Ridge(alpha=10**4).fit(Xtrain,Ytrain)
(Ridge_.coef_*100).tolist()

lasso_ = Lasso(alpha=10**4).fit(Xtrain,Ytrain)
(lasso_.coef_*100).tolist()

# 看来10**4对于Lasso来说是一个过于大的取值
lasso_ = Lasso(alpha=1).fit(Xtrain,Ytrain)
(lasso_.coef_*100).tolist()

#将系数进行绘图
plt.plot(range(1,9),(reg.coef_*100).tolist(),color="red",label="LR")
plt.plot(range(1,9),(Ridge_.coef_*100).tolist(),color="orange",label="Ridge")
plt.plot(range(1,9),(lasso_.coef_*100).tolist(),color="k",label="Lasso")
plt.plot(range(1,9),[0]*8,color="grey",linestyle="--")
plt.xlabel('w')#横坐标是每一个特征所对应的系数
plt.legend()
plt.show()

在这里插入图片描述

  • 相比于岭回归,lasso所带的L1正则项对于系数的惩罚要重得多,并且它会将系数压缩为0,因此可以用来做特征选择。同样,我们往往让lasso的正则化系数 a a a在很小的空间变动,以此来寻找最佳的正则化系数
4.3.3 Lasso选取最佳的正则化参数取值
class sklearn.linear_model.LassoCV (eps=0.001, n_alphas=100, alphas=None, fit_intercept=True,
normalize=False, precompute=’auto’, max_iter=1000, tol=0.0001, copy_X=True, cv=’warn’, verbose=False,
n_jobs=None, positive=False, random_state=None, selection=’cyclic’)
  • lasso对于正则化系数的变动过于敏感,因此设定了一个重要概念 “正则化路径” ,用来设定正则化系数的变动。
  • LassoCV会单独建模。 它会先找出最佳的正则化参数,然后再这个参数下按照模型评估指标进行建模。
  • 需要注意的是:LassoCV的模型评估指标选用的是均方误差,而岭回归的模型评估指标是可以自己设定的,默认为 R 2 R^2 R2.
    在这里插入图片描述
#参数和属性的实践代码

from sklearn.linear_model import LassoCV

#自己建立Lasso进行alpha选择的范围
alpharange = np.logspace(-10,-2,200)

alpharange.shape

lasso_ = LassoCV(alphas = alpharange #自行输入的alpha的取值范围
                ,cv=5 #交叉验证的折数
                ).fit(Xtrain,Ytrain)

#查看被选择出来的最佳正则化系数
lasso_.alpha_

#调用所有的交叉验证的结果
lasso_.mse_path_

#返回每个alpha下的五折交叉验证结果
lasso_.mse_path_.shape

lasso_.mse_path_.mean(axis=1) #有注意到在岭回归中我们的轴向是axis=0吗?


#在岭回归中,我们是留一验证,因此我们的交叉验证结果返回的是,每一个样本在每个alpha下的交叉验证结果
#因此我们要求,每个alpha下的交叉验证均值,就是axis=0,跨行求均值
#而在这里,我们返回的是,每一个alpha取值下,每一折交叉验证的结果
#因此我们要求每个alpha下的交叉验证均值,就是axis=1,跨列求均值

#最佳正则化系数下获得的模型的系数结果
lasso_.coef_

lasso_.score(Xtest,Ytest)

#与线性回归相比如何?
reg = LinearRegression().fit(Xtrain,Ytrain)
reg.score(Xtest,Ytest)

#使用LassoCV自带的正则化路径长度和路径中的alpha个数来自动建立alpha选择的范围
ls_ = LassoCV(eps=0.00001
             ,n_alphas=300
             ,cv=5
             ).fit(Xtrain,Ytrain)

ls_.alpha_

ls_.alphas_#查看所有自动生成的alpha取值

ls_.alphas_.shape

ls_.score(Xtest,Ytest)  
#可以看出结果还是没有线性回归的更好,也说明Lasso本来就不是设计来提升模型效果的

ls_.coef_ #结果可以看出:也没有任何的特征系数被压缩到0

#增大正则化路径长度为0.001.再查看效果
ls_ = LassoCV(eps=0.001
             ,n_alphas=300
             ,cv=5
             ).fit(Xtrain,Ytrain)

ls_.alpha_

ls_.score(Xtest,Ytest) 

ls_.coef_  
#结果出现了0,如果将正则化路径长度改为0.01,我们的alpha 会越来远大,而分数就会越来越小,就有更多的系数被压缩到0

  • 除了解决多重共线性这个核心的问题之外, 线性模型还有更重要的事情要做:提升模型表现。 这才是机器学习最核心的需求,而Lasso和岭回归不是为此而设计的

5 非线性问题:多项式回归

  • 为了提升模型表现而做出的改进

5.1 重塑我们心中的"线性"概念

  • 重塑线性概念,并为大家解决线性回归模型改进的核心之一:帮助线性回归解决非线性问题
5.1.1变量之间的线性关系
  • 常用的线性是指:变量之间的线性关系,即表示两个变量之间可以展开成一条直线,可以使用方程 y = a x + b y=ax+b y=ax+b来进行拟合。可绘制散点图探索是否具有线性关系
5.1.2 数据的线性与非线性
  • 线性数据: 一般来说,一组数据由多个特征和标签组成。当这些特征分别于标签存在线性关系的时候,我们就说这一组数据是线性数据

  • 非线性数据: 当特征矩阵中任意一个特征与标签之间的关系需要使用三角函数、指数函数来定义的时候,我们就说这种数据叫做非线性数据

  • 最简单的判别线性数据和非线性数据方法: 就是利用模型来帮助我们
    1.做分类则使用逻辑回归,做回归则使用线性回归;效果好那说明数据是线性的。效果不好则说明数据不是线性的
    2.也可以使用降维后进行绘图,绘制出的图像分布接近一条直线,则说明数据是线性的

  • 分类问题中的特征与标签[0,1]或者[-1,1]之间关系明显是非线性关系

  • 线性关系图,横坐标是特征,纵坐标是标签。可以通过是否能够使用一条直线来拟合图像判断究竟是线性的还是非线性的(针对回归问题)
    横坐标是标签,纵坐标是特征

  • 数据分布图,横纵坐标代表的是不同的特征,标签则是数据点的颜色。在分类数据中,我们使用 “是否线性可分” 来划分分裂数据集。当分类数据的分布上可以使用一条直线来将两类数据分开是,我们就说数据是线性可分的(针对分类问题)

5.1.3 线性模型与非线性模型
  • 在回归中,线性数据可以使用如下的方程来拟合:线性回归方程
    在这里插入图片描述
  • 线性回归模型: 根据线性回归方程,我们可以拟合出一组参数 w w w,在这组固定的参数下我们可以建立一个模型,这个模型就是线性回归模型
  • 拟合线性数据的线性模型: 建模过程就是寻找参数的过程,我们建立的线性回归模型,是一个用于拟合线性数据的线性模型
    -从线性回归方程总结线性模型的特点:其自变量都是一次项的
  • 线性回归在非线性数据上的表现如何? 利用线性回归和决策树来进行拟合,观察他们在拟合非线性数据集时的表现
#导入需要的库
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor

#创建非线性数据集
rnd = np.random.RandomState(42) #设置随机数种子
X = rnd.uniform(-3,3,size=100) #random.uniform,从输入中任意两个整数中取出size个随机数
#生成y的思路:先使用Numpy中的函数生成一个sin函数图像,然后再人为添加噪声
y = np.sin(X) + rnd.normal(size=len(X)) / 3 #rnd.normal,生成size个服从正态分布的随机数

X #作为横坐标

#使用散点图观察建立的数据集是什么样子
plt.scatter(X,y,marker='o',c='k',s=20)
plt.show()

#为后续建模做准备:sklearn只接受二维以上数组作为特征矩阵的输入
X.shape

X = X.reshape(-1,1)
X.shape

#使用原始数据进行建模
LinearR = LinearRegression().fit(X,y)
TreeR = DecisionTreeRegressor(random_state=0).fit(X,y)

#放置画布, 注意放置画布的命令和绘制图像的命令同一个框内
fig,ax1 = plt.subplots(1)
#创建测试数据:一系列分布在横坐标上的点
line = np.linspace(-3,3,1000,endpoint=False).reshape(-1,1)
#将测试数据带入predict接口,获得模型的拟合效果并进行绘制
ax1.plot(line,LinearR.predict(line),linewidth=2,color='green',label="linear regression")
ax1.plot(line,TreeR.predict(line),linewidth=2,color='red',label="decision tree")
#将原数据上的拟合绘制在图像上
ax1.plot(X[:,0],y,'o',c='k')
#其他图形选项
ax1.legend(loc="best")
ax1.set_ylabel("Regression output")
ax1.set_xlabel("Input feature")
ax1.set_title("Result before discretization")
plt.tight_layout()
plt.show()

  • 使用散点图观察建立的数据集是什么样子
    在这里插入图片描述

  • 从图像来看,可以得出什么结果?
    1.线性回归只拟合出了趋势 ,没有正确拟合出曲线的弧度,没有办法拟合出真实的分布(有趋势,没精度)
    2.决策树非常具体拟合到了每一个点上,(不是光滑的曲线,而是充满噪声的折线),太过于具体,严重过拟合,泛化能力不好
    在这里插入图片描述

  • 结果显示相比之下,还是决策树的拟合效果更好一些,决策树是一个典型的非线性模型

  • 机器学习很灵活,线性模型可以用来拟合非线性数据,而非线性模型也可以用来拟合线性数据,更神奇的是,有得算法没有模型也可以出库各类数据,而有得模型可以既可以是线性,也可以是非线性模型

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值