线性回归是利用数理统计中回归分析,来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法,运用十分广泛。
线性回归的原理
什么是线性回归?
定义与公式
线性回归(Linear regression)是利用回归方程(函数)对一个或多个自变量(特征值)和因变量(目标值)之间关系进行建模的一种分析方式。
特点:只有一个自变量的情况称为单变量回归,多于一个自变量情况的叫做多元回归。通用公式如下:

其中w和x可以理解为:

我们一般将w叫做回归系数,将b叫做偏置。
怎么理解线性回归呢?
我们来看几个例子
●期末成绩 = 0.7考试成绩 + 0.3平时成绩
已知5个人的考试成绩和平时成绩,求他们的期末成绩。
用一个5* 2的矩阵A存放5个学生的2个特征值信息(考试成绩、平时成绩)
A=[ [90,80], [80,85], [70,80], [95,85], [75,85] ]
用一个12的矩阵B存放期末成绩构成系数
B=[0.7, 0.3]
期末成绩=矩阵A矩阵B的转置
●房子价格= 0.02中心区域的距离 + 0.04城市-氧化氮浓度 + (-0.12自住房平均房价)+0.254城镇犯罪率
用一个25的矩阵A存放2个房子的5个特征值信息
A=[[90, 80, 0.2, 85, 0.7], [80, 95, 0.15, 75, 0.85]]
用一个15的矩阵B存放房屋价格构成系数
B=[0.02, 0.04, -1, -0.12, 0.254]
房屋价格 = 矩阵A * 矩阵B的转置
上面两个例子,我们看到特征值与目标值之间建立了一个线性关系,这个关系可以理解为线性模型。
“回归”一词的来历
今天我们所知道的回归是由达尔文( Charles Darwin )的表兄弟Francis Galton发明的。Galton于1877年完成了第一次回归预测,目的是根据上一代豌豆种子(双亲)的尺寸来预测下一代豌豆种子(孩子)的尺寸。Galton在大量对象上应用了回归分析,甚至包括人的身高。他注意到,如果双亲的高度比平均高度高,他们的子女也倾向于比平均高度高,但尚不及双亲。孩子的高度向着平均高度回退(回归)。Galto在多项研究上都注意到这个现象,所以尽管这个英文单词跟数值预测没有任何关系,但这种研究方法仍被称作回归”。
线性回归的特性
- 优点:结果易于理解,计算上不复杂。
- 缺点:对非线性的数据拟合不好。
- 适用数据类型:数值型和标称型数据。
回归的一般方法
- (1)收集数据:采用任意方法收集数据。
- (2)准备数据:回归需要数值型数据,标称型数据将被转成二值型数据。
- (3)分析数据:绘出数据的可视化二维图将有助于对数据做出理解和分析,在采用缩减法求得新回归系数之后,可以将新拟合线绘在图上作为对比。
- (4)训练算法:找到回归系数。
- (5)测试算法:使用R2或者预测值和数据的拟合度,来分析模型的效果。
- (6)使用算法:使用回归,可以在给定输入的时候预测出一个数值,这是对分类方法的提升,因为这样可以预测连续型数据而不仅仅是离散的类别标签。
损失函数的引入
我们知道,一般情况下,我们预测的结果与真实结果之间存在着一定的的误差,既然存在这个误差,那我们就将这个误差给衡量出来,于是引入了损失函数cost
总损失函数定义为:

- y_ i为第i个训练样本的真实值
- h(x_ i)为第i个训练样本特征值组合预测函数
- 损失函数求的是平方误差和,又称最小二乘法
用矩阵表示还可以写做:

优化算法
如何去求出模型当中的W,使得损失最小?
(平方误差和越小,说明线性回归拟合效果越好。)
线性回归经常使用的两种优化算法
- 梯度下降
- 正规方程
使用正规方程优化线性回归
应当怎样从一大堆数据里求出回归方程呢?假定输人数据存放在矩阵x中,而回归系数存放在向量w中。那么对于给定的数据xi,预测结果将会通过Y1=X1^Tw 给出。现在的问题是,手里有一些x和对应的y,怎样才能找到w呢? 一个常用的方法就是找出使误差最小的w。这里的误差是指预测y值和真实y值之间的差值,使用该误差的简单累加将使得正差值和负差值相互抵消,所以我们采用平方误差。

w上方的小标记表示,这是当前可以估计出的w的最优解。从现有数据上估计出的w可能并不是数据中的真实w值,所以这里使用了一个“帽”符号来表示它仅是w的一个最佳估计。
值得注意的是,上述公式中包含(X^TX)^-1,也就是需要对矩阵求逆,因此这个方程只在逆矩阵存在的时候适用。然而,矩阵的逆可能并不存在,因此必须要在代码中对此作出判断。
上述的最佳w求解是统计学中的常见问题,除了矩阵方法外还有很多其他方法可以解决过调用NumPy库里的矩阵方法,我们可以仅使用几行代码就完成所需功能。该方法也称作OLS,意思是“普通最小二乘法”( ordinary least squares )。
示例代码
def loadDataSet(filename):
data = pd.read_csv(filename)
xArr = data.iloc[:, :-1].values
lgY = data.iloc[:, -1].values
data_num, features_num = np.shape(xArr)
lgX = np.mat(np.ones((data_num, features_num + 1)))
lgX[:, 1:5] = np .mat(xArr)
return lgX, lgY
def standRegres(xArr, yArr):
xMat = np.mat(xArr)
yMat = np.mat(yArr).T
xTx = xMat.T * xMat
if np.linalg.det(xTx) == 0.0:
print("矩阵为奇异矩阵,不能求逆")
return
ws = xTx.I * (xMat.T*yMat)
return ws
第一个函数loadDataSet ()打开一个csv文件,这里仍然默认文件每行的最后一个值是 目标值。第二个函数standRegres ()用来计算最佳拟合直线。该函数首先读人x和y并将它们保存到矩阵中;然后计算x’x,然后判断它的行列式是否为零,如果行列式为零,那么计算逆矩阵的时候将出现错误。NumPy提供一个线性代数的库linalg,其中包含很多有用的函数。可以直接调用linalg.det()来计算行列式。最后,如果行列式非零,计算并返回w。如果没有检查行列式是否为零就试图计算矩阵的逆,将会出现错误。NumPy的线性代数库还提供一个函数来解未知矩阵,如果使用该函数,那么代码ws=xTx.I * (xMat .T * yMat)应写成ws=linalg.solve(xTx, xMat.T * yMatT)。
使用梯度下降优化线性回归
梯度下降是一个最优化算法,通俗的来讲也就是沿着梯度下降的方向来求出一个函数的极小值。
通常情况下,数据不可能完全符合我们的要求,所以很难用矩阵去求解,因此我们采用梯度下降,不断迭代,沿着梯度下降的方向来移动,求出极小值。
梯度下降算法
下一个位置 = 当前位置 – 学习率 * 梯度(循环直到结束)
结束标准:1.损失函数小于设定的值;2.运行了设置的周期数
该算法也就是沿着梯度下降的方向求出一个函数的极小值。
- 在一元函数中叫做求导。
- 在多元函数中就叫做求梯度。
迭代的过程用数学公式表达即为:

其中,a为步长,也就是学习速率,控制更新的幅度。
正规方程VS梯度下降
正规方程 | 梯度下降 |
不需要 | 需要选择学习率 |
一次运算得出 | 需要迭代求解 |
需要计算方程,时间复杂度高O(n^3) | 特征数量较大可以使用 |
选择:
V小规模数据:LinearRegression(正规方程)
V大规模数据:SGDRegressor