【笔记】【机器学习基础】监督学习算法2 (补充)

线性模型

线性模型是在实践中广泛使用的一类模型,主要利用输入特征的线性函数(linear function)进行预测。

用于回归的线性模型

对于回归问题,线性模型预测的一般公式如下:
ea206b99524049598b7ec01b3252e4f0.png
x[0]到x[p]表示单个数据点的特征(本例中特征个数为p+1),w和b是学习模型的参数,ŷ是模型的预测结果
aca938cede304e63a848b46e127036b3.png
就是高中数学里的直线方程,w[0]是斜率,b是y轴偏移。
用于回归的线性模型可以表示为这样的回归模型:对单一特征的预测结果是一条直线,两个特征时是一个平面,或者在更高维度(即更多特征)时是一个超平面。
对于有多个特征的数据集而言,线性模型可以非常强大。特别地,如果特征数量大于训练数据点的数量,任何目标y都可以(在训练集上)用线性函数完美拟合

模型之间的区别在于:
1、如何从训练数据中学习参数w和b
2、如何控制模型复杂度

常见线性回归模型

1. 线性回归(又名普通最小二乘法,OLS)

线性回归目标:寻找参数w和b,使得对训练集的预测值与真实的回归目标值y之间的均方误差最小。
均方误差(mean squared error):预测值与真实值之差的平方和除以样本数。
线性回归没有参数,但也因此无法控制模型的复杂度

from sklearn.linear_model import LinearRegression

X,y = mglearn.datasets.make_wave(n_samples=60)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)
#训练模型
lr = LinearRegression().fit(X_train,y_train)
#下划线使得参数与用户设置参数分开
print("斜率w: {}".format(lr.coef_))
print("截距b: {}".format(lr.intercept_))
#评估性能
print("Training set score: {:.2f}".format(lr.score(X_train,y_train)))
print("Test set score: {:.2f}".format(lr.score(X_test,y_test)))

fcb9182bbb11491f8ebfc0a446c76015.png
对于更高维的数据集(即有大量特征的数据集),线性模型将变得更加强大,过拟合的可能性也会变大。
下面使用boston数据集

X, y = mglearn.datasets.load_extended_boston()
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
lr = LinearRegression().fit(X_train, y_train)

print("Training set score: {:.2f}".format(lr.score(X_train, y_train)))
print("Test set score: {:.2f}".format(lr.score(X_test, y_test)))

根据结果,训练集和测试集之间存在性能差异,是过拟合的明显标志
01a59b5a77b347189b24630cc3861d6f.png

2. 岭回归(L2)

为了避免过拟合(?),希望找到一个可以控制复杂度的模型,例如岭回归,其预测公式与普通最小二乘法相同。
在岭回归中,对系数w的选择不仅要在训练数据上得到好的效果,还要拟合附加约束(L2正则化)。
1、每个特征对输出的影响应尽可能小(即斜率很小),同时仍给出很好的预测结果
2、正则化,是指对模型做显式约束,以避免过拟合。岭回归用到的这种被称为L2 正则化

from sklearn.linear_model import Ridge #岭回归
X, y = mglearn.datasets.load_extended_boston()

X_train,X_test, y_train,y_test = train_test_split(X, y,random_state=0)
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在训练集上的分数低于LinearRegression,但在测试集上的分数更高。线性回归是存在过拟合的,但是Ridge加了更强的约束,所以更不容易过拟合。

Ridge可对模型的复杂度和训练集性能之间权衡,可以通过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.79
Test set score: 0.64

plt.plot(ridge.coef_, 's', label="Ridege alpha=1")
plt.plot(ridge.coef_, '^', label="Ridege alpha=10")
plt.plot(ridge.coef_, 'v', label="Ridege alpha=0.1")
 
plt.plot(lr.coef_, 'o', label="LinearRegression")
 
plt.xlabel("Cofficient index")
plt.ylabel("Cofficient magnitude")
plt.hlines(0, 0, len(lr.coef_))
plt.ylim(-25, 25)
plt.legend()

401842f298e247daa0628ced0f5ffc0a.png

mglearn.plots.plot_ridge_n_samples()

6124fed57c0b46ec99cc0e88d863e534.png

3. lasso(L1)

lasso是正则化的线性回归,类似岭回归,约束系数使其接近于0,但是用到的方法不同,叫做L1正则化
L1正则化,某些系数刚好为零,这说明某些特征被忽略,可以看做是自动化的特征选择。

在波士顿房价数据集上应用:
(1)

from sklearn.linear_model import Lasso

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:", np.sum(lasso.coef_ != 0))

OUT :
Training set score: 0.29
Test set score: 0.21
Number of features used: 4
结果表示欠拟合

(2)
为了降低欠拟合,减小alpha,增加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:", np.sum(lasso001.coef_ != 0))

OUT :
Training set score: 0.90
Test set score: 0.77
Number of features used: 33
结果比之前表现更好,性能比Ridge时略好,并且只用了105中的33个特征,模型更容易理解
说明减小alpha,可以拟合更复杂的模型

(3)
如果把alpha设过小,会消除正则化效果,并出现过拟合,得到类似线性回归时候类似结果

lasso00001 = Lasso(alpha=0.0001, max_iter=100000).fit(X_train, y_train)
print("Training set score: {:.2f}".format(lasso00001.score(X_train, y_train)))
print("Test set score: {:.2f}".format(lasso00001.score(X_test, y_test)))
print("Number of features used:", np.sum(lasso00001.coef_ != 0))

OUT :
Training set score: 0.95
Test set score: 0.64
Number of features used: 96

(4)
作图,对不同模型的系数进行作图

plt.plot(lasso.coef_, 's', label="Lasso alpha=1")
plt.plot(lasso001.coef_, '^', label="Lasso alpha=0.01")
plt.plot(lasso00001.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")

OUT :
5449f6d567a24eb7b40d8647fa5eb866.png
对不同alpha的lasso回归与岭回归的系数进行比较:
alpha=0 大部分系数为0,其他系数也很小
alpha=0.01 大部分特征等于0
alpha=0.001 正则化很弱,大部分系数不为0且很大
Ridge alpha=0 与lasso的alpha=0.01的类似,但Ridge所有系数不为0

实践中一般使用岭回归,若特征多并重要的只有其中几个或者要更容易解释的模型,选择lasso

4. 用于二分类的线性模型

线性模型也用于分类问题,二分类公式:
834a473a67934df09f4489faefb8c045.png
没有返回特征的加权求和,为预测值设置了阈值(0),若大于0预测类别+1,小于0预测类别-1。
决策边界是输入的线性函数,即线性分类器用直线、平面、超平面进行分类。

不同线性模型的区别:
1、系数和截距的特定组合对训练数据拟合好坏的度量方法;
2、是否使用正则化,以及使用哪种正则化方法。

最常见的两种线性分类算法是Logistic回归线性支持向量机(线性SVM)

(1)线性SVM与logistics回归在forge数据集上的决策边界(参数默认)

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(clf.__class__.__name__)
    ax.set_xlabel("Feature 0")
    ax.set_ylabel("Feature 1")
axes[0].legend()

789844e4a6824dac9836f59a58e95dea.png

(2)不同C值的线性SVM在forge数据集上的决策边界

mglearn.plots.plot_linear_svc_regularization()

69924642980248609a4ffdde05af9472.png
(3)在乳腺癌数据集上分析LogisticsRegression

from sklearn.datasets import load_breast_cancer
cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(
    cancer.data, cancer.target, stratify=cancer.target, random_state=42)
logreg = LogisticRegression().fit(X_train, y_train)
print("Training set score: {:.3f}".format(logreg.score(X_train, y_train)))
print("Test set score: {:.3f}".format(logreg.score(X_test, y_test)))

Training set score: 0.953
Test set score: 0.958

(4)增大C值拟合更灵活模型

logreg100 = LogisticRegression(C=100).fit(X_train, y_train)
print("Training set score: {:.3f}".format(logreg100.score(X_train, y_train)))
print("Test set score: {:.3f}".format(logreg100.score(X_test, y_test)))

Training set score: 0.972
Test set score: 0.965

(5)使用正则化更强模型(设C=0.01)

logreg001 = LogisticRegression(C=0.01).fit(X_train, y_train)
print("Training set score: {:.3f}".format(logreg001.score(X_train, y_train)))
print("Test set score: {:.3f}".format(logreg001.score(X_test, y_test)))

Training set score: 0.934
Test set score: 0.930

(6)C值(正则化参数)取不同值模型学到的参数,作图(不同C值的logistics回归在乳腺癌数据集上学到的系数)

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()

8cb73a05ce9d4372a4bfeb17d446a007.png
(7)使用L1正则化

for C, marker in zip([0.001, 1, 100], ['o', '^', 'v']):
    lr_l1 = LogisticRegression(C=C, solver='liblinear', penalty="l1").fit(X_train, y_train)
    print("Training accuracy of l1 logreg with C={:.3f}: {:.2f}".format(
          C, lr_l1.score(X_train, y_train)))
    print("Test accuracy of l1 logreg with C={:.3f}: {:.2f}".format(
          C, lr_l1.score(X_test, y_test)))
    plt.plot(lr_l1.coef_.T, marker, label="C={:.3f}".format(C))

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.xlabel("Feature")
plt.ylabel("Coefficient magnitude")

plt.ylim(-5, 5)
plt.legend(loc=3)

f0f17b2bb7f3477da3696fe4312c2ec6.png

5. 用于多分类的线性模型

一对其余(one-vs.-rest),二分类推广,相当于对每个类别都学习一个二分类模型,将这个类别与所有其他类别尽量分开,这样就生成了与类别个数一样多的二分类模型
在测试集上运行所有的二分类模型进行预测,在对应类别上分数高的分类器“胜出”,将这个类别标签返回作为预测结果。

(1)三分类数据集(二维数据集)上应用一对其余法

from sklearn.datasets import make_blobs

X, y = make_blobs(random_state=42)
mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
plt.xlabel("Feature 0")
plt.ylabel("Feature 1")
plt.legend(["Class 0", "Class 1", "Class 2"])

347d90743a904918b5eabd5de9fa30c1.png
(2)训练linearSVC分类器

linear_svm = LinearSVC().fit(X, y)
print("Coefficient shape: ", linear_svm.coef_.shape)
print("Intercept shape: ", linear_svm.intercept_.shape)

Coefficient shape: (3, 2)
Intercept shape: (3,)

(3)将二类分类器的直线可视化

mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
line = np.linspace(-15, 15)
for coef, intercept, color in zip(linear_svm.coef_, linear_svm.intercept_,
                                  mglearn.cm3.colors):
    plt.plot(line, -(line * coef[0] + intercept) / coef[1], c=color)
plt.ylim(-10, 15)
plt.xlim(-10, 8)
plt.xlabel("Feature 0")
plt.ylabel("Feature 1")
plt.legend(['Class 0', 'Class 1', 'Class 2', 'Line class 0', 'Line class 1',
            'Line class 2'], loc=(1.01, 0.3))

7e0a3786335f45608585d72110875850.png
(4)三个“一对其余”分类器得到的多分类决策边界

mglearn.plots.plot_2d_classification(linear_svm, X, fill=True, alpha=.7)
mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
line = np.linspace(-15, 15)
for coef, intercept, color in zip(linear_svm.coef_, linear_svm.intercept_,
                                  mglearn.cm3.colors):
    plt.plot(line, -(line * coef[0] + intercept) / coef[1], c=color)
plt.legend(['Class 0', 'Class 1', 'Class 2', 'Line class 0', 'Line class 1',
            'Line class 2'], loc=(1.01, 0.3))
plt.xlabel("Feature 0")
plt.ylabel("Feature 1")

0dae5090d94046d8b178c7c5ab534314.png

优缺点、参数

1、参数:正则化参数
回归模型:alpha(alpha大,模型简单,正则化强)
分类模型:C(C小,模型简单,正则化强)

2、L1正则化 or L2正则化
L1正则化:很多特征中,只有几个特征比较重要,可解释性强
L2正则化:默认

3、优点
训练速度快、预测速度快
可推广到非常大的数据集,对于稀疏矩阵也很有效
对于特征数量大于样本数量的数据,线性模型表现优秀

4、缺点
不清楚系数怎么来的,尤其当数据集包含高度相关的特征

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值