將均方誤差應用到線性迴歸問題中
首先我們先回顧頻率派的解決方法,即常規解法——利用最小二乘法解決問題。損失函數採用均方誤差函數。
關於模型容量問題:
在《深度學習》中專門指出,模型的容量也是一個需要用戶指定的超參數,即擬合的多項式次數。此處爲了簡化操作,暫定爲一次多項式。
解決代碼如下:
import numpy as np
x = np.random.randn(10) + 5
# 初始參數
k = 2.
b = 6.
y = x * k + b
# 以均方誤差形式解決線性迴歸
k_hat = 1
b_hat = 0
alpha = 0.01
for i in range(10000):
# 採用梯度下降法進行迭代,更新參數k、偏置項b
y_ = k_hat * x + b_hat
# 均方誤差函數
loss = 1 / 2 * (y_ - y) * (y_ - y)
grand = (y_ - y) * x
if i % 1000 == 0:
print("loss:" + str(np.mean(loss)))
k_hat -= alpha * np.mean(grand)
b_hat -= alpha * np.mean(y_ - y)
print('result:')
print(k_hat, b_hat)
輸出結果如下:
loss:58.678592587395315
loss:0.29681809805254167
loss:0.11683356934778104
loss:0.04598804121481371
loss:0.018101817367916613
loss:0.007125239157084194
loss:0.0028046373473878386
loss:0.0011039616322971802
loss:0.00043454148776818417
loss:0.0001710442637384755
result:
2.0105150388524025 5.9472884150823475
可以看出模型最終擬合程度較好,損失不斷下降,最終的參數與初試參數差別不大。
將最大似然估計應用到迴歸問題上
最小二乘法是將線性迴歸作爲學習從輸入x映射到輸出的算法。現在,我們希望模型能夠得到P(yx),而不是得到一個單獨的預測。
我們定義P(yx,w)=N(y;(x;w),),函數(x;k)預測高斯的均值
- 首先我們指定一個方差
- 其次我們需要列出似然函數
- 最後求導,做最大似然估計
ps:在和用最大似然估計做解決分類問題時,有一些差別。分類問題中,我們不需要指定固定的方差。例如在邏輯迴歸問題中,我們僅需要通過非線性映射將概率整合進分類任務中即可。
似然函數定義如下:
最大化該似然函數,等價於最小化均方誤差函數,該方法其實將得到和最小二乘法類似的解法。
貝葉斯線性迴歸
在貝葉斯學派的觀點中,我們將參數w視爲一個隨機變量。我們要先確定好w的先驗分佈。對比於最大似然估計法將P(yx)視爲正態分佈求解問題,在貝葉斯線性迴歸下,我們將w的先驗分佈視爲正態分佈,從而進一步確定其後驗分佈。
貝葉斯的基本模型如下:其中I是單位矩陣。
爲什麼y服從的正態分佈均值爲?
- 因爲均值一旦爲,那麼最終的表達式將會和均值誤差成正比,符合我們前面在極大似然估計處的推理。
爲什麼將的先驗分佈指定爲正態分佈?
- 因爲爲了令具有一定的廣泛性,所以指定一個高熵的分佈。
定義P(w)=N(w;,),這樣我們就確定了w的先驗分佈,雖然該分佈可能會出錯(在樣本較少的情況下),但是在理論上如果樣本點無限多那麼我們可以得出無限收斂於正確參數的估計模型,這也是貝葉斯的基本思想。
貝葉斯公式如下:
在該式子中,分母並不是我們需要關注的點,因爲對於樣本來說分母的值相同,且在後期計算梯度時,將會按常數處理,故我們僅僅研究分子。所以可以得出來參數w的後驗分佈與成正比。
接下來我們通過最大後驗估計(MAP),即最大化從而得到w的最優解,直觀的理解便是令我們後驗概率最大化。求解過程類似於最大似然估計依舊需要取對數,構建似然函數。
很有趣,我們最終得到的式子竟然是均方誤差與正則懲罰項的和(差)。這也回到了一開始的最小二乘法。
MAP爲我們提供了對正則懲罰項的直觀理解!所以我們可以得出結論,利用貝葉斯方法解決線性迴歸問題,可以有效的減少模型的過擬合程度。
由於上面的例子過於簡單,維度爲1。所以爲了更好地舉例,我們創建具有兩個特徵值(維度爲2)的樣本數據,在計算過程中將牽涉到矩陣運算。
解決代碼如下:
# X代表個有10個樣本值,每個樣本有兩個特徵值
# X隨機生成
X = np.random.random([10, 2]) * 10+ 2
W = np.array([
[1],
[2]
])
B = 1
Y = np.dot(X, W) + B
# 初始化
k_hat = np.array([
[0.6],
[0.5]
])
b_hat = 0.5
# 以貝葉斯解決線性迴歸
# 多維情況下
alpha = 0.001
lamt = 0.01 # 代表正則化懲罰程度
# 迭代一千次
for i in range(1000):
y_ = np.dot(X, k_hat) + b_hat
# 帶正則化懲罰項的損失函數
loss = 1 / 2 * np.dot((y_ - Y).T, (y_ - Y)) + lamt * np.dot(k_hat.T, k_hat)
grand = np.dot(X.T, (y_ - Y)) + lamt * k_hat
if i % 100 == 0:
print("loss:" + str(np.mean(loss)))
k_hat -= alpha * (grand)
b_hat -= alpha * (y_ - Y)
print('result:')
print(k_hat)
輸出結果如下:
loss:0.052098026507421846
loss:0.0520601388908503
loss:0.052030256081297147
loss:0.0520057579403434
loss:0.05198566785068535
loss:0.05196918640742312
loss:0.05195565917870616
loss:0.051944550414666016
loss:0.051935421524299995
loss:0.05192791345559716
result:
[[1.05673593]
[2.01810083]]
可以看出最終擬合的權重參數k_hat與初始的W基本相同,且損失值不斷降低。