回归(Regression)是从外语中翻译过来的词。翻译词的特点是带有原词的主要含义,但与原词表达的意思又不完全一样,甚至从中文字面上都难以理解,例如大家最熟悉的函数(function)这个翻译词。回归(Regression)简单理解可以说是“回去归来”,回归于事物的本来面目。
那么什么是线性回归呢?先不说概念,先看一个实例。下表是北京市海淀区中关村地区近期成交二手房源的情况(数据来源于北京链家网http://bj.lianjia.com/)。
面积(米2) | 总价(万元) | |
2016.08.15 | 81 | 715 |
2016.08.15 | 45 | 500 |
2016.08.14 | 59 | 610 |
2016.08.14 | 50 | 560 |
2016.08.14 | 52 | 440 |
2016.08.11 | 48 | 480 |
2016.08.11 | 79 | 852 |
2016.08.11 | 61 | 625 |
2016.08.10 | 56 | 620 |
2016.08.10 | 69 | 690 |
2016.08.10 | 70 | 735 |
2016.08.10 | 72 | 877 |
2016.08.09 | 48 | 495 |
2016.08.08 | 42 | 408 |
2016.08.06 | 55 | 605 |
2016.08.06 | 41 | 342 |
2016.08.05 | 69 | 720 |
2016.08.05 | 77 | 730 |
2016.08.05 | 62 | 590 |
2016.08.04 | 64 | 639 |
2016.08.04 | 53 | 646 |
2016.08.02 | 87 | 986 |
2016.08.02 | 64 | 709 |
2016.08.01 | 60 | 600 |
根据图上的数据分布,可以看到,这些数据近似的分布在一条直线周围。
利用初等数学知识,我们知道直线的函数表示是y=k*x+b,x是自变量,在这里就是房子的面积,y是因变量,这里就是房子的价格,k是直线的斜率,b是截距。如果我们求得了这条直线方程,那么,代入你的房子面积x=108平方米,就能预测你的房子的价格y了。
线性回归简单点说,就是给定一个数据集(本例就是上面链家网给出的北京中关村地区8月1日-15日的二手房销售数据),能够求出一条直线y=k*x+b,而这个直线能够较好的反映这个数据集的数据关系。这种反映一个因变量与一个自变量之间的线性关系的回归就是一元线性回归。一元线性回归形式简单,易于理解,但却蕴含着机器学习中一些重要的基本思想。
我们知道,在初等数学中,如果可以用一次方程(y=k*x+b)来表达两个变量之间关系的话,这两个变量之间的关系称为线性关系,也就是直线关系;当然在更高维度上,线性关系表示的是多个变量的一次方程,这时候就不是直线了,像x+y+z=1表示的就是一个平面。多个自变量(大于1个)的线性回归称为多元线性回归;如果变量之间不是线性关系,那就是非线性回归,多元线性回归和非线性回归将在后面再讲。
那么怎样求出这条直线(y=k*x+b)呢?也就是如何确定k和b呢?假设数据集中只有2条数据,例如前2条:
2016.08.15 | 81 | 715 |
2016.08.15 | 45 | 500 |
那么我们可以联立方程组:
715=k*81+b
500=k*45+b
利用初中数学知识求得k,b分别为k=5.9722,b=231.25。如果我们取最后2条数据:
2016.08.02 | 64 | 709 |
2016.08.01 | 60 | 600 |
709=k*64+b,600=k*60+b,可以求得k,b分别为k=27.25,b=-1035。
显然,仅仅根据数据集中随机选取2个数据,求得的直线方程是不一样的,甚至相差还很大。这很显然,因为从图中就可以看出来,不可能有一条直线穿过所有的点。那么,能不能取一条直线,让数据集中所有点到该直线的距离都尽可能近,从而用这条直线最优化的反映数据集合中所有数据之间的关系呢?实质上这就是线性回归的主要工作。如下图所示:
上图中红色方块分别为数据点到直线的垂直距离,对于数据集合中的所有数据来说,如果这些垂直距离的和最小,那么这条直线就是我们求得的最佳直线。
我们知道点到直线的垂直距离计算公式为:,需要进行开方运算,这样比较麻烦,运算量也大。因此,一般采用的是竖直距离,即从点作平行于Y轴的直线,计算点到直线的这个线段的距离。如下图所示:
我们设最优直线的函数为f(x)=k*x+b,再构造一个代价函数:
其中,表示数据集中第i个数据,表示了第i个数据点到直线的竖直距离的平方。代价函数C也称为损失函数,学过概率论的一眼就能看出这里构建的代价函数与均方误差(mean squared error,MSE)的公式是一样的。实质上还可以用等多种代价函数形式,但一般使用的是均方误差(MSE)形式,至于为什么用这种形式比较好,以后再讲。
那么,实际上我们是在求代价函数C在最小值情况下的(k,b)的值。将数据集中所有数据代入求C的公式:
可以看出,实质上C是k,b的二元二次函数,求C的最小值,实际就是求二元二次函数C=f(k,b)的最小值。求函数最小值的方法有很多,梯度下降算法就是一种。但对于本例的情况,可以简单使用梯度为0的方法。
对于 ,分别对k,b求偏导数,得到:
令上述2个偏导数等于0,联立得到k,b的解为:
,
原始数据保存在regression.txt中:
date,area,cost
2016.08.15,81,715
2016.08.15,45,500
2016.08.14,59,610
2016.08.14,50,560
2016.08.14,52,440
2016.08.11,48,480
2016.08.11,79,852
2016.08.11,61,625
2016.08.10,56,620
2016.08.10,69,690
2016.08.10,70,735
2016.08.10,72,877
2016.08.09,48,495
2016.08.08,42,408
2016.08.06,55,605
2016.08.06,41,342
2016.08.05,69,720
2016.08.05,77,730
2016.08.05,62,590
2016.08.04,64,639
2016.08.04,53,646
2016.08.02,87,986
2016.08.02,64,709
2016.08.01,60,600
代码如下:
import pandas as pd
ds = pd.read_csv("regression.txt")
x, y = ds.area, ds.cost
n = len(ds.area)
ka, kb, kc = 0, 0, 0
for i in range(n):
ka += y[i] * (x[i] - x.mean())
kb += x[i] ** 2
kc += x[i]
k = ka / (kb - kc ** 2 / n)
b = 0
for j in range(n):
b += y[i] - k * x[i]
b = b / n
print('k=', k, 'b=', b)
输出结果:
k= 10.8404658722 b= -50.4279523294
画图看看求得的最佳直线方程与数据的关系:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
ds = pd.read_csv("regression.txt")
x = ds.area
y = ds.cost
T = np.arctan2(x, y)
plt.scatter(x, y, c=T, s=20, alpha=0.8, marker='o')
x1 = np.linspace(35, 95, 100)
k = 10.8404658722
b = -50.4279523294
y1 = k * x1 + b
plt.plot(x1, y1)
plt.show()
可以看出,求得的最佳直线与数据集贴合的非常好。
再回到我们最初的目的,你要出售的房子面积108平方米,预测价格:y=10.8404658722*108-50.4279523294=1120万,哇,发财了。