基于线性回归的房屋价格预测
一、知识预警
1.1 线性代数
(
A
T
)
T
=
A
(A^\mathrm{T})^\mathrm{T}=A
(AT)T=A$
(
A
+
B
)
T
=
A
T
+
B
T
(A+B)^\mathrm{T}=A^\mathrm{T}+B^\mathrm{T}
(A+B)T=AT+BT
(
λ
A
)
T
=
λ
A
T
(\lambda A)^\mathrm{T}=\lambda A^\mathrm{T}
(λA)T=λAT
(
A
B
)
T
=
B
T
A
T
(AB)^\mathrm{T}=B^\mathrm{T}A^\mathrm{T}
(AB)T=BTAT
(
A
−
1
)
−
1
=
A
(A^{-1})^{-1}=A
(A−1)−1=A
(
A
B
)
−
1
=
B
−
1
A
−
1
(AB)^{-1}=B^{-1}A^{-1}
(AB)−1=B−1A−1
1.2 矩阵微积分
为了书写简便,我们通常把单个函数对多个变量或者多元函数对单个变量的偏导数写成向量和矩阵的形式,使其可以被当成一个整体处理.矩阵微积分(Matrix Calculus)是多元微积分的一种表达方式,即使用矩阵和向量来表示因变量每个成分关于自变量每个成分的偏导数。
标量关于向量的偏导数:对于M维向量 x ∈ R x \in \mathbb{R} x∈R和函数 y = f ( x ) ∈ R y=f(x) \in \mathbb{R} y=f(x)∈R,则关于 x x x的偏导数为:
∂
y
∂
x
=
[
∂
y
∂
x
1
,
⋯
,
∂
y
∂
x
M
]
⊤
∈
R
M
×
1
,
\frac{\partial y}{\partial \boldsymbol{x}}=\left[\frac{\partial y}{\partial x_{1}}, \cdots, \frac{\partial y}{\partial x_{M}}\right]^{\top} \quad \in \mathbb{R}^{M \times 1},
∂x∂y=[∂x1∂y,⋯,∂xM∂y]⊤∈RM×1,
向量关于标量的偏导数:对于标量𝑥 ∈ ℝ和函数𝒚 = 𝑓(𝑥) ∈
R
N
\mathbb{R}^N
RN,则𝒚关于𝑥 的
偏导数为
∂
y
∂
x
=
[
∂
y
1
∂
x
,
⋯
,
∂
y
N
∂
x
]
∈
R
1
×
N
\frac{\partial \boldsymbol{y}}{\partial x}=\left[\frac{\partial y_{1}}{\partial x}, \cdots, \frac{\partial y_{N}}{\partial x}\right] \quad \in \mathbb{R}^{1 \times N}
∂x∂y=[∂x∂y1,⋯,∂x∂yN]∈R1×N
向量关于向量的偏导数 对于 𝑀 维向量 𝒙 ∈ ℝ𝑀 和函数 𝒚 = 𝑓(𝒙) ∈ ℝ𝑁,则
𝑓(𝒙)关于𝒙的偏导数(分母布局)为
∂
f
(
x
)
∂
x
=
[
∂
y
1
∂
x
1
⋯
∂
y
N
∂
x
1
⋮
⋱
⋮
∂
y
1
∂
x
M
⋯
∂
y
N
∂
x
M
]
∈
R
M
×
N
\frac{\partial f(\boldsymbol{x})}{\partial \boldsymbol{x}}=\left[\begin{array}{ccc} \frac{\partial y_{1}}{\partial x_{1}} & \cdots & \frac{\partial y_{N}}{\partial x_{1}} \\ \vdots & \ddots & \vdots \\ \frac{\partial y_{1}}{\partial x_{M}} & \cdots & \frac{\partial y_{N}}{\partial x_{M}} \end{array}\right] \in \mathbb{R}^{M \times N}
∂x∂f(x)=
∂x1∂y1⋮∂xM∂y1⋯⋱⋯∂x1∂yN⋮∂xM∂yN
∈RM×N
向量函数及其导数
∂
x
∂
x
=
I
\frac{\partial \pmb x}{\partial \pmb x} = I
∂x∂x=I
∂
A
x
∂
x
=
A
T
\frac{\partial \pmb A \pmb x}{\partial \pmb x} = \pmb A^\mathrm{T}
∂x∂Ax=AT
∂
x
T
A
∂
x
=
A
\frac{ \partial \pmb x^\mathrm{T} A}{\partial \pmb x} = \pmb A
∂x∂xTA=A
二、线性回归(Linear Regression)
2.1 什么是回归分析?
回归分析这是一个来自统计学的概念。回归分析是指一种预测性的建模技术,主要是研究自变量和因变量的关系。通常使用线/曲线来拟合数据点,然后研究如何使曲线到数据点的距离差异最小。如果使用直线进行拟合,则为线性回归(一元线性回归、多元线性回归);如果是对非线性关系进行建模,则为多项式回归。
例如,存在以下数据(左图)。然后我们拟合一条曲线
f
(
x
)
f(x)
f(x)右图,回归分析的目标就是要拟合一条曲线,让图中红色线段加起来的和最小。
![](https://i-blog.csdnimg.cn/blog_migrate/09c05ee0abd6629832af1ef6d6150829.png)
![](https://i-blog.csdnimg.cn/blog_migrate/26d025018f5bbba0ce78f6c09a7735d3.png)
-
假设目标值(因变量)与特征值(自变量)之间线性相关,即满足一个多元一次方程,如: f ( x ) = ( w 1 x 1 + … + w n x n + b ) f(x)=(w_1x_1+…+w_nx_n+b) f(x)=(w1x1+…+wnxn+b)。
-
然后构建损失函数。
-
最后通过令损失函数最小来确定参数。(最关键的一步)
2.2 一元线性回归
一元线性回归(一元:只有一个未知自变量;线性:自变量 x x x的次数都为1次)。
f
(
x
)
=
w
x
+
b
\begin{align} f(x)=wx+b \end{align}
f(x)=wx+b
有
N
N
N组数据,自变量
x
=
(
x
(
1
)
,
x
(
2
)
,
…
,
x
(
n
)
)
x=(x^{(1)},x^{(2)},…,x^{(n)})
x=(x(1),x(2),…,x(n)),因变量
y
=
(
y
(
1
)
,
y
(
2
)
,
…
,
y
(
n
)
)
y=(y^{(1)},y^{(2)},…,y^{(n)})
y=(y(1),y(2),…,y(n)),则训练集
D
=
{
(
x
(
n
)
,
y
(
n
)
)
}
n
=
1
N
\mathcal{D}=\{(x^{(n)} ,y^{(n)})\}_{n=1}^N
D={(x(n),y(n))}n=1N,然后我们假设它们之间的关系是:
y
^
(
n
)
=
f
(
x
)
=
w
x
(
n
)
+
b
\begin{align}\hat y^{(n)}=f(x)=wx^{(n)}+b \end{align}
y^(n)=f(x)=wx(n)+b
那么线性回归的目标就是如何让
f
(
x
)
f(x)
f(x)和
y
y
y之间的差异最小,换句话说就是
a
a
a,
b
b
b取什么值的时候
f
(
x
)
f(x)
f(x)和
y
y
y最接近。
这里我们得先解决另一个问题,就是如何衡量
f
(
x
)
f(x)
f(x)和
y
y
y之间的差异。在回归问题中,均方误差是回归任务中最常用的性能度量。记
J
(
a
,
b
)
J(a,b)
J(a,b)为
f
(
x
)
f(x)
f(x)和
y
y
y之间的差异,即预测值和真实值的差异:
![](https://i-blog.csdnimg.cn/blog_migrate/d4645be89e3ef622f9f55593230f9c2f.png)
给定一组包含N个训练样本的数据集 D = { ( x ( n ) , y ( n ) ) } n = 1 N \mathcal{D}=\{(x^{(n)} ,y^{(n)})\}_{n=1}^N D={(x(n),y(n))}n=1N,则假设函数为:
L
(
w
,
b
)
=
∑
i
=
1
N
(
f
(
x
(
n
)
)
−
y
(
n
)
)
2
=
(
w
x
(
n
)
+
b
−
y
(
n
)
)
2
\begin{align} \mathcal{L}(w,b) &=\sum_{i=1}^N \left(f(x^{(n)}) - y^{(n)}\right)^2 \\ &=(wx^{(n)}+b-y^{(n)})^2 \end{align}
L(w,b)=i=1∑N(f(x(n))−y(n))2=(wx(n)+b−y(n))2
这里称
L
(
w
,
b
)
\mathcal{L}(w,b)
L(w,b)为损失函数,明显可以看出
L
(
w
,
b
)
\mathcal{L}(w,b)
L(w,b)是二次函数,所以有最小值。当
L
(
w
,
b
)
\mathcal{L}(w,b)
L(w,b)取最小值的时候,
f
(
x
)
f(x)
f(x)和
y
y
y的差异最小,然后我们可以通过最小化
L
(
w
,
b
)
\mathcal{L}(w,b)
L(w,b)来确定
a
a
a和
b
b
b的值。求解该问题有很多方法,首先可以想到求偏导。
2.3 多元线性回归
现实中的数据可能是比较复杂的,自变量也可能不止一个,例如,影响房屋价格也很可能不止房屋面积一个因素,可能还有是否在地铁附近,房间数,层数,建筑年代等诸多因素,表示为
x
=
(
x
1
,
x
2
,
.
.
.
,
x
D
)
x=(x_1,x_2,...,x_D)
x=(x1,x2,...,xD)。不过,这些因素对房价影响的权重是不同的,因此,我们可以使用多个权重
w
=
(
w
1
,
w
2
,
.
.
.
,
w
D
)
w=(w_1,w_2,...,w_D)
w=(w1,w2,...,wD)来表示多个因素与房屋价格的关系:
y
^
=
f
(
x
)
=
(
w
1
x
1
+
…
+
w
D
x
D
+
b
)
\begin{align} \hat{y}=f(x)&=(w_1x_1+…+w_Dx_D+b)\\ \end{align}
y^=f(x)=(w1x1+…+wDxD+b)
给定一组包含
N
N
N个训练样本的数据集
D
=
{
(
x
(
n
)
,
y
(
n
)
)
}
n
=
1
N
\mathcal{D}=\{(x^{(n)} ,y^{(n)})\}_{n=1}^N
D={(x(n),y(n))}n=1N,则假设函数为:
y
^
(
n
)
=
f
(
x
)
=
(
w
1
x
1
(
n
)
+
w
2
x
2
(
n
)
+
…
+
w
D
x
D
(
n
)
+
b
)
=
∑
d
=
1
D
w
d
x
d
(
n
)
+
b
\begin{align} \hat{y}^{(n)}=f(x) &=(w_1x_1^{(n)}+w_2x_2^{(n)}+…+w_Dx_D^{(n)}+b) \\ &= \sum_{d=1}^Dw_dx_d^{(n)}+b \end{align}
y^(n)=f(x)=(w1x1(n)+w2x2(n)+…+wDxD(n)+b)=d=1∑Dwdxd(n)+b
写成向量形式:
y ^ ( n ) = f ( x ( n ) ) = w x ( n ) + b \begin{align} \hat{\pmb{y}}^{(n)}=f( \pmb{x}^{(n)})=\pmb{w} \pmb{x}^{(n)}+b \end{align} y^(n)=f(x(n))=wx(n)+b
为表示方便,重新定义向量 w : = w ⨁ b = [ w 1 w 2 ⋮ w D b ] \pmb w:= \pmb w \bigoplus b=\begin{bmatrix} w_{1} \\ w_{2} \\ {\vdots}\\ w_{D} \\ b \\ \end{bmatrix} w:=w⨁b= w1w2⋮wDb , x : = x ⨁ 1 = [ x 1 x 2 ⋮ x D 1 ] \pmb x:=\pmb x \bigoplus 1=\begin{bmatrix} x_{1} \\ x_{2} \\ {\vdots}\\ x_{D} \\ 1 \\ \end{bmatrix} x:=x⨁1= x1x2⋮xD1 ,写成增广向量的形式:
y ^ = f ( x ) = w T x \begin{align} \hat{\pmb{y}}=f( \pmb{x})=\pmb{w ^\mathrm T} \pmb{x} \end{align} y^=f(x)=wTx
尽管公式 ( 7 ) (7) (7)可以描述变量之间的关系,但是一般机器学习领域更喜欢使用公式 ( 9 ) (9) (9)这样的向量乘法的形式。这不仅因为这样表示起来更简单,也是因为现代计算机对向量计算做了大量优化,无论是CPU还是GPU都喜欢向量计算,并行地处理数据,可以得到成百上千倍的加速比。需要注意的是,公式中不加粗的表示标量,加粗的表示向量或矩阵。
![](https://i-blog.csdnimg.cn/blog_migrate/4a398bfc5270a204677b9833221465de.png)
比一元线性回归更为复杂的是,多元线性回归组成的不是直线,是一个多维空间中的超平面,数据点散落在超平面的两侧。多元线性回归的损失函数仍然使用预测值-真实值的平方来计算,损失函数为所有样本点距离超平面的距离之和:
L ( w , b ) = ∑ n = 1 N ( f ( x ( n ) ) − y ( n ) ) 2 = ∑ n = 1 N ( w 1 x 1 ( n ) + w 2 x 2 ( n ) + + … + w D x D ( n ) + b − y ( n ) ) 2 = ∑ n = 1 N ( ( ∑ d = 1 D w d x d ( n ) + b ) − y ( n ) ) 2 ⟺ 1 2 ∑ n = 1 N ( ( ∑ d = 1 D w d x d ( n ) + b ) − y ( n ) ) 2 \begin{align} \mathcal{L}(w,b) &=\sum_{n=1}^N \left(f(x^{(n)}) - y^{(n)}\right)^2 \\ &=\sum_{n=1}^N(w_1x_1^{(n)}+w_2x_2^{(n)}++…+w_Dx_D^{(n)}+b -y^{(n)})^2\\ &=\sum_{n=1}^N \left( \left( \sum_{d=1}^Dw_dx_d^{(n)}+b \right)-y^{(n)} \right)^2\\ &\iff \textcolor{red}{\frac{1}{2} }\sum_{n=1}^N \left( \left( \sum_{d=1}^Dw_dx_d^{(n)}+b \right)-y^{(n)} \right)^2\\ \end{align} L(w,b)=n=1∑N(f(x(n))−y(n))2=n=1∑N(w1x1(n)+w2x2(n)++…+wDxD(n)+b−y(n))2=n=1∑N((d=1∑Dwdxd(n)+b)−y(n))2⟺21n=1∑N((d=1∑Dwdxd(n)+b)−y(n))2
写成矩阵形式,令
X
=
[
x
1
(
1
)
x
1
(
2
)
…
x
1
(
N
)
x
2
(
1
)
x
2
(
2
)
…
x
2
(
N
)
⋮
⋮
⋮
⋮
x
D
(
1
)
x
D
(
2
)
…
x
D
(
N
)
1
1
…
1
]
\pmb X=\begin{bmatrix} x_{1}^{(1)} & x_{1}^{(2)} & {\dots} &x_{1}^{(N)}\\ x_{2}^{(1)} & x_{2}^{(2)} & {\dots} &x_{2}^{(N)}\\ {\vdots} & {\vdots} & {\vdots} & {\vdots}\\ x_{D}^{(1)} &x_{D}^{(2)} & {\dots}&x_{D}^{(N)} \\ 1 & 1 & {\dots} & 1\\ \end{bmatrix}
X=
x1(1)x2(1)⋮xD(1)1x1(2)x2(2)⋮xD(2)1……⋮……x1(N)x2(N)⋮xD(N)1
,
X
\pmb X
X的每一列代表一个样本,
y
=
[
y
(
1
)
y
(
2
)
⋮
y
(
N
)
]
\pmb y=\begin{bmatrix} y^{(1)}\\y^{(2)}\\ \vdots \\y^{(N)}\end{bmatrix}
y=
y(1)y(2)⋮y(N)
则写成矩阵形式:
L
(
w
)
=
1
2
(
X
T
w
−
y
)
T
(
X
T
w
−
y
)
=
1
2
∣
∣
X
T
w
−
y
∣
∣
2
\begin{align} \mathcal{L}(w) &=\frac{1}{2} ( \pmb X^\mathrm{T} \pmb w- \pmb y)^\mathrm{T}( \pmb X^\mathrm{T} \pmb w- \pmb y)\\ &=\frac{1}{2} || \pmb X^\mathrm{T} \pmb w-\pmb y ||^2 \end{align}
L(w)=21(XTw−y)T(XTw−y)=21∣∣XTw−y∣∣2
目标是最小化损失函数式(15),这是一个无约束多元函数求极值问题,有梯度下降、牛顿法、共轭梯度法,智能优化算法(粒子群算法等、遗传算法、鲸鱼算法等),但首先想到的解法是求导令
∂
L
(
w
)
∂
w
=
0
\frac{\partial \mathcal L(w)}{\partial w}=0
∂w∂L(w)=0:
∂ ∂ w L ( w ) = X ( X T w − y ) = X X T w − X y = 0 X X T w = X y w = ( X X T ) − 1 X y \begin{align} \frac{\partial}{\partial w} \mathcal L(w) &=\pmb X (\pmb X^\mathrm{T} \pmb w-\pmb y)\\ &=\pmb X \pmb X^\mathrm{T}\pmb w - \pmb X\pmb y = 0 \\ \pmb X \pmb X^\mathrm{T}\pmb w&=\pmb X\pmb y\\ \pmb w&= (\pmb X \pmb X^\mathrm{T})^{-1}\pmb X \pmb y \end{align} ∂w∂L(w)XXTww=X(XTw−y)=XXTw−Xy=0=Xy=(XXT)−1Xy
以上求偏导令=0的解法,就是最小二乘法,这里的二乘表示用平方来度量观测点与估计点的远近(在古汉语中“平方”称为“二乘”);“最小”指的是参数的估计值要保证各个观测点与估计点的距离的平方和达到最小,是minimize最小化。
吴恩达机器学习编程练习:线性回归+梯度下降
在统计学上把单变量线性回归和多变量线性回归统称为一元线性回归、多元线性回归。
三、基于线性回归的房屋价格预测
线性回归使用梯度下降拟合参数,步骤为:
- 初始化最大迭代次数maxIter,学习率alpha;
- 导入数据:np.loadtxt(),构建假设函数(增广权重矩阵、增广特征向量) w = [ 0 0 ] \pmb w=\begin{bmatrix} 0 \\ 0 \end{bmatrix} w=[00];
- 由式(7)计算梯度;
- 由式(9)更新梯度;
- 由式(6)计算损失函数;
- 判断maxIter>当前迭代次数?,是则转step3,否则算法结束,输出增广权重矩阵 w \pmb{w} w。
3.1 一元线性回归
数据集介绍:吴恩达作业(ex1data1.txt)
6.1101,17.592
5.5277,9.1302
8.5186,13.662
7.0032,11.854
5.8598,6.8233
8.3829,11.886
7.4764,4.3483
8.5781,12
6.4862,6.5987
5.0546,3.8166
5.7107,3.2522
14.164,15.505
5.734,3.1551
8.4084,7.2258
5.6407,0.71618
5.3794,3.5129
6.3654,5.3048
5.1301,0.56077
6.4296,3.6518
7.0708,5.3893
6.1891,3.1386
20.27,21.767
5.4901,4.263
6.3261,5.1875
5.5649,3.0825
18.945,22.638
12.828,13.501
10.957,7.0467
13.176,14.692
22.203,24.147
5.2524,-1.22
6.5894,5.9966
9.2482,12.134
5.8918,1.8495
8.2111,6.5426
7.9334,4.5623
8.0959,4.1164
5.6063,3.3928
12.836,10.117
6.3534,5.4974
5.4069,0.55657
6.8825,3.9115
11.708,5.3854
5.7737,2.4406
7.8247,6.7318
7.0931,1.0463
5.0702,5.1337
5.8014,1.844
11.7,8.0043
5.5416,1.0179
7.5402,6.7504
5.3077,1.8396
7.4239,4.2885
7.6031,4.9981
6.3328,1.4233
6.3589,-1.4211
6.2742,2.4756
5.6397,4.6042
9.3102,3.9624
9.4536,5.4141
8.8254,5.1694
5.1793,-0.74279
21.279,17.929
14.908,12.054
18.959,17.054
7.2182,4.8852
8.2951,5.7442
10.236,7.7754
5.4994,1.0173
20.341,20.992
10.136,6.6799
7.3345,4.0259
6.0062,1.2784
7.2259,3.3411
5.0269,-2.6807
6.5479,0.29678
7.5386,3.8845
5.0365,5.7014
10.274,6.7526
5.1077,2.0576
5.7292,0.47953
5.1884,0.20421
6.3557,0.67861
9.7687,7.5435
6.5159,5.3436
8.5172,4.2415
9.1802,6.7981
6.002,0.92695
5.5204,0.152
5.0594,2.8214
5.7077,1.8451
7.6366,4.2959
5.8707,7.2029
5.3054,1.9869
8.2934,0.14454
13.394,9.0551
5.4369,0.61705
餐馆老板想在不同城市开分店,并收集了这些城市的 人口数和当地餐馆的利润作为训练样本保存在 ex1data1.txt
。该数据集为97行×2列,第一列为人口数(万),第二列为餐馆利润(万元)。请利用线性回归,根据城市的人口数据预测其利润。
3.1.1 加载数据
导入库:
import numpy as np # 科学计算库,处理多维数组,进行数据分析
import pandas as pd # 基于 NumPy 的一种解决数据分析任务工具
import matplotlib.pyplot as plt # 提供一个类似 Matlab 的绘图框架
导入数据集:
data = np.loadtxt("./resources/ex1data1.txt", delimiter=',', dtype=np.float64)
数据级 D = { ( x ( i ) , y ( i ) ) } i = 1 N = 97 \mathcal{D}=\{{(x^{(i)}, y^{(i)})} \}_{i=1}^{N=97} D={(x(i),y(i))}i=1N=97, x ( i ) x^{(i)} x(i)为第 i i i个样本,即第 i i i行的人口数, N N N为样本数量。
3.1.2 假设函数
已知单变量线性回归的假设函数为
f
(
x
)
=
w
x
+
b
f(x)=wx+b
f(x)=wx+b,进一步向量乘法的形式,表示起来更简单,易于编程计算,这里构建增广权重向量
w
=
[
w
b
]
\pmb w=\begin{bmatrix}w \\ b \end{bmatrix}
w=[wb],增广特征向量
x
=
[
x
1
]
\pmb x=\begin{bmatrix}x \\ 1 \end{bmatrix}
x=[x1]:
f
(
x
)
=
w
x
+
b
=
[
w
b
]
[
x
1
]
=
w
T
x
=
x
w
\begin{align} f(x) &= wx+b \\ &=[w \quad b] \begin{bmatrix} x \\1\end{bmatrix}\\ &= \pmb{w}^\mathrm{T} \pmb{x}\\ &= \pmb{x}\pmb{w} \end{align}
f(x)=wx+b=[wb][x1]=wTx=xw
获取数据集中的输入向量 X X X,需要在数据集加入 x 0 = 1 x_0=1 x0=1 的一列:
data = np.loadtxt("ex1data1.txt", delimiter=",", dtype=np.float64)
y = data[:, 1:2]
X = np.insert(data[:, 0:1], obj=1, values=1, axis=1)
初始化参数 w = [ 0 0 ] \pmb w=\begin{bmatrix} 0 \\ 0 \end{bmatrix} w=[00]为2行1列
w = np.zeros(X.shape[1]).reshape(2, 1)
3.1.3 损失函数(代价函数)
令 X = [ x ( 1 ) 1 x ( 2 ) 1 ⋮ ⋮ x ( N ) 1 ] \pmb X=\begin{bmatrix} x^{(1)} &1\\ x^{(2)} &1\\ \vdots & \vdots\\ x^{(N) } &1 \end{bmatrix} X= x(1)x(2)⋮x(N)11⋮1 , y = [ y ( 1 ) y ( 2 ) ⋮ y ( N ) ] \pmb y=\begin{bmatrix}y^{(1)} \\y^{(2)} \\ \vdots \\ y^{(N)}\end{bmatrix} y= y(1)y(2)⋮y(N) ,则损失函数 L ( w ) \mathcal{L}(w) L(w)可以表示为:
L ( w ) = 1 2 N ∑ i = 1 N ( f ( x ( i ) ) − y ( i ) ) 2 = 1 2 N ∣ ∣ X w − y ∣ ∣ 2 \begin{align} \mathcal{L}(w)&=\frac{1}{2N} \sum_{i=1}^N \left(f(x^{(i)}) - y^{(i)} \right)^2\\ &= \frac{1}{2N} ||\pmb X \pmb w- \pmb{y}||^2 \end{align} L(w)=2N1i=1∑N(f(x(i))−y(i))2=2N1∣∣Xw−y∣∣2
def loss_func(w, X, y):
return np.sum(np.square(X.dot(w) - y)) / 2 * X.shape[0]
3.1.4 梯度下降函数
首先对
L
(
w
)
\mathcal{L(w)}
L(w)求导,
∇
L
(
w
)
=
1
N
X
T
(
X
w
−
y
)
\begin{align} \nabla \mathcal{L(w)}=\frac{1}{N} \pmb{X}^\mathrm{T}(\pmb{Xw-y}) \end{align}
∇L(w)=N1XT(Xw−y),这里用到了向量函数及其导数公式:
∂
A
x
∂
x
=
A
T
\frac{\partial \pmb{Ax}}{\partial \pmb{x}}=\pmb{A}^\mathrm{T}
∂x∂Ax=AT。故梯度下降更新公式:
w
:
=
w
−
α
∇
L
(
w
)
:
=
w
−
α
1
N
X
T
(
X
w
−
y
)
\begin{align} \pmb w&:=\pmb w-\alpha \nabla \mathcal{L(w)}\\ &:= \pmb w- \alpha \frac{1}{N} \pmb{X}^\mathrm{T}(\pmb{Xw-y}) \end{align}
w:=w−α∇L(w):=w−αN1XT(Xw−y)
def grad(w, X, y):
return (X.T @ (X.dot(w) - y)) / X.shape[0]
def grad_descent(w, X, y, alpha, maxIter):
loss = []
for i in range(maxIter):
w = w - alpha * grad(w, X, y)
cost = loss_func(w, X, y)
loss.append(cost)
return w, loss
3.1.6 完整代码
import numpy as np
from matplotlib import pyplot as plt
def loss_func(w, X, y):
return np.sum(np.square(X.dot(w) - y)) / 2 * X.shape[0]
def grad(w, X, y):
return (X.T @ (X.dot(w) - y)) / X.shape[0]
def grad_descent(w, X, y, alpha, maxIter):
loss = []
for i in range(maxIter):
w = w - alpha * grad(w, X, y)
cost = loss_func(w, X, y)
loss.append(cost)
return w, loss
def paint(loss, data):
fig = plt.figure(figsize=(10, 4))
# 画第1个图:折线图
ax1 = fig.add_subplot(121)
ax1.plot([i for i in range(maxIter)], loss, color="#FF0000")
ax1.set_title("loss function")
# 画第2个图:散点图
ax2 = fig.add_subplot(122)
ax2.scatter(data[:, 0], data[:, 1])
ax2.plot([5.0, 22.5], [5.0 * w[0] + w[1], 22.5 * w[0] + w[1]], color="#FF0000")
ax2.set_title("linear regression")
plt.show()
if __name__ == "__main__":
maxIter = 10000
data = np.loadtxt("ex1data1.txt", delimiter=",", dtype=np.float64)
y = data[:, 1:2]
X = np.insert(data[:, 0:1], obj=1, values=1, axis=1)
w = np.zeros(X.shape[1]).reshape(2, 1)
w, loss = grad_descent(w, X, y, alpha=0.002, maxIter=maxIter)
print(w)
paint(loss, data)
最后拟合得到的权重矩阵为 w = [ 1.18218457 − 3.78778781 ] \pmb w=\begin{bmatrix} 1.18218457\\ -3.78778781 \end{bmatrix} w=[1.18218457−3.78778781],损失函数收敛图、线性回归拟合结果如图所示:
![](https://i-blog.csdnimg.cn/blog_migrate/734dddb00c12ff8b94c91cebf922d98f.png)
3.2 多变量线性回归
吴恩达机器学习线性回归例题ex1data2.txt
数据集,该数据集共47行×3列,第一列为房子的大小,第二列为卧室数量,第三列为房子的价格,该问题有2个变量(房子的大小,卧室的数量)。请利用线性回归,根据房子的大小和卧室的数量数据预测房子的价格。
2104,3,399900
1600,3,329900
2400,3,369000
1416,2,232000
3000,4,539900
1985,4,299900
1534,3,314900
1427,3,198999
1380,3,212000
1494,3,242500
1940,4,239999
2000,3,347000
1890,3,329999
4478,5,699900
1268,3,259900
2300,4,449900
1320,2,299900
1236,3,199900
2609,4,499998
3031,4,599000
1767,3,252900
1888,2,255000
1604,3,242900
1962,4,259900
3890,3,573900
1100,3,249900
1458,3,464500
2526,3,469000
2200,3,475000
2637,3,299900
1839,2,349900
1000,1,169900
2040,4,314900
3137,3,579900
1811,4,285900
1437,3,249900
1239,3,229900
2132,4,345000
4215,4,549000
2162,4,287000
1664,2,368500
2238,3,329900
2567,4,314000
1200,3,299000
852,2,179900
1852,4,299900
1203,3,239500
数据级 D = { ( x 1 ( i ) , x 2 ( i ) , y ( i ) ) } i = 1 N = 47 \mathcal{D}=\{{(x_1^{(i)},x_2^{(i)}, y^{(i)})} \}_{i=1}^{N=47} D={(x1(i),x2(i),y(i))}i=1N=47, x ( i ) x^{(i)} x(i)为第 i i i个样本,即第 i i i行的人口数, x 1 x_1 x1为房子大小, x 2 x_2 x2为卧室的数量, N N N为样本数量。
3.2.1 加载数据集
导入库:
import numpy as np # 科学计算库,处理多维数组,进行数据分析
import matplotlib.pyplot as plt # 提供一个类似 Matlab 的绘图框架
导入数据集:
data = np.loadtxt("./resources/ex1data1.txt", delimiter=',', dtype=np.float64)
3.2.2 特征缩放
在多变量线性回归中,由于变量的范围有所不同,如x1是0到5000的数,而x2则是0到5的数,这会导致在X与Y坐标轴比例尺相同的情况下,整个图像显得极为修长,且此时梯度下降会需要很多次迭代才能收敛。因此需要进行特征缩放,使x1和x2在保持原有对应关系下,能稳定在-1到1之间。
常用特征缩放方法:
- 线性归一化(Min-Max Normalization): X n o r m = X − X min X max − X min X_{norm}=\frac{X-X_{\min}}{X_{\max}-X_{\min}} Xnorm=Xmax−XminX−Xmin把输入数据都转换到[0,1]的范围。
- 0均值标准化:
3.2.3 假设函数
假设函数为
f
(
x
)
=
w
1
x
1
+
w
2
x
2
+
b
f(x)=w_1x_1+w_2x_2+b
f(x)=w1x1+w2x2+b,进一步向量乘法的形式,表示起来更简单,易于编程计算,这里构建增广权重向量
w
=
[
w
1
w
2
b
]
\pmb w=\begin{bmatrix}w_1 \\ w_2 \\ b \end{bmatrix}
w=
w1w2b
,增广特征向量
x
=
[
x
1
x
2
1
]
\pmb x=\begin{bmatrix}x_1 \\ x_2 \\1 \end{bmatrix}
x=
x1x21
:
f
(
x
)
=
w
1
x
1
+
w
2
x
2
+
b
=
[
w
1
w
2
b
]
[
x
1
x
2
1
]
=
w
T
x
=
x
w
\begin{align} f(x) &= w_1x_1+w_2x_2+b \\ &=[w_1 \quad w_2 \quad b] \begin{bmatrix} x_1 \\x_2\\1\end{bmatrix}\\ &= \pmb{w}^\mathrm{T} \pmb{x}\\ &= \pmb{x}\pmb{w} \end{align}
f(x)=w1x1+w2x2+b=[w1w2b]
x1x21
=wTx=xw
3.2.4 损失函数
令 X = [ x ( 1 ) 1 x ( 2 ) 1 ⋮ ⋮ x ( N ) 1 ] \pmb X=\begin{bmatrix} x^{(1)} &1\\ x^{(2)} &1\\ \vdots & \vdots\\ x^{(N) } &1 \end{bmatrix} X= x(1)x(2)⋮x(N)11⋮1 , y = [ y ( 1 ) y ( 2 ) ⋮ y ( N ) ] \pmb y=\begin{bmatrix}y^{(1)} \\y^{(2)} \\ \vdots \\ y^{(N)}\end{bmatrix} y= y(1)y(2)⋮y(N) ,则损失函数 L ( w ) \mathcal{L}(w) L(w)可以表示为:
L ( w ) = 1 2 N ∑ i = 1 N ( f ( x ( i ) ) − y ( i ) ) 2 = 1 2 N ∣ ∣ X w − y ∣ ∣ 2 \begin{align} \mathcal{L}(w)&=\frac{1}{2N} \sum_{i=1}^N \left(f(x^{(i)}) - y^{(i)} \right)^2\\ &= \frac{1}{2N} ||\pmb X \pmb w- \pmb{y}||^2 \end{align} L(w)=2N1i=1∑N(f(x(i))−y(i))2=2N1∣∣Xw−y∣∣2
def loss_func(w, X, y):
return np.sum(np.square(X.dot(w) - y)) / 2 * X.shape[0]
3.2.5 梯度下降函数
首先对
L
(
w
)
\mathcal{L(w)}
L(w)求导,
∇
L
(
w
)
=
1
N
X
T
(
X
w
−
y
)
\begin{align} \nabla \mathcal{L(w)}=\frac{1}{N} \pmb{X}^\mathrm{T}(\pmb{Xw-y}) \end{align}
∇L(w)=N1XT(Xw−y),这里用到了向量函数及其导数公式:
∂
A
x
∂
x
=
A
T
\frac{\partial \pmb{Ax}}{\partial \pmb{x}}=\pmb{A}^\mathrm{T}
∂x∂Ax=AT。故梯度下降更新公式:
w
:
=
w
−
α
∇
L
(
w
)
:
=
w
−
α
1
N
X
T
(
X
w
−
y
)
\begin{align} \pmb w&:=\pmb w-\alpha \nabla \mathcal{L(w)}\\ &:= \pmb w- \alpha \frac{1}{N} \pmb{X}^\mathrm{T}(\pmb{Xw-y}) \end{align}
w:=w−α∇L(w):=w−αN1XT(Xw−y)
def grad(w, X, y):
return (X.T @ (X.dot(w) - y)) / X.shape[0]
def grad_descent(w, X, y, alpha, maxIter):
loss = []
for i in range(maxIter):
w = w - alpha * grad(w, X, y)
cost = loss_func(w, X, y)
loss.append(cost)
return w, loss
3.2.6 算法步骤
- 初始化最大迭代次数maxIter,学习率alpha;
- 导入数据:np.loadtxt(),构建假设函数(增广权重矩阵、增广特征向量) w = [ 0 0 0 ] \pmb w=\begin{bmatrix} 0 \\ 0\\ 0 \end{bmatrix} w= 000 ;
- 由式(7)计算梯度;
- 由式(9)更新梯度;
- 由式(6)计算损失函数;
- 判断maxIter>当前迭代次数?,是则转step3,否则算法结束,输出增广权重矩阵 w \pmb{w} w。
3.2.7 完整代码
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
np.set_printoptions(suppress=True)
def loss_func(w, X, y):
return np.sum(np.square(X.dot(w) - y)) / 2 * X.shape[0]
def grad(w, X, y):
return (X.T @ (X.dot(w) - y)) / X.shape[0]
def grad_descent(w, X, y, alpha, maxIter):
loss = []
for i in range(maxIter):
w = w - alpha * grad(w, X, y)
cost = loss_func(w, X, y)
loss.append(cost)
return w, loss
if __name__ == "__main__":
maxIter = 10000
# 读取数据
dataset = np.loadtxt("ex1data2.txt", delimiter=",", dtype=np.float64)
# 特征缩放
data = (dataset - np.mean(dataset, axis=0)) / np.std(dataset, axis=0)
# 增广矩阵
X = np.insert(data[:, 0:2], obj=2, values=1, axis=1)
y = data[:, 2:3]
w = np.zeros(shape=X.shape[1]).reshape(3, 1)
w, loss = grad_descent(w, X, y, alpha=0.002, maxIter=maxIter)
print(w)
fig = plt.figure()
ax = fig.add_axes(Axes3D(fig)) # 创建三维坐标
ax.scatter(data[:, 0:1], data[:, 1:2], data[:, -1]) # 散点图
ax.set(xlabel='size', ylabel='bedrooms', zlabel='price') # 坐标轴
# 绘制拟合平面
x1, x2 = np.meshgrid(
np.linspace(np.min(data[:, 0:1]), np.max(data[:, 0:1]), 47),
np.linspace(np.min(data[:, 1:2]), np.max(data[:, 1:2]), 47),
) # 生成网格采样点,这一步很重要
w = w.reshape(1, 3)
f = w[0][0] * x1 + w[0][1] * x2 + w[0][2]
ax.plot_surface(x1, x2, f, color='g', alpha=0.4) # 绘制平面
plt.show()
运行结果
w
=
[
0.88469562
−
0.05310845
−
0.
]
\pmb w=\begin{bmatrix} 0.88469562 \\ -0.05310845\\ -0. \end{bmatrix}
w=
0.88469562−0.05310845−0.
,与正规方程w=np.linalg.inv(X.T@X)@X.T@y
求解结果一致。
![](https://i-blog.csdnimg.cn/blog_migrate/79853f916f8af140cd92eaa0db28fdc3.png)