机器学习第六周 机器学习重要概念补充

机器学习第六周 机器学习重要概念补充

一、学习目标

  • sklearn中的Pipeline
  • 偏差与方差
  • 模型正则化之L1正则、L2正则

二、学习内容

《浅析多项式回归与sklearn中的Pipeline

《ML/DL重要基础概念:偏差和方差

《(理论+代码)模型正则化:L1正则、L2正则

三、开动ing

前面已经对简单线性回归和多元线性回归做了学习,如果数据没有线性关系那该如何处理。也就是对非线性数据如何处理。

1。多项式回归

在数学中学习过多项式函数,类比线性回归,是否是有多项式回归。

多项式回归:一个因变量与一个或多个自变量多项式的回归分析方法。

如何使用多元线性回归方法解决非线性关系的拟合问题。
比 较 y 1 = a x 2 + b x + c , y 2 = a x 2 + b x 1 + c x 0 此 处 x 0 = 1 比较 y_1 = ax^2+bx+c , y_2=ax_2+bx_1+cx_0 此处x_0=1 y1=ax2+bx+cy2=ax2+bx1+cx0x0=1
y2为我们多元线性回归的例子,而y_1则是一元多项式的形式,通过比较是否可以将x**2 ,利用x2替换,使用多元线性回归的方式进行对拟合吗?

#模拟一元二次非线性关系
import numpy  as np
import matplotlib.pyplot as plt
x = np.random.uniform(-3, 3, size =100)
X = x.reshape(-1,1)
y = 0.5 + x**2 + x + 2 + np.random.normal(0,1,size=100)
plt.scatter(x, y)
plt.show()

在这里插入图片描述
上面用到的两个函数np.random.uniform 和 normal

不在numpy中其实也是有random包,有对应的两个函数,这里仅介绍numpy中的。

#均匀分布 [low,high),获得数值将在上述区间范围内
numpy.random.uniform(low=0.0,high = 1.0,size = None)
size 可以为int 或者ints 的tuple (m,n,k)
在绘图中用到de np.random.uniform(-3,3,100) 即在[-3,3)之间随机产生100个数值

#标准(高斯)分布  或者叫做正态分布
np.random.normal(loc=0.0 ,scale=1.0,size=None)
loc 为均值,scale 为standard deviation  标准差 ,size同上

查询类似知识,可以通过浏览器在输入类似
numpy  random  normal  
可查到对应包下的解释

很明显,上面图再用一条直线表示则其误差会很大,直观上感觉更像是一条抛物线,不过开口朝上。

#这里使用简单线性回归拟合,可以看下结果
from  sklearn.linear_model import LinearRegression
lin_reg = LinearRegression()
lin_reg.fit(X,y)
y_predict = lin_reg.predict(X)
plt.scatter(X,y)
plt.plot(x , y_predict , color='r')
plt.show()

在这里插入图片描述
很显然,这样并不合适,利用x平方,用一个新变量替代的方式,我们使用多元线性回归在试一下,(前提是做个转换)
x 2 − − − > x 2 x^2 ---> x_2 x2>x2

#利用多元线性回归拟合非线性数据
x2 = np.hstack([X , X**2])
#这里每一行都扩展为了两个变量
lin_reg2 = LinearRegression()
lin_reg2.fit(x2,y)
y_predict2 = lin_reg2.predict(x2)

plt.scatter(x,y)
#需要拍一下序
#plt.plot(x,y_predict2,color='r')
plt.plot(np.sort(x),y_predict2[np.argsort(x)],color='r')
plt.show()

在这里插入图片描述
x本身是大小相间的,对应的预测值也是,如果不排序,绘制出来的图形则是像下面一样:

在这里插入图片描述
然后得到拟合的系数:

lin_reg2.coef_ ,lin_reg2.intercept_
#系数对应的顺序 x1 x2  ,  b0
(array([0.9319179 , 1.00814005]), 2.545243861036757)

y = 1.00814 x 2 + 0.9319179 x + 2.54524 y = 1.00814x^2+0.9319179x+2.54524 y=1.00814x2+0.9319179x+2.54524

这种方式是通过我们手工方式实现的,而在sklearn的preprocessing 中PolynomialFeatures则已经帮我们实现了,将代码换成他的实现方式则是:

#使用sklearn中的多项式回归,调用库preprocessing
from sklearn.preprocessing import PolynomialFeatures
#degree表示使用多少次幂的多项式
poly = PolynomialFeatures(degree=2)
poly.fit(X)
X2 = poly.transform(X)
X2.shape

针对PolynomialFeatures的解释:

Generate polynomial and interaction features 生成多项式项

如degree=2且 [a,b] ===>[1 ,a ,b, ,a平方,ab,b平方]

http://lijiancheng0614.github.io/scikit-learn/modules/generated/sklearn.preprocessing.PolynomialFeatures.html

#将原始数据通过polynomialfeatures生成相应的多项式特征
#多项式数据可能还需要进行特征归一化处理
#将数据送给线性回归
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler
poly_reg = Pipeline([
    ('poly',PolynomialFeatures(degree=2)),
    ('std_scale',StandardScaler()),
    ('line_reg',LinearRegression())
])
poly_reg.fit(X,y)
y_predict = poly_reg.predict(X)
plt.scatter(x,y)
plt.plot(np.sort(x),y_predict[np.argsort(x)],color='r')
plt.show()
#上述结果是一样的

在具体实现中,如上sklearn中的Pipeline其将几个过程封装到了一起,利用参数列表中每一个元素实现对应的操作过程。

(1)将原始数据通过PolynomialFeatures生成相应的多项式特征

(2)多项式数据进行特征归一化

(3)将数据送给线性回归

2。ML/DL重要基础概念:偏差和方差

机器学习中过拟合和欠拟合,从其字面意思即可看出一种是拟合过度,虽然这个数据集的结果比较理想,但是换了数据集可能就不好了。而欠拟合,则是理解没到位。

偏差bias:衡量模型的预测值与实际值之间的偏离关系。如果模型准确度为96%,说明低偏差

方差 variance:训练数据在不同迭代阶段的训练模型中,预测值的变化波动情况(或离散情况)。每个预测值与预测均值差的平方和再求平均数。

在这里插入图片描述
在低偏差,高方差,这种情况叫做过拟合。是模型太贴合训练数据,导致其泛化或通用的能力变差,这类情况,在使用测试集时往往准确度明显下降。

模型误差=偏差+方差+噪音误差。随着模型复杂度的增加,方差会逐渐增大,而偏差会逐渐变小。

在这里插入图片描述
导致产生误差的原因:

(1)有偏差,可能是假设不对,或者欠拟合。

(2)方差上,一点点数据扰动就会出现较大影响。(模型太复杂)

KNN算法,天生是高方差的算法;线性回归则是高偏差算法

那么如何折中,选择?

在这里插入图片描述

在这里插入图片描述
因此通过上面两个图:

1.在避免偏差是,需要尽量选择正确的模型,

2.在有了正确模型后,慎重选择数据集大小。数据集大到能对整体有代表性后,在增加量,则不会提升模型。训练数据集太小,是欠拟合;过多则会带来过拟合。模型复杂度太高,方差也会很大

3.选择合适的模型复杂度,但复杂度高的模型对训练数据通常有很好的拟合功能,但也可能会导致过拟合。

处理高方差的手段:

降低模型复杂度

减少数据维度;降噪

增加样本书

使用验证集

一种解决过拟合(高方差)的方法:模型正则化

模型正则化 regularization ,对学习算法的修改,限制参数的大小,减少泛化误差而不是训练误差。

正则化的策略包括:约束和惩罚被设计为编码特定类型的先验只是 偏好简单模型 其他形式

from  sklearn.linear_model import LinearRegression
from  sklearn.pipeline import Pipeline
from  sklearn.preprocessing import StandardScaler
from  sklearn.preprocessing import PolynomialFeatures
from  sklearn.metrics import mean_squared_error
from  sklearn.model_selection import train_test_split

lin_reg = LinearRegression()
def PolynomialRegression(degree):
    return Pipeline([
        ('poly',PolynomialFeatures(degree)),
        ('std_scaler',StandardScaler()),
        ('lin_reg',lin_reg)
    ])
np.random.seed(666)
x_train,x_test,y_train,y_test = train_test_split(X,y)

poly30_reg = PolynomialRegression(degree=30)
poly30_reg.fit(x_train,y_train)
y30_predict = poly30_reg.predict(x_test)
mean_squared_error(y_test,y30_predict)
#6.918170737784432
x_plot = np.linspace(-3,3,100).reshape(100,1)
y_plot = poly30_reg.predict(x_plot)
plt.scatter(x,y)
plt.plot(x_plot,y_plot,color='r')
plt.axis([-3,3,0,10])
plt.show()

在这里插入图片描述
30次的多项式拟合,结合图形来看,明显的过拟合。这里目标函数为了尽可能去拟合数据,使得曲线变得很陡峭。表现在数学上,其方程系数很大

lin_reg.coef_ ,lin_reg.intercept_

(array([ 8.04195683e+13, -8.78259044e+00,  5.18157783e+01,  8.75716369e+01,
        -3.74391918e+03, -1.73640368e+03,  9.16252053e+04,  7.28733805e+04,
        -1.19429168e+06, -1.13652427e+06,  9.83824544e+06,  9.42869774e+06,
        -5.53328893e+07, -4.89040470e+07,  2.21124073e+08,  1.70419876e+08,
        -6.41153489e+08, -4.12584616e+08,  1.36031734e+09,  7.02480418e+08,
        -2.10764328e+09, -8.37752038e+08,  2.35331893e+09,  6.84512606e+08,
        -1.84055045e+09, -3.64748419e+08,  9.55356489e+08,  1.14091041e+08,
        -2.95244060e+08, -1.58782105e+07,  4.10754564e+07]),
 5.619906062003203)

如何将这里的系数进行调整?

这里就有L1正则化

L1正则化,是在目标函数中添加L1范数。使用L1正则化的模型叫做LASSO回归。

其思路:原本线性回归问题求解是使其目标最优:
是 使 ∑ i = 1 m ( y ( i ) − θ 0 − θ 1 X 1 i − θ 2 X 2 i − . . . − θ n X n i ) 最 小 是使\sum_{i=1}^{m}(y^{(i)}-\theta_0-\theta_1X_1^i-\theta_2X_2^i-...-\theta_nX_n^i)最小 使i=1m(y(i)θ0θ1X1iθ2X2i...θnXni)
这几就是原始数据y和使用参数后预测值的均方误差尽可能的小

J ( θ ) = M S E ( y , y ^ : θ ) 尽 可 能 小 J(\theta) =MSE(y,\hat{y}:\theta)尽可能小 J(θ)=MSE(y,y^:θ)

如果过拟合的话,正如上面,其参数会非常大。

因此提供思路是限制参数,将参数引入目标函数中,引入正则化:

使 J ( θ ) = M S E ( y , y ^ ; θ ) + α ∑ i = 1 n ∣ θ i ∣ 尽 可 能 小 使J(\theta)=MSE(y,\hat{y};\theta)+\alpha\sum_{i=1}^{n}{|\theta_i|}尽可能小 使Jθ=MSE(y,y^;θ)+αi=1nθi

这样要使其J尽可能小,总和两项,后面带系数的参数绝对值和,要是尽可能小,因此就会避免之前看到的问题。

LASSO : least absolute shrinkage and selection operation regression
: 1 , θ , 这 里 没 有 计 算 、 θ 0 , 因 为 这 个 是 截 距 , 不 影 响 曲 线 的 陡 峭 与 缓 和 , 只 是 将 曲 线 整 体 平 移 。 : 2 , α 表 示 优 化 的 侧 重 , 即 后 面 这 一 项 在 整 体 优 化 目 标 函 数 中 权 重 程 度 :1 ,\theta,这里没有计算、\theta_0,因为这个是截距,不影响曲线的陡峭与缓和,只是将曲线整体平移。 :2 ,\alpha 表示优化的侧重,即后面这一项在整体优化目标函数中权重程度 :1θθ0线线:2α
L1正则化的影响:

稀疏性:模型中很多参数是0

L1正则化可以使得参数稀疏化。对模型进行了一次特征选择,只留下一些比较重要的特征,提高模型的泛化能力,降低过拟合的可能。(降低模型的复杂度)

def LassoRegression(degree,alpha):
    return Pipeline([
        ('poly',PolynomialFeatures(degree)),
        ('std_scaler',StandardScaler()),
        ('lin_reg',Lasso(alpha=alpha))
    ])
    
#lasso
lasso_reg = LassoRegression(degree=30, alpha = 0.0001)
lasso_reg.fit(x_train,y_train)
ylasso_predict = lasso_reg.predict(x_test)
mean_squared_error(y_test,ylasso_predict)
#1.2253114093425905    
x_plot = np.linspace(-3,3,100).reshape(100,1)
y_plot = poly30_reg.predict(x_plot)
ylasso_plot = lasso_reg.predict(x_plot)
plt.scatter(x,y)
plt.plot(x_plot,y_plot,color='r')
plt.plot(x_plot,ylasso_plot,color='b')
plt.axis([-3,3,0,10])
plt.show()

在这里插入图片描述
蓝色的线则是加入了L1正则化后的结果,其方差也有明显变化6.x—>1.x

alpha =0.1时:

在这里插入图片描述
alpha 过大时:

在这里插入图片描述
因此alpha的值要适中。

一般我们在考虑到绝对值时,很自然会想到平方,这时会有另外一种正则化方式L2正则化

L2正则化

岭回归,:
J ( θ ) = M S E ( y , y ^ : θ ) + α ∑ i = 1 n θ 2 尽 可 能 的 小 J(\theta) = MSE(y,\hat{y}:\theta) +\alpha \sum_{i=1}^{n}\theta^2尽可能的小 Jθ=MSE(y,y^:θ)+αi=1nθ2
L2范数的结果,是比较平滑,但是不具有稀疏性。

def ridgeRegression(degree, alpha):
    return Pipeline([
        ('poly',PolynomialFeatures(degree)),
        ('std_scaler',StandardScaler()),
        ('lin_reg',Ridge(alpha=alpha))
    ])
    
#ridge L2范式
ridge_reg = ridgeRegression(degree=30, alpha =0.1)
ridge_reg.fit(x_train, y_train)
yridge_predict = ridge_reg.predict(x_test)
ridge_mse = mean_squared_error(y_test,yridge_predict)
poly30_mse,lasso_mse,ridge_mse
#(6.918170737784432, 1.0131853164117148, 1.2048961054331477)

可以看出L2范式结果的均方误差比过拟合的6.9要好很多。

在这里插入图片描述

#上图绘图的代码如下,黄色是L2正则化,蓝色是L1正则化,红色是过拟合
x_plot = np.linspace(-3,3,100).reshape(100,1)
y_plot = poly30_reg.predict(x_plot)
ylasso_plot = lasso_reg.predict(x_plot)
yridge_plot = ridge_reg.predict(x_plot)
plt.scatter(x,y)
plt.plot(x_plot,y_plot,color='r')
plt.plot(x_plot,ylasso_plot,color='b')
plt.plot(x_plot,yridge_plot,color='y')
plt.axis([-3,3,0,10])
plt.show()

L2 alpha =0.0001

在这里插入图片描述
alpha = 0.1

在这里插入图片描述
alpha =100

在这里插入图片描述
从L1和L2相比较,alpha取值过大都会导致误差增加,拟合曲线会变成直线。

LASSO 更倾向于是的部分参数为0,产生参数稀疏,拟合曲线更倾向于直线。所以作为特征选择使用。Lasso可能会去掉正确的特征,从而降低准确度,但如果特征特别大,使用LASSO可使模型变小。

总结:

本文从非线性回归入手,利用多元线性回归实现了非线性回归。接着高次非线性拟合的过拟合问题入手,介绍了两种正则化的解决方案。

注:本文代码参考值: 数据科学家联盟 木东居士 和 饼干
是机器学习小组的学习笔记。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值