在之前的文章中,我們已經介紹過兩個分類算法,一個是KNN算法,一個是邏輯回歸算法。其中,KNN算法的分類依據是距離,邏輯回歸算法的分類依據是概率。本文要介紹的支持向量機,也是在分類問題中被廣泛應用的一種算法,先來看一下它的定義。
在機器學習領域,支持向量機(Support Vector Machine,簡稱SVM)屬於一種監督學習算法,可以用來解決分類和回歸問題,其中,在分類問題中的應用更加廣泛。
支持向量機是通過某種方式,在一個N維空間中找到一個最優超平面(類似於邏輯回歸中的決策邊界),把樣本劃分到不同的區域中,在不同區域的樣本屬於不同的類別,從而實現分類。
在幾何體中,超平面(Hyperplane)是一維小於其環境空間的子空間。如果空間是3維的,那麼它的超平面是2維平面,而如果空間是2維的,則其超平面是1維線。
在解決線性分類問題時,分類算法的核心是要找到一個分類器,把屬於不同類別的樣本分開,在找分類器的過程中,本質是通過最小化一個損失函數,確定一個最優的分類器。
對於邏輯回歸算法,在確定最優分類器時,藉助的工具有sigmoid函數和最大似然估計,對於接下來要介紹的支持向量機算法,藉助的工具有最大化間隔和核技巧。
因此,簡單理解的話,支持向量機算法是通過某種方式,找到一個最優的分類器,從而實現分類的過程。明白了這一點,下面就具體介紹一下該算法的原理。
先來看一個慄子。
以二分類問題為例,假設有一個1維的數據集,表示重量,現在希望用某個標準,把數據集中的樣本分成兩類,超重和正常。
通過觀察樣本,我們可以選擇一個閾值(臨界值),制定一個規則,當樣本值小於閾值時,將它歸類為正常,當樣本值大於閾值時,將它歸類為超重。
現在有一個新樣本(綠色球),按照上述規則,由於它的值大於閾值,所以應該把它分類為超重。但這麼分的話,似乎並不合適,因為通過觀察可以發現,這個新樣本距離左側的正常類別更近。
因此,上面選擇的閾值不夠合理。
如果把兩個類別邊緣點的中間點作為閾值,如上圖,此時,新樣本值小於閾值,所以應該把它分類為正常。這麼做似乎更合理,因為新樣本離正常類別的距離更近。
可以發現,選擇閾值需要有一個標準,這個標準是最大化間隔(Maximize margin),其中,樣本值和閾值之間最短的距離叫做間隔(Margin)。
當閾值為中點時,正常類別的margin和超重類別的margin相同,且為最大,符合最大化間隔的標準。
如果將閾值向左側移動一點,如圖中藍色線,那么正常類別的margin會變小,同理,向右側移動的話,超重類別的margin會變小,而我們要找的是讓兩個類別的margin都最大時的閾值。
因此,為了有效進行分類,需要構造一個最大化間隔的分類器,從而找到一個合適的閾值。
下面從公式的角度來看一下,最大化間隔是什麼意思。首先,對比邏輯回歸,看一下支持向量機的優化目標。
在邏輯回歸中,當y的取值為1時,我們希望x軸的值遠大於0,將y=1帶入損失函數中,可以得到左下角的損失函數公式。圖中的藍色線代表邏輯回歸的損失函數,橘色線則代表支持向量機的損失函數。
可以看出,橘色線的特點是,以z=1為分界點,當z大於等於1時,損失函數的值為0,其他情況下,損失函數的值大於0。
同理,當y的取值為0時,我們希望x軸的值遠小於0,將y=0帶入損失函數中,可以得到右下角的損失函數公式。圖中的藍色線代表邏輯回歸的損失函數,橘色線則代表支持向量機的損失函數。
可以看出,橘色線的特點是,以z=-1為分界點,當z小於等於-1時,損失函數的值為0,其他情況下,損失函數的值大於0。
在上面的分析中,根據邏輯回歸損失函數的特點,我們引出了支持向量機的損失函數圖,它的名字叫鉸鏈損失函數(Hinge loss),這裡我們不過多糾結它是怎麼來的,先直接記住結論,然後繼續往下分析。
接下來,看一下具體的公式,優化目標的公式由兩個部分組成,損失函數 + 正則化參數(懲罰項),正則化(Regularization)的概念在之前的文章中有介紹過,它的目的是防止模型過擬合。
將公式中的兩個部分一般化為A和B,其中,λ是用來控制兩個部分權重的一個參數,在支持向量機中,把這個參數放在A部分,並且用字母C來表示。又由於m為常數項,對最終的優化結果沒有影響,所以可以去掉。
為了實現損失函數的最小化,當C的取值很大時,我們希望A的取值很小,最好是0。當A取0時,損失函數就可以簡化成紅色框線裡的表達式。
接下來,我們來思考一下,當樣本中存在異常值(Outliers)的情況下該如何處理。
觀察上圖,按照最大化間隔的標準,閾值的位置如上圖所示,靠近右側的超重類別。當輸入一個新樣本(綠色球)時,會將它預測為正常類別,因為它在閾值的左側。
但是,這麼分似乎也不是很合理,因為新樣本的值距離右側的超重類別更近。這裡的問題是,樣本的數據集中存在異常值,可以看出,最大化間隔分類器對異常值是極其敏感的。因此,為了讓得出的閾值對異常值不那麼敏感,必須允許誤分類(Misclassifications)。
在允許誤分類的情況下, 比如,選擇A、B兩個樣本值的中點作為閾值,此時,屬於正常類別的異常值會被誤分類為超重類別,新樣本會被預測為超重類別。這樣的預測結果更合理一些,因為新樣本確實距離右側的超重類別更近。
當允許存在誤分類的情況下,樣本值和閾值之間的距離叫做軟間隔(Soft margin),當允許誤分類的程度不同時,soft margin也會不同。在確定最優的soft margin時,用到的方法是交叉驗證(Cross validation)。
這種用soft margin決定閾值位置的方法,就是在用soft margin分類器(Soft margin classifier)對樣本進行分類,這個分類器也叫支持向量分類器(Support vector classifier)。
在soft margin邊緣和裡面的樣本點叫做支持向量(Support vectors)。
當數據集是2維的,支持向量分類器就是一條1維直線。同樣,也是通過交叉驗證的方法去確定最優的soft margin。
當數據集是3維的,支持向量分類器就是一個2維平面。
可以看到,支持向量分類器能夠解決異常值問題,而且因為它允許誤分類,也可以解決相互重疊的分類問題(Overlapping classifications)。
根據前面推導出的表達式,支持向量機對誤分類的控制,是通過參數C來實現的。
當C的值很大時,公式前半部分的損失函數對結果的重要性提升,它對異常值很敏感,容易出現過擬合的現象,如下圖中的橙色線。
當C的值不是很大時,公式後半部分的正則化項的重要性相對提升,它對異常值的敏感度有所降低,允許一定程度的誤分類,如下圖中的黑色線。
前面已經介紹了如何用最大化間隔的方法去找到一個最優的支持向量分類器,但它並不是萬能的,對於線性不可分的樣本,我們還需要藉助另一個方法:核技巧。
對於下圖中的樣本,不論把閾值放在哪個位置,都不能很好地把兩個類別區分開,需要藉助核技巧的方法。
核技巧(Kernel trick)是一種用線性分類器去解決非線性問題的方法,它會藉助核函數(Kernel functions),把原本在低維空間中線性不可分的樣本,映射到線性可分的高維空間。
為了直觀地理解核技巧的方法,下面舉一個具體的例子來看一下它是怎麼操作的。
原始樣本是一個1維的數據集。
選擇一個核函數:y=x^2,添加一個y軸,把低維數據轉換到高維,即把1維數據轉換成2維數據。比如,下圖A點的值為0.5,對應在y軸的值就是0.5的平方,等於0.25。
將所有樣本點都轉換完成,原來的1維數據就變成了一個2維數據,此時能夠找到一條直線(支持向量分類器),把兩個類別的樣本分開。
對於一個新樣本(綠色球),將它的值平方,由於它落入了支持向量分類器的上方,它應該被分類為正常類別。
在上例中,我們選擇的核函數是 y = x^2,但為什麼是平方,不是立方,或者是平方根呢?這裡就涉及到核函數的選擇問題,核函數的形式有很多,需要具體問題具體分析,本文介紹兩個核函數的形式,多項式核函數(Polynomial Kernel)和徑向內核函數(Radial Basis Function Kernels,RBF Kernel)。
在上例中,我們是用了一個帶有多項式核函數y = x^2的支持向量機,在轉換的高維空間去計算樣本之間的關係,然後基於在高維空間中計算出的關係,找到了一個合適的支持向量分類器。
多項式核函數的一般形式如上圖所示,其中,a和b代表數據集中兩個不同的樣本,r決定多項式的係數,d是多項式的次數。
當r=1/2,d=2時,多項式如上所示,最終能夠表示成點積(Dot product)的形式,它的計算方法是把兩組相同長度的數字序列(向量),對應位置的數字相乘並求和。在這裡,點積的計算結果,可以理解為兩個向量之間的相關關係。
點積展示了樣本數據在高維空間中的坐標信息。括號中的位置1代表x軸,位置2代表y軸,位置3代表z軸,由於位置3的值相同,可以忽略不看。
當r=1,d=2時,多項式如上所示,x軸變成了√2 a,表示原來的樣本值a應該向右移動到√2 a的位置,y軸不變,同樣z軸是相同的常數,可以忽略不看。
回到r=1/2,d=2的例子,既然左側的核函數與右側的點積相等,我們可以將樣本點的值帶入到核函數中,進而得到它們以點積形式表示的、在高維空間的關係。
計算結果16,002.25就代表A、B兩點在2維空間的關係,它被用來確定支持向量分類器的位置,即使我們並沒有把數據實際轉換到2維空間。
因此,通過上面的分析可以看出,多項式核函數用於計算一組樣本之間的關係,因為它可以表示為點積的形式,而這裡點積的計算結果就代表輸入樣本之間的關係。參數r決定多項式的係數,d決定多項式的次數,r和d的取值是用交叉驗證法確定的。
一旦r和d的值確定了,就可以直接把原本低維空間的樣本值帶入多項式核函數中,通過計算,得到它們在高維空間的關係。
類似於多項式核函數(Polynomial Kernel),徑向內核函數(RBF Kernel)也是一種用來計算低維空間樣本的高維空間關係的函數,它的一般表達式如下所示。
徑向內核函數的做法類似於加權最鄰近模型(Weighted nearest neighbor model),也就是說,離新樣本近的樣本,對它的分類結果影響很大,離新樣本遠的樣本,對它的分類結果影響很小。
看一下公式中的參數,a、b代表兩個不同的樣本點,徑向內核函數是關於a和b差值平方(距離的平方)的函數,gamma用來控制a和b差值平方對函數結果的影響程度。
比如,當gamma=1時,將距離比較近的A、B兩個樣本點的值代入公式,得到的結果是0.11,即低維空間的兩點A、B,它們通過徑向內核函數計算出的在高維空間的關係為0.11。
當gamma=2時,同樣將A、B兩個樣本點的值代入公式,得到的結果是0.01,比gamma=1時得到的0.11要小。
再回到gamma=1時的例子,如果選擇兩個距離比較遠的A和C點,得到的結果是一個非常接近於0的值。因此,當兩個樣本點的距離越遠時,它們對彼此的影響越小。
和多項式核函數一樣,當我們將樣本值代入徑向內核函數中,會得到它們在高維空間中的關係。0.11代表距離較近的A和B兩點在高維空間的關係,非常接近於0的值則代表距離較遠的A和C兩點在高維空間的關係。
與多項式核函數不同的是,徑向內核函數是在無限的高維空間裡計算的,下面就從多項式核函數出發,看一下徑向內核函數是如何在無限空間裡進行操作的。
當r=0時,多項式核函數可以寫成關於a和b的點積形式,只不過它還是1維的,比如當d=2時,是將原來1維空間中的樣本值進行了平方,樣本的位置發生了變動,但仍是在1維空間。
當多項式核函數的r=0,d取從1到無窮的不同值並相加時,就會得到一個包含無限空間的點積,這就是徑向內核函數所做的事情。這裡的推導會涉及到泰勒級數展開,本文就先不過多介紹啦。
我們可以導入sklearn.svm模塊中的SVC類實現支持向量機算法,先利用訓練集數據構建模型,再用測試集數據進行預測。
支持向量機算法的實現步驟與邏輯回歸和KNN算法類似:
① 先導入相應的模塊
② 劃分訓練集和測試集
③ 創建一個分類器
④ 放入訓練集數據進行學習,得到預測模型
⑤ 在測試集數據上進行預測
【工具】Python 3
【數據】tushare.pro
【注】本文注重的是方法的講解,請大家靈活掌握,代碼中參數設置的是默認值,暫時不對參數調整做過多介紹。
import tushare as ts
import pandas as pd
import matplotlib.pyplot as plt
pd.set_option("expand_frame_repr", False) # 當列太多時不換行
# 設置token
token = 'your token'
ts.set_token(token)
pro = ts.pro_api()
# 導入000002.SZ前復權日線行情數據,保留收盤價列
df = ts.pro_bar(ts_code='000002.SZ', adj='qfq', start_date='20190101', end_date='20191231')
df.sort_values('trade_date', inplace=True)
df['trade_date'] = pd.to_datetime(df['trade_date'])
df.set_index('trade_date', inplace=True)
df = df[['close']]
# 計算當前、未來1-day漲跌幅
df['1d_future_close'] = df['close'].shift(-1)
df['1d_close_future_pct'] = df['1d_future_close'].pct_change(1)
df['1d_close_pct'] = df['close'].pct_change(1)
df.dropna(inplace=True)
# ====1代表上漲,0代表下跌
df.loc[df['1d_close_future_pct'] > 0, '未來1d漲跌幅方向'] = 1
df.loc[df['1d_close_future_pct'] <= 0, '未來1d漲跌幅方向'] = 0
df = df[['1d_close_pct', '未來1d漲跌幅方向']]
df.rename(columns={'1d_close_pct': '當前1d漲跌幅'}, inplace=True)
print(df.head())
當前1d漲跌幅 未來1d漲跌幅方向
trade_date
2019-01-03 0.007112 1.0
2019-01-04 0.035728 1.0
2019-01-07 0.004815 0.0
2019-01-08 -0.001997 1.0
2019-01-09 0.013203 0.0
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
# 創建特徵 X 和標籤 y
y = df['未來1d漲跌幅方向'].values
X = df.drop('未來1d漲跌幅方向', axis=1).values
# 劃分訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4, random_state=42)
# 創建一個支持向量分類器
# linear kernel
# svm = SVC(kernel='linear', C=1, random_state=0)
# RBF kernel
svm = SVC(kernel='rbf', random_state=0, gamma=.01, C=1)
# 放入訓練集數據進行學習
svm.fit(X_train, y_train)
# 在測試集數據上進行預測
new_prediction = svm.predict(X_test)
print("Prediction: {}".format(new_prediction))
# 測算模型的表現:預測對的個數 / 總個數
print(svm.score(X_test, y_test))
Prediction: [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0.]
0.4948453608247423
需要獲取可運行的Python程序腳本文件,請在本公眾號私信關鍵字「支持向量機」獲取下載連結。
本文介紹了機器學習算法中的支持向量機,包括它的定義、原理、整個推導的過程,涉及到的概念有最大化間隔、軟間隔、核技巧、多項式核函數、徑向內核函數,並且在最後用Python實現了支持向量機算法。
希望本文能夠對大家學習支持向量機算法有幫助啦,如果大家覺得有用,就點亮「在看」讓更多小夥伴們看到吧💗
【推薦閱讀】
圖文實例教會你邏輯回歸
機器學習算法入門之監督學習(I)
機器學習必備技能之「統計思維2.0」
機器學習必備技能之「統計思維1.0」
機器學習必備技能之「數據預處理」
數據科學必備基礎之線性回歸
Pandas必備技能之「分組聚合操作」
END
Support Vector Machine [StatQuest with Josh Starmer]【1】
Support Vector Machines [Andrew Ng]【2】
https://campus.datacamp.com/courses/support-vector-machines-in-r【3】
https://towardsdatascience.com/support-vector-machine-introduction-to-machine-learning-algorithms-934a444fca47【4】
https://medium.com/machine-learning-101/chapter-2-svm-support-vector-machine-theory-f0812effc72【5】
https://towardsdatascience.com/https-medium-com-pupalerushikesh-svm-f4b42800e989【6】
https://datascienceplus.com/radial-kernel-support-vector-classifier/【7】
https://towardsdatascience.com/kernel-function-6f1d2be6091【8】
http://crsouza.com/2010/03/17/kernel-functions-for-machine-learning-applications/【9】
https://giphy.com/explore/spongebob-squarepants【10】