我将介绍线性回归的概念,但主要讨论Python的实现。线性回归是一种统计模型,用于检查两个(简单线性回归)或更多(多线性回归)变量(一个因变量和一个或多个自变量)之间的线性关系。
线性关系基本上意味着当一个(或多个)自变量增加(或减少)时,因变量也会增加(或减少):
如上图,线性关系可能是正的(独立变量上升,因变量上升)或负值(独立变量上升,因变量下降)。
我会将重点放在Python中回归模型的实现,所以我不想在回归模型中深入研究数学,但是我会写一点关于它的内容。
一点点数学
变量Y和X之间的关系由等式:
Y是因变量 - 或者我们试图预测或估计的变量
X是自变量 - 我们用来做出预测的变量
m是回归线的斜率 - 它代表X对Y的影响。换句话说,如果X增加1个单位,Y就会增加m个单位。(“完全披露(Full Disclosure)”:只有当我们知道X和Y有线性关系时才是真实的,在几乎所有的线性回归情况下,这都不是真的!)
b是一个常数,也被称为Y截距。如果X等于0,Y将等于b。这在现实生活中不一定适用 - 我们并不总是知道X和Y之间的确切关系或者具有确切的线性关系
现在进行简单线性回归(SLR):在SLR模型中,我们建立了一个基于数据的模型 - 斜率m和Y截距来自数据; 此外,我们不需要X和Y之间的关系完全线性。
简单线性回归还包括数据中的错误(也称为残差)。我现在不会过多讲解它,以后有机会再来另外写。但残差基本上是Y的真实值与Y的预测/估计值之间的差异。
重要的是,在线性回归中,我们想要预测一个连续变量。
在回归模型中,我们试图通过找到“最佳拟合线”来最小化这些错误。我们试图将红线与蓝点的距离最小化,尽可能接近零。它与(或相当于)最小化均方误差(MSE)或误差平方和(SSE),也称为“残差平方和”(RSS),但这超出了本文讨论的范围:-)
在大多数情况下,我们将有多个自变量,它可以少至两个或多达数百(或理论上甚至数千)变量。在这些情况下,我们将使用多重线性回归模型(MLR)。
多重线性回归方程与简单线性回归方程几乎相同,只是具有更多变量:
这就结束了这篇文章的数学部分:),接下来我们要在Python中实现啦
Python中的线性回归
在Python中实现线性回归有两种主要方法 - 使用Statsmodels和scikit-learn。也可以使用Scipy库,但我觉得这不像其他两个库一样常见。先看看这两个库的线性回归:Statsmodels是一个Python模块,它提供了用于评估许多不同统计模型的类和函数,也能进行统计测试和统计数据探索。“
与Pandas和NumPy一样,获取或安装Statsmodels最简单的方法是通过Anaconda软件包。如果你有兴趣以其他方式安装,请查看此链接。安装完成后,每次需要时都需要导入它:
import statsmodels.api as sm
让我们看看如何实际使用Statsmodels进行线性回归。
首先,我们从sklearn中导入一个数据集:
from sklearn import datasets ## imports datasets from scikit-learn
data = datasets.load_boston() ## loads Boston dataset from datasets library
这是波士顿房价的数据集。由于它是一个用于测试机器学习工具的数据集,因此它带有对数据集的描述,我们可以使用命令data.DESCR 来查看它(这只适用于sklearn数据集,而不是每个数集)。
为了更好地理解变量,我添加了描述的开头部分:
Boston House Prices dataset
===========================
Notes
------
Data Set Characteristics:
:Number of Instances: 506
:Number of Attributes: 13 numeric/categorical predictive
:Median Value (attribute 14) is usually the target
:Attribute Information (in order):
- CRIM per capita crime rate by town
- ZN proportion of residential land zoned for lots over 25,000 sq.ft.
- INDUS proportion of non-retail business acres per town
- CHAS Charles River dummy variable (= 1 if tract bounds river; 0 otherwise)
- NOX nitric oxides concentration (parts per 10 million)
- RM average number of rooms per dwelling
- AGE proportion of owner-occupied units built prior to 1940
- DIS weighted distances to five Boston employment centres
- RAD index of accessibility to radial highways
- TAX full-value property-tax rate per $10,000
- PTRATIO pupil-teacher ratio by town
- B 1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town
- LSTAT % lower status of the population
- MEDV Median value of owner-occupied homes in $1000's
:Missing Attribute Values: None
:Creator: Harrison, D. and Rubinfeld, D.L.
This is a copy of UCI ML housing dataset.
http://archive.ics.uci.edu/ml/datasets/Housing
This dataset was taken from the StatLib library which is maintained at Carnegie Mellon University.
运行data.feature_names和data.target将分别打印自变量和因变量的列名称。这意味着,Scikit-learn已经将房屋价值/价格数据设置为目标变量,并将13个其他变量设置为预测变量。我们来看看如何在这个数据集上运行线性回归。
首先,我们应该将数据加载为一个Pandas DataFrame以便于分析,并将房价设置为我们的目标变量:
import numpy as np
import pandas as pd
# define the data/predictors as the pre-set feature names
df = pd.DataFrame(data.data, columns=data.feature_names)
# Put the target (housing value -- MEDV) in another DataFrame
target = pd.DataFrame(data.target, columns=["MEDV"])
我们在这里完成的是取数据集并将其加载为DataFrame;
然后,我们设置预测变量(如df) - 数据集中预先设置的自变量。我们还设定了target - 因变量或我们试图预测/估计的变量。
接下来我们要训练一个线性回归模型。我们需要选择我们认为可以预测因变量的变量 - 这可以通过检查变量之间的相关性,通过绘制数据和直观地查找关系来完成。
让我们考虑RM(房间的平均数量)和LSTAT(低生活水平人群的百分比)。
需要注意的是,Statsmodels默认不会添加常量。
## Without a constant
import statsmodels.api as sm
X = df["RM"]
y = target["MEDV"]
# Note the difference in argument order
model = sm.OLS(y, X).fit()
predictions = model.predict(X) # make the predictions by the model
# Print out the statistics
model.summary()
输出:第一个表格,无常数
解释表格
首先,我们知道什么是因变量,模型和方法。OLS代表普通最小二乘法,“最小二乘法”方法意味着我们试图拟合一条回归线,该回归线可以最小化回归线距离的平方(见本文的前一部分)
Date、Time和观察次数(No.Observation)就是字面上的意思
残差和模型的Df与自由度有关 - “统计量最终计算中可以随意变化的值的数量
系数3.6534意味着随着RM变量增加1,MDEV的预测值增加3.6534
其他一些重要的值是R平方 - 我们模型解释的方差百分比
标准误差(是统计抽样分布的标准偏差,最常见的是平均值)
t分数和p值,用于假设检验 - RM具有统计学显着的p值;
没有为95%的置信区间RM(意思是我们预测在95%的置信度的值RM之间3.548至3.759)。
如果我们想为模型添加一个常量 - 我们必须使用命令来设置它,
X = sm.add_constant(X)
其中X是包含输入(独立)变量DataFrame的名称。
import statsmodels.api as sm # import statsmodels
X = df["RM"] ## X usually means our input variables (or independent variables)
y = target["MEDV"] ## Y usually means our output/dependent variable
X = sm.add_constant(X) ## let's add an intercept (beta_0) to our model
# Note the difference in argument order
model = sm.OLS(y, X).fit() ## sm.OLS(output, input)
predictions = model.predict(X)
# Print out the statistics
model.summary()
输出:第二个表格,带有常数
解释表格
与前一个表格使用常数项的系数不同的。如果没有常数,我们迫使我们的模型通过原点,但现在我们有一个y截距(const)为-34.67。我们还将RM预测值的斜率从3.634改为9.1021。
现在让我们尝试使用多个变量来拟合回归模型 - 我们将使用前面提到的RM和LSTAT。模型拟合是相同的:
X = df[[“RM”, “LSTAT”]]
y = target[“MEDV”]
model = sm.OLS(y, X).fit()
predictions = model.predict(X)
model.summary()
输出:表格3,使用多个自变量(2个)
解释表格
我们可以在这里看到,这个模型具有更高的R平方值-0.948,这意味着这个模型解释了因变量的94.8%的方差。每当我们为回归模型添加变量时,R-square将会更高,但这是相当高的R-square。
我们可以看到,RM和LSTAT在预测(或估计)房屋中值时具有统计显着性; 我们看到随着RM增加1,MEDV将增加4.9069,当LSTAT增加1时,MEDV将减少 -0.6557。
LSTAT是低生活水平人群的百分比,很遗憾,我们可以用它降低房屋的中位数。同理,房屋的房间越多,价值越高。
这是Statsmodels中单一和多重线性回归的例子。我们可以在我们的回归模型中使用尽可能少或者更多变量(最多可以使用13个变量)!
接下来,我将演示如何在SKLearn中运行线性回归模型。
线性回归在SKLearn中
当涉及到Python中的机器学习时,SKLearn几乎是黄金标准。它有许多学习算法,可用于回归,分类,聚类和降维。
为了使用线性回归,我们需要导入它:
from sklearn import linear_model
让我们使用之前使用过的相同数据集,即波士顿房价。这个过程的前面部分是相同的 - 从SKLearn导入数据集并在波士顿数据集中加载:
from sklearn import datasets ## imports datasets from scikit-learn
data = datasets.load_boston() ## loads Boston dataset from datasets library
接下来,我们将数据加载到Pandas(与之前一样)
# define the data/predictors as the pre-set feature names
df = pd.DataFrame(data.data, columns=data.feature_names)
# Put the target (housing value -- MEDV) in another DataFrame
target = pd.DataFrame(data.target, columns=["MEDV"])
所以现在和之前一样,我们有包含自变量(标记为“df”)的DataFrame和具有因变量(标记为“target”)的DataFrame。我们使用SKLearn来拟合回归模型。
首先,我们将定义我们的X和Y--这次我将使用DataFrame中的所有变量来预测住房价格:
X = df
y = target[“MEDV”]
然后我会训练一个模型:
lm = linear_model.LinearRegression()
model = lm.fit(X,y)
lm.fit()函数适合线性模型。我们希望使用模型进行预测,所以我们将使用lm.predict():
predictions = lm.predict(X)
print(predictions)[0:5]
打印功能会打印Y的前5个预测(我没有打印整个列表以“节省空间”,删除[0:5]会打印整个列表):
[30.00821269 25.0298606 30.5702317 28.60814055 27.94288232]
请记住,lm.predict()使用我们拟合的线性模型预测Y(因变量)。
你一定注意到当我们用SKLearn运行线性回归时,并没有像Statsmodels那样得到一张漂亮的表格(好吧,它不是那么漂亮......但是非常有用)。
我们可以做的是使用内置函数来返回分数,系数和估计的截距。让我们看看它是如何工作的:
lm.score(X,y)
这个输出:
0.7406077428649428
这是我们模型的R²分数。之前讲过,R²是预测的解释方差的百分比。如果你有兴趣,请阅读这里。接下来,我们来看看预测变量的系数:
lm.coef_
会给出这个输出:
array([-1.07170557e-01,4.63952195e-02,2.08602395e-
02,2.68856140e + 00,-1.77957587e + 01,3.80475246e +
00,7.51061703e-04,-1.47575880e + 00,3.05655038e-01 ,
-1.23293463e-02,-9.53463555e-01,9.39251272e-03,
-5.25466633e-01])
来看看截距大小:
lm.intercept_
这将产生这样的结果:
36.491103280363134
这些都是我前面提到的多重回归方程的所有(估计/预测)部分。
好啦,你已经学会了如果用Sklean来做线性回归啦,你也可以查看有关coef_和intercept_的更多信息。
对于如何在Python中进行线性回归,这已经是一个速成(但是很长的篇幅)的学习。
在实践中,你不会使用整个数据集,但是你会将数据分成一个训练数据来训练你的模型,以及一个测试数据来测试你的模型。
下一篇文章,我还会用Python介绍其他的机器学习模型(*^▽^*)