從Linear到Nonlinear:Feature Transform

學著機器分類,從binary的二元線性分類,一直學到了多元分類,基本精神就是算出一個加權分數之後設計成本函數(cost function),想辦法在那個cost function給最小化
資料是線性可分或是接近線性可分的時候,cost的最小化還能的做的不錯
當資料跟linear差的很多的時候,cost的最小化會很難做的很好
參考如下:http://www.cs.rpi.edu/~magdon/courses/LFD-Slides/SlidesLect10.pdf

左邊的圖儘管沒有完全的線性可分,但只差一些,做出來的效果還不錯
而右邊這張的圖就不同了,東南西北都有叉叉,這樣子用linear model做出來的分類器表現會很差
對於這種非線性的資料,要想能分類器可以做的還不錯的方法就是使用特徵轉換

Feature Transform

右邊的圖仔細觀察可以看出他是可以用圓形切割的一群資料
半徑為的圓形方程式可以簡單表示成
可以用將加權分數的算法改成
如果在圓圈圈內(加權分數大於0)是圈圈,如果在圓圈圈外(加權分數小於0)是叉叉,
今天的問題就變成了如何將帶入成本函數時最小化
但問題就出在加權分數的算法不再是
這樣一個簡單的一次方程式,他可能式二次多項式,三次多項式,M次多項式
這個用以前的最小平方法(least squares method)等去做困難度會大幅提升不少

而為了要讓問題簡化,就有了特徵轉換(Feature Transform)這樣一個手法
以剛才的圓型方程式為例

讓上面二次以上的變數用一個符號取代

我們用代表代表
這樣一個把平面XY空間,映射ㄉ到Z空間時候,在Z空間看起來就像是個線性方程式一樣
因此我們只要在Z空間把線性分類做好,某種程度上可以相信我們把XY空間的分類做好了
而把變成,把變成這樣一個過程稱之為特徵轉換(Feature Transform)
如下所示

舉個簡單的例子
在XY平面上有兩個點(2, 4), (-4, 5),今天我想把他做特徵轉換映射到一個代表的Z空間
兩個點就會被轉換成新的特徵(4, 16), (16, 25),這兩個經過轉換的點將是我們拿來做分類預測的新特徵
特徵轉換有很多種方式,不是只有一種 也可能原資料是一堆二元資料,輸出是平均值當作我們的特徵轉換
轉換方式可以依照資料長相做調整

把上面圓形分類的例子用之前做過logistic去實作
原始碼:https://github.com/del680202/MachineLearning-memo/blob/master/src/lr/nonlinear-logistic.py

首先準備圓形分類的資料

class1 = [(1.1,2.1), (-1.2,-2.2), (1.3,-2.3), (-1.4,2.4)]
class2 = [(-10.1, -10.1), (10.2, 10.2), (10.3, -10.3), (-10.4, 10.4)]

準備圓形切割用的Feature Transform函數,假設資料可以從一個以原點為圓心
半徑為根號5的圓切開

def tf(X):
    result = []
    for x in X:
        result.append((1, x[0] ** 2 +  x[1] ** 2 - 5 ))
    return result

原資料(1.1,2.1)進去之後會被轉換成新的特徵(1, 0.62)

將資料組合好後送去做訓練

c1_dataset = tf(class1)
c2_dataset = tf(class2)
training_set = [(v, 1) for v in c1_dataset]
training_set += [(v, 0) for v in c2_dataset]

W = logistic(training_set)

之後準備測試資料,測試資料離圓心由近到遠去驗證我們的特徵轉換是圓形方程式

test_set = [[0, 0],[0, 10], [2, 0], [2.5, 0], [0, 1.5], [0, 2.5]]

畫出預測結果

W = np.array([W])
for data in test_set:
    label = ''
    feature = (np.array(tf([data])))
    if W.dot(feature.T) > 0:
        label = 'bo'
    else:
        label = 'rx'
    plt.plot([data[0]], [data[1]], label)

從上圖可以看出當資料偏離圓心超過一定距離就會被判定成叉叉

上面的範例有一個問題,會知道資料可以被圓型切開是因為從視覺上自己主觀判斷的
但是真實世界的情況大部份都是高維度的資料,我們會需要一個可以更客觀判斷方程式長相的做法

因此在設定維度的時候可以用多項式展開的方式將資料做特徵轉換
而這部分python已經有實作很好的多項式展開的特徵轉換
參考:http://scikit-learn.org/stable/modules/linear_model.html#polynomial-regression-extending-linear-models-with-basis-functions

以二維資料為例
一次多項式展開
二次多項式展開

依此類推,在機器學習裡通常次方項開越高,越能降低訓練資料的error
但這會延伸另一個問題,也就是機器學習裡經典的Overfitting


在訓練分類器的時候用高次項做儘管表現的很好,但是會由於過度去fit資料,而造成離真實世界反而更遠
這樣的狀況就會變成訓練時100分,實戰時不及格,這時候寧願選擇訓練時90分,實戰時80分的分類器

comments powered by Disqus