本blog面向有TensorFlow经验的用户,并有机器学习方面的专业知识和经验。
1,Overview概述
CIFAR-10分类是机器学习中常见的标准基础问题。 问题是分类10个类别的RGB 32x32像素图像:
airplane, automobile, bird, cat, deer, dog, frog, horse, ship, and truck.
1.1,goals
本blog的目标是建立一个相对较小的卷积神经网络(CNN)来识别图像。 在这个过程中,本教程:
选择CIFAR-10的原因是它足够复杂,可以大量运用TensorFlow扩展到大型模型的能力。 同时,这个模型足够小,可以快速训练,这对于尝试新的想法和尝试新的技术是理想的。
1.2,Highlights of the Tutorial
CIFAR-10教程演示了在TensorFlow中设计更大和更复杂模型的几个重要结构:
我们还提供了一个多GPU版本的模型,它演示了:
我们希望本教程为在TensorFlow上进行视觉任务构建更大的CNN提供了一个启动点。
1.3,Model Architecture
CIFAR-10教程中的模型是一个由交替卷积和非线性组成的多层体系结构。 这些层之后是完全连接的层,通向softmax分类器。 该模型遵循Alex Krizhevsky所描述的架构,在前几个层次中有一些差异。
这个模型在GPU的几个小时训练时间内达到了高达86%的精度。 请参阅下面的代码和细节。 它由1,068,298个可学习的参数组成,并且需要大约19.5M的乘加操作来计算单个图像上的inference 。
2,Code Organization
本教程的代码位于models / tutorials / image / cifar10 /中。
3,CIFAR-10 Model
CIFAR-10网络主要包含在cifar10.py中。 完整的训练图包含大约765个操作。 我们发现,通过构建带有以下模块的图,我们可以使代码最为可重用:
3.1,Model Inputs
模型的输入部分由从CIFAR-10 二进制数据文件读取图像的函数inputs() 和distorted_inputs() 构建。 这些文件包含固定的字节长度记录,所以我们使用tf.FixedLengthRecordReader。 请参阅读取数据以了解有关Reader类如何工作的更多信息。
图像处理如下:
对于训练,我们另外应用一系列随机失真来人为地增加数据集大小:
请参阅图像页面以获取可用失真的列表。 我们还附加一个tf.summary.image的图像,以便我们可以在TensorBoard中可视化他们。 这是验证输入是否正确构建的良好实践。
从磁盘读取图像并使其变形可以使用不重要的处理时间。 为了防止这些操作放慢训练速度,我们在连续填充TensorFlow队列的16个独立线程中运行它们。
3.2,Model Prediction
模型的预测部分由inference() 函数构造,该函数添加了用于计算预测的逻辑的操作。 模型的这部分组织如下:
这是一个由TensorBoard生成的图形,描述了推理操作:
inputs()和inference()函数提供了执行模型评估所需的所有组件。 我们现在把重点转移到训练模型的操作上。
3.3,Model Training
训练网络执行N路分类的通常方法是多项式逻辑回归,也就是说。 softmax回归。 Softmax回归将softmax非线性应用于网络的输出,并计算归一化预测与1-hot编码之间的交叉熵。 对于正则化,我们也将通常的权重衰减损失应用于所有学习的变量。 该模型的目标函数是交叉熵损失和所有这些权重衰减项之和,由loss()函数返回。
我们用tf.summary.scalar在TensorBoard中将其可视化:
我们使用标准梯度下降算法(见其他方法的训练)训练模型,其学习速率随着时间呈指数衰减。
train()函数通过计算梯度和更新已学习的变量(请参阅tf.train.GradientDescentOptimizer获取详细信息),添加通过最小化目标所需的操作。 它返回一个执行所有计算的操作,以训练和更新一批图像的模型。
4,Launching and Training the Model
我们已经建立了模型,现在启动它,并使用脚本cifar10_train.py运行训练操作。
python cifar10_train.py
Filling queue with 20000 CIFAR images before starting to train. This will take a few minutes.
2015-11-04 11:45:45.927302: step 0, loss = 4.68 (2.0 examples/sec; 64.221 sec/batch)
2015-11-04 11:45:49.133065: step 10, loss = 4.66 (533.8 examples/sec; 0.240 sec/batch)
2015-11-04 11:45:51.397710: step 20, loss = 4.64 (597.4 examples/sec; 0.214 sec/batch)
2015-11-04 11:45:54.446850: step 30, loss = 4.62 (391.0 examples/sec; 0.327 sec/batch)
2015-11-04 11:45:57.152676: step 40, loss = 4.61 (430.2 examples/sec; 0.298 sec/batch)
2015-11-04 11:46:00.437717: step 50, loss = 4.59 (406.4 examples/sec; 0.315 sec/batch)
...
The script reports the total loss every 10 steps as well as the speed at which the last batch of data was processed. A few comments:
5,Evaluating a Model
现在让我们来评估训练好的模型在保持数据集上的表现如何。该模型由脚本cifar10_eval.py进行评估。它使用inference()函数构建模型,并在CIFAR-10的评估集中使用所有10,000个图像。它计算精度为1:顶部预测与图像的真实标签匹配的频率。
要在训练期间监控模型的改进情况,评估脚本定期在由cifar10_train.py创建的最新检查点文件上运行。
python cifar10_eval.py
你应该看到输出:
2015-11-06 08:30:44.391206:精度@ 1 = 0.860
...
该脚本只是定期返回精度@ 1,在这种情况下它返回86%的精度。 cifar10_eval.py也导出可能在TensorBoard中可视化的摘要。这些总结在评估过程中为模型提供了更多的信息。
训练脚本计算所有学习变量的移动平均版本。评估脚本将所有学习的模型参数替换为移动平均版本。这种替代提高了评估时的模型性能。
6,Training a Model Using Multiple GPU Cards
现代工作站可能包含多个GPU进行科学计算。 TensorFlow可以利用这个环境在多个卡上同时运行培训操作。
以平行分布的方式培训模型需要协调培训流程。对于下面的内容,我们称模型副本为数据子集的模型训练副本。
天真地使用模型参数的异步更新导致次优的训练性能,因为单个模型副本可能在模型参数的陈旧副本上被训练。相反,使用完全同步的更新将会像最慢的模型副本一样慢。
在具有多个GPU卡的工作站中,每个GPU将具有相似的速度并且包含足够的内存来运行整个CIFAR-10模型。因此,我们选择以如下方式设计我们的培训系统:
这是这个模型的图表:
此设置要求所有GPU共享模型参数。 一个众所周知的事实是,将数据传输到GPU和从GPU传输数据相当缓慢。 出于这个原因,我们决定存储和更新CPU上的所有模型参数(参见绿色框)。 当新的一批数据被所有GPU处理时,一组新的模型参数被传送到GPU。
GPU在运行中同步。 所有渐变都从GPU中累积并取平均值(见绿色框)。 模型参数使用所有模型复本平均的梯度进行更新。
6.1,Placing Variables and Operations on Devices
在设备上放置操作和变量需要一些特殊的抽象。
我们需要的第一个抽象是用于计算单个模型副本的推理和梯度的函数。 在代码中,我们将这个抽象称为“塔”。 我们必须为每个塔设置两个属性:
所有变量都固定在CPU上,并通过tf.get_variable访问,以便在多GPU版本中共享。 查看如何共享变量。
6.2,Launching and Training the Model on Multiple GPU cards
如果您的计算机上安装了多个GPU卡,则可以使用它们更快地使用cifar10_multi_gpu_train.py脚本来训练模型。 这个版本的训练脚本在多个GPU卡上并行化模型。
python cifar10_multi_gpu_train.py --num_gpus = 2
请注意,所使用的GPU卡的数量默认为1.此外,如果您的机器上只有1个GPU可用,则即使您要求更多,所有计算也将被放置在其上。
完。