线性回归预测模型属于经典的统计学模型,该模型的应用场景是根据已知的变量(即自变量)来预测某个连续的数值变量(因变量)。例如,餐厅根据每天的营业数据(菜谱价格、就餐人数等等)来预测就餐规模或者营业额;网站根据访问的历史数据(包括新用户的注册量、老用户的活跃度等等)来预测用户的支付转化率;医院根据患者的病历数据(体检指标、既往病史、饮食习惯等等)来预测某种疾病发生的概率。
站在数据挖掘的角度看待线性回归模型,它属于一种有监督的学习算法,即在建模过程中必须同时具备自变量和因变量。此处重点介绍线性回归模型背后的数学原理和应用实践。通过对本知识的学习,我熟悉并基本掌握了以下内容:
有监督的学习算法
有监督学习是一种方法,通过这种方法,您可以使用标记的训练数据来训练一个函数,然后将其推广到新示例。该训练过程需要一位评论员参与,能够指出函数是否正确,然后更改函数以生成正确的结果。
在有监督学习中,训练数据进行了标记并由输入数据和所需输出组成,您可以使用这些数据创建一个函数(或模型)。监督以有用输出的形式出现,这反过来让您能够根据它产生的实际输出来调整函数。在训练后,您可以将此函数应用于新的观察值,生成理想情况下正确响应的输出(预测或分类)。
一元线性回归模型也被称为简单线性回归模型,是指模型中只含有一个自变量和一个因变量,用来建模的数据集可以表示成 { ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . , ( x n , y n ) } \{(x_1,y_1),(x_2,y_2),...,(x_n,y_n)\} {(x1,y1),(x2,y2),...,(xn,yn)}。其中 x i x_i xi表示自变量 x x x的第 i i i个值, y i y_i yi表示因变量 y y y的第 i i i个值, n n n表示数据集的样本量。当模型构建好后,就可以根据其他自变量 x x x的值,预测因变量 y y y的值,该模型的数学公式可以表示成 y = a + b x + ϵ y=a+bx+\epsilon y=a+bx+ϵ如上公式所示,该模型特别像初中所学的一次函数。其中, a a a为模型的截距项, b b b为模型的斜率项, ϵ \epsilon ϵ为模型的误差项。模型中的 a a a和 b b b统称为回归系数,误差项 ϵ \epsilon ϵ的存在主要是为了平衡等号两边的值,通常被称为模型无法解释的部分。
平衡等号两边的值?该参数我们会在接下来进行详细介绍
为了快速理解简单线性回归模型的数学公式,我们以收入数据集为例,探究工作年限与收入之间的关系。首先我们导入数据集,绘制工作年限与收入之间的散点图,并根据散点图添加一条拟合线,部分代码如下:
# 导入数据集
income = pd.read_csv(r'C:\Users\Administrator\Desktop\Salary_Data.csv')
# 绘制散点图
sns.lmplot(x = 'YearsExperience', y = 'Salary', data = income, ci = None)
# 显示图形
plt.show()
如图反映的就是自变量YearsExperience与因变量Salary之间的散点图,从图中趋势来看,工作经验与收入之间存在明显的正相关关系,即工作经验越丰富,收入水平就越高(实时上也确实如此)。图中的直线就是关于散点的线性回归拟合线,那么我们如何得到该拟合线的数学表达式呢?
前面我们的数学表达式中说到:误差项 ϵ \epsilon ϵ的存在主要是为了平衡等号两边的值,我们怎么去理解这句话?我们试想一下,如果拟合线能精确地捕捉到每一个点(即所有的点都落在拟合线上),那么对应的误差项误差项 ϵ \epsilon ϵ应该为0(显然这是不太可能的,只有当自变量与因变量之间是严格的线性相关关系才可能)。按照这个思路来看,我们寻求的一条理想的拟合曲线,就是使得误差项 ϵ \epsilon ϵ达到最小。在这里误差项是 y y y与 a + b x a+bx a+bx的差,结果可正可负,因此我们此处刻画误差项最小的问题从最小二乘法的角度出发,即把问题转化为使误差项平方和最小。
最小二乘法
最小二乘法(又称最小平方法)是一种数学优化技术。它通过最小化误差的平方和寻找数据的最佳函数匹配。利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间误差的平方和为最小。最小二乘法还可用于曲线拟合。其他一些优化问题也可通过最小化能量或最大化熵用最小二乘法来表达。
误差的平方和公式可表示为: J ( a , b ) = ∑ i = 1 n ϵ 2 = ∑ i = 1 n ( y i − [ a + b x i ] ) 2 J(a,b)=\sum_{i=1}^{n}\epsilon^2=\sum_{i=1}^{n}(y_i-[a+bx_i])^2 J(a,b)=i=1∑nϵ2=i=1∑n(yi−[a+bxi])2由于建模时自变量与因变量都是已知的,因此求解误差项平方和最小的问题就是求解上面函数 J ( a , b ) J(a,b) J(a,b)的最小值,而该函数的参数就是我们所要最终求解的回归系数 a a a和 b b b。
该目标函数是一个二元二次函数,如需使得目标函数 J ( a , b ) J(a,b) J(a,b)达到最小,要求一个二元二次函数的极值,我们使用高等数学中求二元二次方程的极值的方法来入手考虑该问题,我们可以令函数分别对两个参数求偏导数,然后令两个偏导式都等于0,解该方程组可求得结果。
二元二次方程的极值
二元二次方程是指含有两个未知数,并且含有未知数的项的最高次数是二的整式方程,叫做二元二次方程。其一般式为ax2+bxy+cy2+dx+ey+f=0。(a、b、c、d、e、f都是常数,且a、b、c中至少有一个不是零;当b=0时,a与d以及c与e分别不全为零;当a=0时,c、e至少一项不等于零,当c=0时,a、d至少一项不为零)。
求解二元二次方程极值的一般方法为分别令方程对x与y的偏导数为0,求解方程组可得极值。
关于目标函数的推导过程如下:
①展开平方项目 J ( a , b ) = ∑ i = 1 n ( y i 2 + a 2 + b 2 x i 2 + 2 a b x i − 2 a y i − 2 b x i y i ) J(a,b)=\sum_{i=1}^{n}(y_i^2+a^2+b^2x_i^2+2abx_i-2ay_i-2bx_iy_i) J(a,b)=i=1∑n(yi2+a2+b2xi2+2abxi−2ayi−2bxiyi)②设偏导数为0 { ∂ J ∂ a = ∑ i = 1 n ( 0 + 2 a + 0 + 2 b x i − 2 y i + 0 ) = 0 ∂ J ∂ b = ∑ i = 1 n ( 0 + 0 + 2 b x i 2 + 2 a x i + 0 − 2 x i y i ) = 0 \begin{cases}\frac{\partial J}{\partial a}=\sum_{i=1}^{n}(0+2a+0+2bx_i-2y_i+0)=0\\\\\frac{\partial J}{\partial b}=\sum_{i=1}^{n}(0+0+2bx_i^2+2ax_i+0-2x_iy_i)=0\end{cases} ⎩⎪⎨⎪⎧∂a∂J=∑i=1n(0+2a+0+2bxi−2yi+0)=0∂b∂J=∑i=1n(0+0+2bxi2+2axi+0−2xiyi)=0③和公式转换 { ∂ J ∂ a = 2 n a + 2 b ∑ i = 1 n x i − 2 ∑ i = 1 n y i = 0 ∂ J ∂ b = 2 b ∑ i = 1 n x i 2 + 2 a ∑ i = 1 n x i − 2 ∑ i = 1 n x i y i = 0 \begin{cases}\frac{\partial J}{\partial a}=2na+2b\sum_{i=1}^{n}x_i-2\sum_{i=1}^{n}y_i=0\\\\\frac{\partial J}{\partial b}=2b\sum_{i=1}^{n}x_i^2+2a\sum_{i=1}^{n}x_i-2\sum_{i=1}^{n}x_iy_i=0\end{cases} ⎩⎪⎨⎪⎧∂a∂J=2na+2b∑i=1nxi−2∑i=1nyi=0∂b∂J=2b∑i=1nxi2+2a∑i=1nxi−2∑i=1nxiyi=0④化解 { a = ∑ i = 1 n y i n − b ∑ i = 1 n x i n b ∑ i = 1 n x i 2 + ( ∑ i = 1 n y i n − b ∑ i = 1 n x i n ) ∑ i = 1 n x i − ∑ i = 1 n x i y i = 0 \begin{cases}a=\frac{\sum_{i=1}^{n}y_i}{n}-\frac{b\sum_{i=1}^{n}x_i}{n}\\\\b\sum_{i=1}^{n}x_i^2+(\frac{\sum_{i=1}^{n}y_i}{n}-\frac{b\sum_{i=1}^{n}x_i}{n})\sum_{i=1}^{n}x_i-\sum_{i=1}^{n}x_iy_i=0\end{cases} ⎩⎪⎨⎪⎧a=n∑i=1nyi−nb∑i=1nxib∑i=1nxi2+(n∑i=1nyi−nb∑i=1nxi)∑i=1nxi−∑i=1nxiyi=0⑤将参数 a a a代入,求解 b b b { a = y ‾ − b x ‾ b = ∑ i = 1 n x i y i − 1 n ∑ i = 1 n x i ∑ i = 1 n y i ∑ i = 1 n x i 2 − 1 n ( ∑ i = 1 n x i ) 2 \begin{cases}a=\overline y-b\overline x\\\\b=\frac{\sum_{i=1}^{n}x_iy_i-\frac{1}{n}\sum_{i=1}^{n}x_i\sum_{i=1}^{n}y_i}{\sum_{i=1}^{n}x_i^2-\frac{1}{n}(\sum_{i=1}^{n}x_i)^2}\end{cases} ⎩⎪⎪⎨⎪⎪⎧a=y−bxb=∑i=1nxi2−n1(∑i=1nxi)2∑i=1nxiyi−n1∑i=1nxi∑i=1nyi如上推导过程所示,参数 a a a和 b b b的值都是关于自变量 x x x和 y y y的公式。接下来,根据该公式,利用Python计算出回归模型的参数 a a a和 b b b。代码如下:
# 简单线性回归模型的参数求解
# 样本量
n = income.shape[0]
# 计算自变量、因变量、自变量平方、自变量与因变量乘积的和
sum_x = income.YearsExperience.sum()
sum_y = income.Salary.sum()
sum_x2 = income.YearsExperience.pow(2).sum()
xy = income.YearsExperience * income.Salary
sum_xy = xy.sum()
# 根据公式计算回归模型的参数
b = (sum_xy-sum_x*sum_y/n)/(sum_x2-sum_x**2/n)
a = income.Salary.mean()-b*income.YearsExperience.mean()
查看 a a a和 b b b的值,结果如下
In [6]: print('回归参数a的值:',a)
...: print('回归参数b的值:',b)
回归参数a的值: 25792.200198668666
回归参数b的值: 9449.962321455081
如上,我们利用Python手动编写每一步的代码,最终得到了模型的回归参数值,但是这种过程无疑是麻烦的,在我们已经对一元线性回归模型有了足够多的了解之后,利用其来解决问题时如果每次都要手动编写代码,无疑会耗费大量的时间在代码的编写上,因为我们理解这个原理之后,对于可以用该模型来建模的现实例子来说,我们关心的只是数据的输入和所得到的回归系数,以及后面利用数据集及得到的回归系数等对模型进行评估。
那么在Python中,是否有现成的第三方模块可以调用呢?答案是肯定的,这个模块就是statsmodels,它是专门用于统计建模的第三方模块,如需实现线性回归模型参数的求解,可以调用其子模块中的ols函数,对该函数的简单介绍如下:
ols(formula, data, subset=None, drop_cols=None)
这个函数的语法非常简单,而且其参数也通俗易懂,但该函数的功能却很强大,不仅可以计算模型的参数,还可以对模型的参数和模型本身做显著性检验、计算模型的决定系数等。
接下来,我们利用该函数来计算模型的参数值,得出结果后与手工方式编写代码的结果进行比对,以验证我们的结果是否正确,代码如下:
# 导入第三方模块
import statsmodels.api as sm
# 利用收入数据集,构建回归模型
fit = sm.formula.ols('Salary ~ YearsExperience', data = income).fit()
查看模型的参数值:
In [8]: # 返回模型的参数值
...: fit.params
Out[8]:
Intercept 25792.200199
YearsExperience 9449.962321
dtype: float64
如上所示,Intercept 表示截距项对应的参数值,YearsExperience表示自变量工作年限对应的参数值。
与我们手工编写代码所获得的结果进行对比,函数计算出来的参数值与手工计算出来的结果完全一致,所以,关于收入的简单线性回归模型可以表示成 S a l a r y = 25792.200199 + 9449.962321 Y e a r s E x p e r i e n c e Salary=25792.200199+9449.962321YearsExperience Salary=25792.200199+9449.962321YearsExperience至此,我们完成了对收入使用简单线性回归模型进行预测。
总结
若两个变量具有明显的正(负)相关关系(可以通过画散点图发现两个变量之间的关系),我们就可以使用简单线性回归模型进行建模和预测,但是至此我们又有新的问题产生:如果是多个变量之间的关系呢?如果其在图中散点分布偏离拟合曲线较远呢?我们如如何对模型进行评估?
这就是下面我们要探讨的多元线性回归模型,上面的问题也会在接下来对多元线性回归模型的讲解及实践中进行解决。
一元线性回归模型比较简单,它反映的是单个自变量对因变量的影响,然而实际情况中,影响因变量的自变量往往不止一个,从而需要将一元线性回归模型扩展到多元线性回归模型,接下来我们就来一起学习多元线性回归模型。
如果构建多元线性回归模型的数据集包含n个观测值、p+1个变量(其中p个自变量和1个因变量),则这些数据可以写成下面的矩阵形式: y = { y 1 y 2 . . . y 3 X = { x 11 x 12 ⋯ x 1 p x 21 x 22 ⋯ x 2 p ⋮ ⋮ ⋮ ⋮ x n 1 x n 2 ⋯ x n p y=\begin{cases}y_1\\y_2\\...\\y_3\end{cases}\qquad X=\begin{cases}x_{11}\quad x_{12}\quad \cdots\quad x_{1p}\\x_{21}\quad x_{22}\quad \cdots\quad x_{2p}\\\ \ \vdots\qquad \vdots\qquad \ \vdots\qquad \vdots\\x_{n1}\quad x_{n2}\quad \cdots\quad x_{np}\end{cases} y=⎩⎪⎪⎪⎨⎪⎪⎪⎧y1y2...y3X=⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧x11x12⋯x1px21x22⋯x2p ⋮⋮ ⋮⋮xn1xn2⋯xnp其中 x i j x_{ij} xij代表第 i i i行第 j j j个变量值。按照一元线性回归的逻辑,那么多元线性回归模型应该就是因变量 y y y与自变量 X X X的线性组合,即可以将多元线性回归模型表示成: y = β 0 + β 1 x 1 + β 2 x 2 + ⋯ + β p x p + ϵ y=\beta_0+\beta_1x_1+\beta_2x_2+\cdots+\beta_px_p+\epsilon y=β0+β1x1+β2x2+⋯+βpxp+ϵ根据线性代数的知识可知,可以将上式表示为 y = X β + ϵ y=X\beta+\epsilon y=Xβ+ϵ。其中, β \beta β为 p × 1 p\times1 p×1的一维向量,代表了多元线性回归模型的偏回归系数; ϵ \epsilon ϵ为 n × 1 n\times1 n×1的一维向量,代表了模型拟合后每一个样本的误差项。
在多元线性回归模型中,求解的思路与一元线性回归模型一致,只是我们此时的 ϵ \epsilon ϵ不是一个参数,而是一个 n × 1 n\times1 n×1的一维向量,求解 ϵ \epsilon ϵ的最小值我们也可以从最小二乘法的思想出发,转化为求 ϵ 2 \epsilon^2 ϵ2的最小值,此时由于 ϵ \epsilon ϵ是一个 n × 1 n\times1 n×1的一维向量,所以 ϵ 2 \epsilon^2 ϵ2刚好代表了向量的内积,问题就转化为求 ϵ \epsilon ϵ的内积的最小值(我们可以这么理解,要使得误差最小,也就是要求每个维度的误差平方和最小,所以要把每个维度的误差平方相加进行综合考虑)。详细的推导过程如下:
①构建目标函数 J ( β ) = ∑ ϵ 2 = ∑ ( y − X β ) 2 J(\beta)=\sum\epsilon^2=\sum(y-X\beta)^2 J(β)=∑ϵ2=∑(y−Xβ)2根据线性代数的知识可知,对一个向量求平方可以转化为求该向量的内积,即等于该向量乘以该向量的转置,接下来从该思路出发,对该式进行平方项的展现。
②展开平方项 J ( β ) = ( y − X β ) ′ ( y − X β ) = ( y ′ − β ′ X ′ ) ( y − X β ) = ( y ′ y − y ′ X β − β X ′ y + β ′ X ′ X β ) J(\beta)=(y-X\beta)'(y-X\beta)\\\ \ \qquad=(y'-\beta'X')(y-X\beta)\\\qquad\qquad\qquad\ \quad=(y'y-y'X\beta-\beta X'y+\beta'X'X\beta) J(β)=(y−Xβ)′(y−Xβ) =(y′−β′X′)(y−Xβ) =(y′y−y′Xβ−βX′y+β′X′Xβ)由线性代数的知识可知,上式中的 y ′ X β y'X\beta y′Xβ和 β ′ X ′ y \beta'X'y β′X′y相等。接下来对目标函数求参数 β \beta β的偏导
③求偏导 ∂ J ( β ) ∂ β = ( 0 − X ′ y − X ′ y − 2 β ′ X ′ X ) = 0 \frac{\partial J(\beta)}{\partial \beta}=(0-X'y-X'y-2\beta'X'X)=0 ∂β∂J(β)=(0−X′y−X′y−2β′X′X)=0如上式所示,根据高等数学的知识可知,欲求目标函数的极值,一般的做法都需要从对目标函数各维变量求偏导,再令偏导函数为0,进而根据等式求得导函数中的参数值。
④计算偏回归系数的值 β ′ X ′ X = X ′ y X ′ X β = X ′ y β = ( X ′ X ) − 1 X ′ y \beta'X'X=X'y\\\ X'X\beta=X'y\\\qquad\qquad\qquad\beta=(X'X)^{-1}X'y β′X′X=X′y X′Xβ=X′yβ=(X′X)−1X′y经过如上四步推导,最终可以得到偏回归系数 β \beta β与自变量 X X X、因变量 y y y的数学关系。这个求解的过程其实就是我们前面所说的“最小二乘法”。基于已知的偏回归系数 β \beta β就可以构造多元线性回归模型。完成模型的构建后,我们便可以根据其他已知的自变量 X X X的值预测未知的因变量 y y y的值。
对于多元线性回归模型的偏回归系数进行求解,我们同样可以利用statamodels模块的ols函数,只是此时的formula参数需要以 ′ y = x 1 + x 2 + ⋯ + x n ′ 'y=x_1+x_2+\cdots+x_n' ′y=x1+x2+⋯+xn′来指明多个自变量及因变量分别是哪几个,接下来在使用回归模型进行预测之前,我们首先要得到回归模型,这里以某产品的利润数据集为例,该数据集包含五个变量,分别是产品的研发成本、管理成本、市场营销成本、销售市场和销售利润,数据集中部分数据如下表所示:
RD_Spend | Administration | Marketing_Spend | State | Profit | |
---|---|---|---|---|---|
0 | 165349.20 | 136897.80 | 471784.10 | New York | 192261.83 |
1 | 162597.70 | 151377.59 | 443898.53 | California | 191792.06 |
2 | 153441.51 | 101145.55 | 407934.54 | Florida | 191050.39 |
3 | 144372.41 | 118671.85 | 383199.62 | New York | 182901.99 |
4 | 142107.34 | 91391.77 | 366168.42 | Florida | 166187.94 |
表中数据集的Profit为因变量,其他变量将作为模型的自变量,也就是说我们要对Profit进行预测。需要注意的是,数据集中的State变量为字符型变量,无法直接带入模型进行计算,所以在建模时需要对该变量做特殊处理,首先我们通过编码来获取利润的模型,具体代码如下:
# 多元线性回归模型的构建和预测
# 导入模块
from sklearn import model_selection
# 导入数据
Profit = pd.read_excel(r'C:\Users\Administrator\Desktop\Predict to Profit.xlsx')
# 将数据集拆分为训练集和测试集
train, test = model_selection.train_test_split(Profit, test_size = 0.2, random_state=1234)
# 根据train数据集建模
model = sm.formula.ols('Profit ~ RD_Spend + Administration + Marketing_Spend + C(State)', data = train).fit()
接下来我们来看看所得模型的偏回归系数
In [6]: print('模型的偏回归系数分别为:\n', model.params)
模型的偏回归系数分别为:
Intercept 58581.516503
C(State)[T.Florida] 927.394424
C(State)[T.New York] -513.468310
RD_Spend 0.803487
Administration -0.057792
Marketing_Spend 0.013779
dtype: float64
如上为得到的多元线性回归模型的回归系数。针对上面代码我们做几点说明:
哑变量
虚拟变量 ( Dummy Variables) 又称虚设变量、名义变量或哑变量,用以反映质的属性的一个人工变量,是量化了的自变量,通常取值为0或1。引入哑变量可使线形回归模型变得更复杂,但对问题描述更简明,一个方程能达到两个方程的作用,而且接近现实。具体做法就是将属性各离散值单独构成列,若当前行数据在原来的属性值上等于当前列属性,则当前列该位置置为1,否则置为0。
通过上面过程我们就得到了一个利润模型,而我们知道如果已经得知某个多元线性回归模型 y = β 0 + β 1 x 1 + β 2 x 2 + ⋯ + β p x p y=\beta_0+\beta_1x_1+\beta_2x_2+\cdots+\beta_px_p y=β0+β1x1+β2x2+⋯+βpxp,当有其他新的自变量值时,就可以将这些值代入如上公式中,最终得到未知的 y y y值。在Python中,实现线性回归模型的预测可以使用predict“方法”,关于该“方法”的参数及含义如下
predict(exog=None, transform=True)
接下来我们来对测试集进行预测,代码如下
# 删除test数据集中的Profit变量,用剩下的自变量进行预测
test_X = test.drop(labels = 'Profit', axis = 1)
pred = model.predict(exog = test_X)
对比预测值和实际值
In [8]: print('对比预测值和实际值的差异:\n',pd.DataFrame({'Prediction':pred,'Real':test.Profit}))
对比预测值和实际值的差异:
Prediction Real
8 150621.345802 152211.77
48 55513.218079 35673.41
14 150369.022458 132602.65
42 74057.015562 71498.49
29 103413.378282 101004.64
44 67844.850378 65200.33
4 173454.059692 166187.94
31 99580.888894 97483.56
13 128147.138397 134307.35
18 130693.433835 124266.90
如上所示,得到了多元线性回归模型在测试集上的预测值,为了比较,我们将预测值和测试集中的真实Profit值罗列在一起,这里我们需要注意一点:
对于上面model的输出的回归系数的结果,我们发现,字符型变量State含有三个不同的值,分别是California、Florida和New York,但为什么只衍生出State[Florida]和State[New York]两个变量呢?其实在这里另外一个变量State[California]变成了对照组,这样做的目的是为了减少强内在相关性,这里不做说明,我们会在后面的回归模型的诊断的多重共线性检验中进行介绍。
那么对于哑变量,我们是否可以指定变量中的某个值作为对照组呢?答案是肯定的。如需实现将指定值作为对照组,我们就要通过pandas模块中的get_dummies函数生成哑变量,然后将所需的对照组对应的哑变量删除即可。这里我们以State变量中的New York值作为对照组,代码如下
# 生成由State变量衍生的哑变量
dummies = pd.get_dummies(Profit.State)
# 将哑变量与原始数据集水平合并
Profit_New = pd.concat([Profit,dummies], axis = 1)
# 删除State变量和California变量(因为State变量已被分解为哑变量,New York变量需要作为参照组)
Profit_New.drop(labels = ['State','New York'], axis = 1, inplace = True)
上面代码实现了将New York值作为对照组,接下来我们对新的数据集进行拆分和建模
# 拆分数据集Profit_New
train, test = model_selection.train_test_split(Profit_New, test_size = 0.2, random_state=1234)
# 建模
model2 = sm.formula.ols('Profit ~ RD_Spend + Administration + Marketing_Spend + Florida + California', data = train).fit()
输出模型的偏回归系数
In [10]: print('模型的偏回归系数分别为:\n', model2.params)
模型的偏回归系数分别为:
Intercept 58068.048193
RD_Spend 0.803487
Administration -0.057792
Marketing_Spend 0.013779
Florida 1440.862734
California 513.468310
dtype: float64
结果如上所示,从离散变量State中衍生出来的哑变量在回归系数的结果里只保留了Florida和California,而New York变量则作为了参照组。以该模型的结果为例,得到的模型公式可表达为 P r o f i t = 58068.048193 + 0.803487 R D S p e n d − 0.057792 A d m i n i s t r a t i o n + 0.013779 M a r k e t i n g S p e n d + 1440.862734 F l o r i d a + 513.468310 C a l i f o r n i a Profit=58068.048193+0.803487RD_Spend-0.057792Administration\\+0.013779Marketing_Spend+1440.862734Florida+513.468310California Profit=58068.048193+0.803487RDSpend−0.057792Administration+0.013779MarketingSpend+1440.862734Florida+513.468310California通过以上步骤我们完成了对某产品的利润数据集进行建模和预测,但是在这之中每个回归系数有什么含义?
以研发成本RD_Spend变量和哑变量Florida为例,解释这两个变量在模型中的作用:在其他变量不变的情况下,研发成本每增加1美元,利润会增加0.803487美元;在其他条件不变的情况下,以New York为基准线,如果在Florida销售产品,利润会增加1440.862734美元。
至此,关于产品利润的多元线性回归模型已经构建完成,但是该模型的好与坏并没有相应的结论,还需要进行模型的显著性检验和回归系数的显著性检验。接下来我们会介绍有关线性回归模型中的几点重要假设检验。
对于回归模型的假设性检验,我们介绍以下两种检验:
模型的显著性检验和回归系数的显著性检验分别使用统计学中的 F F F检验法和 t t t检验法,接下来我们一起来看一下有关 F F F检验和 t t t检验的一些知识和实际操作。
在统计学中,有关假设检验的问题,都有一套成熟的步骤。接下来我们先来看一下如何运用 F F F检验完成模型的显著性检验,具体的步骤如下:
(1)提出问题的原假设和备择假设
(2)在原假设的条件下构造统计量F
(3)根据样本信息,计算统计量的值
(4)对比统计量的值和理论 F F F分布的值,如果计算的统计量的值超过理论的值,则拒绝原假设,否则需要接受原假设。
简单来讲就是对比理论条件下求出的 F F F统计量的值与我们根据样本信息所计算计算统计量的值,如果计算的统计量的值超过理论的值,则表示在误差允许的范围内成立。
下面我们分四个步骤对构造的多元线性回归模型进行 F F F检验,进一步确定模型设计否可用。详细步骤如下:
步骤一:提出假设 { H 0 : β 0 = β 1 = ⋯ = β p = 0 H 1 : 系 数 β 0 , β 1 , ⋯ , β p 不 全 为 0 \begin{cases}H_0:\beta_0=\beta_1=\cdots=\beta_p=0\\H_1:系数\beta_0,\beta_1,\cdots,\beta_p不全为0\end{cases} {H0:β0=β1=⋯=βp=0H1:系数β0,β1,⋯,βp不全为0下面我们对以上假设进行解释
H 0 H_0 H0为原假设,该假设认为模型的所有偏回归系数全部为0,即认为没有一个自变量可以构成因变量的线性组合; H 1 H_1 H1为备择假设,正好是原假设的对立面,该假设认为 p p p个自变量中,至少有一个自变量可以构成因变量的线性组合。就 F F F检验而言,我们往往希望通过数据来推翻原假设 H 0 H_0 H0,而接受备择假设 H 1 H_1 H1的结论,这样我们就可以根据自变量与因变量之间的线性组合构造线性回归模型。(注:前面我们在模型构造完成后尚未进行假设性检验,所以模型是否可用尚未知,这里的可用指在给定的误差范围内总能得出理想的结果)
步骤二:构造统计量
这里我们先介绍几个概念以方便我们理解 F F F统计量的构造过程,首先我们需要理解总的离差平方和、回归离差平方和与误差平方和的概念与差异。
假设用点 p ( x , y ) p(x,y) p(x,y)代表数据集中的某个点,用 y ^ \hat y y^表示点 x x x处的预测值;则 ( y − y ^ ) (y-\hat y) (y−y^)为真实值与预测值之间的差异;用 y ‾ \overline y y表示总体的平均值,则 ( y ^ − y ‾ ) (\hat y-\overline y) (y^−y)为预测值与总体平均值之间的差异; ( y − y ‾ ) (y-\overline y) (y−y)为真实值与总体平均值之间的差异。如果将这些差异向量做平方和的计算,则会得到 { ∑ i = 1 n ( y i − y ^ i ) 2 = E S S ∑ i = 1 n ( y ^ i − y ‾ ) 2 = R S S ∑ i = 1 n ( y i − y ‾ ) 2 = T S S \begin{cases}\sum_{i=1}^{n}(y_i-\hat y_i)^2=ESS\\\\\sum_{i=1}^{n}(\hat y_i-\overline y)^2=RSS\\\\\sum_{i=1}^{n}(y_i-\overline y)^2=TSS\end{cases} ⎩⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎧∑i=1n(yi−y^i)2=ESS∑i=1n(y^i−y)2=RSS∑i=1n(yi−y)2=TSS如上公式所示,这里我们做三点说明
根据统计计算(这里不详细进行计算),这三个平方和之间存在这样的等式关系: T S S = E S S + R S S TSS=ESS+RSS TSS=ESS+RSS。由于 T S S TSS TSS的值不会随着模型的变化而变动,因此 E S S ESS ESS与 R S S RSS RSS之间存在严格的负向关系,即 E S S ESS ESS的降低会导致 R S S RSS RSS的增加。我们在前面内容已经讲过:线性回归模型的参数求解是依据误差平方和最小的理论,所以这里我们需要使得到的 E S S ESS ESS值尽量小(至少应该小于某一置信水平所估计出来的 E S S ESS ESS),如果根据线性回归模型得到的 E S S ESS ESS值达到最小,那么对应的 R S S RSS RSS值就会达到最大,进而 R S S RSS RSS与 E S S ESS ESS的商也会达到最大。
按照这个逻辑,便可以构造 F F F统计量,该统计量可以表示成回归离差平方和 R S S RSS RSS与误差平方和 E S S ESS ESS的公式 F = R S S / p E S S / ( n − p − 1 ) ∼ F ( p , n − p − 1 ) F=\frac{RSS/p}{ESS/(n-p-1)}\sim F(p,n-p-1) F=ESS/(n−p−1)RSS/p∼F(p,n−p−1)其中, p p p和 n − p − 1 n-p-1 n−p−1分别为 R S S RSS RSS和 E S S ESS ESS的自由度(统计学术语,在这里我们不进行详细说明)。模型的拟合度越好, E S S ESS ESS就会越小, R S S RSS RSS则会越大,得到的 F F F统计量也就越大。
置信水平
置信水平是指特定个体对待特定命题真实性相信的程度,也就是概率是对个人信念合理性的量度。概率的置信度解释表明,事件本身并没有什么概率,事件之所以指派有概率只是指派概率的人头脑中所具有的信念证据。置信水平是指总体参数值落在样本统计值某一区内的概率;而置信区间是指在某一置信水平下,样本统计值与总体参数值间误差范围。置信区间越大,置信水平越高。
置信区间的计算公式取决于所用到的统计量。置信区间是在预先确定好的显著性水平下计算出来的,显著性水平通常称为α(希腊字母alpha),如前所述,绝大多数情况会将α设为0.05。置信度为(1-α),或者100×(1-α)%。于是,如果α=0.05,那么置信度则是0.95或95%
——百度词条
显著性水平
显著性水平是估计总体参数落在某一区间内,可能犯错误的概率,用α表示。
显著性水平是假设检验中的一个概念,是指当原假设为正确时人们却把它拒绝了的概率或风险。它是公认的小概率事件的概率值,必须在每一次统计检验之前确定,通常取α=0.05或α=0.01。这表明,当作出接受原假设的决定时,其正确的可能性(概率)为95%或99%。
——百度词条
自由度
在统计学中,自由度(英语:degree of freedom, df)是指当以样本的统计量来估计总体的参数时,样本中独立或能自由变化的数据的个数,称为该统计量的自由度[1]。一般来说,自由度等于独立变量减掉其衍生量数[2];举例来说,方差的定义是样本减平均值的平方之和(一个由样本决定的衍生量),因此对N个随机样本而言,其自由度为N-1。[3]
——维基百科
步骤三:计算统计量
下面按照 F F F统计量的公式,运用Python来计算统计量的值,部分代码如下:
# 计算建模数据中,因变量的均值
ybar = train.Profit.mean()
# 统计变量个数和观测个数
p = model2.df_model
n = train.shape[0]
# 计算回归离差平方和
RSS = np.sum((model2.fittedvalues-ybar) ** 2)
# 计算误差平方和
ESS = np.sum(model2.resid ** 2)
# 计算F统计量的值
F = (RSS/p)/(ESS/(n-p-1))
输出 F F F统计量的值,结果如下
In [15]: print('F统计量的值:',F)
F统计量的值: 174.63721716844685
上面是我们手工编写代码计算所得的 F F F统计量的值,为了验证我们的计算结果是否正确,可以通过fvalue“方法”直接获得模型的 F F F统计量的值(事实上我们在实际应用中也偏向于直接获取以节约时间,而不是手工编写代码),如下
In [5]: # 返回模型中的F值
...: model2.fvalue
Out[5]: 174.6372171570355
经过对比,手工计算的结果与模型自带的 F F F统计量的值完全一致(少量误差是由于计算过程中的浮点数导致,这里不做详细讲解)。
步骤四:对比结果下结论
那么我们怎么根据上述所得的 F F F统计量的值验证原假设是否成立呢(也即判断是否有一个自变量可以构成因变量的线性组合)?我们需要做的就是对比 F F F统计量的值与理论的 F F F分布的值,一种方法是根据置信水平(0.05)和自由度(在这里是5,34)查看对应的分布值。这里直接调用Python的第三方模块SciPy(一个科学计算领域针对不同标准问题域的包集合)来计算理论的分布值:
# 导入模块
from scipy.stats import f
# 计算F分布的理论值
F_Theroy = f.ppf(q=0.95, dfn = p,dfd = n-p-1)
查看 F F F分布的理论值
In [7]: print('F分布的理论值为:',F_Theroy)
F分布的理论值为: 2.502635007415366
如上结果所示,在原假设的前提下,计算出来的 F F F统计量的值远远大于 F F F分布的理论值,所以应当拒绝原假设,即认为该多元线性回归模型是显著的,也就是说回归模型的偏回归系数不全为0(换句话说,就是整个模型中至少存在一个自变量能真正影响到因变量的波动,所以我们基于该数据集构建的线性回归模型在一定的误差允许范围内是有意义的)。
前面我们介绍了模型的显著性检验,模型的显著性检验只能说明关于因变量的线性组合是合理的,但并不能说明每个自变量对因变量都具有显著的意义(事实上也确实如此,我们应该通过对回归系数的显著性检验,排除那些对因变量影响不大的自变量,而找出真正能左右因变量的自变量),所以还需要对模型的回归系数做显著性检验。回归系数的显著性检验使用 t t t检验法,构造 t t t统计量(这里我们对 t t t统计量的数学意义不做深入探讨,事实上我们仅需知道如何使用 t t t统计量来判断回归系数的显著性,而不需要关心其背后的数学意义,当然了解更好)。
下面我们按照模型的显著性检验的四个步骤,对偏回归系数进行显著性检验。
步骤一:提出假设 { H 0 : β j = 0 , j = 1 , 2 , ⋯ , p H 1 : β j ≠ 0 \begin{cases}H_0:\beta_j=0,j=1,2,\cdots,p\\H_1:\beta_j\neq0\end{cases} {H0:βj=0,j=1,2,⋯,pH1:βj=0如上面所介绍的, t t t检验的出发点就是验证每一个自变量是否能成为影响因变量的重要因素。 t t t检验的原假设是假定第 j j j变量的偏回归系数为0,即认为该变量不是因变量的影响因素;而备选假设则是相反的假定,即认为第 j j j变量是影响因变量的重要因素。
步骤二:构造统计量 t = β ^ j − β j s e ( β ^ j ) ∼ t ( n − p − 1 ) t=\frac{\hat\beta_j-\beta_j}{se(\hat\beta_j)}\sim t(n-p-1) t=se(β^j)β^j−βj∼t(n−p−1)其中, β ^ j \hat\beta_j β^j为线性回归模型的第 j j j个系数的估计值(即我们所求出来的偏回归系数); β \beta β为原假设中的假定值,即0; s e ( β ^ j ) se(\hat\beta_j) se(β^j)为回归系数 β ^ j \hat\beta_j β^j的标准误(对于 t t t统计量,这里不做详细说明,仅介绍其数学公式),对应的计算公式如下: s e ( β ^ j ) = c j j ∑ ϵ i 2 n − p − 1 se(\hat\beta_j)=\sqrt{c_{jj}\frac{\sum\epsilon_i^2}{n-p-1}} se(β^j)=cjjn−p−1∑ϵi2其中, ∑ ϵ i 2 \sum\epsilon_i^2 ∑ϵi2为前面提到的误差平方和, c j j c{jj} cjj为矩阵 ( X ′ X ) − 1 (X'X)^{-1} (X′X)−1主对角线上第 j j j个元素。
标准误
标准误差(英文:Standard Error),也称标准误,即样本平均数抽样分布的标准差(英文:Standard Deviation),是描述对应的样本平均数抽样分布的离散程度及衡量对应样本平均数抽样误差大小的尺度
——维基百科
标准差是样本数据方差的平方根,它衡量的是样本数据的离散程度;标准误是样本均值的标准差,衡量的是样本均值的离散程度。而在实际的抽样中,习惯用样本均值来推断总体均值,那么样本均值的离散程度(标准误)越大,抽样误差就越大。所以用标准误来衡量抽样误差的大小。
第三步:计算统计量
这里我们不使用手工编写代码的方式进行统计量的计算,我们可以直接调用模型的summary"方法",输出线性回归模型的各项指标值(前面计算的 F F F统计量也包括在内)。如下:
In [2]: # 模型的概览信息
...: model2.summary()
Out[2]:
"""
OLS Regression Results
==============================================================================
Dep. Variable: Profit R-squared: 0.964
Model: OLS Adj. R-squared: 0.958
Method: Least Squares F-statistic: 174.6
Date: Wed, 08 Apr 2020 Prob (F-statistic): 9.74e-23
Time: 14:12:07 Log-Likelihood: -401.20
No. Observations: 39 AIC: 814.4
Df Residuals: 33 BIC: 824.4
Df Model: 5
Covariance Type: nonrobust
===================================================================================
coef std err t P>|t| [0.025 0.975]
-----------------------------------------------------------------------------------
Intercept 5.807e+04 6846.305 8.482 0.000 4.41e+04 7.2e+04
RD_Spend 0.8035 0.040 19.988 0.000 0.722 0.885
Administration -0.0578 0.051 -1.133 0.265 -0.162 0.046
Marketing_Spend 0.0138 0.015 0.930 0.359 -0.016 0.044
Florida 1440.8627 3059.931 0.471 0.641 -4784.615 7666.340
California 513.4683 3043.160 0.169 0.867 -5677.887 6704.824
==============================================================================
Omnibus: 1.721 Durbin-Watson: 1.896
Prob(Omnibus): 0.423 Jarque-Bera (JB): 1.148
Skew: 0.096 Prob(JB): 0.563
Kurtosis: 2.182 Cond. No. 1.60e+06
==============================================================================
Warnings:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 1.6e+06. This might indicate that there are
strong multicollinearity or other numerical problems.
如上所示,模型的概览信息包含三个部分,第一部分主要是有关模型的信息,例如模型的决定系数 R 2 R^2 R2,用来衡量自变量对因变量的解释程度;模型的 F F F统计量值,用来检验模型的显著性;模型的信息准则 A I C AIC AIC或 B I C BIC BIC,用来对比模型拟合效果的好坏等;第二部分主要包含偏回归系数的信息,例如回归系数的估计值 C o e f Coef Coef、 t t t统计量、回归系数的置信区间等;第三部分主要涉及到模型误差项 ϵ \epsilon ϵ的有关信息,例如用于检验误差项独立性的杜宾-瓦特森统计量 D u r b i n − W a t s o n Durbin-Watson Durbin−Watson;用于衡量误差项是否服从正态分布的 J B JB JB统计量;以及有关误差项偏度 S k e w Skew Skew和峰度 K u r t o s i s Kurtosis Kurtosis的计算值等(后面将会对部分值进行介绍)。上面输出的部分还有两个Warnings,第二个Warnings提醒我们可能意味着有强多重共线性或其它数值问题,这个问题我们在后面会介绍如何进行判断及解决。
决定系数
决定系数(英语:coefficient of determination,记为R2或r2)在统计学中用于度量因变量的变异中可由自变量解释部分所占的比例,以此来判断统计模型的解释力。
——维基百科
F F F统计量
F检验(F-test),最常用的别名叫做联合假设检验(英语:joint hypotheses test),此外也称方差比率检验、方差齐性检验。它是一种在零假设(null hypothesis, H0)之下,统计值服从F-分布的检验。其通常是用来分析用了超过一个参数的统计模型,以判断该模型中的全部或一部分参数是否适合用来估计母体。
——维基百科
信息准则 A I C AIC AIC
AIC信息准则即Akaike information criterion [1] ,是衡量统计模型拟合优良性(Goodness of fit)的一种标准,由于它为日本统计学家赤池弘次创立和发展的,因此又称赤池信息量准则。它建立在熵的概念基础上,可以权衡所估计模型的复杂度和此模型拟合数据的优良性。
——百度百科
AIC综合考虑了模型的拟合程度以及复杂程度,拟合越不好,AIC值也会随着增大;如果参数数量增多,也就是模型复杂度越大,AIC也会增大。单个AIC值参考的意义不大,但如果有两个或者多个AIC值在一起的时候,我们比较两者的AIC值,越小越好。
步骤四:对比结果下结论
在第二部分内容中,含有每个偏回归系数的 t t t统计量值,他的计算就是由估计值 c o e f coef coef和标准误 s t d e r r std\ err std err的商得到的。同时,每个 t t t统计量值都对应了概率值 p p p,用来判别统计量是否显著的直接办法,通常概率值 p p p小于0.05时表示拒绝原假设。从返回值的结果可知,只有截距项 I n t e r c e p t Intercept Intercept和研发成本 R D _ S p e n d RD\_Spend RD_Spend对应的 p p p值小于0.05,说明其余变量都没有通过系数的显著性检验,即在模型中这些变量不是影响利润的重要因素。(我们也可以用另外一个办法, t t t统计量的绝对值若大于2,可拒绝原假设)。
至此我们完成了对模型的显著性检验及回归系数的显著性检验,但这并不意味着建模过程的结素,我们还需对模型进行进一步的诊断,并根据诊断结果对模型进行修正,目的就是使模型更加健壮,接下来我们会对该内容进行介绍。
前面已经讲到,当回归模型构建好之后,并不意味着建模过程的结束,还需要进一步对模型进行诊断,目的就是使诊断过后的模型更加健壮。统计学家在发明线性回归的时候就提出了一些假设前提,只有在满足这些假设前提的情况下,所得的模型才是合理的,接下来我们针对以下几点假设来完成模型的诊断工作(此处只介绍如何利用假设来对模型进行诊断,而不介绍该假设的具体数学意义)。
除了以上几点假设之外,还需要注意的是,线性回归模型对异常值时异常敏感的,即模型的构建过程非常容易受到异常值的影响,所以诊断过程中还需要对原始数据的观测值进行异常点的识别与处理。接下来我们将理论知识与Python结合起来来介绍上面所提到的几点诊断过程以及对异常值的处理。
虽然模型的前提假设是对残差项要求服从正态分布,但其实质就是要求因变量服从正态分布(正态性考察:,本质上还是对残差的正态性考察,不是对因变量的正态性进行考察,尤其是在多重线性回归当中尤为注意,这里我们只是通过对因变量正态性考察的结果来评估残差项的正态性,假设残差项服从正态分布,说明我们在散点图中我们的数据偏离拟合线的均值较为固定,而前面要求 ϵ \epsilon ϵ最小,则是要求散点偏离拟合线的距离要尽量小,这样我们才可以更好地进行拟合,使得模型更加具有参考价值)。
对于多元线性回归模型 y = X β + ϵ y=X\beta+\epsilon y=Xβ+ϵ来说,等式右边的自变量属于已知变量,而等式左边的因变量为未知量(故需要通过建模进行预测)。所以,要求误差项服从正态分布,就是要求因变量服从正态分布(统计学上可以证明,事实上我还不理解,但是我们只需要记得此结论就可以了)。
关于正态性检验通常运用两种方法:
要求残差正态分布,就是在拟合后,看看真实值y与拟合值Y之间的差值是不是符合正态分布,如果不符合,则说明因变量可预测性较低,考虑使用其他模型进行建模。
接下来我们使用上述方法结合Python进行检验
1. 直方图法
部分代码如下
# 导入第三方模块
import scipy.stats as stats
sns.distplot(a = Profit_New.Profit, bins = 10, fit = stats.norm, norm_hist = True,
hist_kws = {'color':'steelblue', 'edgecolor':'black'},
kde_kws = {'color':'black', 'linestyle':'--', 'label':'核密度曲线'},
fit_kws = {'color':'red', 'linestyle':':', 'label':'正态密度曲线'})
查看所绘制的图形
# 显示图例
plt.legend()
# 显示图形
plt.show()
结果如下:
如图绘制了因变量 P r o f i t Profit Profit的直方图、核密度曲线和理论正太分布的密度曲线,添加两条曲线的目的是对比数据的实际分布与理论分布之间的差异。如果两条曲线近似或吻合,就说明该变量近似服从正态分布。从图中看,核密度曲线与正态密度曲线的趋势比较吻合,故直观上可以认为利润变量服从正态分布。
2. PP图与QQ图
# 残差的正态性检验(PP图和QQ图法)
pp_qq_plot = sm.ProbPlot(Profit_New.Profit)
# 绘制PP图
pp_qq_plot.ppplot(line = '45')
plt.title('P-P图')
# 绘制QQ图
pp_qq_plot.qqplot(line = 'q')
plt.title('Q-Q图')
# 显示图形
plt.show()
结果如下
PP图的思想是比对正态分布的累计概率值和实际分布的累计概率值,而QQ图则比对正态分布的分位数和实际的分位数(这里不做详细讲解,仅需知道如何判断)。判断变量是否近似服从正态分布的标准是:如果散点都比较均匀地落在直线上,就说明变量近似服从正太分布,否则就认为数据集不服从正态分布。从上图可以看出,不管是PP图还是QQ图,绘制的散点都较均匀地落在直线附近,没有太大的偏离,故认为利润近似服从正态分布。
3. Shapiro 检验和 K-S 检验
这两种检验方法均属于非参数法,它们的原假设被设定为变量服从正态分布,两者的最大区别在于适用的数据量不一样,若数据量低于5000,则使用 Shapiro 检验法比较合理,否则使用 K-S 检验法。scipy 的子模块 stats 提供了专门的检验函数,分别是 shapiro 函数和 kstest 函数,对于利润数据集,其样本量小于5000,故使用 shapiro 函数对利润做定量的正态性检验:
In [17]: # 导入模块
...: import scipy.stats as stats
...: stats.shapiro(Profit_New.Profit)
Out[17]: (0.9793398380279541, 0.537902295589447)
如上结果所示,返回的结果元组中第一个元素是 shapiro 检验的统计量值,第二个元素是对应的概率值 p p p。由于 p p p值大于置信水平0.05,故接受利润变量服从正态分布的原假设。
为了应用 K-S 检验的函数 kstest ,这里随机生成正态分布变量 x1 和均匀分布变量 x2(numpy模块),具体代码如下:
# 导入模块
import scipy.stats as stats
stats.shapiro(Profit_New.Profit)
# 生成正态分布和均匀分布随机数
rnorm = np.random.normal(loc = 5, scale=2, size = 10000)
runif = np.random.uniform(low = 1, high = 100, size = 10000)
# 正态性检验
KS_Test1 = stats.kstest(rvs = rnorm, args = (rnorm.mean(), rnorm.std()), cdf = 'norm')
KS_Test2 = stats.kstest(rvs = runif, args = (runif.mean(), runif.std()), cdf = 'norm')
查看结果
In [19]: print(KS_Test1)
...: print(KS_Test2)
KstestResult(statistic=0.00479737894891874, pvalue=0.9754489769248833)
KstestResult(statistic=0.05982477830864652, pvalue=1.637553025194719e-31)
如上结果所示,正态分布随机数的检验 p p p值大于置信水平0.05,则需要接受原假设(认为服从正态分布,事实上该数据集就是由正态分布产生的随机数);均匀分布随机数的检验 p p p值远远小于0.05,则需拒绝原假设(即认为不服从正态分布)。
需要说明的是,如果使用 kstest 函数对变量进行正态性检验,必须指定args参数,它用于传递被检验变量的均值和标准差。
如果因变量的检验结果不满足正态分布时,需要对因变量做某种数学转换,这里不详细说明。
多重共线性是指模型中的自变量之间存在较高的线性相关关系,它的存在会给模型带来严重的后果,例如由“最小二乘法”得到的偏回归系数无效、增大了偏回归系数的方差、模型缺乏稳定性等(这里不说明为何会造成此种后果,仅介绍如何进行检验)。由于会导致上面所说的一些后果,所以对模型的多重共线性检验就显得尤为重要了。
关于多重共线性的检验可以使用方差膨胀因子VIF来鉴定,如果VIF大于10,则说明变量间存在多重共线性;如果VIF大于100,则表明变量间存在严重的多重共线性。方差膨胀因子VIF的计算步骤如下:
(1)构造每一个自变量与其余自变量的线性回归模型,例如,数据集中有 p p p个自变量,则第一个自变量与其余的自变量的线性组合可表示为: x 1 = c 0 + α 2 x 2 + ⋯ + α p x p + ϵ x_1=c_0+\alpha_2x_2+\cdots+\alpha_px_p+\epsilon x1=c0+α2x2+⋯+αpxp+ϵ(2)根据如上线性回归模型得到相应的判决系数 R 2 R^2 R2,进而计算第一个自变量的方差膨胀因子VIF: V I F 1 = 1 1 − R 2 VIF_1=\frac{1}{1-R^2} VIF1=1−R21Python中的statsmodels模块提供了计算方差膨胀因子VIF的函数,下面利用该函数演示计算两个自变量的方差膨胀因子:
# 导入statsmodels模块中的函数
from statsmodels.stats.outliers_influence import variance_inflation_factor
# 自变量X(包含RD_Spend、Marketing_Spend和常数列1)
X = sm.add_constant(Profit_New.loc[:,['RD_Spend','Marketing_Spend']])
# 构造空的数据框,用于存储VIF值
vif = pd.DataFrame()
vif["features"] = X.columns
vif["VIF Factor"] = [variance_inflation_factor(X.values, i) for i in range(X.shape[1])]
查看结果
In [23]: print(vif)
features VIF Factor
0 const 4.540984
1 RD_Spend 2.026141
2 Marketing_Spend 2.026141
如上结果所示,两个自变量对于的方差膨胀因子均低于10,说明构建模型的数据间并不存在多重共线性。如果发现变量之间存在多重共线性的话,可以考虑删除变量或者重新选择模型。
线性相关性检验,顾名思义,就是确保用于建模的自变量与因变量之间存在线性关系。关于线性关系的判断,可以使用Pearson相关系数和可视化方式进行判别,有关Person相关系数的计算公式如下: p x , y = C O V ( x , y ) D ( x ) D ( y ) p_{x,y}=\frac{COV(x,y)}{\sqrt {D(x)}\sqrt {D(y)}} px,y=D(x)D(y)COV(x,y)其中, C O V ( x , y ) COV(x,y) COV(x,y)为自变量与因变量之间的协方差, D ( x ) D(x) D(x)和 D ( y ) D(y) D(y)分别为自变量 x x x和因变量 y y y的方差。
Pearson相关系数的计算可以直接使用数据框的corrwith“方法”,该方法最大的好处就是可以计算任意指定变量间的相关系数。
协方差
协方差表示的是两个变量的总体的误差,这与只表示一个变量误差的方差不同。 如果两个变量的变化趋势一致,也就是说如果其中一个大于自身的期望值,另外一个也大于自身的期望值,那么两个变量之间的协方差就是正值。 如果两个变量的变化趋势相反,即其中一个大于自身的期望值,另外一个却小于自身的期望值,那么两个变量之间的协方差就是负值。
——百度词条
相关系数
在统计学中,皮尔逊积矩相关系数(英语:Pearson product-moment correlation coefficient,又称作 PPMCC或PCCs, 文章中常用r或Pearson’s r表示)用于度量两个变量X和Y之间的相关程度(线性相关),其值介于-1与1之间。在自然科学领域中,该系数广泛用于度量两个变量之间的线性相关程度。它是由卡尔·皮尔逊从弗朗西斯·高尔顿在19世纪80年代提出的一个相似却又稍有不同的想法演变而来。这个相关系数也称作“皮尔森相关系数r”。
——维基百科
下面使用该方法来计算自变量与因变量之间的相关系数,代码及输出如下:
In [27]: # 计算数据集Profit_New中每个自变量与因变量利润之间的相关系数
...: Profit_New.drop('Profit', axis = 1).corrwith(Profit_New.Profit)
Out[27]:
RD_Spend 0.978437
Administration 0.205841
Marketing_Spend 0.739307
California -0.083258
Florida 0.088008
dtype: float64
如上结果所示,自变量中只有研发成本和市场营销成本与利润之间存在较高的相关系数,相关性分别达到0.978和0.739,而其他变量与利润之间几乎没有线性相关性可言。通常情况下,可以以下表判断相关系数对应的相关程度:
| p p p | ≥ \geq ≥ 0.8 | 0.5 ≤ \leq ≤ | p p p | <0.8 | 0.3 ≤ \leq ≤ | p p p | <0.5 | | p p p | <0.3 |
---|---|---|---|
高度相关 | 中度相关 | 弱相关 | 几乎不相关 |
以管理成本Administration 为例,与利润之间的相关系数只有0.2,被认定为不相关(注意:这里的不相关只能说明两者之间不存在线性关系)。如果利润和管理成本之间存在非线性关系时,Person相关系数同样也会很小,所以下面我们通过可视化的方式,观察自变量与因变量之间的散点关系。
这里使用seaborn模块中的pairplot函数,该函数可以绘制多个变量间的散点图矩阵。代码如下
# 散点图矩阵
# 导入模块
import matplotlib.pyplot as plt
import seaborn
# 绘制散点图矩阵
seaborn.pairplot(Profit_New.loc[:,['RD_Spend','Administration','Marketing_Spend','Profit']])
# 显示图形
plt.show()
展现的散点图矩阵如下
如图由于 C a l i f o r n i a California California和 F l o r i d a Florida Florida都是哑变量,故没有将其放到散点图矩阵中。
从图中显示的情况可知,研发成本与利润之间几乎为一条向上倾斜的直线(见左下角和右上角的散点图),说明这两个变量之间确实存在着很强的线性关系;市场营销成本与利润的散点图同样向上倾斜,但很多点的分布还是比较分散的(见第一列第三行的散点图);管理成本与利润之间的散点图呈水平趋势,而且分布也比较宽,说明两者之间确实没有任何关系(见第一列第二行的散点图)。
到此我们已经对模型进行了许多分析,对模型分析的目的是要构建更加健壮的模型,此处我们综合考虑相关系数、散点图矩阵以及前面 t t t检验的结果对model2进行修正,最终确定只保留model2的 R D S p e n d RD_Spend RDSpend和 M a r k e t i n g S p e n d Marketing_Spend MarketingSpend两个自变量,下面对该模型进行修正:
# 模型修正
model3 = sm.formula.ols('Profit ~ RD_Spend + Marketing_Spend', data = train).fit()
查看重构后的偏回归系数
In [32]: # 模型回归系数的估计值
...: model3.params
Out[32]:
Intercept 51902.112471
RD_Spend 0.785116
Marketing_Spend 0.019402
dtype: float64
如上结果所示,修正后可将多元线性回归模型表示成: P r o f i t = 51902.112471 + 0.785116 R D S p e n d + 0.019402 M a r k e t i n g S p e n d Profit=51902.112471+0.785116RD_Spend+0.019402Marketing_Spend Profit=51902.112471+0.785116RDSpend+0.019402MarketingSpend
前面已经提到,多元线性回归模型容易受到极端值的影响,故需要利用统计方法对样本进行异常点检测。如果在建模过程中发现异常数据,需要对数据集进行整改,如删除异常值、用中位数或众数取代异常值等。对于线性回归模型来说,通常利用帽子矩阵、DFFITS准则、学生化残差或Cook距离进行异常点的检测。接下来,分别对这四种检测方法做简单介绍。
1. 帽子矩阵
帽子矩阵的设计思路就是考察第 i i i个样本对预测值 y ^ \hat y y^的影响大小,根据前面我们推导得到的回归系数求解公式,可以将多元线性回归模型表示成 y ^ = X β ^ = X ( X ′ X ) − 1 X ′ y = H y \hat y=X\hat \beta=X(X'X)^{-1}X'y=Hy y^=Xβ^=X(X′X)−1X′y=Hy其中 H = X ( X ′ X ) − 1 X ′ H=X(X'X)^{-1}X' H=X(X′X)−1X′, H H H就称为帽子矩阵,全都是关于自变量 X X X的计算。判断样本是否为异常点的方法,可以使用如下公式: h i i ≥ 2 ( p + 1 ) n h_{ii}\geq \frac{2(p+1)}{n} hii≥n2(p+1)其中, h i i h_{ii} hii为帽子矩阵 H H H的第 i i i个主对角线元素, p p p为自变量个数, n n n为用于建模数据集的样本量。如果对角线的元素满足上面的公式,则代表第 i i i个样本为异常值(此处及后面几种判断方法,仅介绍其求解过程,不行详细说明其背后的数学原理)。
2. DFFITS准则
DFFITS准则需要借助于帽子矩阵,构造了另一个判断异常点的统计量,该统计量可以表示成如下公式: D i ( σ ) = h i i 1 − h i i ϵ i σ 1 − h i i D_i(\sigma)=\sqrt{\frac{h_{ii}}{1-h_{ii}}}\frac{\epsilon_i}{\sigma \sqrt{1-h_{ii}}} Di(σ)=1−hiihiiσ1−hiiϵi其中, h i i h_{ii} hii为帽子矩阵 H H H的第 i i i个主对角线元素, ϵ i \epsilon_i ϵi为第 i i i个样本点的预测误差, σ \sigma σ为误差项的标准差,判断样本为异常点的方法,可以使用如下规则: ∣ D i ( σ ) ∣ > 2 p + 1 n |D_i(\sigma)|>2\sqrt{\frac{p+1}{n}} ∣Di(σ)∣>2np+1需要注意的是,在DFFITS准则的公式中,乘积的第二项实际上是学生化残差(一种标准化的残差),也可以用来判定第 i i i个样本是否为异常点,判断的标准如下 ∣ r i ∣ = ∣ ϵ i σ 1 − h i i ∣ > 2 |r_i|=|\frac{\epsilon_i}{\sigma \sqrt{1-h_{ii}}}|>2 ∣ri∣=∣σ1−hiiϵi∣>2
学生化残差
学生化残差是一种标准化的残差,它可以告诉我们哪些数据点的残差较大,一般超过±3的学生化残差可以被看作可能的离群值。
3. Cook距离
Cook距离是一种相对抽象的判断准则,无法通过具体的临界值判断样本是否为异常点,对于该距离,Cook统计量越大的点,其成为异常点的可能性就越大。Cook统计量可以表示为如下公式: D i s t a n c e i = 1 p + 1 ( h i i 1 − h i i ) r i 2 Distance_i=\frac{1}{p+1}(\frac{h_{ii}}{1-h_{ii}})r_i^2 Distancei=p+11(1−hiihii)ri2其中, r i r_i ri为学生化残差。
如果使用如上四种方法判别数据集第 i i i个样本点是否为异常点,前提是已经构建好一个线性回归模型(事实上我们可以在线性回归模型构建之前,对原始数据集进行异常值点的排除,但这并不是一种好的方法,因为如果这样做则无法实时观察删除异常点后对模型的影响,故考虑先建模后慢慢修正是一种更好的方法)。
然后基于get_influence“方法”获得四种统计量的值。我们使用以上方法来检验model3中数据集的样本是否存在异常,代码如下:
# 异常值检验
outliers = model3.get_influence()
# 高杠杆值点(帽子矩阵)
leverage = outliers.hat_matrix_diag
# dffits值
dffits = outliers.dffits[0]
# 学生化残差
resid_stu = outliers.resid_studentized_external
# cook距离
cook = outliers.cooks_distance[0]
合并各异常值检验的统计量值,并查看前5行数据
In [35]: # 合并各种异常值检验的统计量值
...: contat1 = pd.concat([pd.Series(leverage, name = 'leverage'),pd.Series(dffits, name = 'dffits'),
...: pd.Series(resid_stu,name = 'resid_stu'),pd.Series(cook, name = 'cook')],axis = 1)
...: # 重设train数据的行索引
...: train.index = range(train.shape[0])
...: # 将上面的统计量与train数据集合并
...: profit_outliers = pd.concat([train,contat1], axis = 1)
...: profit_outliers.head()
Out[35]:
RD_Spend Administration Marketing_Spend Profit California Florida leverage dffits resid_stu cook
0 28663.76 127056.21 201126.82 90708.19 0 1 0.066517 0.466410 1.747255 0.068601
1 15505.73 127382.30 35534.17 69758.98 0 0 0.093362 0.221230 0.689408 0.016556
2 94657.16 145077.58 282574.31 125370.37 0 0 0.032741 -0.156225 -0.849138 0.008199
3 101913.08 110594.11 229160.95 146121.95 0 1 0.039600 0.270677 1.332998 0.023906
4 78389.47 153773.43 299737.29 111313.02 0 0 0.042983 -0.228563 -1.078496 0.017335
结果如上所示,合并了train数据集和四种统计量值,接下来要做的就是选择一种或多种判断异常值点的方法,将异常值点查询出来,这里使用学生化残差来进行异常点的检测,当学生化残差大于2时,即认为对应的数据点为异常值。
In [36]: # 计算异常值数量的比例
...: outliers_ratio = sum(np.where((np.abs(profit_outliers.resid_stu)>2),1,0))/profit_outliers.shape[0]
...: outliers_ratio
Out[36]: 0.02564102564102564
如上结果所示,通过学生化残差检测到了异常值,并且其比例约为2.56%。对于异常值的处理办法有很多种,这里介绍两种:
# 挑选出非异常的观测点
none_outliers = profit_outliers.loc[np.abs(profit_outliers.resid_stu)<=2,]
使用剔除异常样本后的数据集进行再建模:
In [38]: # 应用无异常值的数据集重新建模
...: model4 = sm.formula.ols('Profit ~ RD_Spend + Marketing_Spend', data = none_outliers).fit()
...: model4.params
Out[38]:
Intercept 51827.416821
RD_Spend 0.797038
Marketing_Spend 0.017740
dtype: float64
如上结果所示,经过异常点的排除,重构后模型的偏回归系数发生了变动,故可以将模型表示为如下公式: P r o f i t = 51827.416821 + 0.797038 R D S p e n d + 0.017740 M a r k e t i n g S p e n d Profit=51827.416821+0.797038RD_Spend+0.017740Marketing_Spend Profit=51827.416821+0.797038RDSpend+0.017740MarketingSpend
残差的独立性检验通常使用 Durbin-Watson值来测试,其目的是为了检验残差项之间的相关性(因为残差项之间如果相关性过大会对模型造成一定的影响,此处不展开深入探讨)。如果DW值在2左右,则表明残差项之间是不相关的,如果与2偏离较远,则说明不满足残差项的独立性假设(事实上DW值介于0-4之间)。对于DW统计量的值,无需另行计算,因为它包含在我们前面所提到的模型概览信息中,以模型model4为例:
# Durbin-Watson统计量
# 模型概览
model4.summary()
其输出的第三个table的内容如下
==============================================================================
Omnibus: 7.188 Durbin-Watson: 2.065
Prob(Omnibus): 0.027 Jarque-Bera (JB): 2.744
Skew: 0.321 Prob(JB): 0.254
Kurtosis: 1.851 Cond. No. 5.75e+05
==============================================================================
如输出结果所示,残差项对应的DW统计量为2.065,比较接近于2,故可以认为模型的残差项之间是满足独立性这个假设前提的。
方差齐性是要求模型残差项的方差不随自变量的变动而呈现某种趋势,否则,残差的趋势就可以被自变量刻画(残差应该是满足白噪声假设的)。如果残差项不满足方差齐性(方差为一个常熟),就会导致偏回归系数不具备有效性,甚至导致模型的预测也不准确。所以,在建模完成后,我们应该验证残差项是否满足方差齐性。
关于方差齐性的检验,一般使用两种方法,图形法(散点图)和统计检验法(BP检验)。
1. 图形法
上面所说,方差齐性是指残差项的方差不随自变量的变动而变动,所以只需要绘制残差项与自变量之间的散点图,就可以观察和发现两者之间存在的某种趋势,代码如下:
# 方差齐性检验
# 设置第一张子图的位置
ax1 = plt.subplot2grid(shape = (2,1), loc = (0,0))
# 绘制散点图
ax1.scatter(none_outliers.RD_Spend, (model4.resid-model4.resid.mean())/model4.resid.std())
# 添加水平参考线
ax1.hlines(y = 0 ,xmin = none_outliers.RD_Spend.min(),xmax = none_outliers.RD_Spend.max(), color = 'red', linestyles = '--')
# 添加x轴和y轴标签
ax1.set_xlabel('RD_Spend')
ax1.set_ylabel('Std_Residual')
# 设置第二张子图的位置
ax2 = plt.subplot2grid(shape = (2,1), loc = (1,0))
# 绘制散点图
ax2.scatter(none_outliers.Marketing_Spend, (model4.resid-model4.resid.mean())/model4.resid.std())
# 添加水平参考线
ax2.hlines(y = 0 ,xmin = none_outliers.Marketing_Spend.min(),xmax = none_outliers.Marketing_Spend.max(), color = 'red', linestyles = '--')
# 添加x轴和y轴标签
ax2.set_xlabel('Marketing_Spend')
ax2.set_ylabel('Std_Residual')
# 调整子图之间的水平间距和高度间距
plt.subplots_adjust(hspace=0.6, wspace=0.3)
# 显示图形
plt.show()
输出结果如下:
如上图所示,标准化的残差并没有随自变量的变动而呈现喇叭形,所有的散点几乎均匀地分布在参考线 y = 0 y=0 y=0附近,所以,可以说明模型的残差项满足方差齐性的前提假设。
2. BP检验
方差齐性检验的另一个统计方法是BP检验,它的原假设是残差的方差为一个常数,通常构造拉格朗日乘子 L M LM LM统计量,实现方差齐性的检验。该检验可以借助于statsmodels模块中的het_breuschpagan函数完成,具体代码及结果如下:
In [50]: # BP检验
...: sm.stats.diagnostic.het_breuschpagan(model4.resid, exog_het = model4.model.exog)
Out[50]:
(1.4675103668307836,
0.48010272699007606,
0.7029751237162208,
0.5019659740962994)
如上结果所示,结果元组中一共包含了四个值,第一个值为 L M LM LM统计量;第二个值是统计量对应的概率 p p p值,该值大于0.05,说明接受残差项方差为常数的原假设;第三个值为 F F F统计量,用于检验残差平方项与自变量之间是否独立,如果独立则表明残差方差齐性;第四个值则为 F F F统计量的概率 p p p值,同样大于0.05,则进一步表明残差项满足方差齐性的假设。
如果模型的残差项不满足方差齐性的话,可以用两类方法类解决:
此处不做详细介绍,但我们最终目的都是想让模型更加健壮,有兴趣的读者可以自行查找解决方差齐性的问题。
3. 回归模型的预测
经过我们前面对模型的构造
假设性检验和模型诊断,最终确定合理的模型model4。接下来我们利用model4完成测试集上的预测,代码如下:
# 模型预测
# model4对测试集的预测
pred4 = model4.predict(exog = test.loc[:,['RD_Spend','Marketing_Spend']])
# 绘制预测值与实际值的散点图
plt.scatter(x = test.Profit, y = pred4)
# 添加斜率为1,截距项为0的参考线
plt.plot([test.Profit.min(),test.Profit.max()],[test.Profit.min(),test.Profit.max()],
color = 'red', linestyle = '--')
# 添加轴标签
plt.xlabel('实际值')
plt.ylabel('预测值')
# 显示图形
plt.show()
结果输出如下图
如上图所示,绘制了有关模型在测试集上的预测值和实际值的散点图,该散点图可以用来衡量预测值与实际值之间的距离差异(如果所有预测值与实际值完全相等的话,可想而知,我们把图中的散点全部连接起来,得到的结果应该是一条斜率为1的直线)。如果两者之间非常接近,那么得到的散点图就是在对角线附近微微波动。从图中的结果来看,大部分的散点都落在对角线附近,说明该模型的预测效果还行。
绘图法可以较为直观地看出模型的预测效果,若散点在对角线附近微微波动,则说明预测效果较好,反之则预测效果较差。当然我们也可以使用数值的方法来判断模型预测效果的好坏,一个简单的方法就是利用”最小二乘法“的思想,构造真实值与预测值之间差的平方的和,若真实值与预测值完全相等,结果应该为0,否则求出来的数值越小越好,另外可以使用均方误差进行衡量,其他方法在此不做介绍,读者可以自行探索。
我们通过对产品的利润数据集的分析,排除了那些非左右利润的因素,提取了左右利润的重要因素,并实现了对利润的预测,在实际生活中可通过构建模型帮助企业或个人进行决策。
本篇重点介绍了有关线性回归模型的理论知识与应用实践,主要的内包括模型回归系数的求解、模型及系数的显著性检验、模型的假设诊断及预测。在实际应用中,如果因变量为数值类型变量,可以优先考虑使用线性回归模型,不过前提是要满足几点假设,如果因变量服从正态分布、自变量间不存在多重共线性、自变量与因变量之间存在线性关系、用于建模的数据集不存在异常点、残差项满足方差异性和独立性。(否则我们可能不优先考虑使用线性回归模型进行求解,或者需要进行一定的变换)。
本篇博文是笔者学习刘顺祥老师所著书籍《从零开始学Python数据分析与挖掘》后整理的部分笔记,文中引用了大量的原书内容,修正了书中部分错误代码,并加入了笔者自己的理解。
笔者在整理过程中,对书中作者提及但没有详细解释的概念尽可能地进行了解释,以及加入自己的理解,学习一个模型、明白如何通过模型的各个假设值进行模型的评估的过程比较简单,但是要理解各个假设值背后的数学意义及原理是十分困难的,笔者尽可能地进行了介绍,但由于笔者才疏学浅,无法完全理解各个参数背后的数学原理及意义,还请有兴趣的读者自行上网查找相关资料。
文中大量概念来自于计量经济学,如读者有兴趣,笔者认为中国大学MOOC网站上由电子科技大学陈磊、杨政两位老师主讲的国家精品课程《计量经济学》将会很有帮助。
笔者认为如果要对数据分析的模型进行学习,选择线性回归作为入门将是一个不错的选择,同时它也是我们生活中比较常见且重要的一个模型,笔者认为需重点掌握!