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大数据挖掘从入门到进阶实战》,喜欢的朋友或同学, 可以在公告栏那里点击购买链接购买博主的书进行学习,在此感谢大家的支持。关注下面公众号,根据提示,可免费获取书籍的教学视频。