【機器學習】算法原理詳細推導與實現(一):線性回歸
今天我們這里要講第一個有監督學習算法,他可以用於一個回歸任務,這個算法叫做 線性回歸
房價預測
假設存在如下 m
組房價數據:
面積(m^2) | 價格(萬元) |
---|---|
82.35 | 193 |
65.00 | 213 |
114.20 | 255 |
75.08 | 128 |
75.84 | 223 |
... | ... |
通過上面的數據,可以做出如下一個圖。橫坐標是 面積(m^2)
,縱坐標是 價格(萬元)
:
那么問題來了,給你這樣一組數據,或者給你這樣一個訓練數據的集合,能否預測房屋的面積大小和房價之間的關系?
構建函數
存在如下符號假設:
m 為訓練數據
x 為輸入特征,即房子的大小
y 為輸出結果,即房子的價格
(x, y) 為一個樣本,即表格中一行代表一個訓練樣本
\((x^{(i)}, y^{(i)})\) 為第 i 個訓練樣本
在監督學習中,我們一般會這樣做:
- 首先找到一個訓練集合
- 提供樣本 m 給算法構建學習函數
- 算法會生成一個學習函數,用 \(h(x)\) 表示
- 給學習函數提供足夠的樣本\(x\),由此輸出結果\(y\)
學習函數
訓練函數
為了設計學習算法(學習函數),假設存在如下函數:
其中 \(x\) 是一個輸入函數,這里代表輸入的面積(m^2),\(h(x)\) 是一個輸出函數,這里代表 輸出的價格(萬元),\(\theta\) 是函數的參數,是需要根據樣本學習的參數。對於如上的學習函數只是一個簡單的二元一次方程,只需要兩組樣本 \((x_0,y_0),(x_1,y_1)\) 就能將 \(\theta_0,\theta_1\) 學習出來,這是一個很簡單的函數,但是這樣在實際情況中並非很合理。
但是影響房子價格的因素不僅僅是房子的大小。除了房子的大小之外,假設這里還知道每個房子的房間數量:
面積(m^2) | 房間(個) | 價格(萬元) |
---|---|---|
82.35 | 2 | 193 |
65.00 | 2 | 213 |
114.20 | 3 | 255 |
75.08 | 2 | 128 |
75.84 | 2 | 223 |
... | ... | ... |
那么我們的訓練集合將有第二個特征,\(x_1\)表示房子的面積(m^2),\(x_2\)表示房子的房間(個),這是學習函數就變成了:
\(\theta\)被稱為參數,決定函數中每個特征\(x\)的影響力(權重)。\(h_\theta(x)\) 為參數為 \(\theta\) 輸入變量為\(x\)的學習函數。如果令\(x_0=1\),那么上述方程可以用求和方式寫出,也可以轉化為向量方式表示:
假設存在\(m\)個特征\(x\),那么上述公式求和可以改成:
訓練參數
在擁有足夠多的訓練數據,例如上面的房價數據,怎么選擇(學習)出參數\(\theta\)出來?一個合理的方式是使學習函數\(h_\theta(x)\) 學習出來的預測值無限接近實際房價值 \(y\)。假設單個樣本誤差表示為:
我們把 \(j(\theta)\) 叫做單個樣本的誤差。至於為什么前面要乘\(\frac{1}{2}\),是為了后面計算方便。
為了表示兩者之間的接近程度,我們可以用訓練數據中所有樣本的誤差的和,所以定義了 損失函數 為:
而最終的目的是為了使誤差和 \(min(J(\theta))\) 最小,這里會使用一個搜索算法來選取 \(\theta\) 使其誤差和無限逼近 \(J(\theta)\) 最小,其流程是:
- 初始化一組向量 \(\vec{\theta}=\vec{0}\)
- 不斷改變 \(\theta\) 的值使其 \(J(\theta)\) 不斷減小
- 直到取得 \(J(\theta)\) 最小值,活得得到最優的參數向量 \(\vec{\theta}\)
該搜索算法為 梯度下降,算法的思想是這樣的,下圖看到顯示了一個圖形和坐標軸,圖像的高度表示誤差和 \(J(\theta)\),而下面的兩條坐標表示不同的參數 \(\theta\) ,這里為了方便看圖只是顯示了 \(\theta_0\) 和 \(\theta_1\) ,即變化參數 \(\theta_0\) 和 \(\theta_1\) 使其誤差和 \(J(\theta)\) 在最低點,即最小值。
首先隨機選取一個點 \(\vec{\theta}\) ,它可能是 \(\vec{0}\) ,也可能是隨機的其他向量。最開始的 + 字符號表示開始,搜索使其 \(J(\theta)\) 下降速度最快的方向,然后邁出一步。到了新的位置后,再次搜索下降速度最快的方向,然后一步一步搜索下降,梯度下降算法是這樣工作的:
梯度下降的核心就在於每次更新 \(\theta\) 的值,公式為:
上面公式代表:\(\theta_j\) 每次都按照一定的 學習速率 \(\alpha\) 搜索使誤差和 \(J(\theta)\) 下降最快的方向更新自身的值。而 \(\frac{\partial J(\theta)}{\partial\theta_j}\) 是 \(J(\theta)\) 的偏導值,求偏導得到極值即是下降最快的方向。假設在房價的例子中,只存在一組訓練數據 \((x,y)\),那么可以推導如下公式:
結合 \((1)(2)\) 可以得到:
對於存在 \(m\) 個訓練樣本,\((1)\) 轉化為:
學習速率 \(\alpha\) 是梯度下降的速率,\(\alpha\) 越大函數收斂得越快,\(J(\theta)\) 可能會遠離最小值,精度越差;\(\alpha\) 越小函數收斂得越慢,\(J(\theta)\) 可能會靠近最小值,精度越高。下面就是下降尋找最小值的過程,在右圖 \(J(\theta)\) 越來越小的時候,左邊的線性回歸越來准:
代碼
選取得到的 150條二手房 數據進行預測和訓練,擬合情況如下:
計算損失函數:
# 損失函數
def computeCost(X, y, theta):
inner = np.power(((X * theta.T) - y), 2)
return np.sum(inner) / (2 * len(X))
梯度下降函數為:
# 梯度下降函數
def gradientDescent(X, y, theta, alpha, iters):
temp = np.matrix(np.zeros(theta.shape))
parameters = int(theta.ravel().shape[1])
cost = np.zeros(iters)
for i in range(iters):
error = (X * theta.T) - y
for j in range(parameters):
term = np.multiply(error, X[:, j])
temp[0, j] = theta[0, j] - ((alpha / len(X)) * np.sum(term))
theta = temp
cost[i] = computeCost(X, y, theta)
return theta, cost
訓練迭代1000次后得到參數 \(\theta\):
# 訓練函數
def train_function():
X, y, theta = get_training_dataset()
# 有多少個x就生成多少個theta
theta = np.matrix(np.zeros(X.shape[-1]))
# 查看初始誤差
# first_cost=computeCost(X, y, theta)
# print(first_cost)
# 設置參數和步長
alpha = 0.01
iters = 1000
# 訓練得到theta和每一次訓練的誤差
g, cost = gradientDescent(X, y, theta, alpha, iters)
computeCost(X, y, g)
return g, cost
數據和代碼下載請關注公眾號【 機器學習和大數據挖掘 】,后台回復【 機器學習 】即可獲取