從零開始,用Python徒手寫線性回歸

2021-02-19 機器之心

選自towardsdatascience

作者:Kumud Lakara
機器之心編譯
編輯:小舟、澤南

先放下 Scikit-learn,我們來看一看真正的技術。

對於大多數數據科學家而言,線性回歸方法是他們進行統計學建模和預測分析任務的起點。這種方法已經存在了 200 多年,並得到了廣泛研究,但仍然是一個積極的研究領域。由於良好的可解釋性,線性回歸在商業數據上的用途十分廣泛。當然,在生物數據、工業數據等領域也不乏關於回歸分析的應用。另一方面,Python 已成為數據科學家首選的程式語言,能夠應用多種方法利用線性模型擬合大型數據集顯得尤為重要。如果你剛剛邁入機器學習的大門,那麼使用 Python 從零開始對整個線性回歸算法進行編碼是一次很有意義的嘗試,讓我們來看看怎麼做吧。機器學習問題的第一步是獲取數據,沒有可以學習的數據就沒有機器學習。本文將使用非常常規的線性回歸數據集——房價預測數據集。這是一個包含俄勒岡州波特蘭市房價的簡單數據集。該數據集中第一列是房屋面積(以平方英尺為單位),第二列是臥室的數量,第三列是房屋價格。該數據集中有多個特徵(例如,house_size 和房間數),因此我們將研究多元線性回歸,標籤 (y) 是我們將要預測的房價。
def load_data(filename):    df = pd.read_csv(filename, sep=",", index_col=False)    df.columns = ["housesize", "rooms", "price"]    data = np.array(df, dtype=float)    plot_data(data[:,:2], data[:, -1])    normalize(data)    return data[:,:2], data[:, -1]

我們稍後將調用上述函數來加載數據集。此函數返回 x 和 y。上述代碼不僅加載數據,還對數據執行歸一化處理並繪製數據點。在查看數據圖之前,我們首先了解上述代碼中的 normalize(data)。查看原始數據集後,你會發現第二列數據的值(房間數量)比第一列(即房屋面積)小得多。該模型不會將此數據評估為房間數量或房屋面積,對於模型來說,它們只是一些數字。機器學習模型中某些列(或特徵)的數值比其他列高可能會造成不想要的偏差,還可能導致方差和數學均值的不平衡。出於這些原因,也為了簡化工作,我們建議先對特徵進行縮放或歸一化,使其位於同一範圍內(例如 [-1,1] 或 [0,1]),這會讓訓練容易許多。因此我們將使用特徵歸一化,其數學表達如下:

Z = (x — μ) / σ

μ : mean

σ : standard deviation

其中 z 是歸一化特徵,x 是非歸一化特徵。有了歸一化公式,我們就可以為歸一化創建一個函數:
def normalize(data):    for i in range(0,data.shape[1]-1):        data[:,i] = ((data[:,i] - np.mean(data[:,i]))/np.std(data[:, i]))

上述代碼遍歷每一列,並使用每一列中所有數據元素的均值和標準差對其執行歸一化。在對線性回歸模型進行編碼之前,我們需要先問「為什麼」。為什麼要使用線性回歸解決這個問題?這是一個非常有用的問題,在寫任何具體代碼之前,你都應該非常清楚要使用哪種算法,以及在給定數據集和待解決問題的情況下,這是否真的是最佳選擇。我們可以通過繪製圖像來證明對當前數據集使用線性回歸有效的原因。為此,我們在上面的 load_data 中調用了 plot_data 函數,現在我們來定義一下 plot_data 函數:
def plot_data(x, y):    plt.xlabel('house size')    plt.ylabel('price')    plt.plot(x[:,0], y, 'bo')    plt.show()

如上圖所示,我們可以粗略地擬合一條線。這意味著使用線性近似能夠做出較為準確的預測,因此可以採用線性回歸。首先我們需要定義假設函數,稍後我們將使用它來計算代價。對於線性回歸,假設是:

但數據集中只有 2 個特徵,因此對於當前問題,假設是:

其中 x1 和 x2 是兩個特徵(即房屋面積和房間數量)。然後編寫一個返回該假設的簡單 Python 函數:
def h(x,theta):    return np.matmul(x, theta)

def cost_function(x, y, theta):    return ((h(x, theta)-y).T@(h(x, theta)-y))/(2*y.shape[0])

到目前為止,我們定義的所有 Python 函數都與上述線性回歸的數學意義完全相同。接下來我們需要將代價最小化,這就要用到梯度下降。梯度下降是一種優化算法,旨在調整參數以最小化代價函數。

因此,我們將代價函數的導數乘以學習率(α),然後用參數(θ)的當前值減去它,獲得新的更新參數(θ)。
def gradient_descent(x, y, theta, learning_rate=0.1, num_epochs=10):    m = x.shape[0]    J_all = []
for _ in range(num_epochs): h_x = h(x, theta) cost_ = (1/m)*(x.T@(h_x - y)) theta = theta - (learning_rate)*cost_ J_all.append(cost_function(x, y, theta))
return theta, J_all

gradient_descent 函數返回 theta 和 J_all。theta 顯然是參數向量,其中包含假設的θs 值,J_all 是一個列表,包含每個 epoch 後的代價函數。J_all 變量並非必不可少,但它有助於更好地分析模型。
x,y = load_data("house_price_data.txt")y = np.reshape(y, (46,1))x = np.hstack((np.ones((x.shape[0],1)), x))theta = np.zeros((x.shape[1], 1))learning_rate = 0.1num_epochs = 50theta, J_all = gradient_descent(x, y, theta, learning_rate, num_epochs)J = cost_function(x, y, theta)print("Cost:", J)print("Parameters:", theta)
#for testing and plotting cost n_epochs = []jplot = []count = 0for i in J_all: jplot.append(i[0][0]) n_epochs.append(count) count += 1jplot = np.array(jplot)n_epochs = np.array(n_epochs)plot_cost(jplot, n_epochs)
test(theta, [1600, 2])

首先調用 load_data 函數載入 x 和 y 值。x 值包含訓練樣本,y 值包含標籤(在這裡就是房屋的價格)。你肯定注意到了,在整個代碼中,我們一直使用矩陣乘法的方式來表達所需。例如為了得到假設,我們必須將每個參數(θ)與每個特徵向量(x)相乘。我們可以使用 for 循環,遍歷每個樣本,每次都執行一次乘法,但如果訓練的樣本過多,這可能不是最高效的方法。在這裡更有效的方式是使用矩陣乘法。本文所用的數據集具備兩個特徵:房屋面積和房間數,即我們有(2+1)三個參數。將假設看作圖形意義上的一條線,用這種方式來思考額外參數θ0,最終額外的θ0 也要使這條線符合要求。

現在我們有了三個參數和兩個特徵。這意味著θ或參數向量(1 維矩陣)的維數是 (3,1),但特徵向量的維度是 (46,2)。你肯定會注意到將這樣兩個矩陣相乘在數學上是不可能的。再看一遍我們的假設:

如果你仔細觀察的話,實際上這很直觀:如果在特徵向量 (x) {維度為 (46, 3)} 的開頭添加額外的一列,並且對 x 和 theta 執行矩陣乘法,將得出 hθ(x) 的方程。記住,在實際運行代碼來實現此功能時,不會像 hθ(x) 那樣返回表達式,而是返回該表達式求得的數學值。在上面的代碼中,x = np.hstack((np.ones((x.shape[0],1)), x)) 這一行在 x 開頭加入了額外一列,以備矩陣乘法需要。在這之後,我們用零初始化 theta 向量,當然你也可以用一些小隨機值來進行初始化。我們還指定了訓練學習率和 epoch 數。定義完所有超參數之後,我們就可以調用梯度下降函數,以返回所有代價函數的歷史記錄以及參數 theta 的最終向量。在這裡 theta 向量定義了最終的假設。你可能注意到,由梯度下降函數返回的 theta 向量的維度為 (3,1)。

所以我們需要三個θ,theta 向量的維度為 (3,1),因此 theta [0]、theta [1] 和 theta [2] 實際上分別為θ0、θ1 和 θ2。J_all 變量是所有代價函數的歷史記錄。你可以列印出 J_all 數組,來查看代價函數在梯度下降的每個 epoch 中逐漸減小的過程。

我們可以通過定義和調用 plot_cost 函數來繪製此圖,如下所示:
def plot_cost(J_all, num_epochs):    plt.xlabel('Epochs')    plt.ylabel('Cost')    plt.plot(num_epochs, J_all, 'm', linewidth = "5")    plt.show()

現在我們可以使用這些參數來找到標籤,例如給定房屋面積和房間數量時的房屋價格。現在你可以測試調用測試函數的代碼,該函數會將房屋面積、房間數量和 logistic 回歸模型返回的最終 theta 向量作為輸入,並輸出房屋價格。
def test(theta, x):    x[0] = (x[0] - mu[0])/std[0]    x[1] = (x[1] - mu[1])/std[1]
y = theta[0] + theta[1]*x[0] + theta[2]*x[1] print("Price of house:", y)

import numpy as npimport matplotlib.pyplot as pltimport pandas as pd
#variables to store mean and standard deviation for each featuremu = []std = []
def load_data(filename): df = pd.read_csv(filename, sep=",", index_col=False) df.columns = ["housesize", "rooms", "price"] data = np.array(df, dtype=float) plot_data(data[:,:2], data[:, -1]) normalize(data) return data[:,:2], data[:, -1]
def plot_data(x, y): plt.xlabel('house size') plt.ylabel('price') plt.plot(x[:,0], y, 'bo') plt.show()
def normalize(data): for i in range(0,data.shape[1]-1): data[:,i] = ((data[:,i] - np.mean(data[:,i]))/np.std(data[:, i])) mu.append(np.mean(data[:,i])) std.append(np.std(data[:, i]))

def h(x,theta): return np.matmul(x, theta)
def cost_function(x, y, theta): return ((h(x, theta)-y).T@(h(x, theta)-y))/(2*y.shape[0])
def gradient_descent(x, y, theta, learning_rate=0.1, num_epochs=10): m = x.shape[0] J_all = []
for _ in range(num_epochs): h_x = h(x, theta) cost_ = (1/m)*(x.T@(h_x - y)) theta = theta - (learning_rate)*cost_ J_all.append(cost_function(x, y, theta))
return theta, J_all
def plot_cost(J_all, num_epochs): plt.xlabel('Epochs') plt.ylabel('Cost') plt.plot(num_epochs, J_all, 'm', linewidth = "5") plt.show()
def test(theta, x): x[0] = (x[0] - mu[0])/std[0] x[1] = (x[1] - mu[1])/std[1]
y = theta[0] + theta[1]*x[0] + theta[2]*x[1] print("Price of house:", y)
x,y = load_data("house_price_data.txt")y = np.reshape(y, (46,1))x = np.hstack((np.ones((x.shape[0],1)), x))theta = np.zeros((x.shape[1], 1))learning_rate = 0.1num_epochs = 50theta, J_all = gradient_descent(x, y, theta, learning_rate, num_epochs)J = cost_function(x, y, theta)print("Cost:", J)print("Parameters:", theta)
#for testing and plotting cost n_epochs = []jplot = []count = 0for i in J_all: jplot.append(i[0][0]) n_epochs.append(count) count += 1jplot = np.array(jplot)n_epochs = np.array(n_epochs)plot_cost(jplot, n_epochs)
test(theta, [1600, 3])

現在你已經學會了從零開始成功編寫線性回歸模型。能夠理解和編寫整個算法並不是一件容易的事,你或許需要時不時地回看才能完全理解。但這些努力是值得的,線性回歸通常是人們學習機器學習算法的第一步,在這之後你可以選擇另一個適用於線性回歸處理的數據集,並嘗試剛寫好的算法。https://towardsdatascience.com/coding-linear-regression-from-scratch-c42ec079902AAAI 2021線上分享 | BERT模型蒸餾技術,阿里雲有新方法在阿里巴巴等機構合作、被AAAI 2021接收的論文《Learning to Augment for Data-Scarce Domain BERT Knowledge Distillation 》中,研究者們提出了一種跨域自動數據增強方法來為數據稀缺領域進行擴充,並在多個不同的任務上顯著優於最新的基準。
1月27日20:00,論文共同一作、阿里雲高級算法專家邱明輝為大家詳細解讀此研究。添加機器之心小助手(syncedai5),備註「AAAI」,進群一起看直播。

© THE END 

轉載請聯繫本公眾號獲得授權

投稿或尋求報導:content@jiqizhixin.com

相關焦點

  • 量化 | 從零開始學量化(五):用Python做回歸
    回歸作為數據分析中非常重要的一種方法,在量化中的應用也很多,從最簡單的因子中性化到估計因子收益率,以及整個Barra框架,都是以回歸為基礎,本文總結各種回歸方法以及python實現的代碼。,Xn與一個因變量Y關係的模型,首先從最簡單的OLS開始,變量假設如下回歸模型可以表示為同時線性回歸還必須滿足「BLUE
  • 從零開始學量化(五):用Python做回歸
    ,Xn與一個因變量Y關係的模型,首先從最簡單的OLS開始,變量假設如下回歸模型可以表示為同時線性回歸還必須滿足「BLUE」的假設,在這些假設下,回歸的目標是在已知X,Y的情況下估計回歸係數beta,OLS的思想是最小化殘差平方和,即
  • 利用python實現簡單的線性回歸
    用python實現簡單的線性回歸利用python實現簡單的線性回歸今天,我們將純粹使用python來實現最流行和最直接的回歸技術-簡單的線性回歸當我說純粹使用python。它指的是沒有使用任何python機器學習庫。當我說簡單的線性回歸,你在想什麼?讓我猜猜:當我說簡單線性回歸的時候,也許我以上的分析你都猜測過,也許上述假設在技術上是合理的。但有一個特別的理由稱之為簡單的線性回歸。首先,讓我們來了解為什麼我們稱之為簡單的線性回歸。然後我們可以開始我最喜歡的部分,在python中編寫簡單的線性回歸。
  • 從零開始學Python【22】--線性回歸診斷(第一部分)
    往期回顧從零開始學Python【21】--線性回歸(實戰部分)從零開始學Python【20】--線性回歸(理論部分
  • python線性回歸
    一.理論基礎1.回歸公式  對於單元的線性回歸,我們有:f(x) = kx + b 的方程(k代表權重,b代表截距)。
  • Python 機器學習:多元線性回歸
    python機器學習:線性回歸往下講,這篇文章要講解的多元線性回歸。1、什麼是多元線性回歸模型?當y值的影響因素不唯一時,採用多元線性回歸模型。例如商品的銷售額可能不電視廣告投入,收音機廣告投入,報紙廣告投入有關係,可以有 sales =β0+β1*TV+β2* radio+β3*newspaper.
  • python數據分析--回歸函數及線性回歸分析
    1.常見的回歸函數2.工具數據分析有很多成熟的工具可以使用,如R、python、此處我們選用python進行分析。首先,我們需要安裝並導入python數據分析常用的庫。__version__)3.線性回歸分析Y= aX + b + e ,e表示殘差。
  • python|線性回歸問題
    線性回歸是利用數理統計中回歸分析,來確定兩種或兩種以上變量間相互依賴的定量關係的一種統計分析方法。可以解釋為,利用線性回歸方程的最小平方函數對一個或多個自變量和因變量之間的關係進行數學建模。這種函數是一個或多個稱為回歸係數的模型參數的線性組合。
  • 線性回歸:簡單線性回歸詳解
    【導讀】本文是一篇專門介紹線性回歸的技術文章,討論了機器學習中線性回歸的技術細節。線性回歸核心思想是獲得最能夠擬合數據的直線。
  • 在 Python 中使用線性回歸預測數據
    這部分沒有實戰例子,不過我會教你怎麼去用線性回歸替換這些值。所以,讓我們投入編程吧(馬上)在動手之前,去把我以前的文章(Python Packages for Data Mining)中的程序包安裝了是個好主意。
  • Python環境下的8種簡單線性回歸算法
    另一方面,由於 Python 正在快速發展為數據科學家的首選程式語言,所以能夠意識到存在很多方法用線性模型擬合大型數據集,就顯得尤為重要。同樣重要的一點是,數據科學家需要從模型得到的結果中來評估與每個特徵相關的重要性。然而,在 Python 中是否只有一種方法來執行線性回歸分析呢?如果有多種方法,那我們應該如何選擇最有效的那個呢?
  • sklearn機器學習心得—線性回歸|粉絲投稿1
    ,也是重要的算法之一,基本上第一次接觸的機器學習算法就是線性回歸了。因為相對其他算法而言,我覺得線性回歸是相對比較容易的算法,從某種意義上來說,在學習函數的時候已經開始接觸線性回歸了,只不過那個時候並沒有涉及到誤差項,其實在中學的時候就有接觸了,學習的最小二乘法就是啦~~1).對於坐標系中給定的點,我們希望用一條線或是一個類似於:f(x)=θ0+θ1*x1+θ2*x2_...θn*xn 方程來擬合這寫數據點,這就是我們說的回歸了2).這次我們要用的是
  • Python 從零開始--入門篇
    從這篇文章開始我將分享 python 系列,從 ptyhon 的起始發展,到現在的方方面面, 從最基礎的語法開始,大家一起學習
  • Python 實戰多元線性回歸模型,附帶原理+代碼
    來源 | 早起Python( ID:zaoqi-python )「多元線性回歸模型」非常常見,是大多數人入門機器學習的第一個案例,儘管如此,裡面還是有許多值得學習和注意的地方。多元線性回歸建模現在我們直接構建多元線性回歸模型:from statsmodels.formula.api import
  • 用 Scikit-Learn 和 Pandas 學習線性回歸
    ,這裡給出一個完整的例子,詳細學完這個例子,對用scikit-learn來運行線性回歸,評估模型不會有什麼問題了。:) 這裡我們用UCI大學公開的機器學習數據來跑線性回歸。也不用我們搞,後面scikit-learn在線性回歸時會先幫我們把歸一化搞定。好了,有了這個csv格式的數據,我們就可以大幹一場了。3. 用pandas來讀取數據我們先打開ipython notebook,新建一個notebook。當然也可以直接在python的交互式命令行裡面輸入,不過還是推薦用notebook。
  • 用 Scikit-learn 與 Pandas 進行線性回歸預測
    ,這裡給出一個完整的例子,詳細學完這個例子,對用scikit-learn來運行線性回歸,評估模型不會有什麼問題了。:) 這裡我們用UCI大學公開的機器學習數據來跑線性回歸。也不用我們搞,後面scikit-learn在線性回歸時會先幫我們把歸一化搞定。好了,有了這個csv格式的數據,我們就可以大幹一場了。我們先打開ipython notebook,新建一個notebook。當然也可以直接在python的交互式命令行裡面輸入,不過還是推薦用notebook。下面的例子和輸出我都是在notebook裡面跑的。
  • SPSS多元線性回歸案例:回歸分析方法實戰
    1.線性回歸(Linear Regression)線性回歸通常是人們在學習預測模型時首選的技術之一。在這種技術中,因變量是連續的,自變量可以是連續的也可以是離散的,回歸線的性質是線性的。線性回歸使用最佳的擬合直線(也就是回歸線)在因變量(Y)和一個或多個自變量(X)之間建立一種關係。
  • 對線性回歸,logistic回歸和一般回歸的認識
    前四節主要講述了回歸問題,回歸屬於有監督學習中的一種方法。該方法的核心思想是從連續型統計數據中得到數學模型,然後將該數學模型用於預測或者分類。該方法處理的數據可以是多維的。講義最初介紹了一個基本問題,然後引出了線性回歸的解決方法,然後針對誤差問題做了概率解釋。之後介紹了logistic回歸。最後上升到理論層次,提出了一般回歸。
  • R數據分析:一般線性回歸的做法和解釋
    發現大家做分析做的最多的還是線性回歸,很多人諮詢的都是線性回歸的問題,今天專門出一個線性回歸的文章。
  • 從statsmodels到線性回歸
    結合計量經濟學知識可知,擬合線性模型通常需要擬合帶截距項的模型,就需要將常係數列合併到解釋變量矩陣中去,使用函數sm.add_constant可以解決這個問題,查看添加常數列的矩陣。統計建模分析中,只得到回歸係數往往是不夠的,回歸係數的顯著水平、模型的R2等都是需要的。如果想得到像其他統計軟體一樣的回歸明細表,對模型返回結果使用summary方法即可。