前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >快速入门Python机器学习(六)

快速入门Python机器学习(六)

作者头像
顾翔
发布2022-05-22 10:28:46
6390
发布2022-05-22 10:28:46
举报
文章被收录于专栏:啄木鸟软件测试

5.2 岭(Ridge)回归、套索(Lasso)回归与弹性网络(Elastic Net)的基本概念

有些数据是不太符合线性关系的,但是我们还是希望使用线性回归,在这里数学家加入了正则化Regularization的概念。

5.2.1 岭回归(Ridge Regression)

正则化Regularization为所有系数的平方和,即L2范数,对应的回归方法叫做Ridge回归,岭回归。

岭回归(英文名:Ridge Regression, Tikhonov Regularization)由前苏联安德烈·季霍诺夫 20世纪40年代提出。它是一种专用于共线性数据分析的有偏估计回归方法,实质上是一种改良的最小二乘估计法,通过放弃最小二乘法的无偏性,以损失部分信息、降低精度为代价获得回归系数更为符合实际、更可靠的回归方法,对病态数据的拟合要强于最小二乘法。岭回归牺牲训练集得分,获得测试集得分。适合密集矩阵

5.2.2 套索回归(Lasso Regression)

所有系数绝对值之和,即L1范数,对应的回归方法叫做套索(Lasso)回归。

在实践中,岭回归与套索回归首先岭回归。如果特征特别多,而某些特征更重要,具有选择性,那就选择套索(Lasso)回归可能更好。它适合稀疏矩阵。套索(Lasso)回归由加拿大学者罗伯特·提布什拉尼 1996年提出。

5.2.3 弹性网络(Elastic Net)

l弹性网络 是一种使用 L1, L2 范数作为先验正则项训练的线性回归模型。

l这种组合允许学习到一个只有少量参数是非零稀疏的模型,就像 Lasso 一样,但是它仍然保持 一些像 Ridge 的正则性质。我们可利用 L1_ratio 参数控制 L1 和 L2 的凸组合。

l弹性网络在很多特征互相联系的情况下是非常有用的。Lasso 很可能只随机考虑这些特征中的一个,而弹性网络更倾向于选择两个。

l在实践中,Lasso 和 Ridge 之间权衡的一个优势是它允许在循环过程(Under rotate)中继承 Ridge 的稳定性。

5.3 岭(Ridge)回归

Sklearn类的岭(Ridge)回归以sklearn.linear_model.Ridge来实现。

sklearn.linear_model.Ridge(alpha=1.0, fit_intercept=True, normalize=False, copy_X=True, max_iter=None, tol=0.001, solver='auto')

属性

属性

解释

alpha

{float, ndarray of shape (n_targets,)}, 默认=1.0正则化强度;必须是正浮点数。正则化改进了问题的条件,减少了估计的方差。值越大,正则化越强。Alpha对应于其他线性模型中的1/(2C),如logisticsregression或LinearSVC。如果传递了数组,则假定惩罚是特定于目标的。因此它们在数量上必须一致。

solver

{'auto','svd','cholesky','lsqr','sparse_cg','sag','saga'}, 默认='auto'在计算例程中使用的解算器:•'auto'根据数据类型自动选择解算器。•'svd'使用X的奇异值分解来计算岭系数。对于奇异矩阵,比'cholesky'更稳定。•'cholesky'使用标准scipy.linalg.solve解决方案函数以获得闭式解。•'sparse_cg'使用共轭梯度解算器,如中所示scipy.sparse.linalg.cg。作为一种迭代算法,该求解器比'cholesky'更适用于大规模数据(可以设置tol和max iter)。•'lsqr'使用专用的正则化最小二乘例程scipy.sparse.linalg.lsqr。它是最快的,并且使用迭代过程。•'sag'使用随机平均梯度下降,'sag'使用改进的无偏版本saga。这两种方法也都使用迭代过程,并且当n_samples和n_features都很大时,通常比其他解算器更快。

coef_

ndarray of shape(1, n_features) or (n_classes, n_features).权重向量。

intercept_

float or ndarray of shape (n_targets,)决策函数中的独立项。如果fit_intercept=False,则设置为0.0。

n_iter_

None or ndarray of shape (n_targets,).每个目标的实际迭代次数。仅适用于sag和lsqr解算器。其他解算器将不返回任何值。

方法

fit(X, y[, sample_weight])

拟合岭回归模型。

get_params([deep])

获取此估计器的参数。

predict(X)

用线性模型预测。

score(X, y[, sample_weight])

返回预测的确定系数R2。

set_params(**params)

设置此估计器的参数。

5.3.1 对无噪音make_regression数据进行岭回归

代码语言:javascript
复制
from sklearn.linear_model import Ridge

def Ridge_for_make_regression():
       myutil = util()
       X,y = make_regression(n_samples=100,n_features=1,n_informative=2,random_state=8)
       X_train,X_test,y_train,y_test = train_test_split(X, y, random_state=8,test_size=0.3)
       clf = Ridge().fit(X,y)
       print('lr.coef_: {} '.format(clf.coef_[:]))
       print('reg.intercept_: {}'.format(clf.intercept_))
       print('训练集得分: {:.2%}'.format(clf.score(X_train,y_train)))
       print('测试集得分: {:.2%}'.format(clf.score(X_test,y_test)))
       title = "make_regression Ridge()回归线(无噪音)"
       myutil.draw_line(X[:,0],y,clf,title)
       cv = ShuffleSplit(n_splits=100,test_size=0.2,random_state=0)
       myutil.plot_learning_curve(clf,title,X,y,ylim=(0.9,1.01),cv=cv)

输出

代码语言:javascript
复制
lr.coef_: [63.7840862] 
reg.intercept_: 4.440892098500626e-15
训练集得分: 100.00%
测试集得分: 100.00%

5.3.2 对有噪音make_regression数据进行岭回归

代码语言:javascript
复制
def Ridge_for_make_regression_add_noise():
       myutil = util()
       X,y = make_regression(n_samples=100,n_features=1,n_informative=2,noise=50,random_state=8)
       X_train,X_test,y_train,y_test = train_test_split(X, y, random_state=8,test_size=0.3)
       clf = Ridge().fit(X,y)
       print('lr.coef_: {} '.format(clf.coef_[:]))
       print('reg.intercept_: {}'.format(clf.intercept_))
       print('训练集得分: {:.2%}'.format(clf.score(X_train,y_train)))
       print('测试集得分: {:.2%}'.format(clf.score(X_test,y_test)))
       title = "make_regression LinearRegression()回归线(有噪音)"
       myutil.draw_line(X[:,0],y,clf,title)
       cv = ShuffleSplit(n_splits=100,test_size=0.2,random_state=0)
       myutil.plot_learning_curve(clf,title,X,y,ylim=(0.9,1.01),cv=cv)

输出

代码语言:javascript
复制
lr.coef_: [68.77648945] 
reg.intercept_: 1.2498738851984426
训练集得分: 70.18%
测试集得分: 64.27%

由此可见,使用岭回归,对有噪音make_regression数据结果是非常不理想的。

5.3.3对糖尿病数据岭分析回归

代码语言:javascript
复制
def Ridge_for_for_diabetes():
       myutil = util()
       X,y = datasets.load_diabetes().data,datasets.load_diabetes().target
       X_train,X_test,y_train,y_test = train_test_split(X, y, random_state=8,test_size=0.3)
       lr = LinearRegression().fit(X_train,y_train)
       print('线性回归,糖尿病数据训练集得分: {:.2%}'.format(lr.score(X_train,y_train)))
       print('线性回归,糖尿病数据测试集得分: {:.2%}'.format(lr.score(X_test,y_test)))
       title = "线性回归 糖尿病数据"
       myutil.plot_learning_curve(LinearRegression(),X,y,title)
       myutil.show_pic(title)
       #######################################################################
       ridge = Ridge().fit(X_train,y_train)
       print('alpha=1,糖尿病数据训练集得分: {:.2%}'.format(ridge.score(X_train,y_train)))
       print('alpha=1,糖尿病数据测试集得分: {:.2%}'.format(ridge.score(X_test,y_test)))
       title = "Ridge 糖尿病数据 alpha=1"
       myutil.plot_learning_curve(Ridge(),X,y,title)
        myutil.show_pic(title)
        #######################################################################
        ridge10 = Ridge(alpha=10).fit(X_train,y_train)
        print('alpha=10,糖尿病数据训练集得分: {:.2%}'.format(ridge10.score(X_train,y_train)))
        print('alpha=10,糖尿病数据测试集得分: {:.2%}'.format(ridge10.score(X_test,y_test)))
        title = "Ridge 糖尿病数据 alpha=10"
        myutil.plot_learning_curve(Ridge(alpha=10),X,y,title)
        myutil.show_pic(title)
        ###################################################################
        ridge01 = Ridge(alpha=0.1).fit(X_train,y_train)
        print('alpha=0.1,糖尿病数据训练集得分: {:.2%}'.format(ridge01.score(X_train,y_train)))
        print('alpha=0.1,糖尿病数据测试集得分: {:.2%}'.format(ridge01.score(X_test,y_test)))
        myutil.plot_learning_curve(Ridge(alpha=0.1),X,y,title)
        myutil.show_pic(title)
        #######################################################################
        title = "Ridge 糖尿病数据 数据分布比较"
        plt.plot(ridge.coef_,'s',label='岭回归 alpha=1')

输出

代码语言:javascript
复制
线性回归,糖尿病数据训练集得分: 53.50%
线性回归,糖尿病数据测试集得分: 45.41%
alpha=1,糖尿病数据训练集得分: 43.01%
alpha=1,糖尿病数据测试集得分: 43.04%
alpha=10,糖尿病数据训练集得分: 14.47%
alpha=10,糖尿病数据测试集得分: 15.88%
alpha=0.1,糖尿病数据训练集得分: 52.48%
alpha=0.1,糖尿病数据测试集得分: 47.11%

我们可以看到

alpha

糖尿病训练集得分

糖尿病测试集得分

线性

53.50%

45.41%

1

43.01%

43.04%

10

14.47%

15.88%

0.1

52.48%

47.11%

对于岭回归对糖尿病数据的分析效果只有在,alpha=0.1的时候与普通线性回归结果类似,但是都不理想。我们再来看一下图。

接下来,我们通过如下代码来看一下3个alpha情况下,数据点的分布。

代码语言:javascript
复制
plt.plot(ridge.coef_,'s',label='Ridge alpha=1')
plt.plot(ridge10.coef_,'^',label='Ridge alpha=10')
plt.plot(ridge01.coef_,'v',label='Ridge alpha=0.1')
plt.plot(lr.coef_,'o',label='Linear Regression')
plt.xlabel('coefficient index')
plt.ylabel('coefficient magnitude')
plt.hlines(0,0,len(lr.coef_))
plt.show()

alpha =10 在0区间变化(^ 橘黄色上箭头)

alpha =1 变化变大(s 蓝色方块)

alpha = 0.1变化更大,接近线性(v 绿色下箭头)

线性:变化超大,超出图(o 红色圆点)

由此可见,回归数据分散、alpha越大越集中。由于岭回归适合于密集矩阵,所以得分比较低。

5.3.4对波士顿房价数据岭分析回归

代码语言:javascript
复制
def Ridge_for_for_boston():
       myutil = util()
       X,y = datasets.load_boston().data,datasets.load_boston().target
       X_train,X_test,y_train,y_test = train_test_split(X, y, random_state=8,test_size=0.3)
       lr = LinearRegression().fit(X_train,y_train)
       print('线性回归,波士顿房价数据训练集得分: {:.2%}'.format(lr.score(X_train,y_train)))
       print('线性回归,波士顿房价数据测试集得分: {:.2%}'.format(lr.score(X_test,y_test)))
       title = "线性回归 波士顿房价病数据"
       myutil.plot_learning_curve(LinearRegression(),X,y,title)
       myutil.show_pic(title)
       #######################################################################
       ridge = Ridge().fit(X_train,y_train)
       print('alpha=1,波士顿房价数据训练集得分: {:.2%}'.format(ridge.score(X_train,y_train)))
       print('alpha=1,波士顿房价数据测试集得分: {:.2%}'.format(ridge.score(X_test,y_test)))
       title = "Ridge 波士顿房价数据 alpha=1"
       myutil.plot_learning_curve(Ridge(),X,y,title)
       myutil.show_pic(title)
        ###########################################################################
       ridge10 = Ridge(alpha=10).fit(X_train,y_train)
       print('alpha=10,波士顿房价数据训练集得分: {:.2%}'.format(ridge10.score(X_train,y_train)))
       print('alpha=10,波士顿房价数据测试集得分: {:.2%}'.format(ridge10.score(X_test,y_test)))
       title = "Ridge 波士顿房价数据 alpha=10"
       myutil.plot_learning_curve(Ridge(alpha=10),X,y,title)
       myutil.show_pic(title)
       #######################################################################
       ridge01 = Ridge(alpha=0.1).fit(X_train,y_train)
       print('alpha=0.1,波士顿房价数据训练集得分: {:.2%}'.format(ridge01.score(X_train,y_train)))
       print('alpha=0.1,波士顿房价数据测试集得分: {:.2%}'.format(ridge01.score(X_test,y_test)))
       title = "Ridge 波士顿房价数据 alpha=0.1"
       myutil.plot_learning_curve(Ridge(alpha=0.1),X,y,title)
       myutil.show_pic(title)
       #######################################################################
       title = "Ridge 波士顿房价数据 数据分布比较"
       plt.plot(ridge.coef_,'s',label='岭回归 alpha=1')
       plt.plot(ridge10.coef_,'^',label='岭回归 alpha=10')
        plt.plot(lr.coef_,'o',label='线性回归 Regression')
       plt.xlabel(u'系数指数')
       plt.ylabel(u'系数大小')
       plt.hlines(0,0,len(lr.coef_))
       myutil.show_pic(title)

输出

代码语言:javascript
复制
线性回归,波士顿房价数据训练集得分: 74.98%
线性回归,波士顿房价数据测试集得分: 70.81%
alpha=1,波士顿房价数据训练集得分: 74.86%
alpha=1,波士顿房价数据测试集得分: 69.76%
alpha=10,波士顿房价数据训练集得分: 74.48%
alpha=10,波士顿房价数据测试集得分: 68.49%
alpha=0.1,波士顿房价数据训练集得分: 74.98%
alpha=0.1,波士顿房价数据测试集得分: 70.64%

我们可以看到

alpha

波士顿房价训练集得分

波士顿房价测试集得分

线性

74.98%

70.81%

1

74.86%

69.76%

10

74.48%

68.49%

0.1

74.98%

70.64%

在不同的alpha下,得分值与线性回归基本相同。

最后来看一下3个alpha情况下,数据点的分布。

alpha =10 (^ 橘黄色上箭头)

alpha =1 (s 蓝色方块)

alpha = 0.1 (v 绿色下箭头)

线性:(o 红色圆点)

同样,线性回归分散、alpha越大越集中。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-05-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档