在机器学习中的线性回归,一般都会使用scikit-learn中的linear_model这个模块,用linear_model的好处是速度快、结果简单易懂,但它的使用是有条件的,就是使用者在明确该模型是线性模型的情况下才能用,否则生成的结果很可能是错误的。
如果不知道该模型是否是线性模型的情况下可以使用statsmodels,statsmodels是python中专门用于统计学分析的包,它能够帮我们在模型未知的情况下来检验模型的线性显著性。
导入模块并准备数据
相关数据准备可以参考金融数据准备。
代码语言:javascript复制import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
import math
import matplotlib.pyplot as plt
import seaborn as sns
import yfinance as yf
symbol = 'TCEHY'
df.head()
Statsmodels
Statsmodels是Python进行拟合多种统计模型、进行统计试验和数据探索可视化的库。statsmodels包含许多经典的统计方法,但没有贝叶斯方法和机器学习模型。
Statsmodels包含的模型有:
- 线性模型,广义线性模型和健壮线性模型
- 线性混合效应模型
- 方差(ANOVA)方法分析
- 时间序列过程和状态空间模型
- 广义矩估计
Statsmodels 的线性模型有两种不同的接口:基于数组和基于公式。
代码语言:javascript复制import statsmodels.api as sm
import statsmodels.formula.api as smf
statsmodels.api
x = sm.add_constant(x)
是给
加上一列常数项
的原因是该模型是一条直线,其在
轴上是有截距的,这个常数
就是反映此截距。
model = sm.OLS(y, x)
就是用最小二乘法来进行建模,最小二乘法(ordinary least squares,即OLS)是回归分析中最常用的方法。
statsmodels.formula.api
Statsmodels.formula.api要求用户输入公式,公式的形式为"parm1 ~ parm2"
,第一个参数parm1
是被解释变量,相对于
,第二个参数parm2
则是解释变量,相对于
。
而smf.ols还要输入数据data
,这个数据必须是pandas.DataFrame格式的,当使用公式和pandas对象时,不需要使用add_constant
。
简单一元线性回归
一元线性回归模型的公式
代码实操
代码语言:javascript复制# 使用一个变量
import statsmodels.api as sm
# from statsmodels.formula.api import ols
# 普通最小二乘法拟合
from statsmodels.sandbox.regression.predstd import wls_prediction_std
# stock_model = ols("Adj_Close ~ Open", data=df).fit()
# stock_model.summary()
x = df.Open.values
#增加一个常数1,对应回归线在y轴上的截距
x = sm.add_constant(x)
y = df.Adj_Close.values
#用最小二乘法建模
model = sm.OLS(y, x)
results = model.fit()
print(results.summary())
summary
结果介绍
Summary
内容较多,其中重点考虑参数R-squared、Prob(F-statistic)以及P>|t| 的两个值,通过这4个参数就能判断的模型是否是线性显著的,同时知道显著的程度如何。
R-squared
决定系数,其值=SSR/SST,SSR是Sum of Squares for Regression,SST是Sum of Squares for Total,这个值范围在[0, 1],其值越接近1,说明回归效果越好。F-statistic
这就是我们经常用到的F检验,这个值越大越能推翻原假设,本例中其值为156.9,这个值过大,说明我们的模型是线性模型,原假设是“我们的模型不是线性模型”。Prob (F-statistic)
这就是上面F-statistic的概率,这个值越小越能拒绝原假设,本例中为1.25e-08,该值非常小了,足以证明我们的模型是线性显著的。P>|t|
统计检验中的P值,这个值越小越能拒绝原假设。
线性回归图像
Statsmodels的plot_regress_exog
函数来帮助我们理解我们的模型。
根据一个回归因子绘制回归结果。在一个2×2
的图中绘制了四幅图:"endog vs exog","残差vs exog","拟合vs exog"和"拟合 残差vs exog"
fig = plt.figure(figsize=(15,8))
fig = sm.graphics.plot_regress_exog(
stock_model,
"Open",
fig=fig)
回归图像解释
"Y和拟合x"
图绘制了因变量相对于预测值与置信区间。图中直线关系在表明开盘价与收盘价是线性正相关的,例如当一个变量增加时另一个变量也增加。
"残差与开盘价"
的图像显示了模型关于预测变量对应的残差。图像中每一个具体的点都是观测值;图中的黑色直线表示那些观测值的平均值。因为有些点与平均没有距离关系,所以OLS假设同方差性成立。
"偏回归图像"
显示了开盘价与收盘价之间的关系,考虑到在已存在的开盘价的协同因素中添加其他独立变量的影响。后面会看到当增加更多的变量后同样的图像会怎样变化。
"分量和分量加残差"
的图像是一个偏回归图像的扩展,但显示了在开盘价的协同因素中添加了其他的独立变量后,增加的影响使得趋势线有误差。
置信区间
下面做图画出拟合线「绿色标记」,样本数据中的观测值「蓝色圆点」,置信区间「红色标记」。
代码语言:javascript复制# 获取置信区间
# wls_prediction_std(housing_model)返回三个值, 标准差,置信区间下限,置信区间上限
_, confidence_interval_lower, confidence_interval_upper = wls_prediction_std(stock_model)
# 创建画布
fig, ax = plt.subplots(figsize=(10,7))
# 'bo' 代表蓝色的圆形,
ax.plot(X, y, 'bo', label="data")
# 绘制趋势线
ax.plot(X, stock_model.fittedvalues, 'g--.', label="OLS")
# 绘制上下置信区间
ax.plot(X, confidence_interval_upper, 'r--')
ax.plot(X, confidence_interval_lower, 'r--')
# 绘制标题,网格,和图例
ax.set_title('Simple Linear Regression')
ax.grid()
ax.legend(loc='best')
线性回归拟合散点图
一般在不使用statsmodels模块时,运用线性回归加散点图的绘制组合图,同样可以以此判断变量是否线性相关性。
以Open
为预测自变量,Adj_Close
为因变量,绘制散点图。由图可发现,两变量呈现较好的线性相关性。
# 预测变量(X)、因变量(y)
model = LinearRegression()
model.fit(X, y)
LinearRegression(copy_X=True,
fit_intercept=True,
n_jobs=None,
normalize=False)
a = model.coef_ * X model.intercept_
plt.figure(figsize=(12,8))
plt.plot(X, y, 'ro', X, a)
多元线性回归
多元线性回归模型公式
运用多元线性回归模型可以加入多个变量,看看哪些自变量的组合更优地满足OLS最小二乘假定。从而分析影响收盘价格的影响因素。
建模
本次共四个字变量Open High Low Volume
,分析每个变量对因变量Adj_Close
的影响。
# 多个特征
stock_models = ols("Adj_Close ~ Open High Low Volume",
data=df).fit()
stock_models.summary()
绘制偏回归图
plot_partregress_grid
绘制多元偏回归图,展示包括截距项在内对多个自变量与因变量间的关系。并同时加上线性拟合线展示对收盘价对影响。
fig = plt.figure(figsize=(20,12))
fig = sm.graphics.plot_partregress_grid(
stock_models, fig=fig)
二阶多项式回归模型
研究一个因变量与一个或多个自变量间多项式的回归分析方法,称为多项式回归 Polynomial Regression 。如果自变量只有一个时,称为一元多项式回归;如果自变量有多个时,称为多元多项式回归。
多项式回归,回归函数是回归变量多项式的回归。多项式回归模型是线性回归模型的一种,此时回归函数关于回归系数是线性的。
Scikit-learn 中,我们可以通过 PolynomialFeatures()
类自动产生多项式特征矩阵。
from sklearn.preprocessing import PolynomialFeatures
# 数据准备
X = df[['Open', 'High']].values
y = df[['Adj_Close']].values
X = np.array(X)
y = np.array(y)
# 产生多项式
poly = PolynomialFeatures(degree=2)
poly_features = poly.fit_transform(X)
poly.fit(X,y)
# 训练回归模型
poly_regression = LinearRegression()
poly_regression.fit(poly_features,y)
X = X[:,:-1]
多项式回归绘制回归图
代码语言:javascript复制poly = PolynomialFeatures(degree=2)
poly_features = poly.fit_transform(X)
poly_regression = LinearRegression()
poly_regression.fit(poly_features,y)
plt.scatter(X,y, color='red')
plt.plot(X,poly_regression.predict(poly_features))
regressor = LinearRegression()
regressor.fit(X,y)
plt.scatter(X,y, color='red')
plt.plot(X,regressor.predict(X))
多元真实情况未必是线性的,有时需要增加指数项,也就是高阶多项式回归。因此通过增加指数型重新拟合数据。根据模型得分找出适合数据的回归模型。
三阶多项式回归模型
代码语言:javascript复制X = df[['Open', 'High', 'Low']].values
y = df[['Adj_Close']].values
poly_3 = PolynomialFeatures(degree=3)
poly_features = poly_3.fit_transform(X)
poly.fit(X,y)
poly_regression = LinearRegression()
poly_regression.fit(poly_features,y)
X = X[:,:-2]
# 绘图代码同上
四阶多项式回归模型
代码语言:javascript复制X = df[['Open', 'High', 'Low', 'Volume']].values
y = df[['Adj_Close']].values
poly_4 = PolynomialFeatures(degree=4)
poly_features = poly_4.fit_transform(X)
poly.fit(X,y)
poly_regression = LinearRegression()
poly_regression.fit(poly_features,y)
X = X[:,:-3]
# 绘图代码同上
代码语言:javascript复制poly_regression.score(X,y)
0.5198490476815341
此时模型得分仅有0.519
,模型已经严重过拟合了。
因为这里我们使用的数据基本是线性的,在其他场景中,需要根据实际情况确定多项式回归的最高次幂,可以绘制学习曲线,根据模型在训练集及测试集上的得分来确定最终结果。