第十一章.支持向量机(SVM)
11.2 支持向量机—SMO算法
1.SMO算法
Microsoft Research的John C. Platt在1998年提出针对线性SVM和数据稀疏时性能更优
1).公式
2).基本思路
先根据约束条件随机给𝛼赋值。然后每次选取两个𝛼,调节这两个𝛼使得目标函数最小。然后再选取两个𝛼,调节𝛼使得目标函数最小,以此类推。
3).线性不可分的情况
-
松弛变量(ε)与惩罚函数
-
线性不可分情形下的对偶问题
①.公式
②.示例
·计算-
1.
-
2.
-
3.
-
2.非线性的情况
1).把低维空间的非线性问题映射到高维空间,变成求解线性问题
①.图像1
②.图像2
③.图像3
2).示例:SVM-低维映射高维
①.代码实现
import matplotlib.pyplot as plt
from sklearn import datasets
x_data, y_data = datasets.make_circles(n_samples=500, factor=.3, noise=.10)
fig = plt.figure(figsize=(8, 4))
fig.add_subplot(121)
plt.scatter(x_data[:, 0], x_data[:, 1], c=y_data)
plt.title("LowData")
z_data = x_data[:, 0] ** 2 + x_data[:, 1] ** 2
ax = fig.add_subplot(122, projection='3d')
ax.scatter(x_data[:, 0], x_data[:, 1], z_data, c=y_data, s=20)
plt.title("HighData")
plt.show()
②.结果展示
3.映射举例
1).映射方法
2).存在的问题
①.原本的代价函数
②.映射后的代价函数
③.存在的问题:维度灾难
- 红色的地方要使用映射后的样本向量做内积,若最初的特征是n维的,我们把它映射到n2维,然后在计算,这样需要的时间就从原来的O(n),变成了O(n2)
④.优化方法
i).引入核函数
我们可以构造核函数使得运算结果等同于非线性映射,同时运算量要远远小于非线性映射。
ii).核函数举例
4.SVM优点
1).训练好的模型的算法复杂度是由支持向量的个数决定的,而不是由数据的维度决定的。所以SVM不太容易产生overfitting
2).SVM训练出来的模型完全依赖于支持向量(SupportVectors), 即使训练集里面所有非支持向量的点都被去除,重复训练过程,结果仍然会得到完全一样的模型。
3).一个SVM如果训练得出的支持向量个数比较小,SVM训练出的模型比较容易被泛化。
5.示例
1).示例1:SVM-线性分类
①.代码实现
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm
# 随机创建40个点
x_data = np.r_[np.random.randn(20, 2) - [2, 2], np.random.randn(20, 2) + [2, 2]] # np.r_是按列连接两个矩阵
y_data = [0] * 20 + [1] * 20
# svm
model_svm = svm.SVC(kernel='linear')
model_svm.fit(x_data, y_data)
coef = model_svm.coef_
# 截距
intercept = model_svm.intercept_
# 获取分离平面
k = -coef[0][0] / coef[0][1]
b = -intercept / coef[0][1]
x_test = np.array([[-5], [5]])
y_test = k * x_test + b
# 画出通过支持向量的分界线
b1 = model_svm.support_vectors_[0]
y_down = k * x_test + (b1[1] - k * b1[0])
b2 = model_svm.support_vectors_[-1]
y_up = k * x_test + (b2[1] - k * b2[0])
# 绘图
plt.scatter(x_data[:, 0], x_data[:, 1], c=y_data)
plt.plot(x_test, y_test, 'k')
plt.plot(x_test, y_down, 'r--')
plt.plot(x_test, y_up, 'b--')
plt.show()
②.结果展示
2).示例2:SVM-非线性分类
①.代码实现
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm
def drawImage(x_data, y_data):
x0 = []
y0 = []
x1 = []
y1 = []
# 切分不同类别的数据
for i in range(len(y_data)):
if y_data[i] == 0:
x0.append(x_data[i, 0])
y0.append(x_data[i, 1])
else:
x1.append(x_data[i, 0])
y1.append(x_data[i, 1])
scatter1 = plt.scatter(x0, y0, c='r', marker='o')
scatter2 = plt.scatter(x1, y1, c='b', marker='x')
plt.legend(handles=[scatter1, scatter2], labels=['label0', 'label1'], loc='best')
def drawContour(x_data, y_data, model):
x_min, x_max = x_data[:, 0].min() - 1, x_data[:, 0].max() + 1
y_min, y_max = x_data[:, 1].min() - 1, x_data[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
np.arange(y_min, y_max, 0.02))
z = model.predict(np.c_[xx.ravel(), yy.ravel()])
zz = z.reshape(xx.shape)
plt.contourf(xx, yy, zz)
drawImage(x_data, y_data)
# 载入数据
data = np.genfromtxt('F:\\LR-testSet2.txt', delimiter=',')
x_data = data[:, :-1]
y_data = data[:, -1]
# 加载模型
# 'linear', 'poly', 'rbf', 'sigmoid'
model = svm.SVC(kernel='rbf', C=2, gamma=1)
model.fit(x_data, y_data)
# 精度
score = model.score(x_data, y_data)
print(score)
# 绘图
drawContour(x_data, y_data, model)
plt.show()
②.结果展示