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

2022-05-22 10:28:46 浏览数 (1)

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越大越集中。

0 人点赞