《机器学习实战——基于Scikit-Learn和TensorFlow》
这是一本非常好的机器学习和深度学习入门书,既有基本理论讲解,也有实战代码示例。
我将认真阅读此书,并为每一章内容做一个知识笔记。
我会摘录一些原书中的关键语句和代码,若有错误请为我指出。
SVM能够执行线性或非线性分类、回归,甚至是异常值检测任务。
SVM特别适用于中小型复杂数据集的分类。
可以将SVM分类器视为在类别之间拟合可能的最宽的街道,也叫大间隔分类。
在街道以外的地方增加更多训练实例,不会对决策边界产生影响:也就是说它完全由位于街道边缘的实例所决定,这些实例被称为 支持向量 。
SVM对特征缩放非常敏感。
严格让所有实例都不在街道上,并且位于正确的一边就是 硬间隔分类 。
硬间隔分类有两个问题:
尽可能在保持街道宽阔和限制间隔违例之间找到良好的平衡,这就是 软间隔分类 。
在scikit-learn的SVM类中,可以通过控制超参数C来控制这个平衡:C越小,街道越宽,但是违例越多。
若SVM过拟合,可以通过降低C来正则化。
import numpy as np
from sklearn import datasets
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC
iris = datasets.load_iris()
X = iris["data"][:, (2, 3)] # petal length, petal width
y = (iris["target"] == 2).astype(np.float64) # Iris-Virginica
svm_clf = Pipeline([
("scaler", StandardScaler()),
("linear_svc", LinearSVC(C=1, loss="hinge", random_state=42)),
])
svm_clf.fit(X, y)
处理非线性数据集的方法之一是添加更多特征,比如多项式特征。
from sklearn.datasets import make_moons
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
polynomial_svm_clf = Pipeline([
("poly_features", PolynomialFeatures(degree=3)),
("scaler", StandardScaler()),
("svm_clf", LinearSVC(C=10, loss="hinge", random_state=42))
])
polynomial_svm_clf.fit(X, y)
如果多项式太低阶,处理不了非常复杂的数据集,而高阶则会创造出大量的特征,导致模型变得太慢。
可以使用 核技巧 ,产生的结果和添加了许多多项式特征一样,但实际上并未添加,所以不存在数量爆炸的组合特征。这个技巧由SVC类来实现。
另一种技术是添加相似特征。
这些特征经过 相似函数 计算得出,相似函数可以测量每个实例与一个特定地标之间的相似度。
比如添加一些地标,然后使用高斯RBF函数来计算新的特征。
可使用SVC类来试试高斯RBF核:
from sklearn.svm import SVC
gamma1, gamma2 = 0.1, 5
C1, C2 = 0.001, 1000
hyperparams = (gamma1, C1), (gamma1, C2), (gamma2, C1), (gamma2, C2)
svm_clfs = []
for gamma, C in hyperparams:
rbf_kernel_svm_clf = Pipeline([
("scaler", StandardScaler()),
("svm_clf", SVC(kernel="rbf", gamma=gamma, C=C))
])
rbf_kernel_svm_clf.fit(X, y)
svm_clfs.append(rbf_kernel_svm_clf)
plt.figure(figsize=(11, 7))
for i, svm_clf in enumerate(svm_clfs):
plt.subplot(221 + i)
plot_predictions(svm_clf, [-1.5, 2.5, -1, 1.5])
plot_dataset(X, y, [-1.5, 2.5, -1, 1.5])
gamma, C = hyperparams[i]
plt.title(r"$\gamma = {}, C = {}$".format(gamma, C), fontsize=16)
save_fig("moons_rbf_svc_plot")
plt.show()
增加gamma的值,会使每个实例的影响范围随之变小,决策边界更加不规则,开始围绕单个实例绕弯。
反过来,减小gamma值使每个实例影响范围增大,决策边界更加平坦。
所以,模型过度拟合时,降低它的值,拟合不足时,提高它的值。
选择核函数时,经验法则是永远从线性核函数开始尝试,特别是训练集非常大或特征非常多的时候。
如果训练集不太大,可以试试高斯RBF核,大多数情况下它都非常好用。
lib库为线性SVM实现了一个优化算法,LinearSVC是基于该库的。
不支持核技巧,训练时间复杂度:O(m*n)。
SVC是基于libsvm库的,支持核技巧。
训练复杂度在O(m2*n)和O(m3*n)之间,完美适用于复杂但是中小型的训练集。
SVM不仅支持线性和非线性分类,还支持线性和非线性回归。
用于回归时,目标不再是尝试拟合两个类别之间可能的最宽的街道的同时限制间隔违例,而是让尽可能多的实例位于街道上,同时限制间隔违例。
街道的宽度由 ε \varepsilon ε控制,它对街道内实例的数量不敏感。
可以使用scikit-learn的LinearSVR类来执行线性SVM回归。
from sklearn.svm import SVR
svm_poly_reg = SVR(kernel="poly", degree=2, C=100, epsilon=0.1, gamma="auto")
svm_poly_reg.fit(X, y)
要解决非线性回归任务,可以使用核化的SVM模型。
from sklearn.svm import SVR
svm_poly_reg1 = SVR(kernel="poly", degree=2, C=100, epsilon=0.1, gamma="auto")
svm_poly_reg2 = SVR(kernel="poly", degree=2, C=0.01, epsilon=0.1, gamma="auto")
svm_poly_reg1.fit(X, y)
svm_poly_reg2.fit(X, y)
SVR是SVC类的回归等价物,LinearSVR类也是LinearSVC类的回归等价物。
LinearSVR与训练集的大小线性相关,而SVR则在训练集变大时,变得很慢。
SVM也可用于异常值检测,可参考scikit-learn。
线性SVM分类器通过简单地计算决策函数来预测新实例的分类。
y ^ = { 0 i f w T ⋅ x + b < 0 1 i f x + b ≥ 0 \hat{y}=\begin{cases}{0}&{if\quad w^T\cdot x+b<0}\\{1}&{if\quad x+b\geq0}\end{cases} y^={01ifwT⋅x+b<0ifx+b≥0
下图虚线表示决策函数等于1或-1的点:它们互相平行,并且与决策边界的距离相等,从而形成了一个间隔。
训练线性SVM意味着找到w和b使得间隔尽可能的宽,避免或限制间隔违例。
决策函数的斜率,等于权重向量的范数。
则权重向量越小,间隔越大,越好。
令正类为+1,负类为-1,则硬间隔:
最 小 化 w , b 1 2 w T ⋅ w 最小化_{w,b}\quad \frac{1}{2}w^T\cdot w 最小化w,b21wT⋅w
使 得 t ( i ) ( w T ⋅ x ( i ) + b ) ≥ 1 ( i = 1 , 2 , . . . , m ) 使得\quad t^{(i)}(w^T\cdot x^{(i)}+b)\geq1(i=1,2,...,m) 使得t(i)(wT⋅x(i)+b)≥1(i=1,2,...,m)
软间隔,添加一个松弛变量,用C来平衡违例和目标:
最 小 化 w , b , ζ 1 2 w T ⋅ w + C ∑ i = 1 m ζ ( i ) 最小化_{w,b,\zeta}\quad \frac{1}{2}w^T\cdot w+C\sum_{i=1}^m{\zeta^{(i)}} 最小化w,b,ζ21wT⋅w+Ci=1∑mζ(i)
使 得 t ( i ) ( w T ⋅ x ( i ) + b ) ≥ 1 − ζ ( i ) 且 ζ ≥ 0 ( i = 1 , 2 , . . . , m ) 使得\quad t^{(i)}(w^T\cdot x^{(i)}+b)\geq1-\zeta^{(i)}\quad 且\zeta\geq0(i=1,2,...,m) 使得t(i)(wT⋅x(i)+b)≥1−ζ(i)且ζ≥0(i=1,2,...,m)
硬间隔和软间隔都属于线性约束的凸二次优化问题。
给定的约束优化问题为 原始问题 ,与之密切相关的为 对偶问题 。
对偶问题的解是只能算是原始问题的下限,但某些情况下可能跟原始问题的解完全相同。
幸运的是,SVM问题刚好就满足这些条件。
对偶形式略。
当训练实例的数量小于特征数量时,解决对偶问题比原始问题更快速。
更重要的是,对偶问题能实现核技巧,而原始问题不能实现。
。。。
。。。