程序員技術分享:訓練機器學習 SVM算法解析

GregLampSVM算法
摘要:支持向量機(SVM)已經成爲一種非常受歡迎的算法。本文主要闡述了SVM是如何進行工作的,同時也給出了使用Python Scikits庫的幾個示例。SVM作爲一種訓練機器學習的算法,可以用於解決分類和迴歸問題,還使用了kernel trick技術進行數據的轉換,再根據轉換信息在可能的輸出之中找到一個最優的邊界。

【CSDN報道】支持向量機(Support Vector Machine)已經成爲一種非常受歡迎的算法。在這篇文章裏,Greg Lamp簡單解釋了它是如何進行工作的,同時他也給出了使用Python Scikits庫的幾個示例。所有代碼在Github上都是可用的,Greg Lamp以後還會對使用Scikits以及Sklearn的細節問題進行更深一步的闡述。CSDN對本篇技術性文章進行了編譯整理:

SVM是什麼?

SVM是一種訓練機器學習的算法,可以用於解決分類和迴歸問題,同時還使用了一種稱之爲kernel trick的技術進行數據的轉換,然後再根據這些轉換信息,在可能的輸出之中找到一個最優的邊界。簡單來說,就是做一些非常複雜的數據轉換工作,然後根據預定義的標籤或者輸出進而計算出如何分離用戶的數據。

是什麼讓它變得如此的強大?

當然,對於SVM來說,完全有能力實現分類以及迴歸。在這篇文章中,Greg Lamp主要關注如何使用SVM進行分類,特別是非線性的SVM或者SVM使用非線性內核。非線性SVM意味着該算法計算的邊界沒有必要是一條直線,這樣做的好處在於,可以捕獲更多數據點集之間的複雜關係,而無需靠用戶自己來執行困難的轉換。其缺點就是由於更多的運算量,訓練的時間要長很多。

什麼是kernel trick?

kernel trick對接收到的數據進行轉換:輸入一些你認爲比較明顯的特徵進行分類,輸出一些你完全不認識的數據,這個過程就像解開一個DNA鏈。你開始是尋找數據的矢量,然後把它傳給kernel trick,再進行不斷的分解和重組直到形成一個更大的數據集,而且通常你看到的這些數據非常的難以理解。這就是神奇之處,擴展的數據集擁有更明顯的邊界,SVM算法也能夠計算一個更加優化的超平面。

其次,假設你是一個農場主,現在你有一個問題——你需要搭建一個籬笆來防止狼對牛羣造成傷害。但是籬笆應該建在哪裏呢?如果你是一個以數據爲驅動的農場主,那麼你就需要在你的牧場上,依據牛羣和狼羣的位置建立一個“分類器”,比較這幾種(如下圖所示)不同的分類器,我們可以看到SVM完成了一個很完美的解決方案。Greg Lamp認爲這個故事漂亮的說明了使用非線性分類器的優勢。顯而易見,邏輯模式以及決策樹模式都是使用了直線方法。

實現代碼如下:farmer.py  Python 

  1. import numpy as np 
  2. import pylab as pl 
  3. from sklearn import svm 
  4. from sklearn import linear_model 
  5. from sklearn import tree 
  6. import pandas as pd 
  7.   
  8.   
  9. def plot_results_with_hyperplane(clf, clf_name, df, plt_nmbr): 
  10.     x_min, x_max = df.x.min() - .5, df.x.max() + .5 
  11.     y_min, y_max = df.y.min() - .5, df.y.max() + .5 
  12.   
  13.     # step between points. i.e. [0, 0.02, 0.04, ...] 
  14.     step = .02 
  15.     # to plot the boundary, we're going to create a matrix of every possible point 
  16.     # then label each point as a wolf or cow using our classifier 
  17.     xx, yy = np.meshgrid(np.arange(x_min, x_max, step),
  18. np.arange(y_min, y_max, step)) 
  19.     Z = clf.predict(np.c_[xx.ravel(), yy.ravel()]) 
  20.     # this gets our predictions back into a matrix 
  21.     ZZ = Z.reshape(xx.shape) 
  22.   
  23.     # create a subplot (we're going to have more than 1 plot on a given image) 
  24.     pl.subplot(2, 2, plt_nmbr) 
  25.     # plot the boundaries 
  26.     pl.pcolormesh(xx, yy, Z, cmap=pl.cm.Paired) 
  27.   
  28.     # plot the wolves and cows 
  29.     for animal in df.animal.unique(): 
  30.         pl.scatter(df[df.animal==animal].x, 
  31.                    df[df.animal==animal].y, 
  32.                    marker=animal
  33.                    label="cows" if animal=="x" else "wolves", 
  34.                    color='black'
  35.                    c=df.animal_type, cmap=pl.cm.Paired) 
  36.     pl.title(clf_name) 
  37.     pl.legend(loc="best"
  38.   
  39.   
  40. data = open("cows_and_wolves.txt").read() 
  41. data = [row.split('\t') for row in data.strip().split('\n')] 
  42.   
  43. animals = [] 
  44. for y, row in enumerate(data): 
  45.     for x, item in enumerate(row): 
  46.         # x's are cows, o's are wolves 
  47.         if item in ['o', 'x']: 
  48.             animals.append([x, y, item]) 
  49.   
  50. df = pd.DataFrame(animals, columns=["x", "y", "animal"]) 
  51. df['animal_type'] = df.animal.apply(lambda x: 0 if x=="x" else 1) 
  52.   
  53. # train using the x and y position coordiantes 
  54. train_cols = ["x", "y"] 
  55.   
  56. clfs = { 
  57.     "SVM": svm.SVC(), 
  58.     "Logistic" : linear_model.LogisticRegression(), 
  59.     "Decision Tree": tree.DecisionTreeClassifier(), 
  60.   
  61. plt_nmbr = 1 
  62. for clf_name, clf in clfs.iteritems(): 
  63.     clf.fit(df[train_cols], df.animal_type) 
  64.     plot_results_with_hyperplane(clf, clf_name, df, plt_nmbr) 
  65.     plt_nmbr += 1 
  66. pl.show() 
  67.  

讓SVM做一些更難的工作吧!

誠然,如果自變量和因變量之間的關係是非線性的,是很難接近SVM的準確性。如果還是難以理解的話,可以看看下面的例子:假設我們有一組數據集,它包含了綠色以及紅色的點集。我們首先標繪一下它們的座標,這些點集構成了一個具體的形狀——擁有着紅色的輪廓,周圍充斥着綠色(看起來就像孟加拉國的國旗)。如果因爲某些原因,我們丟失了數據集當中1/3的部分,那麼在我們恢復的時候,我們就希望尋找一種方法,最大程度地實現這丟失1/3部分的輪廓。

那麼我們如何推測這丟失1/3的部分最接近什麼形狀?一種方式就是建立一種模型,使用剩下接近80%的數據信息作爲一個“訓練集”。Greg Lamp選擇三種不同的數據模型分別做了嘗試:

  • 邏輯模型(GLM)
  • 決策樹模型(DT)
  • SVM 

Greg Lamp對每種數據模型都進行了訓練,然後再利用這些模型推測丟失1/3部分的數據集。我們可以看看這些不同模型的推測結果:

實現代碼如下:svmflag.py Python

  1. import numpy as np 
  2. import pylab as pl 
  3. import pandas as pd 
  4.   
  5. from sklearn import svm 
  6. from sklearn import linear_model 
  7. from sklearn import tree 
  8.   
  9. from sklearn.metrics import confusion_matrix 
  10.   
  11. x_min, x_max = 0, 15 
  12. y_min, y_max = 0, 10 
  13. step = .1 
  14. # to plot the boundary, we're going to create a matrix of every possible point 
  15. # then label each point as a wolf or cow using our classifier 
  16. xx, yy = np.meshgrid(np.arange(x_min, x_max, step), np.arange(y_min, y_max, step)) 
  17.   
  18. df = pd.DataFrame(data={'x': xx.ravel(), 'y': yy.ravel()}) 
  19.   
  20. df['color_gauge'] = (df.x-7.5)**2 + (df.y-5)**2 
  21. df['color'] = df.color_gauge.apply(lambda x: "red" if x <= 15 else "green") 
  22. df['color_as_int'] = df.color.apply(lambda x: 0 if x=="red" else 1) 
  23.   
  24. print "Points on flag:" 
  25. print df.groupby('color').size() 
  26. print 
  27.   
  28. figure = 1 
  29.   
  30. # plot a figure for the entire dataset 
  31. for color in df.color.unique(): 
  32.     idx = df.color==color 
  33.     pl.subplot(2, 2, figure) 
  34.     pl.scatter(df[idx].x, df[idx].y, colorcolor=color) 
  35.     pl.title('Actual') 
  36.   
  37.   
  38. train_idx = df.x < 10 
  39.   
  40. train = df[train_idx] 
  41. test = df[-train_idx] 
  42.   
  43.   
  44. print "Training Set Size: %d" % len(train) 
  45. print "Test Set Size: %d" % len(test) 
  46.   
  47. # train using the x and y position coordiantes 
  48. cols = ["x", "y"] 
  49.   
  50. clfs = { 
  51.     "SVM": svm.SVC(degree=0.5), 
  52.     "Logistic" : linear_model.LogisticRegression(), 
  53.     "Decision Tree": tree.DecisionTreeClassifier() 
  54.   
  55.   
  56. # racehorse different classifiers and plot the results 
  57. for clf_name, clf in clfs.iteritems(): 
  58.     figure += 1 
  59.   
  60.     # train the classifier 
  61.     clf.fit(train[cols], train.color_as_int) 
  62.   
  63.     # get the predicted values from the test set 
  64.     test['predicted_color_as_int'] = clf.predict(test[cols]) 
  65.     test['pred_color'] 
  66. = test.predicted_color_as_int.apply(lambda x: "red" if x==0 else "green") 
  67.      
  68.     # create a new subplot on the plot 
  69.     pl.subplot(2, 2, figure) 
  70.     # plot each predicted color 
  71.     for color in test.pred_color.unique(): 
  72.         # plot only rows where pred_color is equal to color 
  73.         idx = test.pred_color==color 
  74.         pl.scatter(test[idx].x, test[idx].y, colorcolor=color) 
  75.   
  76.     # plot the training set as well 
  77.     for color in train.color.unique(): 
  78.         idx = train.color==color 
  79.         pl.scatter(train[idx].x, train[idx].y, colorcolor=color) 
  80.   
  81.     # add a dotted line to show the boundary between the training and test set 
  82.     # (everything to the right of the line is in the test set) 
  83.     #this plots a vertical line 
  84.     train_line_y = np.linspace(y_min, y_max) #evenly spaced array from 0 to 10 
  85.     train_line_x = np.repeat(10, len(train_line_y))
  86.  #repeat 10 (threshold for traininset) n times 
  87.     # add a black, dotted line to the subplot 
  88.     pl.plot(train_line_x, train_line_y, 'k--', color="black"
  89.      
  90.     pl.title(clf_name) 
  91.   
  92.     print "Confusion Matrix for %s:" % clf_name 
  93.     print confusion_matrix(test.color, test.pred_color) 
  94. pl.show() 

結論:

從這些實驗結果來看,毫無疑問,SVM是絕對的優勝者。但是究其原因我們不妨看一下DT模型和GLM模型。很明顯,它們都是使用的直線邊界。Greg Lamp的輸入模型在計算非線性的x, y以及顏色之間的關係時,並沒有包含任何的轉換信息。假如Greg Lamp它們能夠定義一些特定的轉換信息,可以使GLM模型和DT模型能夠輸出更好的效果,他們爲什麼要浪費時間呢?其實並沒有複雜的轉換或者壓縮,SVM僅僅分析錯了117/5000個點集(高達98%的準確率,對比而言,DT模型是51%,而GLM模型只有12%!)

侷限性在哪裏?

很多人都有疑問,既然SVM這麼強大,但是爲什麼不能對一切使用SVM呢?很不幸,SVM最神奇的地方恰好也是它最大的軟肋!複雜的數據轉換信息和邊界的產生結果都難以進行闡述。這也是它常常被稱之爲“black box”的原因,而GLM模型和DT模型剛好相反,它們很容易進行理解。(編譯/@CSDN王鵬,審校/仲浩)

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