在求解机器学习算法的模型参数时,很多情况下会用到梯度下降,这里稍微记一下学习笔记。
梯度:梯度的本意是一个向量(矢量),表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最快,变化率最大(为该梯度的模)。————百度百科
梯度下降算法本质上就是沿着负梯度方向寻找函数最小值的求解方法
梯度下降法是迭代法的一种,以逐渐逼近解为目的求出解的精确值。牛顿方法也是一种迭代法。
上图是梯度下降的一个直观图像,从某一点开始,沿着下降最快的方向一步一步逼近最小值。(从上图也可看出,梯度下降根据初始点选择的不同,最终求出的解也可能不同,不一定会收敛到最小值,可能会收敛到某个极小值)
1.批梯度下降(耗时长)
最小二乘法求误差的最小平方和,即$J(\theta)$最小值
$$ J(\theta )=\frac{1}{2}\sum_{i=0}^{n}(x_{i}\theta _{i}-y)^{2} $$
更新$\theta$:
$$ \theta _{i}=\theta _{i}-\alpha \frac{\partial J(\theta )}{\partial \theta _{i}} $$
$$ =\theta _{i}-\alpha\sum_{j=1}^{m}(h_{\theta }(x^{(j)})-y^{(j)})x_{i}^{(j)} $$
其中:α控制更新幅度大小,即训练的步长,m是样本数量,n是特征数量,y是给出的样本值,h是以θ为参数的关于x的函数,也是预测值。
批梯度下降每一次更新都会考虑所有m个样本,所以花时间长。
运用梯度下降法的关键在于控制步长$\alpha$的大小,太大可能会导致更新结果越过的最小值,导致震荡(如下图),太小会导致迭代次数过多,运行时间开销大
2.随机梯度下降(速度快,但是不能收敛到最小值)
伪代码如下:
for(j=1;j<=m;j++) $\theta _{i}=\theta _{i}-\alpha(h_{\theta }(x^{(j)})-y^{(j)})x_{i}^{(j)}$
随机梯度下降每次更新只更新 一个样本,对公式做了简化,所以速度快。但是它每次更新都只选取一个样本,所以无法精确逼近最小值。
logistic回归
logistic函数:
$$ g(z)=\frac{1}{1+e^{-z}} $$
可以看到,当x>=0时,y>=0.5,当x<0时,y<0.5。因此,我们可以以x和0的大小关系做分类器,x>0的,y=1,x<0的,y=0。
令 $h_{\theta}(X)=g(\theta^{T}X)=\frac{1}{1+e^{-\theta ^{T}X}}$
$$ P(y=1|x_{i}\theta)=h_{\theta}(x) P(y=0|x_{i}\theta)=1-h_\theta(x) $$
$$ P(y|x_{i}\theta)=h_{\theta}()x^{y}(1-h_{\theta}()x)^{1-y} $$
有关似然函数和贝叶斯公式的内容可阅读这里。
似然函数:
$$ L(\theta)=P(Y|X_{i}\theta)=\prod_{i=1}^{m}P(y^{(i)}|x_{j}^{(i)}\theta) $$
$$ =\prod_{i=1}^{m}h_{\theta }(x^{(i)})y^{(i)}(1-h_{\theta }(x^{(i)}))^{1-y^(i)} $$
取对数似然:
$$ l(\theta)=logL(\theta) $$
$$ =\sum_{i=1}^{m}y^{(i)}logh_{\theta}(x^{(i)})+(1-y^{(i)})log(1-h_{\theta}(x^{(i)})) $$
用梯度上升更新参数$\theta$以求得最大似然:
$$ \theta=theta+\alpha\bigtriangledown _{\theta}l(\theta)(注意这里是+号) $$
计算得到:
$$ \frac{\partial }{\partial \theta_{j}}l(\theta)=\sum_{i=1}^{m}(y^{(i)}-h_{\theta}(x^{(i)}))x_{j}^{(i)} $$
$$ \theta _{j}=\theta _{j}-\alpha\sum_{i=1}^{m}(h_{\theta }(x^{(i)})-y^{(i)})x_{j}^{(i)} $$
可以看到,最终得到的更新公式与之前几乎相同,唯一的区别在于$h(_\theta(x))$函数。
上图的代码实现:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
def sigmoid(z):#逻辑回归模型
return 1/(1+np.exp(-z))
nums=np.arange(-10,10,step=0.5)
fig, ax=plt.subplots()
ax.plot(nums,sigmoid(nums),'#000FFF')