梯度下降的 核心思想就是 负梯度方向作为 下降方向。
数学描述
设 f ( x ) f(x) f(x)在 x ⃗ k \vec{x}_k xk附近连续可微,将 x ⃗ k \vec{x}_k xk做一个小的移动 α d ⃗ \alpha \vec{d} αd,那么此时 x ⃗ = x ⃗ k + α d ⃗ \vec{x}=\vec{x}_k + \alpha \vec{d} x=xk+αd,这里的 d ⃗ \vec{d} d是移动的单位方向( ∣ ∣ d ⃗ ∣ ∣ = 1 ||\vec{d}||=1 ∣∣d∣∣=1),如果 f ( x ) f(x) f(x)不是一个常量,即 ∇ f ( x k ) ≠ 0 \nabla f(x_k)\neq0 ∇f(xk)=0,那么就可以对 f ( x k ) f(x_k) f(xk)进行泰勒展开:
f ( x ⃗ ) = f ( x ⃗ k ) + ( ∇ f ( x ⃗ k ) ) T ( x ⃗ − x ⃗ k ) + o ( ∣ ∣ x ⃗ − x ⃗ k ∣ ∣ ) = f ( x ⃗ k ) + α [ ∇ f ( x ⃗ k ) ] T d ⃗ + o ( α ) , α > 0 f(\vec{x})=f(\vec{x}_k)+(\nabla f(\vec{x}_k))^T(\vec{x}-\vec{x}_k)+o(||\vec{x}-\vec{x}_k||) \\=f(\vec{x}_k)+\alpha[\nabla f(\vec{x}_k)]^T\vec{d}+o(\alpha), \alpha > 0~~~~ f(x)=f(xk)+(∇f(xk))T(x−xk)+o(∣∣x−xk∣∣)=f(xk)+α[∇f(xk)]Td+o(α),α>0
那么上式的变量就是中间的 [ ∇ f ( x ⃗ k ) ] T d ⃗ [\nabla f(\vec{x}_k)]^T\vec{d} [∇f(xk)]Td,因为这是两个向量的点积,也就是说这量的大小不但与这两个向量的大小有关,也与这两个向量的方向有关,这里 d ⃗ \vec{d} d是单位向量,而在给定的 f ( x ⃗ ) f(\vec{x}) f(x)后,导数 ∇ f ( x k ) \nabla f(x_k) ∇f(xk)的大小是确定的,而方向是不确定的:
[ ∇ f ( x ⃗ ) ] T d ⃗ = − ∇ f ( x ⃗ ) ⋅ cos θ [\nabla f(\vec{x})]^T\vec{d}=-\nabla f(\vec{x})\cdot\cos\theta [∇f(x)]Td=−∇f(x)⋅cosθ
只有 θ = 0 \theta=0 θ=0时,即负梯度方向时,这个中间项才取值最小,也就是 f ( x ⃗ ) f(\vec{x}) f(x)下降最快的方向。
算法描述:
输入:f(x)的表达式
输出:极小值点
x
⃗
⋆
\vec{x}^\star
x⋆
- 选择初始点 x 0 x_0 x0, 收敛误差 ϵ > 0 \epsilon>0 ϵ>0,迭代次数为 N N N, 令 k = 0 k=0 k=0。
- 若 ∣ ∇ f ( x ⃗ ) ∣ ≤ ϵ |\nabla f(\vec{x})|\leq\epsilon ∣∇f(x)∣≤ϵ, 则 x ⃗ ⋆ = x ⃗ k \vec{x}^\star=\vec{x}_k x⋆=xk,迭代停止;否则计算 d ⃗ k = − ∇ f ( x ⃗ ) \vec{d}_k=-\nabla f(\vec{x}) dk=−∇f(x)。
- 选择和计算步长影子 α k \alpha_k αk。
- 计算 x ⃗ k + 1 = k ⃗ k + α k d ⃗ k \vec{x}_{k+1}=\vec{k}_k+\alpha_k\vec{d}_k xk+1=kk+αkdk
- 令 k = k + 1 k=k+1 k=k+1,若 k ≥ N k\geq N k≥N,则 x ⃗ ⋆ = x ⃗ k \vec{x}^\star=\vec{x}_k x⋆=xk,停止迭代,否则装到2.
程序实例:
def fun(x):
return x*x + 3
def diff(x):
return 2*x
def grad(n):
lr = 0.01
x = 2
y1 = fun(x)
for i in range(n):
x = x - lr * diff(x)
y2 = fun(x)
if abs(y1 - y2) < 1e-4:
return x, y2
return x, y2
print(grad(1000))
结果:
(3.3659347144319058e-09, 3.0)
即当 x = 3.3659347144319058 e − 09 x=3.3659347144319058e-09 x=3.3659347144319058e−09时, f u n ( x ) fun(x) fun(x)取得最小值3.0。
那么可以小结一下:**
梯度算法是机器学习的必学内容
在我们做计算的时候,其实并不是像上述距离一样简单。其实tensorflow和pytorch已经将求导的公式整合好了,到时候只需要调用即可,但是也是有必要学习一下的。神经网络的层与层之间的链接都有一个激活函数,也就是说,在上一层传过来,都要经过激活函数的求导,那么激活函数就要学习一下。
激活函数
激活函数,顾名思义,当达到一定值的时候,就会激活,然后决定如何向下传输激活函数作用后的值。可以将其理解成一个开关等。
sigmoid函数:
σ ( x ) = s i g m ( x ) = 1 1 + e − 1 \sigma(x)=sigm(x)=\frac{1}{1+e^{-1}} σ(x)=sigm(x)=1+e−11
sigmoid导函数:
σ ′ ( x ) = ( s i g m ( x ) ) ′ = σ ( x ) ( 1 − σ ( x ) ) = − e − x ( 1 + e − x ) 2 \sigma'(x)=(sigm(x))'=\sigma(x)(1-\sigma(x))=-\frac{e^{-x}}{(1+e^{-x})^2} σ′(x)=(sigm(x))′=σ(x)(1−σ(x))=−(1+e−x)2e−x
双曲正切函数tanh:
tanh ( x ) = e x − e − x e x − e − x \tanh(x)=\frac{e^{x}-e^{-x}}{e^{x}-e^{-x}} tanh(x)=ex−e−xex−e−x
双曲正切导函数:
( tanh ( x ) ) ′ = 1 − ( tanh ( x ) ) 2 = ( e x + e − x ) 2 − ( e x − e − x ) 2 ( e x + e − x ) 2 (\tanh(x))'=1-(\tanh(x))^2=\frac{(e^{x}+e^{-x})^2-(e^{x}-e^{-x})^2}{(e^{x}+e^{-x})^2} (tanh(x))′=1−(tanh(x))2=(ex+e−x)2(ex+e−x)2−(ex−e−x)2
激活函数的种类有很多,不同数据,不同模型,激活函数也不尽相同。
这里维基百科上列出了很多激活函数,如下图: