首頁 > 軟體

python中opencv支援向量機的實現

2022-03-10 19:23:32

支援向量機

支援向量機(Support Vector Machine, SVM)是一種二分類模型,目標是尋找一個標準(稱為超平面)對樣本資料進行分割,分割的原則是確保分類最佳化(類別之間的間隔最大)。

當資料集較小時,使用支援向量機進行分類非常有效。

支援向量機是最好的現成分類器之一,“現成”是指分類器不加修改即可直接使用。

在對原始資料分類的過程中,可能無法使用線性方法實現分割。支援向量機在分類時,把無法線性分割的資料對映到高維空間,然後在高維空間找到分類最優的線性分類器。

Python支援向量機的庫: sk-learn , LIBSVM等

OpenCV也提供了對支援向量機的支援

理論基礎

用於劃分不同類別的直線,就是分類器。

構造分類器時,非常重要的一項工作就是找到最優分類器。

找到支援向量機:在已有資料中,找到離分類器最近的點,確保它們離分類器儘可能地遠。

離分類器最近的點到分類器的距離稱為間隔(margin)。希望間隔儘可能地大,這樣分類器在處理資料時,就會更準確。

離分類器最近的那些點叫作支援向量(support vector)。 決定了分類器所在的位置。

將不可分變為可分

支援向量機會將不那麼容易分類的資料通過函數對映變為可分類的。

支援向量機在處理資料時,如果在低維空間內無法完成分類,就會自動將資料對映到高維空間,使其變為(線性)可分的。簡單地講,就是對當前資料進行函數對映操作。

例如: 在分類時,通過函數f的對映,讓左圖中本來不能用線性分類器分類的資料變為右圖中線性可分的資料。

同時: 支援向量機能夠通過核函數有效地降低計算複雜度。

實際上支援向量機可以處理任何維度的資料。在不同的維度下,支援向量機都會盡可能尋找類似於二維空間中的直線的線性分類器。

例如,在二維空間,支援向量機會尋找一條能夠劃分當前資料的直線;在三維空間,支援向量機會尋找一個能夠劃分當前資料的平面(plane);在更高維的空間,支援向量機會嘗試尋找一個能夠劃分當前資料的超平面(hyperplane)。

一般情況下,把能夠可以被一條直線(更一般的情況,即一個超平面)分割的資料稱為線性可分的資料,所以超平面是線性分類器。

“支援向量機”是由“支援向量”和“機器”構成的。

  • “支援向量”是離分類器最近的那些點,這些點位於最大“間隔”上。通常情況下,分類僅依靠這些點完成,而與其他點無關。
  • “機器”指的是分類器。

支援向量機是一種基於關鍵點的分類演演算法。

SVM使用介紹

在使用支援向量機模組時,需要先使用函數cv2.ml.SVM_create()生成用於後續訓練的空分類器模型。

語法格式:

svm = cv2.ml.SVM_create()

獲取了空分類器svm後,針對該模型使用svm.train()函數對訓練資料進行訓練

語法格式

訓練結果= svm.train(訓練資料,訓練資料排列格式,訓練資料的標籤) 
  • 訓練資料:表示原始資料,用來訓練分類器。
  • 訓練資料排列格式:原始資料的排列形式有按行排列(cv2.ml.ROW_SAMPLE,每一條訓練資料佔一行)和按列排列(cv2.ml.COL_SAMPLE,每一條訓練資料佔一列)兩種形式
  • 訓練資料的標籤:原始資料的標籤。
  • 訓練結果:訓練結果的返回值。

例如: 用於訓練的資料為data,其對應的標籤為label,每一條資料按行排列,對分類器模型svm進行訓練,所使用的語句為:

返回值 = svm.train(data, cv2.ml.ROW_SAMPLE, label) 

完成對分類器的訓練後,使用svm.predict()函數即可使用訓練好的分類器模型對測試資料進行分類,其語法格式為:

(返回值,返回結果) = svm.predict(測試資料) 

OpenCV支援對多個引數的自定義,例如:可以通過setType()函數設定類別,通過setKernel()函數設定核型別,通過setC()函數設定支援向量機的引數C ( 懲罰係數,即對誤差的寬容度,預設值為0 )。

例子介紹

題目: 已知員工的筆試成績、面試成績及對應的等級表現,根據新入職員工的筆試成績、面試成績預測其可能的表現。

首先構造一組亂數,並將其劃分為兩類,然後使用OpenCV自帶的支援向量機模組完成訓練和分類工作,最後將運算結果顯示出來。

具體步驟:

  • 生成模擬資料

    模擬生成入職一年後表現為A級的員工入職時的筆試和麵試成績。

    構造20組筆試和麵試成績都分佈在[95, 100)區間的資料對:

    a = np.random.randint(95,100, (20, 2)).astype(np.float32) 

    上述模擬成績,在一年後對應的工作表現為A級。

    模擬生成入職一年後表現為B級的員工入職時的筆試和麵試成績。

    構造20組筆試和麵試成績都分佈在[90, 95)區間的資料對:

    b = np.random.randint(90,95, (20, 2)).astype(np.float32) 

    上述模擬成績,在一年後對應的工作表現為B級。

    最後,將兩組資料合併,並使用numpy.array對其進行型別轉換:

    data = np.vstack((a, b)) 
    data = np.array(data, dtype='float32')     
  • 構造分組標籤

    為對應表現為A級的分佈在[95, 100)區間的資料,構造標籤“0”:

    aLabel=np.zeros((20,1)) 

    為對應表現為B級的分佈在[90, 95)區間的資料,構造標籤“1”:

    bLabel=np.ones((20,1)) 

    將上述標籤合併,並使用numpy.array對其進行型別轉換:

    label = np.vstack((aLabel, bLabel)) 
    label = np.array(label, dtype='int32') 
  • 訓練

    用支援向量機模組對已知的資料和其對應的標籤進行訓練:

    svm = cv2.ml.SVM_create() 
    result = svm.train(data, cv2.ml.ROW_SAMPLE, label) 
  • 分類

    生成兩個隨機的資料對(筆試成績,面試成績)用於測試。

    test = np.vstack([[98,90], [90,99]]) 
    test = np.array(test, dtype='float32') 

    使用函數svm.predict()對隨機成績分類:

    (p1, p2) = svm.predict(test) 
  • 顯示分類結果

    將基礎資料(訓練資料)、用於測試的資料(測試資料)在影象上顯示出來:

    plt.scatter(a[:,0], a[:,1], 80, 'g', 'o') 
    plt.scatter(b[:,0], b[:,1], 80, 'b', 's') 
    plt.scatter(test[:,0], test[:,1], 80, 'r', '*') 
    plt.show() 

    將測試資料及預測分類結果顯示出來:

    print(test) 
    print(p2)

完整程式

import cv2 
import numpy as np 
import matplotlib.pyplot as plt 
# 準備資料 
a = np.random.randint(95,100, (20, 2)).astype(np.float32) 
b = np.random.randint(90,95, (20, 2)).astype(np.float32) 
data = np.vstack((a, b)) 
data = np.array(data, dtype='float32') 
    
# 建立分組標籤,0代表A級,1代表B級 
aLabel=np.zeros((20,1)) 
bLabel=np.ones((20,1)) 
label = np.vstack((aLabel, bLabel)) 
label = np.array(label, dtype='int32') 
    
# 訓練 
svm = cv2.ml.SVM_create() 
# 屬性設定,直接採用預設值即可 
#svm.setType(cv2.ml.SVM_C_SVC)    # svm type 
#svm.setKernel(cv2.ml.SVM_LINEAR) # line 
#svm.setC(0.01) 
result = svm.train(data, cv2.ml.ROW_SAMPLE, label) 
    
#預測 
test = np.vstack([[98,90], [90,99]]) 
test = np.array(test, dtype='float32') 
(p1, p2) = svm.predict(test)   # test 是 [[資料1],[資料2]] 結構的
   
# 結果 
print(test)
print("res1",p2[0])
print("res2",p2[1]) 
plt.scatter(a[:,0], a[:,1], 80, 'g', 'o') 
plt.scatter(b[:,0], b[:,1], 80, 'b', 's') 
plt.scatter(test[:,0], test[:,1], 80, 'r', '*') 
plt.show() 

到此這篇關於python中opencv支援向量機的實現的文章就介紹到這了,更多相關opencv 向量機內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com