赞
踩
1.SVM简介
支持向量机(support vector machines, SVM)是一种二分类模型,它的基本模型是定义在特征空间上的间隔最大的线性分类器,间隔最大使它有别于感知机;SVM还包括核技巧,这使它成为实质上的非线性分类器。SVM的的学习策略就是间隔最大化,可形式化为一个求解凸二次规划的问题,也等价于正则化的合页损失函数的最小化问题。SVM的的学习算法就是求解凸二次规划的最优化算法。
2.SVM算法原理
SVM学习的基本想法是求解能够正确划分训练数据集并且几何间隔最大的分离超平面。如下图所示, 即为分离超平面,对于线性可分的数据集来说,这样的超平面有无穷多个(即感知机),但是几何间隔最大的分离超平面却是唯一的。
拉格朗日乘子法
首先定义原始目标函数,拉格朗日乘子法的基本思想是把约束条件转化为新的目标函数的一部分(关于的意义我们一会儿再解释),从而使有约束优化问题变成我们习惯的无约束优化问题。那么该如何去改造原来的目标函数使得新的目标函数的最优解恰好就在可行解区域中呢?这需要我们去分析可行解区域中最优解的特点。
1)最优解的特点分析
推论1:“在那个宿命的相遇点(也就是等式约束条件下的优化问题的最优解),原始目标函数的梯度向量必然与约束条件的切线方向垂直。”
推论2:“函数的梯度方向也必然与函数自身等值线切线方向垂直。”
推论3:“函数与函数的等值线在最优解点处相切,即两者在点的梯度方向相同或相反”
2)构造拉格朗日函数
3)KKT条件
对于不等式约束条件的情况,如图4所示,最优解所在的位置有两种可能,或者在边界曲线上或者在可行解区域内部满足不等式的地方。
第一种情况:最优解在边界上,就相当于约束条件就是。参考图4,注意此时目标函数的最优解在可行解区域外面,所以函数在最优解附近的变化趋势是“在可行解区域内侧较大而在区域外侧较小”,与之对应的是函数在可行解区域内小于0,在区域外大于零,所以在最优解附近的变化趋势是内部较小而外部较大。这意味着目标函数的梯度方向与约束条件函数的梯度方向相反。因此根据公式(3.1),可以推断出参数.
1KKT条件是对最优解的约束,而原始问题中的约束条件是对可行解的约束。
2KKT条件的推导对于后面马上要介绍的拉格朗日对偶问题的推导很重要。
拉格朗日对偶
4)对偶问题同解的证明
3.smo算法
SMO(Sequential Minmal Optimization)序列最小化算法,是一种对SVM的高效的优化算法。
但是怎么证明他的正确性:详情请查看:https://www.jianshu.com/p/0c433f6f4141
4.核函数
核函数K(kernel function)就是指K(x, y) = <f(x), f(y)>,其中x和y是n维的输入值,f(·) 是从n维到m维的映射(通常,m>>n)。<x, y>是x和y的内积(inner product)(也称点积(dot product))。
要注意,核函数和映射没有关系。核函数只是用来计算映射到高维空间之后的内积的一种简便方法。
5.SVM回归 (转载https://www.cnblogs.com/whiteBear/p/13096398.html)
SVM回归任务是限制间隔违规情况下,尽量防止更多的样本在“街道”上。“街道”的宽度由超参数ϵϵ控制
在随机生成的线性数据上,两个线性SVM回归模型,一个有较大的间隔(ϵ=1.5ϵ=1.5),另一个间隔较小(ϵ=0.5ϵ=0.5),训练情况如下:
代码如下:
造数据与训练:
- np.random.seed(42)
- m = 50
- X = 2 * np.random.randn(m,1)
- y = (4 + 3 * X + np.random.randn(m,1)).ravel()
-
- from sklearn.svm import LinearSVR
-
- svm_reg1 = LinearSVR(epsilon=1.5, random_state=42)
- svm_reg2 = LinearSVR(epsilon=0.5, random_state=42)
-
- svm_reg1.fit(X, y)
- svm_reg2.fit(X,y)
可视化编码
- def find_support_vectors(svm_reg, X, y):
- y_pred = svm_reg.predict(X)
- off_margin = (np.abs(y - y_pred) >= svm_reg.epsilon)
- return np.argwhere(off_margin)
-
- svm_reg1.support_ = find_support_vectors(svm_reg1, X, y)
- svm_reg2.support_ = find_support_vectors(svm_reg2, X, y)
-
- eps_x1 = 1
- eps_y_pred = svm_reg1.predict([[eps_x1]])
- def plot_svm_regression(svm_reg, X, y, axes):
- x1s = np.linspace(axes[0], axes[1], 100).reshape(100, 1)
- y_pred = svm_reg.predict(x1s)
- plt.plot(x1s, y_pred, "k-", linewidth=2, label=r"$\hat{y}$")
- plt.plot(x1s, y_pred + svm_reg.epsilon, "k--")
- plt.plot(x1s, y_pred - svm_reg.epsilon, "k--")
- plt.scatter(X[svm_reg.support_], y[svm_reg.support_], s=180, facecolors='#FFAAAA')
- plt.plot(X, y, "bo")
- plt.xlabel(r"$x_1$", fontsize=18)
- plt.legend(loc="upper left", fontsize=18)
- plt.axis(axes)
-
- plt.figure(figsize=(9, 4))
- plt.subplot(121)
- plot_svm_regression(svm_reg1, X, y, [0, 2, 3, 11])
- plt.title(r"$\epsilon = {}$".format(svm_reg1.epsilon), fontsize=18)
- plt.ylabel(r"$y$", fontsize=18, rotation=0)
- #plt.plot([eps_x1, eps_x1], [eps_y_pred, eps_y_pred - svm_reg1.epsilon], "k-", linewidth=2)
- plt.annotate(
- '', xy=(eps_x1, eps_y_pred), xycoords='data',
- xytext=(eps_x1, eps_y_pred - svm_reg1.epsilon),
- textcoords='data', arrowprops={'arrowstyle': '<->', 'linewidth': 1.5}
- )
- plt.text(0.91, 5.6, r"$\epsilon$", fontsize=20)
- plt.subplot(122)
- plot_svm_regression(svm_reg2, X, y, [0, 2, 3, 11])
- plt.title(r"$\epsilon = {}$".format(svm_reg2.epsilon), fontsize=18)
-
- plt.show()
可视化展示:
非线性拟合
造数据
- np.random.seed(42)
- m = 100
- X = 2 * np.random.rand(m, 1) - 1
- y = (0.2 + 0.1 * X + 0.5 * X**2 + np.random.randn(m, 1)/10).ravel()
- from sklearn.svm import SVR
-
- 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)
可视化编程
- plt.figure(figsize=(9, 4))
- plt.subplot(121)
- plot_svm_regression(svm_poly_reg1, X, y, [-1, 1, 0, 1])
- plt.title(r"$degree={}, C={}, \epsilon = {}$".format(svm_poly_reg1.degree, svm_poly_reg1.C, svm_poly_reg1.epsilon), fontsize=18)
- plt.ylabel(r"$y$", fontsize=18, rotation=0)
- plt.subplot(122)
- plot_svm_regression(svm_poly_reg2, X, y, [-1, 1, 0, 1])
- plt.title(r"$degree={}, C={}, \epsilon = {}$".format(svm_poly_reg2.degree, svm_poly_reg2.C, svm_poly_reg2.epsilon), fontsize=18)
-
- plt.show()
可视化展示:
6.代码实现
代码
- from sklearn import svm
- import numpy as np
- import matplotlib.pyplot as plt
- #准备训练样本
- x=[[1,8],[3,20],[1,15],[3,35],[5,35],[4,40],[7,80],[6,49]]
- y=[1,1,-1,-1,1,-1,-1,1]
- ##开始训练
- clf=svm.SVC() ##默认参数:kernel='rbf'
- clf.fit(x,y)
- #print("预测...")
- #res=clf.predict([[2,2]]) ##两个方括号表面传入的参数是矩阵而不是list
- ##根据训练出的模型绘制样本点
- for i in x:
- res=clf.predict(np.array(i).reshape(1, -1))
- if res > 0:
- plt.scatter(i[0],i[1],c='r',marker='*')
- else :
- plt.scatter(i[0],i[1],c='g',marker='*')
- ##生成随机实验数据(15行2列)
- rdm_arr=np.random.randint(1, 15, size=(15,2))
- ##回执实验数据点
- for i in rdm_arr:
- res=clf.predict(np.array(i).reshape(1, -1))
- if res > 0:
- plt.scatter(i[0],i[1],c='r',marker='.')
- else :
- plt.scatter(i[0],i[1],c='g',marker='.')
- ##显示绘图结果
- plt.show()
运行截图
代码
- from sklearn import svm
- import numpy as np
- import matplotlib.pyplot as plt
- ##设置子图数量
- fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(7, 7))
- ax0, ax1, ax2, ax3 = axes.flatten()
- # 准备训练样本
- x = [[1, 8], [3, 20], [1, 15], [3, 35], [5, 35], [4, 40], [7, 80], [6, 49]]
- y = [1, 1, -1, -1, 1, -1, -1, 1]
- ##设置子图的标题
- titles = ['LinearSVC (linear kernel)',
- 'SVC with polynomial (degree 3) kernel',
- 'SVC with RBF kernel', ##这个是默认的
- 'SVC with Sigmoid kernel']
- ##生成随机试验数据(15行2列)
- rdm_arr = np.random.randint(1, 15, size=(15, 2))
- def drawPoint(ax, clf, tn):
- ##绘制样本点
- for i in x:
- ax.set_title(titles[tn])
- res = clf.predict(np.array(i).reshape(1, -1))
- if res > 0:
- ax.scatter(i[0], i[1], c='r', marker='*')
- else:
- ax.scatter(i[0], i[1], c='g', marker='*')
- ##绘制实验点
- for i in rdm_arr:
- res = clf.predict(np.array(i).reshape(1, -1))
- if res > 0:
- ax.scatter(i[0], i[1], c='r', marker='.')
- else:
- ax.scatter(i[0], i[1], c='g', marker='.')
-
-
- if __name__ == "__main__":
- ##选择核函数
- for n in range(0, 4):
- if n == 0:
- clf = svm.SVC(kernel='linear').fit(x, y)
- drawPoint(ax0, clf, 0)
- elif n == 1:
- clf = svm.SVC(kernel='poly', degree=3).fit(x, y)
- drawPoint(ax1, clf, 1)
- elif n == 2:
- clf = svm.SVC(kernel='rbf').fit(x, y)
- drawPoint(ax2, clf, 2)
- else:
- clf = svm.SVC(kernel='sigmoid').fit(x, y)
- drawPoint(ax3, clf, 3)
- plt.show()
运行截图
代码
- from sklearn import svm
- import numpy as np
- import matplotlib.pyplot as plt
- ##设置子图数量
- fig, axes = plt.subplots(nrows=1, ncols=2,figsize=(7,7))
- ax0, ax1 = axes.flatten()
- #准备训练样本
- x=[[1,8],[3,20],[1,15],[3,35],[5,35],[4,40],[7,80],[6,49]]
- y=[1,1,-1,-1,1,-1,-1,1]
- ##设置子图的标题
- titles = ['SVC (linear kernel)',
- 'LinearSVC']
- ##生成随机试验数据(15行2列)
- rdm_arr=np.random.randint(1, 15, size=(15,2))
- ##画图函数
- def drawPoint(ax,clf,tn):
- ##绘制样本点
- for i in x:
- ax.set_title(titles[tn])
- res=clf.predict(np.array(i).reshape(1, -1))
- if res > 0:
- ax.scatter(i[0],i[1],c='r',marker='*')
- else :
- ax.scatter(i[0],i[1],c='g',marker='*')
- ##绘制实验点
- for i in rdm_arr:
- res=clf.predict(np.array(i).reshape(1, -1))
- if res > 0:
- ax.scatter(i[0],i[1],c='r',marker='.')
- else :
- ax.scatter(i[0],i[1],c='g',marker='.')
-
- if __name__=="__main__":
- ##选择核函数
- for n in range(0,2):
- if n==0:
- clf = svm.SVC(kernel='linear').fit(x, y)
- drawPoint(ax0,clf,0)
- else :
- clf= svm.LinearSVC().fit(x, y)
- drawPoint(ax1,clf,1)
- plt.show()
运行截图
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。