線性迴歸算法擬合數據原理分析以及源代碼解析

線性迴歸算法擬合數據原理分析以及源代碼解析

前言

前面的博客講的都是分類問題,接下來的幾篇博客,會着重於迴歸,傾向於對數據進行預測。大家是不是一聽到預測就眼睛一閃,是不是可以用來預測股票漲跌、彩票號碼什麼的!我只能告訴你有人做出來的股票預測軟件,而且正確率挺可觀的。作爲一個學習者,彆着急,千里之行始於足下。踏踏實實的從原理到代碼,一步一腳印。

項目源碼已上傳至GitHubb上,有需要的自取:項目地址
如果項目對你有些許幫助,不要忘記給個小⭐⭐

線性迴歸原理以及公式

1. 簡單知識回顧

二元一次方程式大家都已經非常熟悉了,下面這個是他的一般式【式子1】:

img

不過通常呢,我們會將這個一般式中的y單獨拿到等式一側,其餘的放在另一側【式子2】:

img

注意,這兩個式子的a和b不是一回事,各自表示對應式子的係數或者常數。

我們都知道,對於式子2來講,決定這個式子在圖像中的顯示位置的是係數a,和常數b。

timg

對於圖上這張圖來說,紅色這條直線對應的二元一次方程式子2的係數a爲2,b爲-1.藍色這條線對應的式子2的係數a爲-1,b爲5.

也就是說,只要給出a和b的值,那麼,我就能畫出這樣一條直線。

那這跟我們的算法有什麼關係呢?

說到的,我們就是針對數據,找出這樣的a和b,以此得出一條直線方程。

本次呢,主要是針對單屬性數據量做算法介紹,針對多屬性值數據來講, 道理相同,無非就是將數據2的係數a和變量x變成向量,同時對於常量b,我們也可以寫道向量裏。也就相當於下面公式:

img

img

這裏的n表述數據的屬性個數,m表示數據量。

2. 最小二乘法解二元一次方程

首先我們得先了解一下最小二乘法的原理,先看一下下面這張圖:

u=141283350,3911788756&fm=26&gp=0

圖中淺藍色的點是我們真實數據點的位置,黃色點是預測的數據點,中間這個綠色直線就是我們所

擬合出來的直線。預測點和真實數據點之間的距離,我們稱之爲誤差。我們假設這條直線方程:

img

那麼,針對這個誤差,我們使用誤差平方和來表示(其好處是能夠解決正負值相互抵消問題):

img

爲了達到更好的擬合效果,我們需要這個誤差平方和達到最小。理想情況下,所有數據點均在擬合直線上,那麼此時,這個誤差平方和爲0.

在代碼方面,我們通常會將累積求和公式,使用向量的形式來進行表示,下面,我們對上面的公式進行向量化書寫:

img

和普通的二次方程求解一樣,我們對α進行求導,並且令導數爲0,即可得出α的取值,使得上述式子達到最小值:

img

這裏能進行合併的原因是 Yt X α 是一個標量,也就是這個結果是一個數,所以它的轉置等於其本身

接着對其進行求導:

img

我們令其等於0,可求出α的求解公式:

img

向量求導這一塊,也是我薄弱的環節,文末會給出一些參考資料,大家可以去深入瞭解一下,一起學習!

源代碼實戰講解

下面開始我們的代碼實戰:

1. 加載數據

首先我們先看一下文本數據的屬性有哪些

image-20200624113916873

圖中最座標紅色方塊是數據的常數1,用來求解常量,對應着就是我們前面公式的b。

中間黃色的是我們的屬性值α1.

最右邊白色的是我們數據的值,也就是y值。

我們來看一下數據的分佈情況:

image-20200624115800582

def LoadData(filename):
    dataMat = []
    labelMat = []
    with open(filename) as f:
        numFeat = len(f.readline().split('\t'))-1
        for line in f.readlines():
            lineArr = []
            curLine = line.strip().split('\t')
            for i in range(numFeat):
               lineArr.append(float(curLine[i]))
            dataMat.append(lineArr)
            labelMat.append(float(curLine[-1]))
        return dataMat,labelMat
  1. 首先從文件中加載進來數據
  2. 獲取數據的屬性個數numFeat
  3. 將數據的屬性值和y值分別放入到dataMat列表和labelMat列表中

2. 計算α的值

def standRegres(xArr,yArr):
    xMat = np.mat(xArr);yMat = np.mat(yArr).T#由於原來形狀是(1,199),所以這裏需要轉置
    print("yMat",yMat.shape)#yMat (199, 1)
    xTx = xMat.T*xMat
    if np.linalg.det(xTx)==0.0:
        print("false")
        return
    print("xtx.shape",xTx.shape)#形狀:(2,2)
    print("xTx.I",xTx.I)#矩陣的逆
    print("xMat.T",(xMat.T).shape)
    ws = xTx.I*(xMat.T*yMat)#(xMat.T*yMat)形狀爲(2,1)
    return ws
  1. 直接使用我們前面推導的公式,就能夠直接得出α的值,對應代碼中的,就是ws。
  2. xTx.I 是對xTx.I求逆
  3. xMat.T是求其轉置。

3. 原數據以及擬合直線顯示

def showdata(xArr,yMat,ws):
    fig = plt.figure()
    ax = fig.add_subplot(111)
    xCopy = xArr.copy()
    xCopy.sort(0)
    yHat = xCopy*ws
  ax.scatter(xArr[:,1].flatten().tolist(),yMat.T[:,0].flatten().tolist(),s=20,alpha=0.5)
    ax.plot(xCopy[:,1],yHat)
    plt.show()
  1. 具體如何畫圖,不清楚的可以看一下這個專欄matplotlib畫圖
  2. 我們需要先對x進行排序,否則擬合直線無法正常顯示

image-20200624115637613

圖中的直線就是我們所擬合的直線。

模型評價準則

任何一個模型都有適合它的評價準則,來判斷這個模型的優良程度,那麼,對於這個模型來說,我們使用的評價準則是Pearson相關分析,具體參考博客python數據分析-相關分析

總的就是用來評價兩個變量之間的相關性程度,如果值接近1,表示強相關,如果接近於0,表示基本無關。

def pearsoncor(yHat,yMat):
    result = np.corrcoef(yHat.T,yMat)#相關係數分析。越接近1,表示相似度越高
    print("pearson-result:",result)

我們使用預測值和真實值進行相關係數分析,我們來看一下結果:

image-20200624120413501

正對角線一定都是1,因爲和自己的相關係數值一定爲1

反對角線上的值就是預測值和真實值的相關係數。我們看到相關係數爲0.98,表示我們擬合的直線與數據整體狀態還是非常一致的。

總結

這裏我們主要分析了一下線性迴歸對數據擬合的算法原理和代碼,但是呢,會出現一個問題,就是會出現欠擬合。什麼意思呢?就是擬合的直線無法很好的表現真實數據。那有沒有改進方式呢,我們下一篇博客會講到一種改進方法:局部加權線性迴歸

參考資料

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