线性回归作为数据分析的一项基本操作,是非常关键的,也是初学者必须掌握的内容,针对线性回归,本篇主要阐述如果用Python实现线性回归。
第三篇:10分钟学会用Python做线性回归
导语:线性回归作为数据分析的一项基本操作,是非常关键的,也是初学者必须掌握的内容,针对线性回归,本篇主要阐述如果用Python实现线性回归。
一、理解什么是线性回归
线性回归也被称为最小二乘法回归。它的数学模型是这样的:y = a+ bx+e 其中,a被称为常数项或截距;b被称为模型的回归系数或斜率;e为误差项。a和b是模型的参数。当然,模型的参数只能从样本数据中估计出来:y'= a' + b'x
我们的目标是选择合适的参数,让这一线性模型最好地拟合观测值。拟合程度越高,模型越好。
那么,接下来的问题就是,我们如何判断拟合的质量呢?
高斯和勒让德找到的方法是:被选择的参数,应该使算出来的回归线与观测值之差的平房和最小。用函数表示为:
这就是通常我们说的最小二乘法,其原理为:当预测值和实际值距离的平方和最小时,就选定模型中的两个参数a、b。
python的statsmodels包已经有进行最小二乘法的函数,我们只要会用就行,想详细了解其数学推导过程的同学可以自己翻阅计量经济学相关书籍。
二、利用statsmodels进行线性回归
首先我们创造一条线
In [3]:
import numpy as np
import pandas as pd
import statsmodels.api as sm
import matplotlib.pyplot as plt
# 创找一列从0到10等步长的array,共100个值
x = np.linspace(0, 10, 100)
x[:20]
Out[3]:
array([ 0. , 0.1010101 , 0.2020202 , 0.3030303 , 0.4040404 ,
0.50505051, 0.60606061, 0.70707071, 0.80808081, 0.90909091,
1.01010101, 1.11111111, 1.21212121, 1.31313131, 1.41414141,
1.51515152, 1.61616162, 1.71717172, 1.81818182, 1.91919192])
为x增加一列1的常数项
In [4]:
X = sm.add_constant(x)
X[:10]
Out[4]:
array([[ 1. , 0. ],
[ 1. , 0.1010101 ],
[ 1. , 0.2020202 ],
[ 1. , 0.3030303 ],
[ 1. , 0.4040404 ],
[ 1. , 0.50505051],
[ 1. , 0.60606061],
[ 1. , 0.70707071],
[ 1. , 0.80808081],
[ 1. , 0.90909091]])
然后设置模型里的a和b,这里我们设置成2和8
In [5]:
beta = np.array([2, 8])
用np.random.normal生成一个长度为100的随机数作为误差项,数据服从正态分布。
In [6]:
e = np.random.normal(size=100)
e[:10]
Out[6]:
array([-0.5062008 , 0.42405168, 0.85732075, -1.44337927, 0.25390632,
-0.8546313 , -0.12931056, -2.28387215, -0.76175643, -0.66263649])
生成对应的y值,并画出曲线
In [7]:
y = np.dot(X,beta) + e
plt.plot(x,y,'r--.',label='data')
plt.show()
仅知道x,y情况下利用statsmodels进行OLS回归,计算系数。
In [8]:
model = sm.OLS(y,X)
获得拟合结果。
In [9]:
results = model.fit()
打印计算到的的系数
In [10]:
print(results.params)
[ 1.45477708 8.09692123]
打印更详细的回归数据,包括对各参数的t检验,R-squared,AIC,BIC等
In [11]:
results.summary()
Out[11]:
| Dep. Variable: | y | R-squared: | 0.998 |
|---|---|---|---|
| Model: | OLS | Adj. R-squared: | 0.998 |
| Method: | Least Squares | F-statistic: | 5.290e+04 |
| Date: | Tue, 13 Feb 2018 | Prob (F-statistic): | 9.70e-136 |
| Time: | 15:52:10 | Log-Likelihood: | -143.50 |
| No. Observations: | 100 | AIC: | 291.0 |
| Df Residuals: | 98 | BIC: | 296.2 |
| Df Model: | 1 | ||
| Covariance Type: | nonrobust |
| | coef | std err | t | P>|t| | [0.025 | 0.975] | | ----- | ------ | ------- | ------- | ------- | ------ | ------ | | const | 1.4548 | 0.204 | 7.140 | 0.000 | 1.050 | 1.859 | | x1 | 8.0969 | 0.035 | 230.002 | 0.000 | 8.027 | 8.167 |
| Omnibus: | 8.027 | Durbin-Watson: | 2.193 |
|---|---|---|---|
| Prob(Omnibus): | 0.018 | Jarque-Bera (JB): | 3.681 |
| Skew: | -0.201 | Prob(JB): | 0.159 |
| Kurtosis: | 2.151 | Cond. No. | 11.7 |
取出其中的具体数据方法为:
输入 results. 再按tab
In [13]:
print(results.aic)
print(results.bic)
print(results.fvalue)
290.990361332
296.200701704
52900.7567873
获得拟合数据
In [14]:
y_predict = results.predict()
y_predict[:10]
Out[14]:
array([ 1.45477708, 2.27264791, 3.09051874, 3.90838957, 4.72626041,
5.54413124, 6.36200207, 7.1798729 , 7.99774373, 8.81561456])
画出原曲线和拟合曲线
In [15]:
plt.subplots(figsize=(8,6))
plt.plot(x,y,'r--.',label='data')
plt.plot(x,y_predict,'b--.',label='OLS')
plt.show()
应用:利用OLS计算股票历史Beta
首先获得上证指数一年的数据,并计算每日涨幅。
In [16]:
value1 = get_price('000001.SH',None,'20160105','1d',['close'],True,'pre',240)
value1['roc1'] = value1.close/value1.close.shift(1) - 1.0
value1[:3]
Out[16]:
| close | roc1 | |
|---|---|---|
| 2015-01-13 | 3235.30 | NaN |
| 2015-01-14 | 3222.44 | -0.003975 |
| 2015-01-15 | 3336.46 | 0.035383 |
获得天津港600717.SH一年的数据,并计算每日涨幅。
In [17]:
value2 = get_price('600717.SH',None,'20160105','1d',['close'],True,'pre',240)
value2['roc2'] = value2.close/value2.close.shift(1) - 1.0
value2[:3]
Out[17]:
| close | roc2 | |
|---|---|---|
| 2015-01-13 | 16.65 | NaN |
| 2015-01-14 | 16.31 | -0.020420 |
| 2015-01-15 | 16.83 | 0.031882 |
将两数据横向合并,删除空数据。
In [18]:
value3 = pd.concat([value1,value2],axis=1)
value3 = value3.dropna() #删掉nan数据
value3[:3]
Out[18]:
| close | roc1 | close | roc2 | |
|---|---|---|---|---|
| 2015-01-14 | 3222.44 | -0.003975 | 16.31 | -0.020420 |
| 2015-01-15 | 3336.46 | 0.035383 | 16.83 | 0.031882 |
| 2015-01-16 | 3376.50 | 0.012001 | 17.00 | 0.010101 |
以天津港600717.SH每日涨幅为横轴,上证指数每日涨幅为纵轴,画图。
In [19]:
y = value3.roc1.values
x = value3.roc2.values
plt.subplots(figsize=(8,6))
plt.plot(x,y,'r.',label='data')
plt.show()
用statsmodels包进行拟合,并画图。
In [20]:
import numpy as np
import pandas as pd
import statsmodels.api as sm
import matplotlib.pyplot as plt
X = sm.add_constant(x)
model = sm.OLS(y,X)
results = model.fit()
y_predict = results.predict()
plt.subplots(figsize=(8,6))
plt.plot(x,y,'r.',label='data')
plt.plot(x,y_predict,'b.-',label='data')
plt.show()
计算的到的k值即股票相对大盘的Beta值
In [21]:
print('天津港600717.SH相对上证指数的Beta值为:'+str(results.params[1]))
天津港600717.SH相对上证指数的Beta值为:0.526072480204
查看以上策略详情请到supermind量化交易官网查看:同花顺Supermind量化交易 财务分析建模 -10分钟学会用Python做线性回归