Python机器学习及实践——基础篇3(SVM)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chenKFKevin/article/details/79247430

    

 图中有三种颜色的线,用来划分这两种类别的训练样本。其中绿色直线H1在这些训练样本上表现不佳,本身就带有分类错误;蓝色直线H2和红色直线H3如果作为这个二分类问题的线性分类模型,在训练集上的表现都是完美的。

 然而,由于这些分类模型最终都是要应用在未知分布的测试数据上,因此我们更加关注如何最大限度地为未知分布的数据提供足够的待预测空间。比如如果有一个黑色样本稍稍向右偏离橙色直线,那么这个黑色样本很有可能被误判为白色样本,造成误差;而红色直线在空间中的分布位置依然可以为更多“稍稍偏离”的样本提供足够的“容忍度”。因此,我们更希望学习到红色的直线作为更好的分类模型。

 支持向量机(SVM),便是根据训练样本的分布,搜索所有可能的线性分类器中最佳的那个。进一步仔细观察图中的红色直线,可以发现决定其直线位置的样本并不是所有训练数据,而且其中的两个空间间隔最小的两个不同类别的数据点,我们把这种可以用来真正帮助决策最优线性分类模型的数据点叫做“支持向量”。逻辑斯蒂回归模型在训练过程中由于考虑了所有训练样本对参数的影响,因此不一定获得最佳的分类器。

 下面我们用支持向量机分类器处理Scikit-learn内部集成的手写体数字图片数据集,并且通过如下代码提取数据:

# 从sklearn.datasets里导入手写体数字加载器。
from sklearn.datasets import load_digits
# 从通过数据加载器获得手写体数字的数码图像数据并储存在digits变量中。
digits = load_digits()
# 检视数据规模和特征维度。
digits.data.shape
 (1797L, 64L) 

 可以看出数据共有1797条,并且每幅图是由8X8=64的像素矩阵表示。在模型使用这些像素矩阵的时候,我们习惯将2D的图片像素矩阵逐行首尾拼接为1D的像素特征向量。这样做也许会损失一些数据本身的结构信息,但遗憾的是,我们当下介绍的经典模型都没有对结构性信息进行学习的能力。

 依照惯例,我们通过数据分割获取75%的训练样本和25%的测试样本,代码如下:

# 从sklearn.cross_validation中导入train_test_split用于数据分割。
from sklearn.cross_validation import train_test_split

# 随机选取75%的数据作为训练样本;其余25%的数据作为测试样本。
X_train, X_test, y_train, y_test = train_test_split(digits.data, digits.target, test_size=0.25, random_state=33
y_train.shape
(1347L,)
y_test.shape
(450L,)
 接下来,我们使用上述代码产生的1347条样本训练基于线性假设的支持向量机模型,代码如下:
# 从sklearn.preprocessing里导入数据标准化模块。
from sklearn.preprocessing import StandardScaler

# 从sklearn.svm里导入基于线性假设的支持向量机分类器LinearSVC。
from sklearn.svm import LinearSVC

# 从仍然需要对训练和测试的特征数据进行标准化。
ss = StandardScaler()
X_train = ss.fit_transform(X_train)
X_test = ss.transform(X_test)

# 初始化线性假设的支持向量机分类器LinearSVC。
lsvc = LinearSVC()
#进行模型训练
lsvc.fit(X_train, y_train)
# 利用训练好的模型对测试样本的数字类别进行预测,预测结果储存在变量y_predict中。
y_predict = lsvc.predict(X_test)

 使用与上一篇中一样的评价指标,准确性、召回率、精确率和F1指标,用这4个测度对支持向量机(分类)模型从事手写体数字图像识别任务进行性能评估,详见下面的代码:

# 使用模型自带的评估函数进行准确性测评。
print 'The Accuracy of Linear SVC is', lsvc.score(X_test, y_test)
The Accuracy of Linear SVC is 0.953333333333
# 依然使用sklearn.metrics里面的classification_report模块对预测结果做更加详细的分析。
from sklearn.metrics import classification_report
print classification_report(y_test, y_predict, target_names=digits.target_names.astype(str))
             precision    recall  f1-score   support



          0       0.92      1.00      0.96        35

          1       0.96      0.98      0.97        54

          2       0.98      1.00      0.99        44

          3       0.93      0.93      0.93        46

          4       0.97      1.00      0.99        35

          5       0.94      0.94      0.94        48

          6       0.96      0.98      0.97        51

          7       0.92      1.00      0.96        35

          8       0.98      0.84      0.91        58

          9       0.95      0.91      0.93        44



avg / total       0.95      0.95      0.95       450
 通过上述代码的测试代码可以知道,支持向量机(分类)模型的确能够提供比较高的手写体数字识别性能。平均而言,各项指标都在95%上下。

 需要进一步指出的是:召回率、准确率和F1指标最先适用于二分类任务;但是在本文示例中,我们的分类目标有10个类别,即0~9的10个数字。因此无法直接计算上述三个指标。通常的做法是,逐一评估某个类别的这三个性能指标:我们把所有其他的类别看做阴性(负)样本,这样一来,就创造了10个二分类任务。事实上,不仅学习模型在对待多分类任务时是这样做的,而且上述代码的输出也证明了笔者的观点。

 特点分析:支持向量机模型曾经在机器学习研究领域繁荣发展了很长一段时间。主要原因在于其精妙的模型假设,可以帮助我们在海量甚至高纬度的数据中,筛选对预测任务最为有效的少数训练样本。这样做不仅节省了模型学习所需要的数据内存,同时也提高了模型的预测性能。然而,要获得如此的优势就必然要付出更多的计算代价(CPU资源和计算时间)。因此,我们需要实际使用的时候权衡利弊,进而完成各自的任务目标。

 

猜你喜欢

转载自blog.csdn.net/chenKFKevin/article/details/79247430
今日推荐