機器學習:Python中如何使用支持向量機(SVM)算法


   (簡單介紹一下支持向量機,詳細介紹尤其是算法過程可以查閱其他資)

   在機器學習領域,支持向量機SVM(Support Vector Machine)是一個有監督的學習模型,通常用來進行模式識別、分類(異常值檢測)以及回歸分析。

   其具有以下特征:

   (1)SVM可以表示為凸優化問題,因此可以利用已知的有效算法發現目標函數的全局最小值。而其他分類方法都采用一種基於貪心學習的策略來搜索假設空間,這種方法一般只能獲得局部最優解。

  (2) SVM通過最大化決策邊界的邊緣來實現控制模型的能力。盡管如此,用戶必須提供其他參數,如使用核函數類型和引入松弛變量等。

  (3)SVM一般只能用在二類問題,對於多類問題效果不好。
   
  1. 下面是代碼及詳細解釋(基於sklearn包):
   
from sklearn import svm
import numpy as np
import matplotlib.pyplot as plt

#准備訓練樣本
x=[[1,8],[3,20],[1,15],[3,35],[5,35],[4,40],[7,80],[6,49]]
y=[1,1,-1,-1,1,-1,-1,1]

##開始訓練
clf=svm.SVC()  ##默認參數:kernel='rbf'
clf.fit(x,y)

#print("預測...")
#res=clf.predict([[2,2]])  ##兩個方括號表面傳入的參數是矩陣而不是list

##根據訓練出的模型繪制樣本點
for i in x:
    res=clf.predict(np.array(i).reshape(1, -1))
    if res > 0:
        plt.scatter(i[0],i[1],c='r',marker='*')
    else :
        plt.scatter(i[0],i[1],c='g',marker='*')

##生成隨機實驗數據(15行2列)
rdm_arr=np.random.randint(1, 15, size=(15,2))
##回執實驗數據點
for i in rdm_arr:
    res=clf.predict(np.array(i).reshape(1, -1))
    if res > 0:
        plt.scatter(i[0],i[1],c='r',marker='.')
    else :
        plt.scatter(i[0],i[1],c='g',marker='.')
##顯示繪圖結果
plt.show()

     結果如下圖:

     

       從圖上可以看出,數據明顯被藍色分割線分成了兩類。但是紅色箭頭標示的點例外,所以這也起到了檢測異常值的作用。

      

      2.在上面的代碼中提到了kernel='rbf',這個參數是SVM的核心:核函數

        重新整理后的代碼如下:       

from sklearn import svm
import numpy as np
import matplotlib.pyplot as plt

##設置子圖數量
fig, axes = plt.subplots(nrows=2, ncols=2,figsize=(7,7))
ax0, ax1, ax2, ax3 = axes.flatten()

#准備訓練樣本
x=[[1,8],[3,20],[1,15],[3,35],[5,35],[4,40],[7,80],[6,49]]
y=[1,1,-1,-1,1,-1,-1,1]
'''
    說明1:
       核函數(這里簡單介紹了sklearn中svm的四個核函數,還有precomputed及自定義的)
        
    LinearSVC:主要用於線性可分的情形。參數少,速度快,對於一般數據,分類效果已經很理想
    RBF:主要用於線性不可分的情形。參數多,分類結果非常依賴於參數
    polynomial:多項式函數,degree 表示多項式的程度-----支持非線性分類
    Sigmoid:在生物學中常見的S型的函數,也稱為S型生長曲線

    說明2:根據設置的參數不同,得出的分類結果及顯示結果也會不同
    
'''
##設置子圖的標題
titles = ['LinearSVC (linear kernel)',  
          'SVC with polynomial (degree 3) kernel',  
          'SVC with RBF kernel',      ##這個是默認的
          'SVC with Sigmoid kernel']
##生成隨機試驗數據(15行2列)
rdm_arr=np.random.randint(1, 15, size=(15,2))

def drawPoint(ax,clf,tn):
    ##繪制樣本點
    for i in x:
        ax.set_title(titles[tn])
        res=clf.predict(np.array(i).reshape(1, -1))
        if res > 0:
           ax.scatter(i[0],i[1],c='r',marker='*')
        else :
           ax.scatter(i[0],i[1],c='g',marker='*')
     ##繪制實驗點
    for i in rdm_arr:
        res=clf.predict(np.array(i).reshape(1, -1))
        if res > 0:
           ax.scatter(i[0],i[1],c='r',marker='.')
        else :
           ax.scatter(i[0],i[1],c='g',marker='.')

if __name__=="__main__":
    ##選擇核函數
    for n in range(0,4):
        if n==0:
            clf = svm.SVC(kernel='linear').fit(x, y)
            drawPoint(ax0,clf,0)
        elif n==1:
            clf = svm.SVC(kernel='poly', degree=3).fit(x, y)
            drawPoint(ax1,clf,1)
        elif n==2:
            clf= svm.SVC(kernel='rbf').fit(x, y)
            drawPoint(ax2,clf,2)
        else :
            clf= svm.SVC(kernel='sigmoid').fit(x, y)
            drawPoint(ax3,clf,3)
    plt.show()

     結果如圖:

 

    由於樣本數據的關系,四個核函數得出的結果一致。在實際操作中,應該選擇效果最好的核函數分析。

   3.在svm模塊中還有一個較為簡單的線性分類函數:LinearSVC(),其不支持kernel參數,因為設計思想就是線性分類。如果確定數據

可以進行線性划分,可以選擇此函數。跟kernel='linear'用法對比如下:

  

from sklearn import svm
import numpy as np
import matplotlib.pyplot as plt

##設置子圖數量
fig, axes = plt.subplots(nrows=1, ncols=2,figsize=(7,7))
ax0, ax1 = axes.flatten()

#准備訓練樣本
x=[[1,8],[3,20],[1,15],[3,35],[5,35],[4,40],[7,80],[6,49]]
y=[1,1,-1,-1,1,-1,-1,1]

##設置子圖的標題
titles = ['SVC (linear kernel)',  
          'LinearSVC']

##生成隨機試驗數據(15行2列)
rdm_arr=np.random.randint(1, 15, size=(15,2))

##畫圖函數
def drawPoint(ax,clf,tn):
    ##繪制樣本點
    for i in x:
        ax.set_title(titles[tn])
        res=clf.predict(np.array(i).reshape(1, -1))
        if res > 0:
           ax.scatter(i[0],i[1],c='r',marker='*')
        else :
           ax.scatter(i[0],i[1],c='g',marker='*')
    ##繪制實驗點
    for i in rdm_arr:
        res=clf.predict(np.array(i).reshape(1, -1))
        if res > 0:
           ax.scatter(i[0],i[1],c='r',marker='.')
        else :
           ax.scatter(i[0],i[1],c='g',marker='.')

if __name__=="__main__":
    ##選擇核函數
    for n in range(0,2):
        if n==0:
            clf = svm.SVC(kernel='linear').fit(x, y)
            drawPoint(ax0,clf,0)
        else :
            clf= svm.LinearSVC().fit(x, y)
            drawPoint(ax1,clf,1)
    plt.show()
 
 

 結果如圖所示:

 


免責聲明!

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



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