支持向量機SVM

      在〈支持向量機SVM〉中尚無留言

Support Vector Machines, SVM

SVM是一種非常經典的資料分類演算法,稱為支持向量機。其目的是在找出一個超平面,將二個不同的集合分開。

所謂的超平面,其實是指高維度而以。比如在二維中,找到一條線將二者分開,這一條線就是超平面。若在三維空間中,找到一個平面將二者分開,那麼這一個平面也叫超平面。同樣的,四維中找到三維,那麼三維也叫超平面。

SVM分為線性可分集合及非線性可分集合。

線性可分集合

如下圖,資料可分為左右二邊的二種狀況。以信用卡客戶為例,紅點為不按時繳錢的客戶,藍點為信用良好的客戶。

為什麼客戶會違約呢?? 銀行當然會對客戶的一些條件進行分析。比如客戶的總資產,薪資,負債,貸款,是否有賭博習慣,是否為澳客習慣性積欠等因素進行評估。但條件愈多愈難評估,也愈難講解,所以此例僅就總資產及薪資二個條件評估。

下圖的每個點都是給定的訓練實例,每個訓練實例被標記為屬於兩個類別中的其中一個。SVM訓練演算法會將一個新的實例分配給兩個類別其中之一,使其成為非概率的二元線性分類器。

SVM模型將實例表示為空間中的點,這樣對應就使得單獨類別的實例被盡可能寬度間隔分開。然後將新的實例對映到同一空間,並基於它們落在間隔的哪一側來預測所屬類別。所以SVM簡單的說,就是計算中間灰色虛線的演算法。

非線性可分集合

如果不是一條線可以分開的話呢。以下圖而言,紅藍可能質量不一樣,所以就可以往桌子上一拍,讓質量較輕的紅點行上跳高一點,較重的藍點會跳低一點,所以就可以在中間產生一個超平面,將二者分開。這就是SVM使用核函數技巧,有效地進行非線性分類,將其輸入隱式對應到高維特徵空間中。

當資料未被標記時,不能進行監督式學習,需要用非監督式學習,它會嘗試找出資料到叢集的自然聚類,並將新資料對映到這些已形成的叢集中。

手寫數字實例練訓

底下使用SVM模型來預測手寫的數字。首先由svm.SVC產生model模型,再用model.fit()開始訓練模型。傳入模型的資料必需是二維陣列,第 0 維為訓練的筆數,第 1 維為每筆資料的長度。所以如果是1000張圖片的話,必需把這1000張的長寬轉成 (1000, w*h)。

第1維的資料長度,可以想像成不同的狀況。比如要預測房價的漲或跌,可把影響房價的因素列出,比如通膨狀況,有無戰爭,有無疫情,物價指數,人口數,死亡數,地點等等因素。反正就是因素愈多就愈準確。

最後使用model.predict()將要預測的資料傳入,即可取得計算後的結果。

svm.SVC(C=100., kernel=’linear’),C為懲罰係數,數字愈大,愈不能容忍誤差,當然也會降低速度。

執行代碼之後,這下神奇了,幾乎全部都正確了

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import scale
import pylab as plt
from sklearn import svm
#載入資料並進行標準常態分配
digits = datasets.load_digits()
data = scale(digits.data)

#拆開資料,3/4為訓練資料,1/4為預測資料
x_train, x_test, y_train, y_test = train_test_split(data, digits.target, train_size=0.75, random_state=42)

#建立模型
model = svm.SVC(C=100., kernel='linear')

#開始訓練模型
model.fit(x_train, y_train)

#傳入預測資料並取得結果
predict = model.predict(x_test)

for i in range(50):
    sub=plt.subplot(5,10,i+1)
    sub.set_title(predict[i])
    sub.set_xticks([])
    sub.set_yticks([])
    sub.imshow(x_test[i].reshape(8,8), cmap='gray')
plt.show()

使用 mnist 資料

底下使用 mnist 的資料進行訓練偵測,但使用 svm.SVC訓練60000筆資料要非常久,所以可以改用
model = svm.LinearSVC(C=100.)。LinearSVC也是線性演算法,但跟SVC不一樣,速度較快。

from keras.datasets import mnist
import pylab as plt
from sklearn import svm
(x_train, y_train), (x_test, y_test)=mnist.load_data()
x_train=x_train.reshape(60000,784)
x_train=x_train[:10000]
y_train=y_train[:10000]
x_test=x_test.reshape(10000,784)
x_test=x_test[:100]
y_test=y_test[:100]
#建立模型
model = svm.SVC(C=100., kernel='linear')
#LinearSVC為線性演算,但演算法跟 SVC不一樣,速度較快,可用來訓練60000筆資料
#model = svm.LinearSVC(C=100.) #開始訓練模型 model.fit(x_train, y_train) #儲存模型可以使用底下的二種方法 #joblib.dump(model, "mnist_model") pickle.dump(model, open("model.pkl", "wb"), protocol=0) #傳入預測資料並取得結果 predict = model.predict(x_test) for i in range(50): sub=plt.subplot(5,10,i+1) sub.set_title(predict[i]) sub.set_xticks([]) sub.set_yticks([]) sub.imshow(x_test[i].reshape(28,28), cmap='gray') plt.show()

載入模型

載入模型也可以使用底下二種方式

import pickle
import joblib
from keras.datasets import mnist
import pylab as plt

#model=joblib.load("mnist_model")
with open("model.pkl",'rb') as f:
    model=pickle.load(f)

(x_train, y_train), (x_test, y_test)=mnist.load_data()
x_test=x_test[:100]
x_test=x_test.reshape((100,784))
labels=model.predict(x_test)
for i in range(50):
    ax=plt.subplot(5,10,i+1)
    ax.axis("off")
    ax.set_title(labels[i])
    ax.imshow(x_test[i].reshape((28,28)), cmap='gray')
plt.show()

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *