本文最初發表在 Towards Data Science 博客,經原作者 Braden Riggs 授權,InfoQ 中文站翻譯並分享。
數學建模和機器學習常常會讓人感覺像是難以探索和學習的課題,尤其是對那些不熟悉計算機科學和數學領域的人來說尤為如此。我很驚訝地從我的非理工科的朋友那裡聽到,他們在自己的項目中嘗試使用基本的建模技術時感到不知所措,而且他們可能會陷入這個領域的語義中。這是一種恥辱,因為線性建模在許多情況下都是非常有用的,並且加上網際網路上的所有開放原始碼,實現自己的模型從未如此簡單過。因此,下面是我用 Python 理解並實現基本線性回歸模型的簡單指南。
線性回歸是一種數學建模的一種形式,通常用於評估因變量(如體重)和自變量(如身高)之間的關係。我們的大腦能夠很自然地做到這一點,只是以一種不太精確的方式而已。如果我讓你判定 189 釐米和 158 釐米的人哪個人體重更重,你可能會選擇 189 釐米的人。當然,158 釐米的人也可能會更重,但我敢打賭,在你與人交往的經歷中,你已經確定了人的身高與體重之間的某種關係。線性回歸就是建立這種關係並從中提取意義的一種精確的數學方法。
線性回歸的工作原理是通過創建一條最佳擬合線。最佳擬合線是最能捕捉 X 軸和 Y 軸之間關係的直線。例如,這種關係可以是,隨著「X」的增加,「Y」也會隨之增加:
隨著 X 增加,Y 也隨之增加。
或者,這種關係也可以是:隨著「X」增加,「Y」也隨之減少。
隨著 X 增加,Y 也隨之減少。
在上面的示例中,確定趨勢的大致方向是很容易的。但是,根據數據,它可能會變得更加複雜。此外,這條線的精確細節可能很難手工計算。在許多情況下,得到直線的精確方程會非常有幫助,使我們能夠理解這兩個變量之間的關係,並根據另一個變量的值來推測另一個變量的值。
為了使線性回歸有效發揮作用,你至少需要兩個變量:一個你認為可能是因變量的變量,如 NBA 球員的體重(以公斤為單位),另一個你認為可能是影響該因變量的變量,比如 NBA 球員的身高(以釐米為單位)。一個 Pandas 數據幀,包含與 NBA 球員有關的各種數據點,其中包括身高和體重
如果這兩個變量都是連續的,那麼線性回歸的效果最好。我所說的連續是指兩個值之間有一個連續性。有些人的體重可以是 68.49 公斤,或 68.95 公斤,或 68.72 公斤,或 68.82 公斤,等等。這不同於離散的或分類變量(例如電影分級或課堂上給出的分數)。還有其他技術可以處理這些類型的數據,但我們現在將重點放在線性回歸。
身高和體重是連續變量素數之間建立線性關係的兩個完美示例。如果你使用的是 Python,請確保這兩個連續變量都是 浮點型 的,這將對後面的步驟有所幫助。
如果你有興趣使用已經清理過的數據集進行嘗試這一操作,你可以跟隨我正在使用的 NBA 數據集(可以在 這裡 找到)。
為了加載數據,我推薦使用 Python 的 Pandas 包:
import pandas as pd #Load the Pandas package
df = pd.read_csv("archive/all_seasons.csv") #Read the NBA file
df.head() #Display the NBA file's data
輸出應該與上面所示的表類似。
現在,我們已經加載了數據,讓我們來看看 NBA 球員的體重和身高之間的關係:
df.plot.scatter("player_height","player_weight", figsize=(15,10))
NBA 球員身高(X 軸)和體重(Y 軸)的散點圖。
除了一些離群值外,我們已經可以看到,NBA 球員的身高和體重之間存在著直接的相關性。正如我們上面所揭示的,線性回歸就像從圖的左邊到圖的右邊繪製出了一條最符合數據關係的直線。以我們的 NBA 球員為例,我們可以猜測,最佳擬合線應該是從 60 公斤左右的某處開始,然後向右上角移動。問題在於,我們人類遠遠不夠精確,無法繪製出一條能夠完美捕捉數據趨勢的直線。取而代之的是,讓我們使用一個工具。
Scikit-Learn,或稱 SKLearn,是一個 Python 包,包含了各種機器學習工具,其中有一種用於以簡單有效的方式構建線性回歸模型的工具。要使用 SKLearn,我們需要從 Pandas 數據幀中分離出兩個變量:
from sklearn import linear_model
#By calling to_numpy() we convert the series into a numpy array
#We then reshape the numpy array into a format parsable for sklearn
X = df["player_height"].to_numpy().reshape(-1, 1)
y = df["player_weight"].to_numpy().reshape(-1, 1)
我們的數據現在是 NumPy 數組格式。
正如你所見,「X」數組包含了所有的身高,「Y」數組包含了所有的體重。現在,我們可以對模型進行擬合了。在這種情況下,對模型進行擬合意味著我們正將數據呈現給函數,並允許 SKLearn 找到最能捕捉「X」和「Y」之間關係的直線。
#First we call the linear regression function from SKLearn linear_model
#Then using this object we fit the data to a linear model.
lm = linear_model.LinearRegression()
model = lm.fit(X,y)
現在模型已經擬合好,讓我們看看它產生了什麼樣的結果。
在我們的模型完成擬合之後,是時候看看它從我們提供的數據中建立了什麼。首先,讓我們看看它為數據評估的參數:
print(model.coef_) #prints the slope of the line
[1]: [[1.13557995]]
print(model.intercept_) #prints the intercept of the line
[2]: [-127.40114263]
對於熟悉數學的人來說,你可能還記得直線斜率的公式是 y = mx + b。在這種情況下,「b」是截距,可以認為是直線與 Y 軸相交的位置,而「m」是直線的斜率。因此,對於我們擬合的線性回歸模型,方程式大致為 y = 1.13x - 127.4。這意味著,「x」每增加一個數字,「y」就增加 1.13,或者更確切地說,球員身高每增加 1 釐米,球員的體重就應該增加 1.13 公斤。從視覺上看,如果我們在 NBA 球員身高和體重的散點圖上繪製出這條直線,我們就會得到:
import numpy as np #numpy can be used for creating a lsit of numbers
X = np.arange(150,250) # create a list of example values
#plot
df.plot.scatter("player_height","player_weight", figsize=(15,10)).plot(X, model.predict(X.reshape(-1,1)),color='k')
NBA 球員身高(X 軸)與體重(Y 軸)的散點圖,這一次包括我們的線性回歸模型創建的最佳擬合線。
在這種情況下,黑線是我們已經對數據擬合的直線。根據這條直線,我們可以推測,一個身高 180 釐米的球員大約在 70 公斤左右。但是,使用 SKLearn 和我們創建的模型,我們可以估算出:
model.predict(np.array(180).reshape(-1,1))
[3]: array([[77.00324856]])
因此,身高 180 釐米的球員應該大約有 77 公斤重。
現在這個模型已訓練好,你可以用任何值進行嘗試。下面是我在 NBA 的體重:
model.predict(np.array(188).reshape(-1,1))
[4]: array([[86.08788817]])
雖然這只是一個微不足道的例子,但線性回歸對於許多任務和項目都非常有用,因此,每個人都應該儘可能掌握線性回歸。我這個項目的完整代碼如下所示,我鼓勵你自己嘗試一下。另外,如果你還想了解更多有關信息,我在下面提供了一些參考資料。
import pandas as pd
from sklearn import linear_model
df = pd.read_csv("archive/all_seasons.csv")
X = df["player_height"].to_numpy().reshape(-1, 1)
y = df["player_weight"].to_numpy().reshape(-1, 1)
lm = linear_model.LinearRegression()
model = lm.fit(X,y)
model.predict(np.array(188).reshape(-1,1))
哇!只需 8 行代碼!!
延伸閱讀:
Braden Riggs,澳大利亞人,加利福尼亞大學聖地牙哥分校數據科學系留學生,GSI Technology 實習生。
原文連結:
https://towardsdatascience.com/a-guide-to-building-your-first-regression-model-in-just-8-lines-of-code-2d1a2a755811