機器學習之線性迴歸:算法兌現爲python代碼

前面三天推送機器學習線性迴歸算法之最小二乘法,從假設到原理,詳細分析了直接求解和梯度下降兩種算法,接下來手動編寫python代碼實現線性迴歸的算法吧。

1 數據預處理

在拿到一個數據集後,往往需要經過漫長的預處理過程,不要忽視這個看似與建立模型,求解模型無關的步驟,它其實非常重要的,爲後續工作做好準備的一步。現在這節的重點不是在論述預處理的方法,所以在此不詳細介紹預處理的過程,而是重點例子模擬線性迴歸最小二乘法的兩個求解方法。

獲得了數據集後,經過預處理後得到的數據前10條展示如下,其中第一列爲房屋的面積,第二列爲房屋使用年限,第三列爲房屋的價值,是標籤值,這些值都已經經過預處理了。

       房屋面積        使用年限           價值
       [[ 0.35291809,  0.16468428,  0.35774628],
       [-0.55106013, -0.10981663,  0.25468008],
       [-0.65439632, -0.71406955,  0.1061582 ],
       [-0.19790689,  0.61536205,  0.43122894],
       [-0.00171825,  0.66827656,  0.44198075],
       [-0.2739687 , -1.16342739,  0.01195186],
       [ 0.11592071, -0.18320789,  0.29397728],
       [-0.02707248, -0.53269863,  0.21784183],
       [ 0.7321352 ,  0.27868019,  0.42643361],
       [-0.76680149, -0.89838545,  0.06411818]]

下面用直接求法和梯度下降法求解線性迴歸。

首先介紹下使用的庫:
'導入numpy庫'
import numpy as np
'導入pyplot'
import matplotlib.pyplot as plt
'導入時間模塊'
import time

本次模擬取數據集的前100條數據進行迭代計算,即 m = 100 。
做一個偏移量和2個特徵的組合,這樣與前面推送的理論部分銜接在一起,組合的代碼
如下所示:

'偏移量 b shape=(100,1)'
b = np.array([1])
b=b.repeat(100)
'將偏移量與2個特徵值組合 shape = (100,3)'
X = np.column_stack((b,X))

2 直接求解參數

我們知道當我們建立線性迴歸的模型時,因爲是線性的,並且誤差項滿足高斯分佈,此時藉助最大似然估計可以直接拿到權重參數的計算公式,如果想看下理論部分,請參考 直接求解 :

這裏寫圖片描述

'這是一個求矩陣的逆所用到的模塊'
from numpy.linalg import linalg as la
xtx = X.transpose().dot(X)
xtx = la.inv(xtx)
'直接求出參數'
theta = xtx.dot(X.transpose()).dot(y)

這個解法很簡單,直接套用公式,求出權重參數如下:

array([0.29348374, 0.10224818, 0.19596799])

即偏移量爲 0.29,第一個特徵的權重參數爲0.10,第二個特徵的權重參數爲0.195 。
下面用梯度下降法求解,這纔是我們論述的重點,這個思路與機器學習的其他算法,比如邏輯迴歸等思路是一致的,因此有必要好好研究下。

3 梯度下降求參數

梯度下降的詳細介紹,請參考梯度下降求解權重參數部分,下面我們論述如何由理論兌現爲代碼。
首先列舉梯度下降的思路步驟,採取線性迴歸模型,求出代價函數,進而求出梯度,求偏導是重要的一步,然後設定一個學習率迭代參數,當與前一時步的代價函數與當前的代價函數的差小於閾值時,計算結束,如下思路:

 'model' 建立的線性迴歸模型
'cost' 代價函數
'gradient'  梯度公式
'theta update'  參數更新公式
'stop stratege'  迭代停止策略:代價函數小於閾值法

下面分別寫出以上五步的具體實現代碼,

'model'
def model(theta,X):
    theta = np.array(theta)
    return X.dot(theta)
'cost'
def cost(m,theta,X,y):
    'print(theta)'
    ele = y - model(theta,X)
    item = ele**2
    item_sum = np.sum(item)
    return item_sum/2/m
'gradient'
def gradient(m,theta,X,y,cols):
    grad_theta = []
    for j in range(cols):
        grad = (y-model(theta,X)).dot(X[:,j])
        grad_sum = np.sum(grad)    
        grad_theta.append(-grad_sum/m)
    return np.array(grad_theta)
'theta update'
def theta_update(grad_theta,theta,sigma):
    return theta - sigma * grad_theta
'stop stratege'
def stop_stratege(cost,cost_update,threshold):
    return cost-cost_update < threshold
'OLS algorithm'
def OLS(X,y,threshold):
    start = time.clock()
    '樣本個數'
    m=100
    '設置權重參數的初始值'
    theta = [0,0,0]
    '迭代步數'
    iters = 0;
    '記錄代價函數的值'
    cost_record=[]
    '學習率'
    sigma = 0.0001
    cost_val = cost(m,theta,X,y)
    cost_record.append(cost_val)
    while True:
        grad = gradient(m,theta,X,y,3)
        '參數更新'
        theta = theta_update(grad,theta,sigma)
        cost_update = cost(m,theta,X,y)
        if stop_stratege(cost_val,cost_update,threshold):
            break
        iters=iters+1
        cost_val = cost_update
        cost_record.append(cost_val)
    end = time.clock()
    print("OLS convergence duration: %f s" % (end - start))
    return cost_record, iters,theta

結果顯示經過,OLS梯度下降經過如下時間得到初步收斂,OLS convergence duration: 7.456927 s,經過3萬多個時步迭代,每個時步計算代價函數的取值,如下圖所示:

這裏寫圖片描述
收斂時,得到的權重參數爲:

array([ 0.29921652,  0.09754371,  0.1867609 ])   

可以看到梯度下降得到的權重參數與直接求出法得出的基本相似,這其中的誤差是因爲沒有進一步再迭代。

4 總結

以上就是最小二乘法的兩種解法的代碼實現,至此我們已經將線性迴歸算法的最基本的OLS從理論,假設,到現在的代碼兌現都闡述完了。讓我們看一下遠邊的大海,和巍峨的高山,放鬆一下吧!


這裏寫圖片描述

然而,有些數據集的某兩列或多列存在強相關性,當面對這樣的數據集,OLS還能勝任嗎? 如果不能勝任,這其中的原因又是什麼呢?

請看明天的推送,OLS算法的缺陷及原理。

歡迎關注「 算法channel 」

交流思想,注重分析,看重過程,包含但不限於:經典算法,機器學習,深度學習,LeetCode 題解,Kaggle 實戰,英語沙龍,定期邀請專家發推。期待您的到來!

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章