为了找出尽可能小的损失函数的值,将会利用函数斜率的梯度法,神经网络的梯度求解的本质就是求导。
1.数值微分:
函数的导数公式如下:
$$
\frac{df\left( x \right)}{dx}=\lim_{h\rightarrow 0} \frac{f\left( x+h \right) -f\left( x \right)}{h}
$$
一般基于数学公式的求导过程称为“解析式求导/解析式求解”,比如求解y=x²
的导数,可以通过
$$\frac{dy}{dx}=2x$$
解析性的求解出来,也就是说解析式求导过程得到的导数是不含误差的“真的导数”。
而利用微小的差分求导数的过程称为“数值微分(numerical differentiation)”,比如赋予下面h一个微小值就可以近似求出函数在某点的导数。
$$
\frac{f\left( x+h \right) -f\left( x \right)}{h}
$$
代码中的实现:
def numerical_differentiation(f,x):
h = 1e-4
return (f(x+h)-f(x-h)) / (2*h)
此处需要注意的是:
- h的值不能使用过小的值,否则会产生“舍入误差(rounding error)”错误。
- 因为数值微分求导含有误差,为了减小这个误差,应该采用中心差分(计算f(x)在(x+h)和(x-h)之间的差分),而不应该采用前向差分(计算f(x)在(x+h)和(x)之间的差分)。
2.数值微分实例:
采用数值微分的方法,对下面函数求导:
$$
y=0.01x^2+0.1x
$$
计算该函数在x=5处的导数
import numpy as np
import matplotlib.pylab as plt
def numerical_diff(f, x):
h = 1e-4 # 0.0001
return (f(x+h) - f(x-h)) / (2*h)
def function_1(x):
return 0.01*x**2 + 0.1*x
def tangent_line(f, x):
d = numerical_diff(f, x)
print(d)
y = f(x) - d*x
return lambda t: d*t + y
x = np.arange(0.0, 20.0, 0.1)
y = function_1(x)
plt.xlabel("x")
plt.ylabel("f(x)")
tf = tangent_line(function_1, 5)
y2 = tf(x)
plt.plot(x, y)
plt.plot(x, y2)
plt.show()
运行得到结果:
0.1999999999990898
以及采用数值微分求解的值为斜率的直线:
另外通过解析式过程得到的函数解析解为:
$$
\frac{\text{d}f\left( x \right)}{\text{d}x}=0.02x+0.1
$$
进而求得,函数在x=5处的导数值为0.2.可以看出与采用数值微分求得的结果之间的误差非常小,两者近似相等。
3.偏导数:
现在来看下面这个函数,与上面的函数不同的是,该函数有两个变量。
$$
f\left( x_0,x_1 \right) =x_{0}^{2}+x_{1}^{2}
$$
对多变量函数的求导时要区分对哪个变量求导,有多个变量的函数的导数就称为“偏导数”,用数学式表达如下:
$$
\frac{\partial f}{\partial x_0}\text{、}\frac{\partial f}{\partial x_1}
$$
现在通过数值微分的方法来求解偏导数。
- 求x0=3,x1=4时,关于x0的偏导数:
def numerical_differentiation(f,x):
h = 1e-4
return (f(x+h)-f(x-h)) / (2*h)
def function(x0):
return x0*x0 + 4.0**2.0
print(numerical_differentiation(function,3.0))
运行得到结果
6.00000000000378
- 同理可以,求得x0=3,x1=4时,关于x1的偏导数:
def numerical_differentiation(f,x):
h = 1e-4
return (f(x+h)-f(x-h)) / (2*h)
def function(x1):
return 3.0**2.0 + x1*x1
print(numerical_differentiation(function,4.0))
运行得到结果
7.999999999999119
通过上述例子,可以看出偏导数和单变量的导数一样,都是求某个地方的斜率。不同的是,偏导数需要将多个变量中的某一个变量定位目标变量,并将其他变量固定为某个值,也就是说要对每个变量单独求导。
Reference:
《Deep Learning from Scratch》