Day4_线性模型python实现

上文学习从理论的角度(算法)学习了线性模型的一些知识
本文将使用python的模块来简单使用了解一些这些算法

线性模型

对于回归问题,线性模型预测的一般公式如下:

y ^ = w [ 0 ] x [ 0 ] + w [ 1 ] x [ 1 ] + + w [ p ] x [ p ] + b ŷ = w[0] * x[0] + w[1] * x[1] + … + w[p] * x[p] + b

这里 x [ 0 ] x[0] x [ p ] x[p] 表示单个数据点的特征(本例中特征个数为 p + 1 p+1 ),$w b 是学习模型的 参数, ŷ 是模型的预测结果。 对于单一特征的数据集,公式如下: ŷ = w[0] * x[0] + b$
w [ 0 ] : 0.393906 b : 0.031804 w[0]: 0.393906 b: -0.031804

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

在这里插入图片描述

线性回归(又名普通最小二乘法)

线性回归,或者普通最小二乘法(ordinary least squares,OLS),是回归问题最简单也最经 典的线性方法。线性回归寻找参数 w w b b ,使得对训练集的预测值与真实的回归目标值 y y 之间的均方误差最小。均方误差(mean
squared error)是预测值与真实值之差的平方和除 以样本数。线性回归没有参数,这是一个优点,但也因此无法控制模型的复杂度。

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

X0, y0 = mglearn.datasets.make_wave(n_samples=60)
X_train0, X_test0, y_train0, y_test0 = train_test_split(X0, y0, random_state=42)

lr = LinearRegression().fit(X_train0, y_train0)

print("lr.coef_: {}".format(lr.coef_))
print("lr.intercept_: {}".format(lr.intercept_))
"""
“斜率”参数(w,也叫作权重或系数)被保存在 coef_ 属性中,而偏移或截距
(b)被保 存在 intercept_ 属性中,这里的下划线“_”是用于与用户设置的参
数区分开来
lr.coef_: [0.39390555]
lr.intercept_: -0.031804343026759746
"""
print("Training set score: {:.2f}".format(lr.score(X_train0, y_train0)))
print("Test set score: {:.2f}".format(lr.score(X_test0, y_test0)))

"""
Training set score: 0.67
Test set score: 0.66
"""
################################
#   更高维的数据集进行训练       #
################################
#这里使用的Boston的房价数据集(506,104)  一共506个样本,104个特征
X, y = mglearn.datasets.load_extended_boston()

X_train, X_test, y_train, y_test = train_test_split(X, y,random_state=0)
lr1 = LinearRegression().fit(X_train, y_train)
print("Traning set score: {:.2f}".format(lr1.score(X_train,y_train)))
print(X_test.shape)
print("Test set score: {:.2f}".format(lr1.score(X_test ,y_test)))

"""
Traning set score: 0.95
Test set score: 0.61
"""

岭回归

岭回归也是一种用于回归的线性模型,因此它的预测公式与普通最小二乘附加法相同。但在岭回归中,对系数( w w )的选择不仅要在训练数据上得到好的预测结果,而且还要拟合约束。我们还希望系数尽量小。换句话说, w w 的所有元素都应接近于0。直观上来看,这意味着每个特征对输出的影响应尽可能小(即斜率很小),同时仍给出很好的预测结果。
这种约束是所谓正则化( r e g u l a r i z a t i o n regularization )的一个例子。正则化是指对模型做显式约束以避免过拟合。岭回归用到的这种被称为L2正则化。

from sklearn.linear_model import Ridge

ridge = Ridge().fit(X_train, y_train)
print("Training set score: {:.2f}".format(ridge.score(X_train, y_train)))
print("Test set score: {:.2f}".format(ridge.score(X_test, y_test)))
"""
Training set score: 0.89
Test set score: 0.75
可以看出Ridge在训练集的分数高于测试集的分数,与预期一致。线性回归存在过拟合,而Ridge
则不容易过拟合。。复杂度更小的模型意味着在训练集上的性能更差,但泛化性能更好。由于我
们只对泛化性能感兴趣,所以应该选择 Ridge 模型而不是 LinearRegression 模型。

Ridge 模型在模型的简单性(系数都接近于 0)与训练集性能之间做出权衡。简单性和训练 集
性能二者对于模型的重要程度可以由用户通过设置 alpha 参数来指定。在前面的例子中, 我
们用的是默认参数 alpha=1.0。但没有理由认为这会给出最佳权衡。alpha 的最佳设定 值取
决于用到的具体数据集。增大 alpha 会使得系数更加趋向于 0,从而降低训练集性能, 但可
能会提高泛化性能。
"""
ridge10 = Ridge(alpha=10).fit(X_train, y_train)
print("Training set score: {:.2f}".format(ridge10.score(X_train, y_train)))
print("Test set score: {:.2f}".format(ridge10.score(X_test, y_test)))
"""
Training set score: 0.93 
Test set score: 0.77
"""
ridge01 = Ridge(alpha=0.1).fit(X_train, y_train)
print("Training set score: {:.2f}".format(ridge01.score(X_train, y_train)))
print("Test set score: {:.2f}".format(ridge01.score(X_test, y_test)))

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="LinearRegression")
plt.xlabel("Coefficient index")
plt.ylabel("Coefficient magnitude")
plt.hlines(0, 0, len(lr.coef_))
plt.ylim(-25, 25)
plt.legend()
plt.show()

在这里插入图片描述

mglearn.plots.plot_ridge_n_samples()
plt.show()

在这里插入图片描述

Lasso 回归


from sklearn.linear_model import Lasso

#同样使用Boston的房价数据集
lasso = Lasso().fit(X_train, y_train)
print("Training set score: {:.2f}".format(lasso.score(X_train, y_train)))
print("Test set score: {:.2f}".format(lasso.score(X_test, y_test)))
print("Number of features used: {}".format(np.sum(lasso.coef_ != 0)))
"""
Training set score: 0.29
Test set score: 0.21
Number of features used: 4
如你所见,Lasso 在训练集与测试集上的表现都很差。这表示存
在欠拟合,我们发现模型 只用到了 105 个特征中的 4 个。与 
Ridge 类似,Lasso 也有一个正则化参数 alpha,可以控 制系
数趋向于 0 的强度。在上一个例子中,我们用的是默认值alpha=1.0。
为了降低欠拟合,我们尝试减小 alpha。这么做的同时,我们还需
要增加 max_iter 的值(运行迭代的最大次数):
"""
# 我们增大max_iter的值,否则模型会警告我们,说应该增大max_iter
lasso001 = Lasso(alpha=0.01, max_iter=100000).fit(X_train, y_train)
print("Training set score: {:.2f}".format(lasso001.score(X_train, y_train)))
print("Test set score: {:.2f}".format(lasso001.score(X_test, y_test)))
print("Number of features used: {}".format(np.sum(lasso001.coef_ != 0)))
"""
Training set score: 0.90
Test set score: 0.77
Number of features used: 33
可以看出alpha值变小,可以拟合一个更复杂的模型,在训练集和测试集
上的表现也更好。模型性能比使用 Ridge 时略好一点,而且我们只用到
105 个特征中的 33 个。
但如果把alpha 设得太小,那么就会消除正则化的效果,并出现过拟合,
得到与 LinearRegression 类似的结果
"""
lasso0001=Lasso(alpha=0.0001,max_iter=100000).fit(X_train,y_train)
print("Training set score :{:.2f}".format(lasso0001.score(X_train,y_train)))
print("Test set score: {:.2f}".format(lasso0001.score(X_test ,y_test)))
print("Number of features used:{}".format(np.sum(lasso0001.coef_!=0)))
"""
此时的正则化很弱,太多的线性相关的参数不为零
Training set score :0.95
Test set score: 0.64
Number of features used:96
"""
plt.plot(lasso.coef_, 's', label="Lasso alpha=1")
plt.plot(lasso001.coef_, '^', label="Lasso alpha=0.01")
plt.plot(lasso0001.coef_, 'v', label="Lasso alpha=0.0001")

plt.plot(ridge01.coef_, 'o', label="Ridge alpha=0.1")
plt.legend(ncol=2, loc=(0, 1.05))
plt.ylim(-25, 25)
plt.xlabel("Coefficient index")
plt.ylabel("Coefficient magnitude")
plt.show()

在这里插入图片描述

用于分类的线性模型

我们首先来看二分类。这时可以利用下面的公式进行预测:

y ^ = w [ 0 ] x [ 0 ] + w [ 1 ] x [ 1 ] + + w [ p ] x [ p ] + b > 0 ŷ = w[0] * x[0] + w[1] * x[1] + …+ w[p] * x[p] + b > 0

最常见的两种线性分类算法是 L o g i s t i c Logistic 回归( l o g i s t i c r e g r e s s i o n logistic regression )和线性支持向量机( l i n e a r s u p p o r t v e c t o r m a c h i n e linear support vector machine ,线性 S V M SVM ),前者在linear_model.LogisticRegression 中实现, 后者在svm.LinearSVC S V C SVC 代表支持向量分类器)中实现。虽然LogisticRegression的名字中含有回归( r e g r e s s i o n regression ),但它是一种分类算法,并不是回归算法,不应与 LinearRegression 混淆。

 from sklearn.linear_model import LogisticRegression
from sklearn.svm import LinearSVC

X, y = mglearn.datasets.make_forge()

fig, axes = plt.subplots(1, 2, figsize=(10, 3))

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

在这里插入图片描述

上图第一特征位于x轴,第二个特征位于y轴,分别展示了LinearSVCLogisticRegression得到的决策边界,都是直线。但上图都有分类错误的点,两个模型都默认使用 L 2 L_2 正则化对于LogisticRegressionLinearSVC,决定正则化强度的权衡参数叫作 C C C C 值越大,对应的正则化越弱。换句话说,如果参数 C C 值较大,那么LogisticRegressionLinearSVC 将尽可能将训练集拟合到最好,而如果 C C 值较小,那么模型更强调使系数向量( w w )接近于 0 0 。参数 C C 的作用还有另一个有趣之处。较小的 C C 值可以让算法尽量适应“大多数”数据点, 而较大的 C C 值更强调每个数据点都分类正确的重要性

mglearn.plots.plot_linear_svc_regularization()
plt.show()

在这里插入图片描述

LogisticRegression详细分析

from sklearn.datasets import load_breast_cancer
cancer=load_breast_cancer()
X_train2,X_test2,y_train2,y_test2=train_test_split(cancer.data,cancer.target,stratify=cancer.target,random_state=42)
logreg=LogisticRegression().fit(X_train2,y_train2 )
print("Training score: {:.4f}".format(logreg.score(X_train2,y_train2) ))
print("Test score: {:.4f}".format(logreg.score(X_test2,y_test2)))
"""
Training score: 0.9484
Test score: 0.9580
C=1 的默认值给出了相当好的性能,在训练集和
测试集上都达到 95% 的精度。但由于训练集和
测试集的性能非常接近,所以模型很可能是欠拟
合的。我们尝试增大C来拟合一个更灵活的模型
"""
logreg001 = LogisticRegression(C=0.01).fit(X_train2, y_train2)
print("Training1 set score: {:.3f}".format(logreg001.score(X_train2, y_train2)))
print("Test set1 score: {:.3f}".format(logreg001.score(X_test2, y_test2)))
"""
Training1 set score: 0.937
Test set1 score: 0.930
C=0.01时,此时已经欠拟合的模型继续向左移动,精度都下降
"""
logreg100 = LogisticRegression(C=100).fit(X_train2, y_train2)
print("Training2 set score: {:.3f}".format(logreg100.score(X_train2, y_train2)))
print("Test set2 score: {:.3f}".format(logreg100.score(X_test2, y_test2)))
"""
Training2 set score: 0.944
Test set2 score: 0.958
c=100时,可以得到更高的训练集、测试集精度
说明更复杂的模型性能更好
"""
# 下面查看不同C值下的参数
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)
plt.hlines(0, 0, cancer.data.shape[1])
plt.ylim(-5, 5)
plt.xlabel("Coefficient index")
plt.ylabel("Coefficient magnitude")
plt.legend()
plt.show()

在这里插入图片描述

引用

《Python机器学习基础教程》 人 民 邮 电 出 版 社
维基百科

发布了20 篇原创文章 · 获赞 6 · 访问量 873

猜你喜欢

转载自blog.csdn.net/qq_43605381/article/details/104363440
今日推荐