Menu

Lab11 sklearn中的SVM应用实践

利用 scikit-learn 中自带的 iris 数据集,学习数据规范化、数据集切分、分类、预测,以及分类器 SVC 的测试评估等。

sklearn 官网:http://scikit-learn.org/stable/,包含 sklearn 资源,模块下载,文档、例程等。

实验目的

sklearn 库的 SVM 分类器的实现。

实验环境

硬件

所用机器型号为 VAIO Z Flip 2016

  • Intel(R) Core(TM) i7-6567U CPU @3.30GHZ 3.31GHz
  • 8.00GB RAM

软件

  • Windows 10, 64-bit (Build 17763) 10.0.17763
  • Visual Studio Code 1.39.2
    • Python 2019.10.41019:九月底发布的 VSCode Python 插件支持在编辑器窗口内原生运行 juyter nootbook 了,非常赞!
    • Remote - WSL 0.39.9:配合 WSL,在 Windows 上获得 Linux 接近原生环境的体验。
  • Windows Subsystem for Linux [Ubuntu 18.04.2 LTS]:WSL 是以软件的形式运行在 Windows 下的 Linux 子系统,是近些年微软推出来的新工具,可以在 Windows 系统上原生运行 Linux。
    • Python 3.7.4 64-bit (‘anaconda3’:virtualenv):安装在 WSL 中。

操作习题

参照 PPT, 可视化基于 iris 数据集的 SVM 分类器的决策边界,并操作说明decision_function()方法得的功能和用法,以及matplotlib.pyplot.contour()的功能和用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import numpy
from matplotlib import pyplot
from sklearn import svm
from sklearn.datasets import load_iris

if __name__ == '__main__':
    # 导入数据集
    iris = load_iris()
    X = iris.data[:, :2]  # 只取前两维特征
    y = iris.target

    h = .02  # 网格中的步长

    # 创建支持向量机实例,并拟合出数据
    C = 1.0  # SVM正则化参数
    svc = svm.SVC(kernel='linear', C=C).fit(X, y)  # 线性核
    rbf_svc = svm.SVC(kernel='rbf', gamma=0.7, C=C).fit(X, y)  # 径向基核
    poly_svc = svm.SVC(kernel='poly', degree=3, C=C).fit(X, y)  # 多项式核
    lin_svc = svm.LinearSVC(C=C).fit(X, y)  # 线性核
    # print('decision_function:')
    # decision_function计算的是样本x到各个分割平面的距离<也就是决策函数的值>
    # print(svc.decision_function(X))
    # print(svc.decision_function(X).shape)

    # 创建网格,以绘制图像
    x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx, yy = numpy.meshgrid(numpy.arange(x_min, x_max, h),
                            numpy.arange(y_min, y_max, h))

    for i, clf in enumerate((svc, lin_svc, rbf_svc, poly_svc)):
        # 绘出决策边界,不同的区域分配不同的颜色
        pyplot.subplot(2, 2, i + 1)  # 创建一个2行2列的图,并以第i个图为当前图
        pyplot.subplots_adjust(wspace=0.4, hspace=0.4)  # 设置子图间隔

        # 将xx和yy中的元素组成一对对坐标,作为支持向量机的输入,返回一个array
        Z = clf.predict(numpy.c_[xx.ravel(), yy.ravel()])

        # 把分类结果绘制出来
        Z = Z.reshape(xx.shape)  # (220, 280)
        pyplot.contour(xx, yy, Z, cmap=pyplot.cm.Paired,
                       alpha=0.8)  # 使用等高线的函数将不同的区域绘制出来

        # 将训练数据以离散点的形式绘制出来
        pyplot.scatter(X[:, 0], X[:, 1], c=y, cmap=pyplot.cm.Paired)
        pyplot.xlabel('Sepal length')
        pyplot.ylabel('Sepal width')
        pyplot.xlim(xx.min(), xx.max())
        pyplot.ylim(yy.min(), yy.max())
        pyplot.xticks(())
        pyplot.yticks(())
        pyplot.title(['SVC with linear kernel',
                      'LinearSVC (linear kernel)',
                      'SVC with RBF kernel',
                      'SVC with polynomial (degree 3) kernel'][i])
    pyplot.show()

可视化决策边界

按照上述步骤,对手写体数字集识别,并利用 matplotlib 可视化测试集中前 10 个数字的灰度图像。注:sklearn.datasets 中包含 digits,可用如下方式导入:from sklearn.datasets import load_digits digits = datasets.load_digits() 深入了解该数据集,请参考官网

1
2
3
4
5
6
7
8
9
10
11
from sklearn.datasets import load_digits
from matplotlib import pyplot

if __name__ == '__main__':
    digits = load_digits()
    for i in range(10):
        pyplot.subplot(3, 4, i+1)
        pyplot.imshow(digits.images[i])
        # 用目标值标记图像
        pyplot.text(-1, -1, str(digits.target[i]))
    pyplot.show()

手写体数字集识别

利用 SVR 预测患有疝病的马的死亡率,并分别利用网格搜索和随机搜索寻找最佳组合参数。(数据集见 Lab9)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import RandomizedSearchCV


def loadData(filename):
    data = []
    target = []
    for line in open(filename).readlines():
        lineArr = line.strip().split('\t')
        data.append([float(inst) for inst in lineArr[:-1]])
        target.append(float(lineArr[-1]))
    return data, target


if __name__ == '__main__':
    train_data, train_target = loadData('horseColicTraining.txt')
    test_data, test_target = loadData('horseColicTest.txt')

    clf = SVC().fit(train_data, train_target)
    print(clf.score(test_data, test_target, sample_weight=None))

    search = GridSearchCV(SVC(), {'kernel': ['rbf', 'linear']}).fit(
        train_data, train_target)
    print(search.best_params_)
    print(search.best_score_)
    clf = search.best_estimator_
    print(clf.score(test_data, test_target, sample_weight=None))

    search = RandomizedSearchCV(SVC(), {'kernel': ['rbf', 'linear']}, n_iter=2).fit(
        train_data, train_target)
    print(search.best_params_)
    print(search.best_score_)
    clf = search.best_estimator_
    print(clf.score(test_data, test_target, sample_weight=None))

运行结果如下。

1
2
3
4
5
6
7
0.7164179104477612
{'kernel': 'linear'}
0.6822742474916388
0.7611940298507462
{'kernel': 'linear'}
0.6822742474916388
0.7611940298507462

实验总结

通过本次实验,我大致了解了sklearnsvm分类器的使用,并掌握了网格搜索和随机搜索在机器学习超参数调节中的使用。