神经网络的特征就是可以从数据中学习,也就是说可以由数据自动决定权重参数的值。
1.从数据中学习:
这里还是以之前提到的MNIST数据集为例,此时需要我们来设计一个能够识别手写字体的程序,那么人类、机器学习和深度学习会给出三种不同的方法。
其中:
- 人类需要人工的从数据中发现规律性,然后提炼出数据中的模式,但是要想从MNIST数据集中提炼出规律性,其实是不太可能的。
- 机器学习的方法则是,先从数据中提取处特征量(需要注意的是,特征量仍是人工设计完成的,同时针对不同的问题需要不同的特征量),然后再通过机器学习算法学习这些特征量的模式,从而解决问题。但是可以看出机器学习方法已经在极力避免人为的介入,而是尝试从数据中寻找模式。
- 神经网络/深度学习方法则是进一步地避免人为介入,数据中的特征也是靠网络来自己学习的,可以看出神经网络是从原始数据直接得到答案,也就是说从一端(输入数据)直接到另一端(输出结果),因此深度学习有时也被称为端到端学习(end-to-end machine learning)。
神经网络的优点是对所有问题都可以用同样的流程来解决,也就是说与问题无关,神经网络可以将数据直接作为输入,进行端到端的学习。
但是为了保证学习的质量,一般需要将输入的原始数据划分为训练数据和测试数据两部分。
- 首先,使用训练数据进行学习,寻找最优的参数;
- 然后,使用测试数据集来评价训练得到的模型的实际能力。
之所以要采取上面的做法,是为了能提高学习得到的模型的泛化能力(指处理未被观察过的数据的能力)。
因此仅仅在一个数据集去学习和评价,是没法正确的评价模型的泛化能力的。还可能出现模型可以很好的处理某个数据集,但是在其他数据集上的表现就很差,这种状态也就神经网络中的过拟合(over fitting)问题。
2.损失函数:
为了使神经网络能进行学习,将引入损失函数(loss function)这一指标。
因为,神经学习的目的就是以损失函数为基准,学习的目标是为了得到使得损失函数最小的权重参数的值。
损失函数可以使用任意函数,下面介绍两种常用的损失函数,均方误差和交叉熵误差。
2.1 均方误差
均方误差公式如下所示:
其中,yk表示神经网络的输出,tk表示测试数据,k表示数据的维度。
也就是说,均方误差会计算神经网络输出与正确解的各个元素之差的平方和。
用python实现就是:
import numpy as np
# 定义均方误差函数
def mean_squared_error(y,t):
return 0.5*np.sum((y-t)**2)
# 定义k,以mnist数据集为例,假设2位正确解
t = [0,0,1,0,0,0,0,0,0,0]
# 第一组y,其中2的概率最高为0.6
y1 = [0.1,0.05,0.6,0.0,0.05,0.1,0.0,0.1,0.0,0.0]
# 计算均方误差的值
print('第一组均方误差为:',mean_squared_error(np.array(y1),np.array(t)))
# 第二组y,其中2的概率最高为0.4
y2 = [0.1,0.05,0.4,0.0,0.05,0.1,0.0,0.1,0.1,0.1]
# 计算均方误差的值
print('第二组均方误差为:',mean_squared_error(np.array(y2),np.array(t)))
# 第二组y,其中7的概率最高为0.6
y3 = [0.1,0.05,0.1,0.0,0.05,0.1,0.0,0.6,0.0,0.0]
# 计算均方误差的值
print('第三组均方误差为:',mean_squared_error(np.array(y3),np.array(t)))
运行得到结果
第一组均方误差为: 0.09750000000000003
第二组均方误差为: 0.20750000000000002
第三组均方误差为: 0.5975
通过结果可以看出第一组的均方误差最小,其损失函数最小,也就是说该输出值与真实值之间的误差最小。而第三组误差最大,因为其预测结果错误。
2.2 交叉熵误差
交叉熵误差公式如下所示:
其中,yk表示神经网络的输出,tk表示测试数据,k表示数据的维度。
用python实现就是:
import numpy as np
# 定义交叉熵误差函数
def cross_entropy_error(y,t):
delta = 1e-7
# 为了防止出现log0的情况,加上了一个微小值delta
return -np.sum(t*np.log(y + delta))
# 定义k,以mnist数据集为例,假设2位正确解
t = [0,0,1,0,0,0,0,0,0,0]
# 第一组y,其中2的概率最高为0.6
y1 = [0.1,0.05,0.6,0.0,0.05,0.1,0.0,0.1,0.0,0.0]
# 计算均方误差的值
print('第一组交叉熵误差为:',cross_entropy_error(np.array(y1),np.array(t)))
# 第二组y,其中2的概率最高为0.4
y2 = [0.1,0.05,0.4,0.0,0.05,0.1,0.0,0.1,0.1,0.1]
# 计算均方误差的值
print('第二组交叉熵误差为:',cross_entropy_error(np.array(y2),np.array(t)))
# 第二组y,其中7的概率最高为0.6
y3 = [0.1,0.05,0.1,0.0,0.05,0.1,0.0,0.6,0.0,0.0]
# 计算均方误差的值
print('第三组交叉熵误差为:',cross_entropy_error(np.array(y3),np.array(t)))
运行得到结果
第一组交叉熵误差为: 0.510825457099338
第二组交叉熵误差为: 0.9162904818741863
第三组交叉熵误差为: 2.302584092994546
可以看出,结果与之前的均方误差一致。
3.mini-batch版损失函数:
神经网络的学习是需要针对所有训练数据计算损失函数的值,也就说如果训练数据有100个,那么就要把这100个损失函数的值的总和作为学习的指标。
那么如果要求所有训练数据的损失函数的总和,以交叉熵为例,式子表示如下:
其中,训练数据数量为N,tnk/ynk表示第n个数据的第k个元素的值。
之所以前面除以N,视为了求单个数据的“平均损失函数”,通过这样的平均化,可以获得和训练数据的数量无关的统一指标。
3.1 mini-batch版交叉熵误差
实现mini-batch版交叉熵只需要对之前的函数进行改进就可以。
用python实现就是:
import numpy as np
# 定义交叉熵误差函数
def cross_entropy_error(y,t):
# 如果维度为1,即求单个数据的交叉熵误差的时候,需要改变数据的形状
if y.ndim == 1:
t = t.reshape(1,t.size)
y = y.reshape(1,y.size)
batch_size = y.shape[0]
return -np.sum(t*np.log(y + 1e-7)) / batch_size
Reference:
《Deep Learning from Scratch》