iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 10
1

今天開始比較完整一點的跟大家介紹線性模型。

什麼是線性模型呢?之前的Curve Fitting就是一種,還記得嗎?這個我們叫他basis function(基函數),他與 w 這個向量內積得到我們要的輸出,的定義有許多種,有線性的、也有非線性的,但是他們在這邊都是線性模型,為什麼呢?因為我們要去調整的是 w ,而 w 僅是與phi做內積,所以不管phi再怎麼樣非線性,他都是 w 的線性函數,這也是為什麼叫做線性模型。

今天我們先介紹一個相當實用的計算方式,也就是今天的標題之一循序學習。
為什麼要循序呢?在第一次的動手做看看,我們知道,也就是我們要進行矩陣的運算,而且不只是相乘,還要取反矩陣,取反矩陣其實是一個很麻煩的計算,當資料量太大的時候,這個計算會便得不可行,所以我們必須要循序學習。

所以我們要怎麼樣循序學習呢?我們利用梯度下降!

我們計算反矩陣的方式,是直接令他的一次微分等於零,而一次微分就是我們所謂的梯度。現在我們不直接令他等於零,我們透過迭代,一次讀一筆資料,一筆資料一次迭代,讓梯度接近最小值,迭代方式如下


其中那個很像n,可是右邊比較長的叫做eta,這邊是學習率(learning rate)的意思,我們需要調整他以確保w最後會收斂;而那個三角形又有一個w的意思是,對取w的梯度,也就是對w偏微分。

而這個就是最簡單的梯度下降法(gradient descent)!

但是這樣的方式,其實沒有辦法解決我們提到的問題,因為在計算E(w)的偏微分時,我還是得計算所有的資料,這是因為,裡面的累加,使得我們其實沒有減少到計算量。

因此我們會使用隨機梯度下降法(stochastic gradient descent)。
怎麼個隨機法呢?其實很簡單,就是我們直接不算那個累加,我們直接對這次拿到的資料進行微分就好了,如此一來我們的計算量就會少很多了!雖然需要花更久的時間才能使 w 迭代到我們要的值,可是會使得我們的計算便得可行。也就是我們的更新方式成為了

下面是用這個方式算出來的曲線,藍色是以之前算反矩陣的方式算,橘色則是以SGD的方式算

下面是畫出上圖的程式碼,關於eta的選擇,其實有很多理論可以參考,大家有興趣也可以去查閱。不過我這邊就是很簡單的try & error選出來一個會收斂的數字!

def phi(x, degree):
	X = [1.]
	out = float(x)
	for term in range(degree):	
		X += [float(out)]
		out =  out * float(x)
	X = np.asarray(X)
	return X
def regression(target, feature, degree, lamda):
	target = np.asarray(target)
	mat = phi(feature[0], degree)
	for i in range(1, len(feature)):
		mat = np.vstack((mat, phi(feature[i], degree)))
	if lamda == 0:
		inverse = pinv(mat)
	else:
		inverse =  inv(mat.T.dot(mat) + lamda*np.identity(degree + 1)).dot(mat.T)
	return inverse.dot(target)    

#stochastic gradient descent
def sgd(target, feature, order):
    w = np.zeros((order+1, 1))
    eta = 0.0001 #eta需要小心選擇確保收斂
    for epoch in range(30000): #看完所有資料一次算一代(epoch)
        for n in range(len(target)):
            w += eta*(np.asarray(target[n]).reshape(1) - w.T.dot(phi(feature[n],order).reshape(order+1,1)))*phi(feature[n],order).reshape(order+1,1) #循序更新
    return w

def f(x):
    return np.sin(x) + np.random.normal(0,1,len(x))

train_data = np.linspace(0,6,50)
train_target = f(train_data)

order = 2 #用幾次方的phi去fit,改變order也需要更新你的eta與epoch確保他收斂
plt.plot(train_data, train_target, 'bo')
w = regression(train_target, train_data, order, 0)
ws = sgd(train_target, train_data, order)

print ws
print w

line = np.linspace(0,6,50)
lx = []
sx = []
for l in line:
    lx += [w.dot(phi(l, order))]
    sx += [ws.T.dot(phi(l, order).reshape((order+1,1))).reshape(1)]
plt.plot(line, lx, linestyle ='-')
plt.plot(line, sx)
plt.show()

從這個例子可以看到,在這種scale的問題中,以SGD是沒效率的,不過正如前面所說,若資料很多時,也只能使用這樣的方式了,另外就是當沒有公式解的時候,這就會是一個很好逼近最佳解的方式了!


上一篇
機率 - 再探Curve Fitting
下一篇
線性模型 - 貝氏回歸與預測分佈
系列文
機器學習你也可以 - 文組帶你手把手實做機器學習聖經30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言