1. 什麼是迴歸?
分類的目標變量是標稱型數據,而回歸是對連續型數據的預測。迴歸分析是一種預測建模技術,研究因變量和自變量之間的關係,如銷售量預測或製造缺陷預測等,下圖中的紅線表示的就是迴歸曲線。
迴歸不同於分類和聚類,他們的區別可以用下圖形象的表達出來。
2. 迴歸模型
這裏使用sklearn
進行代碼實現,如果想手動實現的話,可以看《機器學習實戰》,那本書有部分的算法實現,下面介紹的算法統一使用的函數如下
def load_data(file_path):
num_feat = len(open(file_path).readline().split("\t")) - 1
data_mat = list()
lable_mat = list()
fr = open(file_path)
for line in fr.readlines():
line_arr = list()
cur_line = line.strip().split("\t")
for i in range(num_feat):
line_arr.append(float(cur_line[i]))
data_mat.append(line_arr)
lable_mat.append(float(cur_line[-1]))
return data_mat, lable_mat
def plot_regression(model, x_data, y_data):
x_data = np.mat(x_data)
y_data = np.mat(y_data).T
x_train, y_train = x_data[:150,1:], y_data[:150,:]
x_test, y_test = x_data[150:,1:], y_data[150:,:]
model.fit(x_train, y_train)
score = model.score(x_test, y_test)
result = model.predict(x_train)
plt.figure()
srt_idx = x_train.argsort(0)
plt.plot(x_train[srt_idx].reshape(-1,1), y_train[srt_idx].reshape(-1,1), 'go', label = "true value")
plt.plot(x_train[srt_idx].reshape(-1,1), result[srt_idx].reshape(-1,1), 'ro-', label = "predict value")
plt.title("score:%f" % score)
plt.legend()
plt.show()
2.1 線性迴歸
2.1.1 普通線性迴歸
提到迴歸,首先想到的肯定是線性迴歸(linear regression),因爲它是最容易理解,最簡單的迴歸方法。設待擬合的數據對象爲X={x1,x2,...,xm},其對應的真實值爲y={y1,y2,...,ym},線性模型可以寫爲
y^=Xw
其中,w爲迴歸係數,我們用平方誤差來衡量擬合的誤差
L(X)=i=1∑m(yi−xiTw)2=(y−Xw)2
上式對w求導等於0可以得到
∂w∂L(X)=∂w∂(yTy−wTXTy−yTXw−wTXTXw)=2XT(y−Xw)=0
可以得到
w^=(XTX)−1XTy
上述方式容易對訓練數據欠擬合,一種好的解決方式是局部加權線性迴歸,爲每個誤差增加一個權重wi(這裏的w並不是上面的w^),此時誤差函數可以寫成
L(X)=i=1∑mwi(yi−xiTw)2=[W(y−Xw)]2
其中,W是一個對角矩陣,也叫做核,核的類型可以自由選擇,最常見的就是高斯核,高斯覈對應的權重如下
W(j,j)=exp(−2k2∥xi−xj∥2)
注意:這裏的xi是指的單個數據,每個數據對應的權重矩陣都不同。
同樣的,對新的誤差函數L(X)求導可以得到此時迴歸係數爲
w^=(XTWX)−1XTWy
這裏的W其實是WTW,但是使用W代替具有同樣的意義並且簡便。
sklearn
調用代碼:
x_data, y_data = load_data("ex0.txt")
from sklearn import linear_model
model_linear_regression = linear_model.LinearRegression()
plot_regression(model_linear_regression, x_data, y_data)
繪製出的迴歸曲線如下圖所示
2.1.2 嶺迴歸
我們看線性迴歸中的輸入集X={x1,x2,...,xm},假設其維度爲n,當n>m的時候,X不是滿秩矩陣,無法求解逆矩陣,這時候就需要用到**嶺迴歸(ridge regression)**了,在矩陣XTX上加上一個λI讓其成爲滿秩矩陣,那麼這個時候的迴歸係數爲
w^=(XTX+λI)−1XTy
sklearn
調用代碼:
x_data, y_data = load_data("ex0.txt")
from sklearn import linear_model
model_ridge = linear_model.Ridge(alpha = 0.01)
plot_regression(model_ridge, x_data, y_data)
繪製出的迴歸曲線如下圖所示
2.2 決策樹迴歸
決策樹學習常用的算法有ID3、C4.5、CART(classification and regression tree),這介紹用於迴歸的決策樹CART,具體的方法理論參考李航的《統計學習方法》。
我們考慮輸入的訓練數據D={X,y}={(x1,y1),(x1,y1),...,(xm,ym)},一個迴歸樹對應着輸入空間(即特徵空間)的一個劃分以及在劃分的單元上的輸出值,假設已將輸入空間劃分爲M個單元R1,R2,...,RM,並且在每一個單元上都有一個固定的輸出值cm,那麼迴歸樹模型可以表示爲
f(x)=m=1∑McmI(x∈Rm)
其中,函數I對應着0-1函數。當輸入空間的劃分確定時,可以用平方誤差∑xi∈Rm(yi−f(xi))來表示迴歸樹對於訓練數據的預測誤差,用平方誤差最小的準則求解每個單元上的最優輸出值,那麼單元Rm上的最優值cm^是Rm上的所有輸入實例xi對應的輸出yi的均值,即
cm^=ave(yi∣xi∈Rm)
上面是整個樹的輸出形式,關鍵的問題來了,怎麼對輸入空間進行劃分?這裏採用啓發式的算法,選擇第j個變量和它取的值s作爲切分變量(spliting variable)和切分點(spliting point),並定義兩個區域
R1(j,s)={x∣xj≤s}R2(j,s)={x∣xj>s}
然後尋找最優切分變量和最優切分點,即
m(s)=j,smin⎣⎡c1minxi∈Rj(j,s)∑(yi−c1)2+c2minxi∈Rj(j,s)∑(yi−c2)2⎦⎤
簡單的理解,就是在要求切分點s兩邊的區域的均方差都儘量小的同時,保證兩個區域的最小均方差和是最小的。
對每一對(j,s),均值表示爲
c1^=ave(yi∣xi∈R1(j,s))c2^=ave(yi∣xi∈R2(j,s))
遍歷所有輸入變量,找到最優的對(j,s),從而將輸入空間切分爲兩個區域,接着對切分的兩個區域重複上述劃分過程,直到滿足停止條件爲止,這樣一個迴歸樹的生成就完成了。
舉個🌰,輸入數據D如下表所示。
xi |
1 |
2 |
3 |
4 |
5 |
6 |
yi |
5.56 |
5.70 |
5.91 |
6.40 |
6.90 |
7.95 |
對上述連續型變量,只有一個切分變量,那麼考慮切分點爲1.5, 2.5, 3.5, 4.5, 5.5。對切分點依次求解R1,R2,c1,c2,m(s),例如當切分點爲2.5時,R1={1,2},R2={3,4,5,6},其他的計算如下
c1=N11xi∈R1(j,s)∑yi=21(5.56+5.70)=5.63c2=N21xi∈R2(j,s)∑yi=41(5.91+6.40+6.90+7.95)=6.79sm=j,smin⎣⎡c1minxi∈R1(j,s)∑(yi−c1)2+c2minxi∈R2(j,s)∑(yi−c2)2⎦⎤=2.294
第一次切分時,對象爲全體輸入,計算出來的sm值如下表所示。
切分點 |
1.5 |
2.5 |
3.5 |
4.5 |
5.5 |
s(m) |
3.23468 |
2.294 |
1.31373333 |
0.956725 |
1.21752 |
可以看到,當s=4.5時,取得最小的s(m)值,此時的迴歸估計值爲全體輸入的均值6.403,遞歸求解左子樹和右子樹的迴歸估計值,最終求解的迴歸方程爲
f(x)=⎩⎪⎪⎪⎨⎪⎪⎪⎧5.7236.46.97.95x≤3.53.5<x≤4.54.5<x≤5.5x>5.5
這個過程可以使用graphviz
模塊顯示出來。
使用本文一開始提到的數據,決策樹迴歸的代碼如下
from sklearn import tree
model_decisiontree_regression = tree.DecisionTreeRegress(min_weight_fraction_leaf=0.01)
plot_regression(model_decisiontree_regression, x_data, y_data)
2.3 SVM迴歸
先回顧一下在基本線性可分情況下的SVM模型:
err(xi,yi)={0∣yi−w⋅xi−b∣−ε∣yi−w⋅xi−b∣≤ε∣yi−w⋅xi−b∣>ε
分類SVM模型中要讓訓練集中的每個樣本儘可能遠離自己類別一側的支持向量,迴歸模型也一樣,沿用的是最大建哥分類器的思想。
對於迴歸模型,優化的目標函數和分類模型保持一致,依然是minw,b21∥w∥2,但是約束條件不一樣,迴歸模型的目標是讓訓練集中的每個樣本點(xi,yi)儘量擬合到一個線性模型yi=wxi+b上,對於一般的迴歸模型使用均方誤差MSE作爲損失函數的,但是SVM迴歸不是這樣定義的。
SVM需要我們定義一個常量ε>0,對於某一個點(xi,yi),如果∣yi−wxi−b∣≤ε,則完全沒有損失,如果∣yi−wxi−b∣>ε,則對應的損失爲∣yi−wxi−b∣−ε,這個和均方差損失不同,對於均方差,只要∣yi−wxi−b∣=0就會有損失。
如下圖所示,在藍色條帶裏面的點是沒有損失的,但是在外面的點是有損失的,損失大小爲紅色線的長度。
總結下,我們的SVM迴歸模型的損失函數度量爲
err(xi,yi)={0∣yi−w⋅xi−b∣−ε∣yi−w⋅xi−b∣≤ε∣yi−w⋅xi−b∣>ε
有了損失函數之後,我們就可以定義SVM迴歸的目標函數爲
min21∥w∥22 s.t ∣yi−w⋅xi−b∣≤ε(i=1,2,…,m)
這個模型的最優解求解過程這裏不再贅述,有興趣的可以看參考[2]或者[3]中的論述。
使用本文一開始提到的數據,SVM迴歸的代碼如下
from sklearn import svm
model_svr = svm.SVR()
plot_regression(model_svr, x_data, y_data)
參考
[1] 李航. 統計學習方法, 清華大學出版社
[2] CSDN-SVM迴歸博客
[3] cnblog-SVM迴歸博客