我们求点(3, 4)、(0, 2)、(3, 0)处的梯度前言:本章的主题是神经网络的学习。这里所说的“学习”是指从训练数据中自动获取最优权重参数的过程。本章中,为了使神经网络能进行学习,将导入损失函数这一指标。而学习的目的就是以该损失函数为基准,找出能使它的值达到最小的权重参数。为了找出尽可能小的损失函数的值,本章我们将介绍利用了函数斜率的梯度法。
目录
损失函数
什么是损失函数
损失函数是表示神经网络性能的“恶劣程度”的指标,即当前的 神经网络对监督数据在多大程度上不拟合,在多大程度上不一致。
为什么要引入损失函数
我们的目标是获得使识别精度尽可能高的神经网络,而在进行神经网络的学习时,不能将识别精度作为指标。因为如果以识别精度为指标,则参数的导数在绝大多数地方都会变为0。
阶跃函数只在某个瞬间产生变化。而sigmoid函数, 如图4-4所示,不仅函数的输出(竖轴的值)是连续变化的,曲线的斜率(导数) 也是连续变化的。也就是说,sigmoid函数的导数在任何地方都不为0。这对 神经网络的学习非常重要。得益于这个斜率不会为0的性质,神经网络的学习得以正确进行。
常见的损失函数
均方误差
公式如下,yk是表示神经网络的输出,tk表示监督数据,k表示数据的维数
交叉熵误差
数学知识
导数
导数表示某个瞬间的变化量,求f(x)关于x的导数公式如下:
数值微分
利用微小的差分求导数的过程,函数的代码实现如下。(就是公式法求两点的切线),这里设置的h比较小可以用切线近似代替导数值。
def numerical_diff(f, x):
h = 1e-4 # 0.0001
return (f(x+h) - f(x-h)) / (2*h)
例子:求y = 0.01 + 0.1
函数图像
def function_1(x):
return 0.01*x**2 + 0.1*x
import numpy as np
import matplotlib.pylab as plt
x = np.arange(0.0, 20.0, 0.1)
y = function_1(x)
plt.xlabel("x")
plt.ylabel("f(x)")
plt.plot(x, y)
plt.show()
用数值微分得到的斜率画直线,虽然不是真正的切线,但误差非常小可以认为是近似相等。
偏导数
有多个变量的函数的导数称作偏导数,例如
偏导数和单变量的导数一样,都是求某个地方的斜率。不过, 偏导数需要将多个变量中的某一个变量定为目标变量,并将其他变量固定为某个值。对x0求偏导,将x1设置为固定值。同理对x1求偏导,将x0设置为固定值。
在这些问题中,我们定义了一个只有一个变量的函数,并对这个函数进行了求导。例如,问题1中,我们定义了一个固定x1 = 4的新函数,然后对 只有变量x0的函数应用了求数值微分的函数。从上面的计算结果可知,问题 1的答案是6.00000000000378,问题2的答案是7.999999999999119,和解析解的导数基本一致。公式法求x0的偏导 2x0,结果就是2*3 = 6; 公式法求x1的偏导 2x1,结果就是2*4 = 8。所以可以用数值微分近似求导,结果相差不大(几乎可以忽略不计)。
梯度
梯度指示的方向是各点处的函数值减小最多的方向
上述函数梯度的实现如下,本质上和单变量求数值微分没有什么区别。对Numpy数组x中的每个元素都进行数值微分求解。
def numerical_gradient(f,x):
h = 1e-4 #0.0001
grad = np.zeros_like(x)
for idx in range(x.size):
tmp_val = x[idx]
x[idx] = tmp_val + h
fxh1 = f(x)
x[idx] = tmp_val - h
fxh2 = f(x)
grad[idx] = (fxh1 - fxh2) / (2*h)
x[idx] = tmp_val #还原值
return grad
这里我们求点(3, 4)、(0, 2)、(3, 0)处的梯度
def function_2(x):
return x[0]**2 + x[1]**2
print(numerical_gradient(function_2,np.array([3.0,4.0])))
print(numerical_gradient(function_2,np.array([0.0,2.0])))
print(numerical_gradient(function_2,np.array([3.0,0.0])))
对应结果为
[6. 8.]
[0. 4.]
[6. 0.]
梯度法
虽然梯度的方向并不一定指向最小值,但沿着它的方向能够最大限度地减小函数的值。通过不断地沿梯度方向前进, 逐渐减小函数值的过程就是梯度法(gradient method)。梯度法是解决机器学习中最优化问题的常用方法,特别是在神经网络的学习中经常被使用。
寻找最小值的梯度法称为梯度下降法(gradient descent method), 寻找最大值的梯度法称为梯度上升法(gradient ascent method)。一般来说,神经网络(深度学习)中,梯度法主要是指梯度下降法。
η表示更新量,在神经网络的学习中,称为学习率(learning rate)。学习率决定在一次学习中,应该学习多少,以及在多大程度上更新参数。式(4.7)是表示更新一次的式子,这个步骤会反复执行。python实现梯度下降法
def gradient_descent(f, init_x, lr=0.01, step_num=100):
x = init_x
for i in range(step_num):
grad = numerical_gradient(f, x)
x -= lr * grad
return x
参数f是要进行最优化的函数,init_x是初始值,lr是学习率learning rate(这里学习率要设置合适的值,过大或者过小都不行),step_num是梯度法的重复次数。numerical_gradient(f,x)会求函数的梯度,用该梯度乘以学习率得到的值进行更新操作,由step_num指定重复的 次数。 使用这个函数可以求函数的极小值,顺利的话,还可以求函数的最小值。
设初始值为(-3.0, 4.0),开始使用梯度法寻找最小值。最终的结 果是(-6.1e-10, 8.1e-10),非常接近最小值(0,0)。 通过梯度法基本得到最小值,梯度法的更新过程如下图。
总结:这一章涉及导数、偏导数、梯度等数学知识以及损失函数、梯度下降等概念。