Python機器學習(三十二)Sklearn 支持向量機


前面章節嘗試了K均值聚類模型,准確率並不高。接下來我們嘗試一種新方法:支持向量機(SVM)。

支持向量機

支持向量機(support vector machine/SVM),通俗來講,它是一種二類分類模型,其基本模型定義為特征空間上的間隔最大的線性分類器,其學習策略便是間隔最大化,最終可轉化為一個凸二次規划問題的求解。本系列教程聚焦於SciKit-Learn 庫的使用介紹,關於支持向量機詳細原理,限於篇幅不再贅述,讀者可參考相關資料。

如前所訴,K均值聚類模型是一種無監督學習模型,與此不同,支持向量機是一種有監督學習模型,是很常用的一種機器學習模型。

創建模型

下面的代碼,創建了一個支持向量機模型。

import numpy as np
from sklearn import datasets

# 加載 `digits` 數據集
digits = datasets.load_digits()

# 導入 `train_test_split`
from sklearn.model_selection import train_test_split

# 數據分成訓練集和測試集
# `test_size`:如果是浮點數,在0-1之間,表示測試子集占比;如果是整數的話就是測試子集的樣本數量,`random_state`:是隨機數的種子
X_train, X_test, y_train, y_test, images_train, images_test = train_test_split(digits.data, digits.target, digits.images, test_size=0.33, random_state=42)

# 導入“svm”模型
from sklearn import svm

# 創建SVC/Support Vector Classification/支持向量機分類器模型
svc_model = svm.SVC(gamma=0.001, C=100., kernel='linear')

# 將數據擬合到SVC模型中,此處用到了標簽值y_train,是有監督學習
svc_model.fit(X_train, y_train)

可以看到,我們使用X_trainy_train數據來訓練SVC模型(Support Vector Classification/支持向量機分類器模型),此處用到了標簽值y_train,是有監督學習。

另外,我們手動設置了gamma的值,通過使用網格搜索和交叉驗證等工具,可以自動找到合適的參數值。

測試模型

接下來,我們使用測試數據測試模型。

# 預測“X_test”標簽
print(svc_model.predict(X_test))

# 打印' y_test '檢查結果
print(y_test)

輸出:

[6 9 3 7 2 1 5 2 5 2 1 4 4 0 4 2 3 7 8 8 4 3 9 7 5 6 3 5 6 3 4 9 1 4 4 6 9
 4 7 6 6 9 1 3 6 1 3 0 6 5 5 1 9 5 6 0 9 0 0 1 0 4 5 2 4 5 7 0 7 5 9 5 5 4
 7 0 4 5 5 9 9 0 2 3 8 0 6 4 4 9 1 2 8 3 5 2 9 0 4 4 4 3 5 3 1 3 5 9 4 2 7
 7 4 4 1 9 2 7 8 7 2 6 9 4 0 7 2 7 5 8 7 5 7 9 0 6 6 4 2 8 0 9 4 6 9 9 6 9
 0 5 5 6 6 0 6 4 3 9 3 9 7 2 9 0 4 5 3 6 5 9 9 8 4 2 1 3 7 7 2 2 3 9 8 0 3
 2 2 5 6 9 9 4 1 5 4 2 3 6 4 8 5 9 5 7 8 9 4 8 1 5 4 4 9 6 1 8 6 0 4 5 2 7
 4 6 4 5 6 0 3 2 3 6 7 1 5 1 4 7 6 5 8 5 5 1 6 2 8 8 9 9 7 6 2 2 2 3 4 8 8
 3 6 0 9 7 7 0 1 0 4 5 1 5 3 6 0 4 1 0 0 3 6 5 9 7 3 5 5 9 9 8 5 3 3 2 0 5
 8 3 4 0 2 4 6 4 3 4 5 0 5 2 1 3 1 4 1 1 7 0 1 5 2 1 2 8 7 0 6 4 8 8 5 1 8
 4 5 8 7 9 8 5 0 6 2 0 7 9 8 9 5 2 7 7 1 8 7 4 3 8 3 5 6 0 0 3 0 5 0 0 4 1
 2 3 4 5 9 6 3 1 8 8 4 2 3 8 9 8 8 5 0 6 3 3 7 1 6 4 1 2 1 1 6 4 7 4 8 3 4
 0 5 1 9 4 5 7 6 3 7 0 5 9 7 5 9 7 4 2 1 9 0 7 5 8 3 6 3 9 6 9 5 0 1 5 5 8
 3 3 6 2 6 5 7 2 0 8 7 3 7 0 2 2 3 5 8 7 3 6 5 9 9 2 9 6 3 0 7 1 1 9 6 1 8
 0 0 2 9 3 9 9 3 7 7 1 3 5 4 6 1 2 1 1 8 7 6 9 2 0 4 4 8 8 7 1 3 1 7 1 8 5
 1 7 0 0 2 2 6 9 4 1 9 0 6 7 7 9 5 4 7 0 7 6 8 7 1 4 6 2 8 7 5 9 0 3 9 6 6
 1 9 1 2 9 8 9 7 4 8 5 5 9 7 7 6 8 1 3 5 7 9 5 5 2 4 1 2 2 4 8 7 5 8 8 9 4
 9 0]
[6 9 3 7 2 1 5 2 5 2 1 9 4 0 4 2 3 7 8 8 4 3 9 7 5 6 3 5 6 3 4 9 1 4 4 6 9
 4 7 6 6 9 1 3 6 1 3 0 6 5 5 1 9 5 6 0 9 0 0 1 0 4 5 2 4 5 7 0 7 5 9 5 5 4
 7 0 4 5 5 9 9 0 2 3 8 0 6 4 4 9 1 2 8 3 5 2 9 0 4 4 4 3 5 3 1 3 5 9 4 2 7
 7 4 4 1 9 2 7 8 7 2 6 9 4 0 7 2 7 5 8 7 5 7 7 0 6 6 4 2 8 0 9 4 6 9 9 6 9
 0 3 5 6 6 0 6 4 3 9 3 9 7 2 9 0 4 5 3 6 5 9 9 8 4 2 1 3 7 7 2 2 3 9 8 0 3
 2 2 5 6 9 9 4 1 5 4 2 3 6 4 8 5 9 5 7 8 9 4 8 1 5 4 4 9 6 1 8 6 0 4 5 2 7
 4 6 4 5 6 0 3 2 3 6 7 1 5 1 4 7 6 8 8 5 5 1 6 2 8 8 9 9 7 6 2 2 2 3 4 8 8
 3 6 0 9 7 7 0 1 0 4 5 1 5 3 6 0 4 1 0 0 3 6 5 9 7 3 5 5 9 9 8 5 3 3 2 0 5
 8 3 4 0 2 4 6 4 3 4 5 0 5 2 1 3 1 4 1 1 7 0 1 5 2 1 2 8 7 0 6 4 8 8 5 1 8
 4 5 8 7 9 8 5 0 6 2 0 7 9 8 9 5 2 7 7 1 8 7 4 3 8 3 5 6 0 0 3 0 5 0 0 4 1
 2 8 4 5 9 6 3 1 8 8 4 2 3 8 9 8 8 5 0 6 3 3 7 1 6 4 1 2 1 1 6 4 7 4 8 3 4
 0 5 1 9 4 5 7 6 3 7 0 5 9 7 5 9 7 4 2 1 9 0 7 5 3 3 6 3 9 6 9 5 0 1 5 5 8
 3 3 6 2 6 5 5 2 0 8 7 3 7 0 2 2 3 5 8 7 3 6 5 9 9 2 5 6 3 0 7 1 1 9 6 1 1
 0 0 2 9 3 9 9 3 7 7 1 3 5 4 6 1 2 1 1 8 7 6 9 2 0 4 4 8 8 7 1 3 1 7 1 9 5
 1 7 0 0 2 2 6 9 4 1 9 0 6 7 7 9 5 4 7 0 7 6 8 7 1 4 6 2 8 7 5 9 0 3 9 6 6
 1 9 8 2 9 8 9 7 4 8 5 5 9 7 7 6 8 1 3 5 7 9 5 5 2 1 1 2 2 4 8 7 5 8 8 9 4
 9 0]

我們也可以使用matplotlib可視化測試數據及其預測標簽:

# 導入 matplotlib
import matplotlib.pyplot as plt

# 將預測值賦給 `predicted`
predicted = svc_model.predict(X_test)

# 將images_test和images_prediction中的預測值壓縮在一起
images_and_predictions = list(zip(images_test, predicted))

# 對於images_and_prediction中的前四個元素
for index, (image, prediction) in enumerate(images_and_predictions[:4]):
    # 在坐標i+1處初始化一個1×4的網格中的子圖
    plt.subplot(1, 4, index + 1)
    # 不顯示坐標軸
    plt.axis('off')
    # 在網格中的所有子圖中顯示圖像
    plt.imshow(image, cmap=plt.cm.gray_r, interpolation='nearest')
    # 添加標題
    plt.title('Predicted: ' + str(prediction))

# 顯示圖形
plt.show()

顯示:

圖

可以看到顯示的這幾張圖形,預測的標簽都是正確的。

評估模型

最后,我們來評估一下模型的性能,看看它准確率怎么樣。

# 導入 `metrics`
from sklearn import metrics

# 打印的分類報告 `y_test` 與 `predicted`
print(metrics.classification_report(y_test, predicted))

# 打印“y_test”和“predicted”的混淆矩陣
print(metrics.confusion_matrix(y_test, predicted))

輸出:

              precision    recall  f1-score   support

           0       1.00      1.00      1.00        55
           1       0.98      0.96      0.97        55
           2       1.00      1.00      1.00        52
           3       0.98      0.96      0.97        56
           4       0.97      1.00      0.98        64
           5       0.97      0.97      0.97        73
           6       1.00      1.00      1.00        57
           7       0.98      0.98      0.98        62
           8       0.94      0.94      0.94        52
           9       0.97      0.97      0.97        68

    accuracy                           0.98       594
   macro avg       0.98      0.98      0.98       594
weighted avg       0.98      0.98      0.98       594

[[55  0  0  0  0  0  0  0  0  0]
 [ 0 53  0  0  1  0  0  0  1  0]
 [ 0  0 52  0  0  0  0  0  0  0]
 [ 0  0  0 54  0  1  0  0  1  0]
 [ 0  0  0  0 64  0  0  0  0  0]
 [ 0  0  0  0  0 71  0  1  0  1]
 [ 0  0  0  0  0  0 57  0  0  0]
 [ 0  0  0  0  0  0  0 61  0  1]
 [ 0  1  0  1  0  1  0  0 49  0]
 [ 0  0  0  0  1  0  0  0  1 66]]

可以看到,這個模型比前面章節的K均值聚類模型,效果要好得多。

我們再看一下預測標簽與實際標簽的散點圖。

# 導入 `Isomap()`
from sklearn.manifold import Isomap

# 創建一個isomap,並將“digits”數據放入其中
X_iso = Isomap(n_neighbors=10).fit_transform(X_train)

# 計算聚類中心並預測每個樣本的聚類指數
predicted = svc_model.predict(X_train)

# 在1X2的網格中創建帶有子圖的圖
fig, ax = plt.subplots(1, 2, figsize=(8, 4))

# 調整布局
fig.subplots_adjust(top=0.85)

# 將散點圖添加到子圖中 
ax[0].scatter(X_iso[:, 0], X_iso[:, 1], c=predicted)
ax[0].set_title('Predicted labels')
ax[1].scatter(X_iso[:, 0], X_iso[:, 1], c=y_train)
ax[1].set_title('Actual Labels')


# 加標題
fig.suptitle('Predicted versus actual labels', fontsize=14, fontweight='bold')

# 顯示圖形
plt.show()

顯示

圖

從圖中可以看出,模型的預測結果與實際結果匹配度非常好,模型的准確率很高。

參數值

前面在創建模型時,手動設置了gamma等參數的值,通過使用網格搜索和交叉驗證等工具,可以自動找到合適的參數值。

盡管這不是本篇教程的重點,本節內容演示如何使用網格搜索和交叉驗證等工具,自動找到合適的參數值。

import numpy as np
from sklearn import datasets

# 加載 `digits` 數據集
digits = datasets.load_digits()

# 導入 `train_test_split`
from sklearn.model_selection import train_test_split

# 將 `digits` 數據分成兩個相等數量的集合
X_train, X_test, y_train, y_test = train_test_split(digits.data, digits.target, test_size=0.5, random_state=0)

# 導入“svm”模型
from sklearn import svm

# 導入 GridSearchCV
from sklearn.model_selection import GridSearchCV

# 設置參數候選項
parameter_candidates = [
  {'C': [1, 10, 100, 1000], 'kernel': ['linear']},
  {'C': [1, 10, 100, 1000], 'gamma': [0.001, 0.0001], 'kernel': ['rbf']},
]

# 使用參數候選項創建分類器
clf = GridSearchCV(estimator=svm.SVC(), param_grid=parameter_candidates, n_jobs=-1)

# 根據訓練數據訓練分類器
clf.fit(X_train, y_train)

# 打印結果
print('訓練數據的最佳得分:', clf.best_score_)
print('最佳懲罰參數C:',clf.best_estimator_.C)
print('最佳內核類型:',clf.best_estimator_.kernel)
print('最佳gamma值:',clf.best_estimator_.gamma)

# 將分類器應用到測試數據上,查看准確率得分
clf.score(X_test, y_test)

# 用網格搜索參數訓練一個新的分類器,評估得分
score = svm.SVC(C=10, kernel='rbf', gamma=0.001).fit(X_train, y_train).score(X_test, y_test)
print(score)

輸出

C:\Anaconda3\python.exe "C:\Program Files\JetBrains\PyCharm 2019.1.1\helpers\pydev\pydevconsole.py" --mode=client --port=64053
import sys; print('Python %s on %s' % (sys.version, sys.platform))
sys.path.extend(['C:\\app\\PycharmProjects', 'C:/app/PycharmProjects'])
Python 3.7.6 (default, Jan 8 2020, 20:23:39) [MSC v.1916 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 7.12.0 -- An enhanced Interactive Python. Type '?' for help.
PyDev console: using IPython 7.12.0
Python 3.7.6 (default, Jan 8 2020, 20:23:39) [MSC v.1916 64 bit (AMD64)] on win32
runfile('C:/app/PycharmProjects/ArtificialIntelligence/test.py', wdir='C:/app/PycharmProjects/ArtificialIntelligence')
訓練數據的最佳得分: 0.9866480446927375
最佳懲罰參數C: 10
最佳內核類型: rbf
最佳gamma值: 0.001
0.9911012235817576

可以看到,我們獲取到了合適的參數。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM