【機器學習】算法原理詳細推導與實現(一):線性迴歸

【機器學習】算法原理詳細推導與實現(一):線性迴歸

今天咱們這裏要講第一個有監督學習算法,他能夠用於一個迴歸任務,這個算法叫作 線性迴歸算法

房價預測

假設存在以下 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 個訓練樣本spa

在監督學習中,咱們通常會這樣作:設計

  1. 首先找到一個訓練集合
  2. 提供樣本 m 給算法構建學習函數
  3. 算法會生成一個學習函數,用 \(h(x)\) 表示
  4. 給學習函數提供足夠的樣本$x$,由此輸出結果$y$

學習函數3d

graph TD A[訓練集合]--"樣本m"-->B[學習函數] B[學習函數]--"生成"-->C["h(x)"]

訓練函數code

graph LR A[輸入]--"面積(m^2)"-->B["h(x)"] B["h(x)"]--"價格(萬元)"-->C[輸出]

爲了設計學習算法(學習函數),假設存在以下函數:blog

\[h(x)=\theta_0+\theta_1x \]

其中 \(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$表示房子的房間(個),這是學習函數就變成了:

\[h(x)=\theta_0+\theta_1x_1+\theta_2x_2=h_\theta(x) \]

$\theta$被稱爲參數,決定函數中每一個特徵$x$的影響力(權重)。\(h_\theta(x)\) 爲參數爲 \(\theta\) 輸入變量爲$x$的學習函數。若是令$x_0=1$,那麼上述方程能夠用求和方式寫出,也能夠轉化爲向量方式表示:

\[\begin{split} h_\theta(x)&=\theta_0x_0+\theta_1x_1+\theta_2x_2 \\ &=\sum^2_{i=0}{\theta_ix_i} \\ &=\theta^Tx \\ \end{split} \]

假設存在$m$個特徵$x$,那麼上述公式求和能夠改爲:

\[\begin{split} h_\theta(x)&=\sum^m_{i=0}{\theta_ix_i} \\ &=\theta^Tx \\ \end{split} \]

訓練參數

在擁有足夠多的訓練數據,例如上面的房價數據,怎麼選擇(學習)出參數$\theta$出來?一個合理的方式是使學習函數$h_\theta(x)$ 學習出來的預測值無限接近實際房價值 \(y\)。假設單個樣本偏差表示爲:

\[j(\theta)=\frac{1}{2}(h_\theta(x^{(i)})-y^{(i)})^2 \]

咱們把 \(j(\theta)\) 叫作單個樣本的偏差。至於爲何前面要乘$\frac{1}{2}$,是爲了後面計算方便。

爲了表示二者之間的接近程度,咱們能夠用訓練數據中全部樣本的偏差的和,因此定義了 損失函數 爲:

\[\begin{split} J(\theta)&=j_1(\theta)+j_2(\theta)+...+j_m(\theta) \\ &=\frac{1}{2}\sum^m_{i=1}{(h_\theta(x^{(i)})-y^{(i)})^2} \\ \end{split} \]

而最終的目的是爲了使偏差和 \(min(J(\theta))\) 最小,這裏會使用一個搜索算法來選取 \(\theta\) 使其偏差和無限逼近 \(J(\theta)\) 最小,其流程是:

  1. 初始化一組向量 \(\vec{\theta}=\vec{0}\)
  2. 不斷改變 \(\theta\) 的值使其 \(J(\theta)\) 不斷減少
  3. 直到取得 \(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:=\theta_j-\alpha\frac{\partial J(\theta)}{\partial\theta_j}\tag{1} \]

上面公式表明:\(\theta_j\) 每次都按照必定的 學習速率 \(\alpha\) 搜索使偏差和 \(J(\theta)\) 降低最快的方向更新自身的值。而 \(\frac{\partial J(\theta)}{\partial\theta_j}\)\(J(\theta)\) 的偏導值,求偏導獲得極值便是降低最快的方向。假設在房價的例子中,只存在一組訓練數據 \((x,y)\),那麼能夠推導以下公式:

\[\begin{split} \frac{\partial J(\theta)}{\partial\theta_j}&=\frac{\partial}{\partial\theta_j}\frac{1}{2}(h_{\theta}(x)-y)^2 \\ &=2\frac{1}{2}(h_{\theta}(x)-y)\frac{\partial}{\partial\theta_j}(h_{\theta}(x)-y) \\ &=(h_{\theta}(x)-y)\frac{\partial}{\partial\theta_j}(\sum^m_{i=0}{\theta_ix_i}-y) \\ &=(h_{\theta}(x)-y)\frac{\partial}{\partial\theta_j}(\theta_0x_0+\theta_1x_1+...+\theta_mx_m-y) \\ &=(h_{\theta}(x)-y)x_j \\ \end{split}\tag{2} \]

結合 \((1)(2)\) 能夠獲得:

\[\theta_j:=\theta_j-\alpha(h_{\theta}(x)-y)x_j\tag{3} \]

對於存在 \(m\) 個訓練樣本,\((1)\) 轉化爲:

\[\theta_j:=\theta_j-\sum^m_{i=1}\alpha(h_{\theta}(x^{(i)})-y^{(i)})x_j\tag{4} \]

學習速率 \(\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

數據和代碼下載請關注公衆號【 機器學習和大數據挖掘 】,後臺回覆【 機器學習 】便可獲取

相關文章
相關標籤/搜索