【Python機器學習】103:使用正規方程式解決線性 & 非線性回歸模型

Using Normal Equation to solve linear & nonlinear regression models

張育晟 Eason Chang
展開數據人生
10 min readMay 22, 2020

--

Photo by Aman Dhakal on Unsplash

介紹完基礎的Scikit-Learn,我們終於可以自己訓練回歸模型啦。一般情況,資料分析師在面對陌生資料的時候,都會先看一下資料的外觀,不管是用describe()函數還是畫直方圖和散步圖。

這一篇會用到大量大聯盟的打者資料,所以我們先瀏覽一下資料大概長什麼樣子。一般在秋季結束的時候,自由球員或是新人都會跟球團簽約,但是要怎麼決定要簽多少金額的合約呢?最好的方法就是跟大家看齊,否則出的太低球員不願意跟你簽約,出的太高球團的薪資空間又會被壓縮。

MLB打者:年薪的直方圖(Histogram plot):

MLB Player’s Salary is right-tailed, left-skewed

MLB打者:打擊率與年薪的散佈圖(Scatter plot):

Batting Average vs. Salary

直方圖的結果與職業球員的年資有右尾的現象,說明大聯盟大部分的球員都是拿基本底薪,但還是有少數頂尖球員拿非常高的薪資。最後觀察散佈圖後發現:似乎不是打擊率越高薪水就越高,大部分球員的打擊率都落在0.2~0.35之間。

在介紹回歸之前,先幫大家複習幾個向量、矩陣相乘的特性:

𝑥 與 𝑦 兩個維度相同的向量相乘為 𝑥的轉置矩陣乘以y、亦等於 𝑦 的轉置矩陣乘以x

𝐴 與 𝐵 矩陣相乘後的轉置運算為 (𝐴𝐵)的轉置矩陣=𝐵的轉置矩陣乘以𝐴的轉置矩陣

𝐴𝑥=𝑏 的解為 𝑥=𝐴的inverse矩陣乘以b

反矩陣的函數為np.linalg.inv(),其中linalg為線性代數linear algebra的簡稱

1、線性回歸模型

建立一個輸入向量 𝑥 能夠得到純量 𝑦̂ 輸出的系統 ℎ,𝑥 與 𝑦̂ 符合線性關係,其中向量 𝑤 稱為是系統的參數

第二行公式補了一個常熟項x0(數值都是1的向量),在機器學習裡x0有個專有名詞叫bias

在上述的公式裡:x 向量是和某球員有關的所有資料(身高、體重、打擊率、盜壘數、失誤等),w0是截距而剩下的w向量是系統h的參數也是x的係數,最後乘起來就會得到一個輸出𝑦̂,也就是預測出該球員的年薪。而我們的任務就是要訓練系統h,如果系統h表現得好(預測出來的年薪不錯),則該球員就會和我簽約,如系統h表現得很糟糕,就不會續約。

由於x和w向量都是(n, 1),根據剛才提到的公式一,其中一個向量要轉置。

𝑤作為系統的參數:

  • If 𝑤𝑖 為正,表示 𝑥𝑖 這個特徵對 𝑦̂ 的影響為正向
  • If 𝑤𝑖 為負,表示 𝑥𝑖 這個特徵對 𝑦̂ 的影響為負向
  • If 𝑤𝑖 為零,表示 𝑥𝑖 這個特徵對 𝑦̂ 沒有影響

上述例子中,x向量只包含了1位球員,假如想要同時看很多球員的年薪呢?這時候x就變成一個 m*n 的特徵矩陣,最後會得到m位球員的年薪。

將h表示得更廣泛

最後再使用MSE(Mean Squared Error)評估訓練出來的模型好壞:下圖中公式的𝑦̂其實是我用y-validation預測出來的y-predict。預測出來的年薪(𝑦̂)與最後的實際簽約金額做比較,不管是猜高還是低都是錯誤的,因此才要平方。

當預測出來的年薪(𝑦̂)跟實際簽約金額相同,MSE為零。

機器學習的任務:找出一組w向量使得MSE最小。這當然有很多種做法:比如說我們可以窮舉w,然後看哪一組的MSE最小,但這個方法顯然太費時。

我們只需要算出MSE對w的偏微分=0時,w向量的值:

這個求解稱為 normal equations,又稱 closed form solution

這邊我們來手動算一下在給定X_train & y-train的情況下,如何使用normal equations求出w:

X_train中,X_0都補了1

一樣使用mlb-batter的資料,只是我們這次在取出特徵矩陣的時候會發現,Python並沒有主動幫我們加入x0,於是我們使用np.ones創立一個(m*1)且數值都是1的向量,再用np.concatenate合併。記得在使用concatenate的時候要加參數axis=1,因為它的預設值為0,會自動幫向量上下合併,但我們要的是左右合併,因此設定axis = 1。

最後,再用上一篇教的train_test_split得出我們X_train, X_validation, y_train & y_validation。套用公式後就可以得到我們的w0(截距項)為-1,545,512,而w1為36,270,111。

那在知道w 和 X_validation的情況下,我們要如何計算validation的MSE呢?畢竟我們的目標式就是要讓模型的MSE最小化。根據公式,y_pred = X乘上係數w:

當然我們先前提到了,Scikit-Learn是個強大的分析工具,所以像是算w和MSE根本不需要自己動手算XDD,直接呼叫Scikit-Learn裡的function就行了。

有沒有發現得到的值跟w是相同的呢?沒錯,我們其實可以直接使用LinearRegression這個Predictor得到我們的截距項 & 係數,得到的值就是我們的w,只是這裡求出來的截距項是浮點數,而係數是一個一維的ndarray。

我們稍微整理一下讓他變成一個w:

MSE我們可以使用 sklearn.metrics 中的mean_squared_error來計算,參數裡先放y的真實值,再放求出來的預測值:

這個mse其實就是y-validation跟h這條線之間的平均距離

接下來我們把系統h在訓練資料上描繪出來:

單季打擊率最高大概0.4左右,所以我們這邊使用np.linspace()函數,可以在0~0.4中打50個點(預設值),再丟到h裡面,就會得到對應的𝑦̂。那這50個點連起來就是h的樣子。

將h在驗證資料上描繪出來:

剛才的mse就是算validation跟h這條線的距離

2、非線性回歸模型:

剛才計算得到的MSE非常大,模型一定錯誤的地方。在現實生活中,大聯盟的球員薪資也不會單單只看打者的打擊率。那如果我想要增加一些更多的變數到模型裡呢?這就要用到非線性回歸模型。

我們先前有提到機器學習的任務:於可及範圍的 𝐻 中挑選一個與 𝑓 最相似的 ℎ,那我要怎麼擴增回歸模型的可及範圍H呢?

加入更多的特徵(features) ex:加入高次項(polynomials)

如果我們加入二次項,那原本的h會變成什麼樣子?

在原本的X 新增打擊率的平方(二次項):

把打擊率平方之後再用concatenate函數合併。大家可能也想到了,沒錯,Scikit-Learn 其實也有相對應的工具幫我們增加二次項。我們可以使用sklearn.preprocessing中的PolynomialFeatures新增二次項。

還記得在上一篇文章的尾聲有提到 Scikit-Learn 有兩種Estimator嗎?PolynomialFeatures就是屬於第二種Estimator——Transformer。

Transformer跟Predictor其中一個差別就是Transformer不需要先fit,他可以直接呼叫fit_transform

Transformer一樣要初始化(一般小括號是不放參數的),但是PolynomialFeatures 初始化的預設值為 degree = 2,所以如果我們下次要增加3次項就要記得設參數。

不知道大家有沒有發現:PolynomialFeatures函數會自動幫我們增加 X0(都是1的向量)

另外,如果我的X有兩個變數了話,PolynomialFeatures函數除了會把兩個變數都平方以外,還會新增一項變數:兩變數相乘

得到的X_poly分別為X0,X1,X1平方, X1X2, X2平方

一樣,w可以透過 sklearn.linear_model 中的LinearRegression求出;MSE則使用 sklearn.metrics 中的mean_squared_error 計算。

這一篇我們先複習了3個重要的矩陣公式,再從normal equations得到w,可以用mean_squared_error幫助我們算mse,也可以用PolynomialFeatures增加高次項。下一篇我們將會教大家加入類別變數的回歸模型要怎麼算。

MLB_batter 資料來源:

年薪資料:https://www.spotrac.com/mlb/rankings/2019/batters/

球員數據:https://www.rotowire.com/baseball/stats.php?filter=1

感謝你閱讀完這篇文章,如果你覺得這些文章對你有幫助請在底下幫我拍個手(長按最多可以拍50下手)。

上一章:【Python機器學習】102:如何使用Scikit-Learn預測器完成數值預測

下一章:【Python機器學習】104:如何處理加入類別變數的回歸模型

--

--

張育晟 Eason Chang
展開數據人生

在不斷變動中努力思索自己的定位,想做的事情很多,但最希望的是不要變成無趣的人。 Linkedin: https://www.linkedin.com/in/stareason1997