用Python開始機器學習(8:SVM支持向量機)

SVM支持向量機是建立於統計學習理論上的一種分類算法,適合與處理具備高維特徵的數據集。

SVM算法的數學原理相對比較複雜,好在由於SVM算法的研究與應用如此火爆,CSDN博客裏也有大量的好文章對此進行分析,下面給出幾個本人認爲講解的相當不錯的:

支持向量機通俗導論(理解SVM的3層境界):http://blog.csdn.net/v_july_v/article/details/7624837

JULY大牛講的是如此詳細,由淺入深層層推進,以至於關於SVM的原理,我一個字都不想寫了。。強烈推薦。

還有一個比較通俗的簡單版本的:手把手教你實現SVM算法:http://blog.csdn.net/alvine008/article/details/9097105


SVN原理比較複雜,但是思想很簡單,一句話概括,就是通過某種核函數,將數據在高維空間裏尋找一個最優超平面,能夠將兩類數據分開。

針對不同數據集,不同的核函數的分類效果可能完全不一樣。可選的核函數有這麼幾種:

線性函數:形如K(x,y)=x*y這樣的線性函數;

多項式函數:形如K(x,y)=[(x·y)+1]^d這樣的多項式函數;

徑向基函數:形如K(x,y)=exp(-|x-y|^2/d^2)這樣的指數函數;

Sigmoid函數:就是上一篇文章中講到的Sigmoid函數。

我們就利用之前的幾個數據集,直接給出Python代碼,看看運行效果:

測試1:身高體重數據

[python] view plain copy
  1. # -*- coding: utf-8 -*-  
  2. import numpy as np  
  3. import scipy as sp  
  4. from sklearn import svm  
  5. from sklearn.cross_validation import train_test_split  
  6. import matplotlib.pyplot as plt  
  7.   
  8. data   = []  
  9. labels = []  
  10. with open("data\\1.txt") as ifile:  
  11.         for line in ifile:  
  12.             tokens = line.strip().split(' ')  
  13.             data.append([float(tk) for tk in tokens[:-1]])  
  14.             labels.append(tokens[-1])  
  15. x = np.array(data)  
  16. labels = np.array(labels)  
  17. y = np.zeros(labels.shape)  
  18. y[labels=='fat']=1  
  19. x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.0)  
  20.   
  21. h = .02    
  22. # create a mesh to plot in  
  23. x_min, x_max = x_train[:, 0].min() - 0.1, x_train[:, 0].max() + 0.1  
  24. y_min, y_max = x_train[:, 1].min() - 1, x_train[:, 1].max() + 1  
  25. xx, yy = np.meshgrid(np.arange(x_min, x_max, h),  
  26.                      np.arange(y_min, y_max, h))  
  27.   
  28. ''''' SVM '''  
  29. # title for the plots  
  30. titles = ['LinearSVC (linear kernel)',  
  31.           'SVC with polynomial (degree 3) kernel',  
  32.           'SVC with RBF kernel',  
  33.           'SVC with Sigmoid kernel']  
  34. clf_linear  = svm.SVC(kernel='linear').fit(x, y)  
  35. #clf_linear  = svm.LinearSVC().fit(x, y)  
  36. clf_poly    = svm.SVC(kernel='poly', degree=3).fit(x, y)  
  37. clf_rbf     = svm.SVC().fit(x, y)  
  38. clf_sigmoid = svm.SVC(kernel='sigmoid').fit(x, y)  
  39.   
  40. for i, clf in enumerate((clf_linear, clf_poly, clf_rbf, clf_sigmoid)):  
  41.     answer = clf.predict(np.c_[xx.ravel(), yy.ravel()])  
  42.     print(clf)  
  43.     print(np.mean( answer == y_train))  
  44.     print(answer)  
  45.     print(y_train)  
  46.   
  47.     plt.subplot(22, i + 1)  
  48.     plt.subplots_adjust(wspace=0.4, hspace=0.4)  
  49.       
  50.     # Put the result into a color plot  
  51.     z = answer.reshape(xx.shape)  
  52.     plt.contourf(xx, yy, z, cmap=plt.cm.Paired, alpha=0.8)  
  53.       
  54.     # Plot also the training points  
  55.     plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train, cmap=plt.cm.Paired)  
  56.     plt.xlabel(u'身高')  
  57.     plt.ylabel(u'體重')  
  58.     plt.xlim(xx.min(), xx.max())  
  59.     plt.ylim(yy.min(), yy.max())  
  60.     plt.xticks(())  
  61.     plt.yticks(())  
  62.     plt.title(titles[i])  
  63.       
  64. plt.show()  
運行結果如下:

可以看到,針對這個數據集,使用3次多項式核函數的SVM,得到的效果最好。

測試2:影評態度

下面看看SVM在康奈爾影評數據集上的表現:(代碼略)

SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0, degree=3, gamma=0.0,  kernel='linear', max_iter=-1, probability=False, random_state=None,
  shrinking=True, tol=0.001, verbose=False)
0.814285714286


SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0, degree=3, gamma=0.0,  kernel='poly', max_iter=-1, probability=False, random_state=None,  shrinking=True, tol=0.001, verbose=False)
0.492857142857


SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0, degree=3, gamma=0.0,  kernel='rbf', max_iter=-1, probability=False, random_state=None,  shrinking=True, tol=0.001, verbose=False)
0.492857142857


SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0, degree=3, gamma=0.0,  kernel='sigmoid', max_iter=-1, probability=False, random_state=None,
  shrinking=True, tol=0.001, verbose=False)
0.492857142857
可見在該數據集上,線性分類器效果最好。

測試3:圓形邊界

最後我們測試一個數據分類邊界爲圓形的情況:圓形內爲一類,原型外爲一類。看這類非線性的數據SVM表現如何:

測試數據生成代碼如下所示:

[python] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. ''''' 數據生成 '''  
  2. h = 0.1  
  3. x_min, x_max = -11  
  4. y_min, y_max = -11  
  5. xx, yy = np.meshgrid(np.arange(x_min, x_max, h),  
  6.                      np.arange(y_min, y_max, h))  
  7. n = xx.shape[0]*xx.shape[1]  
  8. x = np.array([xx.T.reshape(n).T, xx.reshape(n)]).T  
  9. y = (x[:,0]*x[:,0] + x[:,1]*x[:,1] < 0.8)  
  10. y.reshape(xx.shape)  
  11.   
  12. x_train, x_test, y_train, y_test\  
  13.     = train_test_split(x, y, test_size = 0.2)  
測試結果如下:

SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0, degree=3, gamma=0.0,  kernel='linear', max_iter=-1, probability=False, random_state=None,
  shrinking=True, tol=0.001, verbose=False)
0.65
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0, degree=3, gamma=0.0,  kernel='poly', max_iter=-1, probability=False, random_state=None,
  shrinking=True, tol=0.001, verbose=False)
0.675
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0, degree=3, gamma=0.0,  kernel='rbf', max_iter=-1, probability=False, random_state=None,
  shrinking=True, tol=0.001, verbose=False)
0.9625
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0, degree=3, gamma=0.0,  kernel='sigmoid', max_iter=-1, probability=False, random_state=None,
  shrinking=True, tol=0.001, verbose=False)
0.65


可以看到,對於這種邊界,徑向基函數的SVM得到了近似完美的分類結果。而其他的分類器顯然束手無策。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章