Machine-Learning 编程作业
Programming Exercise 6:Support Vector Machines
SVM的简单应用
part1 示例文件1使用线性核函数
part2 示例文件2运用高斯核函数
part3 示例文件3运用验证集找最优参数
part4 垃圾邮件分类
这周的作业SVM的实现因为使用的是sklearn库中的SVM库,所以较为简单。但让我最头秃的就是每一次分类之后分类边界的绘制,matplotlab的学习路途任重而道远啊,花了我一下午时间找到三种绘图方法,,太难了。
线性核函数的应用
导入数据集可视化
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.io import loadmat
from sklearn.svm import LinearSVC, SVC
raw_data = loadmat('data/ex6data1')
data = pd.DataFrame(raw_data['X'], columns=['X1', 'X2'])
data['y'] = raw_data['y']
print(data)
positive = data[data['y'].isin([1])]
negative = data[data['y'].isin([0])]
fig, ax = plt.subplots(figsize=(6,4))#定义图的大小
ax.scatter(positive['X1'], positive['X2'], s=50, c='b', marker='o', label='Positive')
ax.scatter(negative['X1'], negative['X2'], s=50, c='r', marker='x', label='Negative')
ax.legend()#在图形中加入颜色不同的备注
ax.set_xlabel('X1')
ax.set_ylabel('X2')
plt.show()
评估分类器性能
#下面有两种svm库的使用方法,但几乎都是同样的功能,因为SVC的核函数选为了 线性核函数
# clf = LinearSVC(C=100, loss='hinge', max_iter=1000)
clf = SVC(C=100, kernel='linear', gamma= 0.001)
clf.fit(data[['X1', 'X2']], data['y'])
print(clf.score(data[['X1', 'X2']], data['y']))#评估分类器性能
svc2 = LinearSVC(C=1, loss='hinge', max_iter=1000)
svc2.fit(data[['X1', 'X2']], data['y'])
print(svc2.score(data[['X1', 'X2']], data['y']))
结果如下:
两个分类结果。第一个表示全部分类正确了,但看下图就知道有些过拟合了。第二个较第一个稍低。
分类结果边界可视化
data['SVM 1 Confidence'] = clf.decision_function(data[['X1', 'X2']])
fig, ax = plt.subplots(figsize=(6,4))
ax.scatter(data['X1'], data['X2'], s=50, c=data['SVM 1 Confidence'], cmap='seismic')
ax.set_title('SVM (C=100) Decision Confidence')
# plt.show()
data['SVM 2 Confidence'] = svc2.decision_function(data[['X1', 'X2']])
fig, ax = plt.subplots(figsize=(6,4))
ax.scatter(data['X1'], data['X2'], s=50, c=data['SVM 2 Confidence'], cmap='seismic')
ax.set_title('SVM (C=1) Decision Confidence')
# plt.show()
分类结果:
可以看到第一张图中,红色的异常点也检测正确了
第二章图中,异常点判为了另外一类。但这样看着不太明显,我们试着画出来分类边界的线条吧。
画边界线
def visualize_boundary(clf,X, x_min, x_max, y_min, y_max): #x,y轴的取值范围
h = .02
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))#在x,y轴上以0.02为间隔,生成网格点
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])#预测每个网格点的类别0/1
Z = Z.reshape(xx.shape) #转型为网格的形状
ax.scatter(X['X1'], X['X2'], s=50, c=data['SVM 1 Confidence'], cmap='seismic') #这里我给第一张图画的边界,,也可以改成第一张图的哦,我太懒了不想改
plt.contour(xx, yy,Z, level=[0],colors='r') #等高线图 将0/1分界线(决策边界)画出
plt.show()
visualize_boundary(clf,data, 0, 4.5, 1.5, 5)
结果如下:
高斯核函数的应用
这里找了第三种便捷绘制方法,我感觉这一种是最好的,以后就用这个吧。过程几乎一样,我就整体上代码了。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.svm import SVC
from scipy.io import loadmat
#定义高斯核函数验证其性能
def gaussian_kernel(x1, x2, sigma):
return np.exp(-(np.sum((x1 - x2) ** 2) / (2 * (sigma ** 2))))
x1 = np.array([1.0, 2.0, 1.0])
x2 = np.array([0.0, 4.0, -1.0])
sigma = 2
# print(gaussian_kernel(x1, x2, sigma))
def visualize_boundary(clf, X, x_min, x_max, y_min, y_max): #x,y轴的取值范围
h = .02
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))#在x,y轴上以0.02为间隔,生成网格点
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])#预测每个网格点的类别0/1
Z = Z.reshape(xx.shape) #转型为网格的形状
plt.contour(xx, yy,Z, level=[0],colors='r') #等高线图 将0/1分界线(决策边界)画出来
#上面这一小部分是昨夜里要求验证的,和下面内容无关。
#导入训练示例2,并可视化
raw_data = loadmat('data/ex6data2')
data = pd.DataFrame(raw_data['X'], columns=['X1', 'X2'])
data['y'] = raw_data['y']
# print(data)
#可视化数据
positive = data[data['y'].isin([1])]
negative = data[data['y'].isin([0])]
fig, ax = plt.subplots(figsize=(6,4))#定义图的大小
ax.scatter(positive['X1'], positive['X2'], s=5, c='b', marker='o', label='Positive')
ax.scatter(negative['X1'], negative['X2'], s=5, c='r', marker='x', label='Negative')
ax.legend()#在图形中加入颜色不同的备注
ax.set_xlabel('X1')
ax.set_ylabel('X2')
plt.show()
X = raw_data['X']
y = raw_data['y'].flatten()
# print(X,y)
clf = SVC(C=100, kernel='rbf', gamma= 10, probability=True)
# # clf = SVC(C=100, gamma=10, probability=True)
clf.fit(X, y)
print(clf.score(data[['X1', 'X2']], data['y']))#评估分类器性能
#准备画图
plot_step = 0.02
# x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
# y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
x_min, x_max = 0, 1.05
y_min, y_max = 0.38, 1.02
xx,yy = np.meshgrid(np.arange(x_min, x_max, plot_step),
np.arange(y_min, y_max, plot_step))
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
cs = plt.contourf(xx, yy, Z, camp=plt.cm.Paired)
plt.axis("tight")
class_name = "AB"
plot_colors = "rb"
for i, n, c in zip(range(2), class_name, plot_colors):
idx = np.where(y == i)
plt.scatter(X[idx, 0], X[idx, 1],s=1, c=c, cmap=plt.cm.Paired, label = "Class %s" %n)
plt.xlim(x_min, x_max)
plt.ylim(y_min, y_max)
plt.legend(loc='upper right')
plt.xlabel('x')
plt.ylabel('y')
plt.title('Decision Boundary')
plt.show()
结果如下:
这个真好看,哈哈
找最优参数
上代码,更简单
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import numpy as pd
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.svm import SVC
from scipy.io import loadmat
raw_data = loadmat('data/ex6data3.mat')
X = raw_data['X']
Xval = raw_data['Xval']
y = raw_data['y'].ravel()
yval = raw_data['yval'].ravel()
C_values = [0.01, 0.03, 0.1, 0.3, 1, 3, 10, 30, 100]
gamma_values = [0.01, 0.03, 0.1, 0.3, 1, 3, 10, 30, 100]
best_score = 0
best_params = {'C': None, 'gamma': None}
for C in C_values:
for gamma in gamma_values:
clf = SVC(C=C, gamma=gamma)
clf.fit(X, y)
score = clf.score(Xval, yval)
if score > best_score:
best_score = score
best_params['C'] = C
best_params['gamma'] = gamma
print(best_score, best_params)
结果如下:
垃圾邮件分类
这个和前面过程也几乎一样。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.svm import SVC
from scipy.io import loadmat
spam_train = loadmat('data/spamTrain.mat')
spam_test = loadmat('data/spamTest.mat')
print(spam_train)
X = spam_train['X']
Xtest = spam_test['Xtest']
y = spam_train['y'].ravel()
ytest = spam_test['ytest'].ravel()
print(X.shape, y.shape, Xtest.shape, ytest.shape)
#使用所有默认参数
clf = SVC() #什么都不填就是默认参数,也可以自己改,详情参考sklearn库中sklearn.svm.SVC函数的使用说明
clf.fit(X, y)
print('Training accuracy = {0}%'.format(np.round(clf.score(X, y) * 100, 2)))
print('Test accuracy = {0}%'.format(np.round(clf.score(Xtest, ytest) * 100, 2)))
结果如下:
可以自己在SVC函数里设置参数,试试结果。 OK,大功告成!