1.概述
前面一篇部落格給大家介紹了多元線性迴歸的一些概念和對應的方程式的程式碼實現。今天筆者再為大家介紹線性迴歸的實戰演練。比如,通過空氣溼度、氣壓、風速等來預測當天的溫度。
2.內容
線性迴歸是對標量因變數和一個或者多個自變數之前的線性關係的建模的最簡單,且非常強大的方法。線性迴歸方程公式如下:
接著,我們匯入天氣資料,列印天氣資料前三行,實現程式碼如下:
import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt weather_data = pd.read_csv("/data/weatherHistory.csv") print(weather_data.head(3))
預覽截圖如下:
檢視資料資訊:
weather_data.info()
結果如下:
檢視資料集中的分類變數:
print(weather_data.describe(include='all'))
預覽結果如下:
print(weather_data.describe(include=['O']))
預覽截圖如下:
要預測溫度,所以需要找出資料集中不同變數之間的相關性,程式碼如下:
print(weather_data.corr())
預覽截圖如下:
相關性在-1到1之間變化,1表示強相關,相關係數-1表示完全負相關,相關係數為0表示變數之間不存在關係。從上圖可知,我們看到溫度與表觀溫度、溼度之間有很強的關係,也許我們還可以包括能見度。接著,我們將所有相關屬性放入一個新的資料集中並再次檢查相關性。
具體實現程式碼如下所示:
data_set=weather_data.iloc[:,[0,3,4,5,8]] print(data_set.corr())
預覽截圖如下:
現在,讓我們視覺化溫度和其他因變數之間的資料,繪製溫度和溼度之間的散點圖。實現程式碼如下:
# 指定繪圖物件的寬度和高度 plt.figure(figsize=(14,4)) plt.xlabel('Temperature (C)') plt.ylabel('Humidity') # 繪製溫度和溼度散點圖 sns.regplot(x=data_set["Temperature (C)"], y=data_set["Humidity"],data=data_set) plt.show()
預覽截圖:
圖中,溼度和溫度之間存在負相關,我們也看到了一些異常值。我們可以嘗試找到這些異常值,並將這些異常值進行刪除。在統計中瞭解到,異常值會極大的影響線性迴歸。下面,我們通過編寫一個函式來幫助我們識別資料集中溼度變數的異常值。它發現異常值的方式是基於標準差大於3。實現程式碼如下所示:
outliers=[] def detect_outlier(data_1): threshold=3 mean_1 = np.mean(data_1) std_1 =np.std(data_1) for y in data_1: z_score= (y - mean_1)/std_1 if np.abs(z_score) > threshold: outliers.append(y) return outliers outlier_data = detect_outlier(data_set["Humidity"]) print (outlier_data)
預覽結果如下:
接著,我們從資料集中刪除這些行以獲得用於迴歸的乾淨資料集。因此,我們在data_set中搜尋所有值大於0.15的溼度值並建立一個新的資料集data_set_clean。實現程式碼如下:
data_set_clean = data_set[data_set["Humidity"]>0.15]
然後,我們再來再次繪製溫度和溼度之間的資料以檢查是否還有異常值。實現程式碼如下:
# 繪製乾淨資料的溫度和溼度的散點圖 sns.regplot(x=data_set_clean["Temperature (C)"], y=data_set_clean["Humidity"]) plt.show()
預覽截圖如下:
現在,讓我們在溫度和表觀溫度之間再畫一個散點圖,實現程式碼如下:
# 溫度與表觀溫度的散點圖 sns.regplot(x=data_set["Temperature (C)"], y=data_set["Apparent Temperature (C)"]) plt.show()
預覽截圖:
從上圖看起來溫度和表觀溫度之間存在很強的正相關性,這也很明顯。下面,我們再繪製溫度和能見度之間的散點圖,實現程式碼如下:
# 溫度與能見度散點圖 sns.regplot(x=data_set["Temperature (C)"], y=data_set["Visibility (km)"]) plt.show()
預覽截圖:
從圖中,我們沒有看到溫度和能見度之間有很強的關係,所以我們可以降低能見度。這裡X是我們與溼度和表觀溫度的自變數,Y是我們試圖首先學習然後計劃預測的溫度因變數。程式碼如下:
# 過濾資料集 data_set_clean = data_set[data_set["Humidity"]>0.15] y= data_set_clean.iloc[:,[1]] X= data_set_clean.iloc[:,[2,3]] print(data_set_clean[data_set_clean["Humidity"]<=0.15])
預覽截圖:
列印一行X以檢視我們的自變數,程式碼如下:
print(X.head(1))
預覽截圖:
通過,80:20的比例將資料集拆分為訓練集和測試集,程式碼如下:
# 80:20 進行拆分 from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0) # 訓練集 from sklearn.linear_model import LinearRegression regressor =LinearRegression() regressor.fit(X_train, y_train)
我們使用sklearn庫的linear_models來擬合多元線性迴歸的訓練資料,然後,從sklearn.linear_models匯入庫線性迴歸,並建立一個迴歸物件,然後嘗試擬合訓練資料。
接著,我們列印迴歸量的不同值並瞭解它們的含義。程式碼如下:
print(regressor.coef_)
結果如下:
記住線性迴歸方程式,公式如下:
- 0.857是b1,其中x1是表觀溫度
- -2.648是b2,其中x2是溼度
接著,我們找b0,程式碼如下:
print(regressor.intercept_)
截圖如下:
現在,讓我們把這些數字帶入公式內進行計算,公式如下:
溫度 = 4.58 + (表觀溫度 * 0.857) + (-2.648 * 溼度)
我們現在可以預測測試資料集的溫度,程式碼如下:
# 預測測試集結果 y_pred = regressor.predict(X_test)
那我們如何知道衡量模型的適用性呢?一個好的擬合模型是這樣一種模型,其中實際值或觀察值與基於模型的預測值之間的差異很小且無偏。所以,如果一些統計資料告訴我們實際值和預測值之間的R2可以衡量模型或迴歸線對實際結果的複製程度,這是基於模型解釋的預測的總變化。
R2始終介於0和1之間或者0%到100%之間。值1表示該模型解釋了預測變數圍繞其均值的所有變化。
- SSE = 實際值 - 預測值,表示與實際值相比,預測的值有多遠;
- SST = 實際值 - 平均值,表示實際值與平均值相比有多遠;
- SSR = 預測值 - 平均值
如果預測誤差較低,則SSE將較低且R2將接近1。這裡需要注意的是,當我們新增更多的自變數時,R2會獲得更高的值,R2值隨著更多的自變數的加入而不斷增加,即使它們可能不會真正對預測產生重大影響。為了解決這個問題,我們對R2進行了調整,調整後R2會在每次新增一個無關緊要的自變數時修正該模型。
print(regressor.score(X,y))
結果如下:
當R2接近1的值表示擬合良好。
另外,我們還可以計算均方根誤差,也稱RMSE。
RMSE顯示預測值和實際值之間的變化,由於預測值和實際值之間的差異可以是正值也可以是負值,為了抵消這種差異,我們取預測值和實際值之間的差異的平方。
- 找出每個觀測值的預測值和實際值之間的差異,然後將值的平方並累加:sum(預測值-實際值)2
- 總和除以觀察次數:sum(預測值-實際值)2/觀察次數
- 取第2步中的值的平方根
實現程式碼如下:
from sklearn import metrics import math print(math.sqrt(metrics.mean_squared_error(y_test, y_pred)))
預覽截圖:
接著,我們可以使用另一個庫statsmodel,程式碼如下:
import statsmodels.api as sm ones_1 =[1] * X.count() X["b0"]=ones_1
現在,我們使用OLS普通最小二乘法來找到最佳擬合迴歸線,程式碼如下:
model = sm.OLS(y_pred,X_test).fit() print(model.summary())
預覽結果如下:
從上圖執行結果可以看出,我們從之前的0.987值得到了一個更加好的0.997平方根值。
3.總結
整個例項的執行程式碼,如下所示:
import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt weather_data = pd.read_csv("/data/weatherHistory.csv") # print(weather_data.head(3)) # weather_data.info() # print(weather_data.describe(include='all')) # print(weather_data.describe(include=['O'])) # print(weather_data.corr()) data_set=weather_data.iloc[:,[0,3,4,5,8]] # print(data_set.corr()) # 指定繪圖物件的寬度和高度 plt.figure(figsize=(14,4)) plt.xlabel('Temperature (C)') plt.ylabel('Humidity') # 繪製溫度和溼度散點圖 # sns.regplot(x=data_set["Temperature (C)"], y=data_set["Humidity"],data=data_set) # plt.show() outliers=[] def detect_outlier(data_1): threshold=3 mean_1 = np.mean(data_1) std_1 =np.std(data_1) for y in data_1: z_score= (y - mean_1)/std_1 if np.abs(z_score) > threshold: outliers.append(y) return outliers outlier_data = detect_outlier(data_set["Humidity"]) # print (outlier_data) data_set_clean = data_set[data_set["Humidity"]>0.15] # 繪製乾淨資料的溫度和溼度的散點圖 # sns.regplot(x=data_set_clean["Temperature (C)"], y=data_set_clean["Humidity"]) # plt.show() # 溫度與表觀溫度的散點圖 # sns.regplot(x=data_set["Temperature (C)"], y=data_set["Apparent Temperature (C)"]) # plt.show() # 溫度與能見度散點圖 # sns.regplot(x=data_set["Temperature (C)"], y=data_set["Visibility (km)"]) # plt.show() # 過濾資料集 data_set_clean = data_set[data_set["Humidity"]>0.15] y= data_set_clean.iloc[:,[1]] X= data_set_clean.iloc[:,[2,3]] # print(data_set_clean[data_set_clean["Humidity"]<=0.15]) # print(X.head(1)) # 80:20 進行拆分 from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0) # 訓練集 from sklearn.linear_model import LinearRegression regressor =LinearRegression() regressor.fit(X_train, y_train) # print(regressor.coef_) # print(regressor.intercept_) # 預測測試集結果 y_pred = regressor.predict(X_test) # print(regressor.score(X,y)) from sklearn import metrics import math # print(math.sqrt(metrics.mean_squared_error(y_test, y_pred))) import statsmodels.api as sm ones_1 =[1] * X.count() X["b0"]=ones_1 model = sm.OLS(y_pred,X_test).fit() print(model.summary())
4.結束語
這篇部落格就和大家分享到這裡,如果大家在研究學習的過程當中有什麼問題,可以加群進行討論或傳送郵件給我,我會盡我所能為您解答,與君共勉!
另外,博主出書了《Kafka並不難學》和《Hadoop大資料探勘從入門到進階實戰》,喜歡的朋友或同學, 可以在公告欄那裡點選購買連結購買博主的書進行學習,在此感謝大家的支援。關注下面公眾號,根據提示,可免費獲取書籍的教學視訊。