xiaochao 6 小时前发布
这篇文章我们接着前一篇文章,使用 Weather Underground 网站获取到的数据,来继续探讨用机器学习的方法预测内布拉斯加州林肯市的天气
上一篇文章我们已经探讨了如何收集、整理、清洗数据。这篇文章我们将使用上一篇文章处理好的数据,建立线性回归模型来预测天气。为了建立线性回归模型,我要用到 python 里非常重要的两个机器学习相关的库:Scikit-Learn 和 StatsModels 。
第三篇文章我们将使用 google TensorFlow 来建立神经网络模型,并把预测的结果和线性回归模型的结果做比较。
这篇文章中会有很多数学概念和名词,如果你理解起来比较费劲,建议你先 google 相关数据概念,有个基础的了解。
在这个Github 仓库,有个名为 Underground API.ipynb 的 Jupyter Notebook 文件,这个文件记录了我们这篇文章和下一篇文章要用到的数据的获取、整理步骤。你还会发现一个名为 end-part1_df.pkl 的文件,如果你自己没有处理好数据,可以直接用这个文件,然后使用下面的代码来把数据转成 Pandas DataFrame 类型。
- import pickle
- with open('end-part1_df.pkl','rb')as fp:
- df = pickle.load(fp)
如果运行上面的代码遇到错误:
,那么说明你用的 pandas 库的版本和我的 (v0.18.1) 不一致,为了避免这样的错误发生,我还准备了个 csv 文件,你可以从上述的 Github 仓库获取,然后使用下面的代码读入数据。
- Nomodule named 'pandas.indexes'
- import pandas as pd
- df = pd.read_csv('end-part2_df.csv').set_index('date')
线性回归模型的目标是使用一系列线性相关的数据和数字技术来根据预测因素 X(自变量)来预测可能的结果 Y(因变量),最终建立一个模型 (数学公式) 来预测给定任意的预测因素 X 来计算对应的结果 Y。
线性回归的一般公式为:
- ŷ=β0+β1* x1 +β2* x2 +...+β(p - n) x(p - n)+Ε
关于公式的详细解释,查看百度百科 - 线性回归模型
线性回归技术要求的关键假设是,因变量和每个自变量之间有一个线性关系。针对我们的数据,就是温度和其他变量,然后计算 Pearson 相关系数。Pearson 相关系数(r)是输出范围为 - 1 到 1 的值的等长阵列之间的线性相关量的量度。范围从 0 到 1 的相关值表示越来越强的正相关性。 这意味着当一个数据序列中的值与另一个序列中的值同时增加时,两个数据序列呈正相关,并且由于它们两者的上升幅度越来越相等,Pearson 相关值将接近 1。从 0 到 - 1 的相关值被认为是相反或负相关的,因为当一个系列的值增加相反系列减小的相应值时,但是当系列之间的幅度变化相等(相反的方向)时, 相关值将接近 - 1。 紧密地跨越零的 Pearson 相关值暗示着具有弱的线性关系,随着值趋近于零而变弱。
关于相关系数的强度界定,统计学家和统计书籍中的观点各不相同。 但是,我发现一个普遍接受的关联强度分类集合如下:
为了评估这个数据中的相关性,我将调用 Pandas DataFrame 对象的 corr()方法。通过 corr()函数的调用,我可以选择我感兴趣的数据 (meantempm),然后再对返回的结果(Pandas Series object)调用 sort_values() 函数,这将输出从最负相关到最正相关的相关值。
- df.corr()[['meantempm']].sort_values('meantempm')
在选择包括在这个线性回归模型中的特征时,我想在包含具有中等或较低相关系数的变量时略微宽容一些。 所以我将删除相关值的绝对值小于 0.6 的特征。 此外,由于 "mintempm" 和 "maxtempm" 变量与预测变量 "meantempm" 同一天,我也将删除这些(即,如果我已经知道最高和最低温度,那么我已经有了我的答案)。有了这些信息,我现在可以创建一个新的 DataFrame,它只包含我感兴趣的变量。
- predictors =['meantempm_1','meantempm_2','meantempm_3',
- 'mintempm_1','mintempm_2','mintempm_3',
- 'meandewptm_1','meandewptm_2','meandewptm_3',
- 'maxdewptm_1','maxdewptm_2','maxdewptm_3',
- 'mindewptm_1','mindewptm_2','mindewptm_3',
- 'maxtempm_1','maxtempm_2','maxtempm_3']
- df2 = df[['meantempm']+ predictors]
因为大多数人,包括我自己在内,都更习惯于用视觉来评估和验证模式,所以我将绘制每个选定的预测因子来证明数据的线性关系。 要做到这一点,我将利用 matplotlib 的 pyplot 模块。
对于这个图,我希望将因变量 "meantempm" 作为沿所有 18 个预测变量图的一致 y 轴。 一种方法是创建一个的网格。 Pandas 的确有一个有用的绘图函数叫做 scatter_plot(),但是通常只有当大约只有 5 个变量时才使用它,因为它将绘图变成一个 N×N 的矩阵(在我们的例子中是 18×18) 变得难以看到数据中的细节。 相反,我将创建一个六行三列的网格结构,以避免牺牲图表的清晰度。
- import matplotlib
- import matplotlib.pyplot as plt
- import numpy as np
- # manually set the parameters of the figure to and appropriate size
- plt.rcParams['figure.figsize']=[16,22]
- # call subplots specifying the grid structure we desire and that
- # the y axes should be shared
- fig, axes = plt.subplots(nrows=6, ncols=3, sharey=True)
- # Since it would be nice to loop through the features in to build this plot
- # let us rearrange our data into a 2D array of 6 rows and 3 columns
- arr = np.array(predictors).reshape(6,3)
- # use enumerate to loop over the arr 2D array of rows and columns
- # and create scatter plots of each meantempm vs each feature
- for row, col_arr in enumerate(arr):
- for col, feature in enumerate(col_arr):
- axes[row, col].scatter(df2[feature], df2['meantempm'])
- if col ==0:
- axes[row, col].set(xlabel=feature, ylabel='meantempm')
- else:
- axes[row, col].set(xlabel=feature)
- plt.show()
从上面的图中可以看出,所有其余的预测变量与响应变量("meantempm")显示出良好的线性关系。 此外,值得注意的是,这些关系都是均匀随机分布的。 我的意思是,在没有任何扇形或圆锥形状的情况下,数值的扩散似乎有相对相等的变化。 使用普通最小二乘算法的线性回归的另一个重要假设是沿点的均匀随机分布。
一个强大的线性回归模型必须选取有意义的、重要的统计指标的指标作为预测指标。 为了选择统计上显着的特征,我将使用 Python statsmodels 库。然而,在使用 statsmodels 库之前,我想先说明采取这种方法的一些理论意义和目的。
在分析项目中使用统计方法(如线性回归)的一个关键方面是建立和测试假设检验,以验证所研究数据假设的重要性。 有很多假设检验已经被开发来测试线性回归模型对各种假设的稳健性。 一个这样的假设检验是评估每个包含的预测变量的显着性。
βj 参数意义的假设检验的正式定义如下:
通过使用概率测试来评估每个βj 在选定阈值Α处超过简单随机机会的显着性的可能性,我们可以在选择更严格数据,以保证模型的鲁棒性。
然而在许多数据集中,数据间的相互影响会导致一些简单的假设检验不符合预期。 为了在线性回归模型中测试相互作用对任何一个变量的影响,通常应用被称为逐步回归的技术。 通过增加或者删除变量来评估每个变量的变化,对产生的模型的影响。在本文中,我将使用一种称为 "后向消除" 的技术,从一个包含我感兴趣数据的模型开始。
后向消除工作流程如下:
下面我们使用 statsmodels 按照上面的步骤,来构建我们的模型。
- # import the relevant module
- import statsmodels.api as sm
- # separate our my predictor variables (X) from my outcome variable y
- X = df2[predictors]
- y = df2['meantempm']
- # Add a constant to the predictor variable set to represent the Bo intercept
- X = sm.add_constant(X)
- X.ix[:5,:5]
- # (1) select a significance value
- alpha =0.05
- # (2) Fit the model
- model = sm.OLS(y, X).fit()
- # (3) evaluate the coefficients' p-values
- model.summary()
调用 summary() 函数输出的数据如下:
R 平方 - 一个衡量标准,我们的模型可以解释结果的整体变化的多少
这并不是说在这个输出中的其他价值是没有价值的,恰恰相反,它们涉及到线性回归的更深奥的特质,我们现在根本没有时间考虑到。对于他们的完整解释,我会推迟到高级回归教科书,如 Kutner 的应用线性回归模型,第五版。 以及 statsmodels 文件。
- # (3) cont. - Identify the predictor with the greatest p-value and assess if its > our selected alpha.
- # based off the table it is clear that meandewptm_3 has the greatest p-value and that it is
- # greater than our alpha of 0.05
- # (4) - Use pandas drop function to remove this column from X
- X = X.drop('meandewptm_3', axis=1)
- # (5) Fit the model
- model = sm.OLS(y, X).fit()
- model.summary()
关于您的阅读时间,为了保持文章的合理长度,我将省略构建每个新模型所需的剩余消除周期,评估 p 值并删除最不重要的值。 相反,我会跳到最后一个周期,并为您提供最终的模型。 毕竟,这里的主要目标是描述过程和背后的推理。下面你会发现我应用反向消除技术后收敛的最终模型的输出。 您可以从输出中看到,所有其余的预测变量的 p 值显着低于我们的 0.05。 另外值得注意的是最终输出中的 R 平方值。 这里需要注意两点:(1)R 平方和 Adj。 R 平方值是相等的,这表明我们的模型被过度拟合的风险最小,(2)0.894 的值被解释为使得我们的最终模型解释了结果变量中观察到的变化的大约 90% ,"meantempm"。
- model = sm.OLS(y, X).fit()
- model.summary()
现在我们已经完成了选择具有统计意义的预测指标(特征)的步骤,我们可以使用 SciKit-Learn 创建预测模型并测试其预测平均温度的能力。 SciKit-Learn 是一个非常完善的机器学习库,在工业界和学术界广泛使用。关于 SciKit-Learn 的一件事非常令人印象深刻的是,它在许多数值技术和算法中保持了一个非常一致的 "适应","预测" 和 "测试"API,使得使用它非常简单。除了这个一致的 API 设计,SciKit-Learn 还提供了一些有用的工具来处理许多机器学习项目中常见的数据。
我们将通过使用 SciKit-Learn 从 sklearn.model_selection 模块中导入 train_test_split()函数来开始将我们的数据集分割成测试和训练集。我将把训练和测试数据集分成 80%的训练和 20%的测试,并且分配一个 12 的 random_state,以确保你将得到和我一样的随机选择数据。这个 random_state 参数对结果的可重复性非常有用。
- from sklearn.model_selection import train_test_split
- # first remove the const column because unlike statsmodels, SciKit-Learn will add that in for us
- X = X.drop('const', axis=1)
- X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=12)
接下来的操作是使用训练数据集建立回归模型。 为此,我将从 sklearn.linear_model 模块导入并使用 LinearRegression 类。 正如前面提到的,scikit-learn 分数通过通用的 fit() 和 predict() 这两个函数计算得到。
- from sklearn.linear_model importLinearRegression
- # instantiate the regressor class
- regressor =LinearRegression()
- # fit the build the model by fitting the regressor to the training data
- regressor.fit(X_train, y_train)
- # make a prediction set using the test set
- prediction = regressor.predict(X_test)
- # Evaluate the prediction accuracy of the model
- from sklearn.metrics import mean_absolute_error, median_absolute_error
- print("The Explained Variance: %.2f"% regressor.score(X_test, y_test))
- print("The Mean Absolute Error: %.2f degrees celsius"% mean_absolute_error(y_test, prediction))
- print("The Median Absolute Error: %.2f degrees celsius"% median_absolute_error(y_test, prediction))
- TheExplainedVariance:0.90
- TheMeanAbsoluteError:2.69 degrees celsius
- TheMedianAbsoluteError:2.17 degrees celsius
正如你可以在上面几行代码中看到的那样,使用 scikit-learn 构建线性回归预测模型非常简单。
为了获得关于模型有效性的解释性理解,我使用了回归模型的 score()函数来确定该模型能够解释在结果变量(平均温度)中观察到的约 90%的方差。 此外,我使用 sklearn.metrics 模块的 mean_absolute_error()和 median_absolute_error()来确定平均预测值约为 3 摄氏度关闭,一半时间关闭约 2 摄氏度。
在本文中,我演示了基于上一篇文章收集的数据如何使用线性回归机器学习算法来预测未来的平均天气温度。在本文中,我演示了如何使用线性回归机器学习算法来预测未来的平均天气温度,基于上一篇文章收集的数据。 我演示了如何使用 statsmodels 库来根据合理的统计方法选择具有统计显着性的预测指标。 然后,我利用这些信息来拟合基于 Scikit-Learn 的 LinearRegression 类的训练子集的预测模型。 然后使用这个拟合的模型,我可以根据测试子集的输入预测预期值,并评估预测的准确性。
来源: https://segmentfault.com/a/1190000012681601