1、用于分类的线性模型
y = w[0]*x[0] + w[1] * x[1] + … + w[p] * x[p] + b > 0
上述公式中,没有返回特征的加权求和,而是为预测设置了阈值(0)。
如果函数值小于0,预测类别-1;如果函数值大于0,则预测类别+1。
对于用于分类的线性模型,决策边界是输入的线性函数。换句话说,(二元)线性分类器是利用直线、平面或超平面来分开两个类别的分类器。
tip:学习线性模型有很多种算法,区别在于以下两点:、
1)、系数和截距的特定组合对训练数据拟合好坏的度量方式;
2)、是否使用正则化,以及使用哪种正则化方式。
最常见的两种线性分类算法是Logistic回归(logistic regression)和线性支持向量机(linear support vector machine, 线性SVM),前者在linear_model.LogisticRegression中实现,后者在svm.linearSVC(SVC代表支持向量分类器)中实现。
注:logisticRegression虽然名字有regression,但它是一种分类算法而不是回归算法,不应与LinearRegression混淆。
代码:
from sklearn.linear_model import LogisticRegression
from sklearn.svm import LinearSVC
import mglearn
from matplotlib import pyplot as plt
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()
tip1:对于LogisticRegression和LinearSVC,决定正则化强度的权衡参数叫作C。C值越大,对应的正则化越弱。换句话说,如果参数C值较大,那么LogisticRegression和LinearSVC将尽可能将训练集拟合到最好,而如果C值较小,那么模型更强调使系数向量(w)接近于0。
tip2:较小的C值可以让算法尽量适应“大多数”数据点,而较大的C值更强调每个数据点都分类正确的重要性。
mglearn.plots.plot_linear_svc_regularization()
plt.show()
说明:在左侧的图中,C值很小,对应强正则化。大部分属于类别0的点都位于底部,大部分属于类别1的点都位于顶部。强正则化的模型会选择一条相对水平的线,有两个点分类错误。在中间的图中,C值稍大,模型更关注两个分类错误的样本,使决策边界的斜率变大。最后,在右侧的图中,模型的C值非常大,使得决策边界的斜率也很大,现在模型对类别0中所有点的分类都是正确的。类别1中仍有一个点分类错误,这是因为对这个数据集来说,不可能用一条直线将所有点都分类正确。右侧图中的模型尽量使所有点的分类都正确,但可能无法正握类别的整体分布。也就是说这个模型很可能过拟合。
tip3:如果想要一个解释性更强的模型,使用L1正则化可能更好,因为它约束模型只使用少数几个特征。
2、用于多分类的线性模型
许多线性分类模型只适用于二分类问题,不能轻易推广到多类别问题(除了Logistic回归)。将二分类算法推广到多分类算法的一种常见方法是“一对其余”(one-vs.-rest)方法。在“一对其余”方法中,对每个类别都学习一个二分类模型,将这个类别与其他类别尽量分开,这样就生成了与类别个数一样多的二分类模型。在测试点上运行所有二类分类器来进行预测。在对应类别上分数最高的分类器“胜出”,将这个类别标签返回作为预测结果。下面给出的是分类置信方程,其结果中最大值对应的类别即为预测的类别标签:
w[0] * x[0] + w[1] *x [1] + … + w[p] * x[p] + b
代码:
import mglearn
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.svm import LinearSVC
#包含3个类别的二维玩具数据集
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"])
plt.show()
#将这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_, ['b', 'r', 'g']):
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))
plt.show()
#二维空间中所有区域的预测结果
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_, ['b', 'r', 'g']):
plt.plot(line, -(line * coef[0] + intercept) / coef[1], c=color)
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))
plt.show()
3、线性模型总结
线性模型的主要参数是正则化参数,在回归模型中叫做alpha,在LinearSvC和Logistic-Regression中叫做C。alpha值较大或C值较小,说明模型比较简单。特别是对于回归模型而言,调节这些参数非常重要。通常参数在对数尺度上对C和alpha进行搜索。你还需要确定的是用L1正则化还是L2正则化。如果你假定只有几个特征是真正重要的,那么你应该用L1正则化,否则应默认使用L2正则化。如果模型的可解释性很重要的话,使用L1也会有帮助。由于L1只用到几个特征,所以更容易解释哪些特征对模型是重要的,以及这些特征的作用。
线性模型的训练速度非常快,预测速度也很快。这种模型可以推广到非常大的数据集,对稀疏矩阵也很有效。如果你的数据包含数十万甚至上百万个样本,你可能需要研究如何使用LogisticRegression和Ridge模型的solver='sag’选项,在处理大型数据时,这一选项比默认值要更快。其它选项还有SGDClassfier类和SGDRegressor类,他们对前面提到的线性模型实现了可扩展性更强的版本。
线性模型的另一个优点在于,利用我们之间见过的用于回归和分类的公式,理解如何进行预测是相对比较容易的。不行的是,往往并不完全清楚系数为什么是这样的。如果你的数据集中包含高度相关的特征,这一问题尤其突出。这种情况下,可能很难对系数做出解释。
如果特征数量大于样本数量,线性模型的表现通常都很好。它也常用于非常大的数据集,只是因为训练其它模型并不可行。但在更低维的空间中,其它模型的泛化性能可能更好。