几个变量的约定
X代表属性的矩阵, x ( i ) x^{(i)} x(i)代表X的第i行, x j ( i ) x^{(i)}_j xj(i)代表X第i行第j列, θ \theta θ是参数向量。
线性回归
估计函数
h
(
x
)
=
∑
i
=
0
m
x
(
i
)
θ
=
X
θ
h(x)=\sum_{i=0}^mx^{(i)}\theta=X\theta
h(x)=i=0∑mx(i)θ=Xθ
代价函数
J
(
θ
)
=
1
2
m
∑
i
=
0
m
(
x
(
i
)
θ
−
y
(
i
)
)
2
=
1
2
m
∑
i
=
0
m
(
X
θ
−
y
)
2
J(\theta) = \frac{1}{2m}\sum^m_{i=0}(x^{(i)}\theta - y^{(i)})^2=\frac{1}{2m}\sum_{i=0}^m(X\theta - y)^2
J(θ)=2m1i=0∑m(x(i)θ−y(i))2=2m1i=0∑m(Xθ−y)2
上述代价函数其实就是是预估值与真实值得偏差,除2m而不是m得原因是为了之后好求导。(当然求解的方法中不是所有都要求导的)
线性回归的目标:求得合适的 θ \theta θ,使得J( θ \theta θ)最小。得到的 θ \theta θ代回到h(x)中,就可以得到线性的模型。
求解方法
- 梯度下降法
根据偏导得定义,使用迭代的方法求解。首先给 θ \theta θ一个初值,然后根据以下公式进行迭代: θ ( i ) = θ ( i ) − α δ J δ θ ( i ) \theta^{(i)} = \theta^{(i)}-\alpha\frac{\delta J}{\delta\theta^{(i)}} θ(i)=θ(i)−αδθ(i)δJ其中 δ J δ θ ( i ) \frac{\delta J}{\delta\theta^{(i)}} δθ(i)δJ是 θ ( i ) \theta^{(i)} θ(i)方向的偏导, α \alpha α为学习效率,这个值得大小需要手动尝试。如果 α \alpha α太大。可能不收敛, α \alpha α太小那么收敛速度太慢。可以尝试0.001,0.01,0.1,0.3,1等值
为了好表示,上述的i记为j
式中
δ
J
δ
θ
(
j
)
=
1
m
∑
i
=
0
m
(
x
(
i
)
θ
−
y
(
i
)
)
x
j
(
i
)
\frac{\delta J}{\delta\theta^{(j)}} = \frac{1}{m}\sum_{i=0}^m(x^{(i)}\theta - y^{(i)})x^{(i)}_j
δθ(j)δJ=m1i=0∑m(x(i)θ−y(i))xj(i)
上述的求导公式比较繁琐,可以用矩阵的方式表示: θ = θ − α m ( X θ − y ) X \theta = \theta - \frac{\alpha}{m}(X\theta - y)X θ=θ−mα(Xθ−y)X
有了以上公式就可以很容易的使用python的numpy库进行运算了。可以设定迭代次数为终止条件,也可以设定前一次和这一次 θ \theta θ的变化量小于某个值(比如0.01)作为终止条件。
以下是一个简单的实现,求解的问题属性只有1个,除了默认的1.
import numpy as np
import matplotlib.pyplot as plt
#样本
x = np.array([1 , 3, 5, 7, 8, 10])
y = np.array([3, 6 , 9, 12, 15, 20])
#矩阵X
X = np.column_stack((np.array([1,1,1,1,1,1]),x))
#m为样本的数量
m = x.shape[0]
#学习效率
alpha = 0.01
#初始化theta
theta = [0, 0]
#更新theta
newTheta = theta - alpha / m * (X @ theta - y) @ X
#计数,判断迭代了多少次
cnt = 1
#迭代的总次数
total = 100
#代价函数的截断误差
precision = 0.01
#迭代
while np.any(newTheta - theta > precision) and cnt < total:
theta = newTheta
newTheta = theta - alpha / m * (X @ theta - y) @ X
cnt = cnt + 1
#获得估计的Y值
predY = X @ newTheta
plt.scatter(x, y)
plt.plot(x, predY)
plt.show()
线性回归的结果如下:
2.使用正规方程
θ
=
(
X
T
X
)
−
1
X
T
y
\theta = (X^TX)^{-1}X^Ty
θ=(XTX)−1XTy
这个方法实现起来简单,但是当规模太大的时候,复杂度太高。吴恩达对这个问题表示当特征值的个数大于万以上,就考虑其他方法了。
以下是这个方法的实现,直接使用梯度下降法的例子,我们可以直观的看到他们的回归的结果。为了代码的简练,只写了这个算法求解 θ \theta θ的代码。
theta1 = np.linalg.inv(X.T@X)@X.T@y
predY1 = X @ theta1
图像如下:
蓝色的直线是上述梯度下降法求解的归回直线,橙色的是正规方程求解的直线,我们可以看到,两条直线十分接近,几乎重叠了。