python-机器学习打卡(三)--监督学习(二)--线性模型

线性模型

线性模型是实践中使用比较广泛的模型,利用输入数据的线性函数进行预测。

用于回归的线性模型

回归问题使用的显现函数如下:
y ^ = W ∗ X + b = w [ 0 ] ∗ x [ 0 ] + w [ 1 ] ∗ x [ 1 ] + ⋅ ⋅ ⋅ + w [ p ] ∗ x [ p ] + b \hat{y} =W*X+b= w[0]*x[0]+w[1]*x[1]+···+w[p]*x[p]+b y^=WX+b=w[0]x[0]+w[1]x[1]++w[p]x[p]+b
X={x[0],x[1],x[2],···,x[p]}是输入数据点的特征,W和b是模型参数, y ^ \hat{y} y^是模型预测结果。如果输入数据特征单一,则X = x[0].
如果给定数据只有一个特征,则
y ^ = w [ 0 ] ∗ x [ 0 ] + b \hat{y} = w[0]*x[0]+b y^=w[0]x[0]+b
这边类似于一元一次线性方程,w[0]是方程的斜率,b是方程的截距。
我们可以用sklearn的wave数据集进行观测:

import mglearn.datasets
import matplotlib.pyplot as plt

mglearn.plots.plot_linear_regression_wave()
plt.show()

预览(图1)
图1
与之前的KNN模型的可视化图对比,会发现线性模型预测能力十分受限,数据细节都丢失了。是因为观察数据点只有一个维度的特征,如果数据点有多个维度的特征,那线性模型可以表现出十分好的性能。

线性回归(最小二乘法)

线性回归是最简单也最经典的线性方法,是寻找参数w和b使得训练集的预测值和真实回归目标值y之间的均方误差最小。

MSE: Mean Squared Error
均方误差是指参数估计值与参数真值之差平方的期望值;
MSE可以评价数据的变化程度,MSE的值越小,说明预测模型描述实验数据具有更好的精确度。

M S E = 1 N ∑ t ∈ 1 N ( y − y ^ ) 2 MSE=\frac{1}{N}\sum_{t \in{1}}^{N} (y - \hat{y})^2 MSE=N1t1N(yy^)2
图一可以使用下面代码生成:

from sklearn.linear_model import LinearRegression
from mglearn.datasets import make_wave

X,y = make_wave(n_samples=60)
Xtrain,Xtest ,ytrain,ytest = train_test_split(X,y,random_state=0)
lr = LinearRegression().fit(Xtrain,ytrain)

print( "lr.coef_ is {}".format(lr.coef_))
print( "lr.intercept_ is {}".format(lr.intercept_))

输出

lr.coef_ is [0.44153666]
lr.intercept_ is -0.01711124414733381

  coef_和intercept_都包含了下划线,原因是sklearn为了将其与用户定义的参数区分开。
  系数(斜率) 的参数w被保存在coef_中,intercept_保存了偏移(截距) b 的值

上述代码是对wave数据集(数据点只有一个特征),结果可能太过于片面。如果使用波士顿房价数据集(包含506个样本,105个测试特征)。使用之前线性模型

from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
import mglearn.datasets

x,y = mglearn.datasets.load_extended_boston()

xtrain,xtest ,ytrain,ytest = train_test_split(x,y,random_state=0)
fits = LinearRegression().fit(xtrain, ytrain)
print("Train set score is {:.2}".format(fits.score(xtrain,ytrain)))
print("Test set score is {:.2}".format(fits.score(xtest,ytest)))

输出

Train set score is 0.95
Test set score is 0.61

我们可以看到测试集的结果远低于训练集,即模型过拟合了,我们可以通过正则化降低过拟合。

岭回归(ridge regression)

岭回归也是一种线性回归的模型,和之前的最小二乘法相同。但是为了减小过拟合,我摸会附加约束条件,是的参数w尽可能的小,同时还能给出预测结果。
正则化有两种L1正则化:
L 1 : J = J 0 + α ∑ w ∣ w ∣ L1: J = J_0 + \alpha\sum_{w}|w| L1:J=J0+αww
和L2正则化:
L 2 : J = J 0 + α ∑ w w 2 L2: J = J_0 + \alpha\sum_{w}w^2 L2:J=J0+αww2
都是对原始损失函数 J 0 J_0 J0添加约束值。L1正则化和L2正则化的详细直观解释

岭回归使用的是L2正则化,代码:

from sklearn.linear_model import Ridge
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
import mglearn.datasets

x, y = mglearn.datasets.load_extended_boston()
xtrain, xtest, ytrain, ytest = train_test_split(x, y, random_state=0)

reg = Ridge().fit(xtrain, ytrain)
score1 = reg.score(xtrain,ytrain)
score2 = reg.score(xtest,ytest)
print("Train set score is {:.2}".format(score1))
print("Test set score is {:.2}".format(score2))

输出

Train set score is 0.89
Test set score is 0.75

可以看到虽然训练集的结果低于线性回归,但是模型泛化能力变好了。对于该模型的参数中存在一个 α \alpha α,默认是1 ,该参数增大会使得系数更趋向于0,降低训练集性能,提高模型泛化能力。我们分别对 α \alpha α设置不同值,查看其泛化能力:

reg = Ridge(alpha=0.1).fit(xtrain, ytrain)
score1 = reg.score(xtrain,ytrain)
score2 = reg.score(xtest,ytest)
print("Train set score is {:.2}".format(score1))
print("Test set score is {:.2}".format(score2))

Train set score is 0.93
Test set score is 0.77

如果alpha的值过小,对系数限制就小,可能产生结果和最小二乘一样过拟合,如果吧alpha设置为10则:

reg = Ridge(alpha=10).fit(xtrain, ytrain)
score1 = reg.score(xtrain,ytrain)
score2 = reg.score(xtest,ytest)
print("Train set score is {:.2}".format(score1))
print("Test set score is {:.2}".format(score2))

Train set score is 0.79
Test set score is 0.64

我们对于不同的alpha值的岭回归模型的coef_值进行可视化:

from sklearn.linear_model import Ridge
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
import mglearn.datasets
import matplotlib.pyplot as plt
from sklearn.linear_model import Lasso
x, y = mglearn.datasets.load_extended_boston()
xtrain, xtest, ytrain, ytest = train_test_split(x, y, random_state=0)

reg10 = Ridge(alpha=10).fit(xtrain, ytrain)
reg1 = Ridge(alpha=0.1).fit(xtrain, ytrain)
reg = Ridge().fit(xtrain, ytrain)
fit = LinearRegression().fit(xtrain, ytrain)

plt.plot(reg10.coef_, "s", label="Ridge alpha 10")
plt.plot(reg.coef_, "o", label="Ridge alpha 0.1")
plt.plot(reg1.coef_, "v", label="Ridge alpha 1")
plt.plot(fit.coef_, "^", label="regressLiner")
plt.ylim(-25, 25)
plt.xlabel("coffient")
plt.ylabel("cofficient magnitude")
plt.hlines(0, 0, len(fit.coef_))

plt.legend()
plt.show()

预览在这里插入图片描述
这里x轴表示coef_的元素,数值代表对应索引值的特征系数。y轴代表系数实际值。
除了正则化参数,还有一种方法理解正则化的影响,就是改变数据量。

import mglearn.datasets
import matplotlib.pyplot as plt
mglearn.plots.plot_ridge_n_samples()
plt.show()

预览
在这里插入图片描述
可以看到,如果有足够数据集,正则化也不是那么重要。

lasso回归

除了岭回归,lasso也是一种使用正则化约束模型的线性回归。但是使用的是L1 正则化,L1正则化是使得某些系数刚好为0,就是某些数据点的某些特征被完全忽视。
Lasso模型在sklearn的linear_model模块下 ,我们同样使用它测试波士顿房价:

from sklearn.model_selection import train_test_split
import mglearn.datasets
from sklearn.linear_model import Lasso
import numpy as np

x, y = mglearn.datasets.load_extended_boston()
xtrain, xtest, ytrain, ytest = train_test_split(x, y, random_state=0)
lasso = Lasso().fit(xtrain,ytrain)

print("Training set score is :{:.2}".format(lasso.score(xtrain,ytrain)))
print("Test ser score is :{:.2}".format(lasso.score(xtest,ytest)))
print("Number of feature user:{}".format(np.sum(lasso.coef_ !=0) ))

输出

Training set score is :0.29
Test ser score is :0.21
Number of feature user:4

我们可以看到,模型结果很差。因为对于波士顿房价数据集中,每个数据点有105个特征,而在这里只用到了4个。L1正则化同样也拥有一个参数 α \alpha α
L1正则化:
L 1 : J = J 0 + α ∑ w ∣ w ∣ L1: J = J_0 + \alpha\sum_{w}|w| L1:J=J0+αww

对于这个参数,默认是alpha = 1 ,我们可以通过改变这个参数来改变模型的性能。L1中的参数变小,增加模型复杂度,但如果太小会导致正则化失效,模型过拟合。

from sklearn.model_selection import train_test_split
import mglearn.datasets
from sklearn.linear_model import Lasso
import numpy as np

x, y = mglearn.datasets.load_extended_boston()
xtrain, xtest, ytrain, ytest = train_test_split(x, y, random_state=0)
lasso = Lasso(alpha=0.01,max_iter=100000).fit(xtrain,ytrain)

print("Training set score is :{:.2}".format(lasso.score(xtrain,ytrain)))
print("Test ser score is :{:.2}".format(lasso.score(xtest,ytest)))
print("Number of feature user:{}".format(np.sum(lasso.coef_ !=0) ))

输出

Training set score is :0.9
Test ser score is :0.77
Number of feature user:33

我们将不同参数的Lasso回归模型与Ridge回归模型可视化:

from sklearn.model_selection import train_test_split
import mglearn.datasets
from sklearn.linear_model import Ridge
from sklearn.linear_model import Lasso
import numpy as np
import matplotlib.pyplot as plt

x, y = mglearn.datasets.load_extended_boston()
xtrain, xtest, ytrain, ytest = train_test_split(x, y, random_state=0)
lasso = Lasso().fit(xtrain,ytrain)
lasso001 = Lasso(alpha=0.01,max_iter=100000).fit(xtrain,ytrain)
reg = Ridge().fit(xtrain, ytrain)
lasso00001 = Lasso(alpha=0.0001,max_iter=100000).fit(xtrain,ytrain)

plt.plot(lasso.coef_, "s", label="lasso alpha 1")
plt.plot(lasso001.coef_, "o", label="lasso alpha 0.01")
plt.plot(lasso00001.coef_, "v", label="lasso alpha 0.00001")
plt.plot(reg.coef_, "^", label="Ridge ")
plt.ylim(-25, 25)
plt.xlabel("coffient")
plt.ylabel("cofficient magnitude")
plt.legend()
plt.show()

预览
在这里插入图片描述
可以看到档Alpha = 1 时,lasso回归的大部分系数都是0,其他系数也很小,当alpha = 0.01时得到橙色圆形,大部分特征也是0。所以当增大alpha会增加正则化的约束。

在实践中,一般首选岭回归,但如果特征很多,也能确定其中只有几个是很重要的,那么选择Lasso回归更好。同时Lasso的可解释性更好,因为他只选择了一部分特征。

sklearn中linear_model模块拥有另一种模型:ElasticNet,结合了L1和L2正则化的惩罚项,但需要调节两个参数。

用于分类的线性模型

线性模型也用于分类任务,对于二分类如下
y ^ = W ∗ X + b = w [ 0 ] ∗ x [ 0 ] + w [ 1 ] ∗ x [ 1 ] + ⋅ ⋅ ⋅ + w [ p ] ∗ x [ p ] + b > 0 \hat{y} =W*X+b= w[0]*x[0]+w[1]*x[1]+···+w[p]*x[p]+b >0 y^=WX+b=w[0]x[0]+w[1]x[1]++w[p]x[p]+b>0
我们不在像回归一样,去求一个准确的值,而是寻找一个阈值,如果预测值 y ^ > 0 \hat{y}>0 y^>0 我们认为预测类别+1,反之-1。对于回归,我们是使用线性模型输出的是一个函数、平面或者超平面。而对于分类,我们是使用这个输出作为边界来划分类别。

线性模型有很多种算法,区别在于:

  • 系数和截距的特定组合对训练数据拟合好坏的度量方法。
  • 是否使用正则化,使用那个正则化。

最常见的线性分类算法有两种:Logistics 回归(Logistics regression)和线性支持向量机(线性SVM)详细内容看—>逻辑回归详解.

我们可以将Logistics regression和LinearSVC模型应用到forge上,并将其可视化:

from sklearn.linear_model import LogisticRegression
from sklearn.svm import LinearSVC
from sklearn.model_selection import train_test_split
import mglearn.datasets
import matplotlib.pyplot as plt

x, y = mglearn.datasets.make_forge()
figs, axes = plt.subplots(1, 2, figsize=(10, 3))

for model, axe in zip([LogisticRegression, LinearSVC], axes):
    fit = model().fit(x, y)
    mglearn.plots.plot_2d_separator(fit, x, fill=False, eps=0.5, ax=axe, alpha=0.7)
    mglearn.discrete_scatter(x[:, 0], x[:, 1], y, ax=axe)
    axe.set_title("{}".format(fit.__class__.__name__))
    axe.set_xlabel("Feature 0")
    axe.set_ylabel("Feature 1")

axes[0].legend()
plt.show()

预览
在这里插入图片描述
这两个模型都使用了L2正则化,决定正则化强度的参数是C,C越大对应正则化越弱。C越大,意味着模型可能更容易过拟合,如果C越小,意味着模型的系数向量w更接近于0。

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split

from sklearn.linear_model import LogisticRegression

cancer = load_breast_cancer()
Xtrain, Xtest, ytrain, ytest = train_test_split(cancer.data, cancer.target, stratify=cancer.target, random_state=42)

logreg = LogisticRegression().fit(Xtrain, ytrain)

print("Training set score is {:.3}".format(logreg.score(Xtrain, ytrain)))
print("Test set score is {:.3}".format(logreg.score(Xtest, ytest)))

logreg100 = LogisticRegression(C=100).fit(Xtrain, ytrain)

print("Training set score is {:.3}".format(logreg100.score(Xtrain, ytrain)))
print("Test set score is {:.3}".format(logreg100.score(Xtest, ytest)))

logreg001 = LogisticRegression(C=0.01).fit(Xtrain, ytrain)

print("Training set score is {:.3}".format(logreg001.score(Xtrain, ytrain)))
print("Test set score is {:.3}".format(logreg001.score(Xtest, ytest)))


输出

Training set score is 0.958
Test set score is 0.958
Training set score is 0.984
Test set score is 0.972
Training set score is 0.953
Test set score is 0.951

如果有警告:
在这里插入图片描述
则在 LogisticRegression(max_iter=5000)添加最大迭代次数。

对上述不同参数值进行可视化话后:

plt.plot(logreg.coef_.T, 'o', label="C=1")
plt.plot(logreg100.coef_.T, '^', label="C=100")
plt.plot(logreg001.coef_.T, 'v', label="C=0.001")
plt.xticks(range(cancer.data.shape[1]), cancer.feature_names, rotation=90)
xlims = plt.xlim()
plt.hlines(0, xlims[0], xlims[1])
plt.xlim(xlims)
plt.ylim(-5, 5)
plt.xlabel("Feature")
plt.ylabel("Coefficient magnitude")
plt.legend()
plt.show()

预览
在这里插入图片描述如果要使模型使用L1正则化,则需要使用模型参数penalty:

LogisticRegression(penalty="l1")

小结

  • 线性模型主要参数就是正则化参数,回归模型中叫做alpha,分类模型为C
  • alpha值越大或者C的值越小,模型就会越简单
  • 如果确定数据点中特征数只有几个有用,那就使用L1正则化,否则使用L2
  • 如果模型可解释性很重要,则使用L1正则化
  • 线性模型训练速度非常快,在稀疏矩阵也可以得到很好的效果。
  • 对于回归和分类任务的公式,理解如何预测是相对容易的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值