本章包括
1、一个神经网络的例子
2、张量和张量操作
3、神经网络如何通过反向传播和梯度下降来学习
一、一个神经网络的例子
GitHub链接
使用Python库Keras学习对手写数字进行分类的神经网络(将手写数字(28*28px)的灰度图像分为10个类别:0-9;使用MNIST数据集,含有6000张测试图像,10000张训练图像)
1、 在Keras中加载MNIST数据集
from keras.datasets import mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
其中图像编码为numpy数组,label是一个标签数组(范围0-9),图像标签一一对应,流程:1)向神经网络提供训练数据;2)network学习相关的图像和标签;3)让network为test_image生成预测、验证预测是否与test_label中的标签匹配,再次建立网络
2、 网络架构
from keras import models
from keras import layers
network = models.Sequential()
network.add(layers.Dense(512, activation='relu', input_shape=(28 * 28,)))
network.add(layers.Dense(10, activation='softmax'))
深度学习模型就像是数据处理的筛子由一系列日益完善的数据过滤器—layers组成
选择三件事,作为编译步骤的一部分:
1) loss function–衡量模型在训练上的表现
2) An optimizer 优化器–自行更新的机制
3) 要监控的指标–在这里只关心准确性(正确分类的图像的分数)
3、 编译步骤
network.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
训练前,将数据重新整形为网络所需要的形状并对其进行缩放,时期在[0,1]内来预处理数据:uint8 255 (6000,28,28)矩阵–>float [0,1] (6000,28*28)数组
4、 准备数据图像
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255
test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255
5、 准备标签
from keras.utils import to_categorical
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
都准备好后,在Keras中通过调用网络的拟合方法来完成模型与训练数据相应匹配:
network.fit(train_images, train_labels, epochs=5, batch_size=128)
显示训练数据在网络丢失和网络对训练数据的准确性、输出在测试数据上的准确性:
test_loss, test_acc = network.evaluate(test_images, test_labels)
print('test_acc:', test_acc)
二、神经网络的数据表示—张量
张量是数据的容器 - 几乎总是数字数据。
1、 标量(0D张量)
仅包含一个数字的张量称为标量(或标量张量,或0维张量,或0D张量)。 在Numpy中,float32或float64数字是标量张量(或标量数组)。标量张量有0轴(ndim == 0)。
2、 向量(1D张量)
数组数组称为向量或1D张量,1D张量恰好具有一轴。
注意区分轴与维度,例如:x = np.array([12, 3, 6, 14]); 5D矢量仅具有一个轴并且沿其轴具有五个维度,而5D张量具有五个轴(并且沿着每个轴可以具有任意数量的维度)。
3、 矩阵(2D张量)
向量数组是矩阵或2D张量,矩阵有两个轴(通常称为行和列)。
4、 3D张量和高维张量
x = np.array([[[5, 78, 2, 34, 0],
[6, 79, 3, 35, 1],
[7, 80, 4, 36, 2]],
[[5, 78, 2, 34, 0],
[6, 79, 3, 35, 1],
[7, 80, 4, 36, 2]],
[[5, 78, 2, 34, 0],
[6, 79, 3, 35, 1],
[7, 80, 4, 36, 2]]])
在视觉上可以将其解释为数字的立方体。通过在阵列中打包3D张量,可以创建4D张量,依此类推。
5、 三个关键属性:
1) 轴数(等级):ndim
2) 形状:shape
3) 数据类型:dtype
6、 数据批量的概念
通常,在深度学习中遇到的所有数据张量中的第一个轴(轴0,因为索引从0开始)将是样本轴(有时称为样本维度)。 在MNIST示例中,样本是数字的图像。 此外,深度学习模型不会立即处理整个数据集; 相反,他们将数据分成小批量。 当考虑这种批量张量时,第一轴(轴0)称为批量轴或批量维度。
7、 数据张量的真实示例,常见的如下:
1) 矢量数据 - 形状的2D张量(样本,特征)
一个人的精算数据集,我们考虑每个人的年龄,邮政编码,和收入。 每个人可以被表征为3个值的向量,因此可以将100,000个人的整个数据集存储在2D张量形状(100000,3)中。
2) 时间序列数据或序列数据 - 形状的3D张量(样本,时间步长,特征)
按照惯例,时间轴始终是第二轴(索引1的轴)。
股票价格数据集。 每分钟,我们存储当前的股票价格,过去一分钟的最高价格和过去一分钟的最低价格。因此,每分钟编码为一个3D矢量,整个交易日编码为2D张量 形状(390,3)(在交易日有390分钟),250天的数据可以存储在3D张量的形状(250,390,3)中。 在这里,每个样本都是一天的数据
3) 图像-4D形状张量(样本,高度,宽度,通道)或(样本,通道,高度,宽度)
图像通常具有三个维度:高度,宽度和颜色深度。
4) 视频-5D形状张量(样本,帧,高度,宽度,通道)或(样本,帧,通道,高度,宽度)
三、张量运算
在我们的初始示例中,我们通过将Dense图层堆叠在一起来构建我们的网络。
1、 元素操作,可以在numpy中十分简单的就做好
2、 广播
广播包括两个步骤:1)轴(称为广播轴)被添加到较小的张量以匹配较大张量的ndim;2)较小的张量与这些新轴重复,以匹配较大张量的整个形状
*
3、 np.dot(x,y)—矩阵相乘;
则表示逐个元素相乘
4、 shape()显示当前矩阵形状、reshape()改变矩阵形状
四、神经网络的引擎:基于梯度的优化
training loop步骤:
1)绘制一批训练样本x和相应的目标y。
2)在x上运行网络(称为前向传递的步骤)以获得预测y_pred。
3)计算批次上网络的loss,衡量y_pred和y之间的不匹配。
4)以略微减少此批次损失的方式更新网络的所有权重。
更新网络权重是最难的一个步骤,给定网络中的单个权重系数,如何计算系数是应该增加还是减少,以及增加多少?一种好的方法是利用网络中使用的所有操作都是可微分的这一事实,并根据网络系数计算损耗的梯度。 然后,可以从梯度向相反方向移动系数,从而减少损失。
1、张量运算的导数:梯度
以张量作为输入的函数。 考虑输入向量x,矩阵W,目标y和损失函数损失。 可以使用W计算目标候选y_pred,并计算目标候选y_pred和目标y之间的loss或者 mismatch
y_pred = dot(W, x)
loss_value = loss(y_pred, y)
2、随机梯度下降
给定一个可微函数,理论上可以分析地找到它的最小值:已知函数的最小值是导数为0的点,所以我们要做的就是找到所有点,这里导数变为0,并检查这些点中的哪一个函数具有最低值。应用于神经网络,这意味着在分析上找到产生最小可能损失函数的权重值的组合。 这可以通过求解W的方程梯度(f)(W)= 0来完成。从梯度更改相反方向的权重,每次丢失的次数会少一些,更新网络的所有权重的有效方法如下:
1)绘制一批训练样本x和相应的目标y。
2)在x上运行网络以获取预测y_pred。
3)计算批次上网络的丢失,衡量y_pred和y之间的不匹配。
4)根据网络参数计算loss的梯度(反向传递)。
5)在与梯度相反的方向上稍微移动参数 - 例如W - = step * gradient - 从而减少批次上的loss。
为步长因子选择合理的值非常重要。如果它太小,曲线下降将需要多次迭代,并且它可能会陷入局部最小值。如果步长太大,更新最后可能会带到曲线上完全随机的位置。
注意,小批量SGD算法的一种变体是在每次迭代时绘制单个样本和目标,而不是绘制一批数据。另外,存在多种SGD变体,其在计算下一个权重更新时考虑先前的权重更新而不是仅仅查看梯度的当前值而不同。
3、反向传播算法
将链式规则应用于神经网络的梯度值的计算产生称为反向传播的算法(有时也称为反向模式区分)
五、对第一个例子的总结
这是输入数据
Numpy,在这里格式化为float32类型:
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255
test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255
network如下:
network = models.Sequential()
network.add(layers.Dense(512, activation='relu', input_shape=(28 * 28,)))
network.add(layers.Dense(10, activation='softmax'))
网络编译步骤:
categorical_crossentropy是用作学习权重张量的反馈信号的损失函数,训练阶段将尝试最小化。 这种损失的减少是通过小批量随机梯度下降发生的。 控制梯度下降的特定使用的确切规则由作为第一个参数传递的rmsprop优化器定义。
network.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
最后,训练循环:
网络将开始以128个样本的小批量重复训练数据,5次以上(对所有训练数据的每次迭代称为纪元)。 在每次迭代时,网络将根据批次上的损失计算权重的梯度,并相应地更新权重。 在这5个时期之后,网络将执行2,345个梯度更新(每个时期469个),并且网络的丢失将足够低,使得网络能够以高精度对手写数字进行分类。
network.fit(train_images, train_labels, epochs=5, batch_size=128)