在机器学习领域,卷积神经网络是大多数最早进的计算机视觉解决方案的核心,适用于各类任务。其中Tensorflow的Inception代码库也是基于此网络解决了图像分类问题。Inception网络实现了2015年发表的论文《从新思考计算机视觉的初始架构》(Rethinking the Inception Architecture for Computer Vision)。
在论文中探索了经过适当的分解卷积和积极的正则化,尽量有效地利用增长的算力,而达到相比现有水平更好的实质性收益。 在论文中也描述了一些具备指导意义的网络设计原则,尽管这些基于大规模试验的设计原则的实用性是推测的,未来须要更多的实验数据来评估其准确性和有效性,但经验证如严重偏离这些原则会每每致使网络质量的降低,而且按照原则执行修复误差也会使总体架构获得改善。git
原则一,网络设计早期不该过分压缩输入输出数据。在设计网络的时候须要根据特征图的各个维度的数据粗略的提取其中的特征,一般到达网络层的特征图数据的大小从输入到输出逐渐减少,但若是早期就过分压缩数据,就会致使信息的大量丢失。信息内容不只仅经过特征图的维度进行评估,也须要相关结构等重要因素。信息丢失将会影响网络训练的质量。
原则二,高纬度的特征图表示能够在本地用网络代替。在卷积神经网络中逐步增长非线性激活响应能够得到更多特征,加快网络训练的速度。
原则三,在卷积网络以前对多通道的低维特征进行降维,不会下降特征的信息。 例如,在执行(例如3×3)卷积以前,能够在空间聚合以前减少输入表示的维度但并不会产生严重的不利影响。基于假设其缘由是相邻单元之间的强相关性致使在降维期间信息损失小得多。鉴于这些原理,应能够进行数据的压缩,尺寸的减少应该能够促进更快的学习。
原则四,找到最佳的网络结构,平衡网络的宽度和深度,使网络的性能达到最优。平衡每级的滤波器数量和网络深度,能够提升网络的最佳性能。增长网络的宽度和深度能够提升网络质量。若是二者并行增长,能够达到恒定计算量的最佳优化结果。 所以,计算预算应以平衡的方式分布在网络的深度和宽度之间。github
虽然这些原则可能有意义,但直接应用它们来提升网络质量并不是易事。Inception网络也只是在逐步的靠近这些设计原则,模模糊糊中使用它们。
关于论文部分再也不细述,请参考该论文:Rethinking the Inception Architecture for Computer Vision 。
ICLR 2017年的一篇分析论文 An analysis of deep neural network models for practical applications 对实际应用中的重要技术进行了全面分析:精度,内存占用,参数,操做计数,推理时间和功耗。其中在精度上,Inception网络得到了最佳表现,固然在其余维度并无得到全部的最佳表现力。精度评测结果以下:算法
Google在开源Tensorflow的同时开源了一个名为 Models的代码库。该代码库包含了[TensorFlow](https://www.tensorflow.org)中实现的许多不一样模型,结构以下:
- official:使用TensorFlow的高级API的示例模型的集合。旨在经过最新最稳定的TensorFlow API进行开发,通过测试并保持代码最新。官方推荐新的TensorFlow用户从这里开始学习。
- research:是研究人员在TensorFlow中实施的大量模型集合。它们没有获得官方支持,是由个体研究人员来维护模型,但也是最活跃的代码目录。
- samples:包含代码片断和较小的模型,用于演示TensorFlow的功能,包括各类博客文章中提供的代码。
- tutorials:是TensorFlow教程中描述的模型集合。
其中,本文介绍的 Inception 代码库就是research的一部分,文件结构及说明以下:bash
├── README.md #很是全面的inception代码库的描述
├── WORKSPACE #bazel编译使用
├── g3doc
│ └── inception_v3_architecture.png #inception_v3网络体系结构的说明图示
└── inception
├── BUILD
├── data #训练数据的标注和代码目录
│ ├── build_image_data.py #使用protos将图片数据转换为TFRecord文件格式
│ ├── build_imagenet_data.py #使用protos将ImageNet图片数据集转换为TFRecord文件格式
│ ├── download_and_preprocess_flowers.sh #下载花朵数据集并将数据集转化为TFRecord文件格式
│ ├── download_and_preprocess_flowers_mac.sh
│ ├── download_and_preprocess_imagenet.sh #下载2012ImageNet训练和评估数据集并将数据集转化为TFRecord文件格式
│ ├── download_imagenet.sh # 下载2012ImageNet训练和评估数据集
│ ├── imagenet_2012_validation_synset_labels.txt #训练数据的标签与preprocess_imagenet_validation_data.py一块儿对数据进行处理
│ ├── imagenet_lsvrc_2015_synsets.txt #训练数据的标签
│ ├── imagenet_metadata.txt #训练数据的标签和对应的语义
│ ├── preprocess_imagenet_validation_data.py #将2012 ImageNet图片和标签相关联
│ └── process_bounding_boxes.py #将图片数据和标签数据相关联的脚本
├── dataset.py # 轻量级的管理训练数据集合的库
├── flowers_data.py # 使用DataSet管理的花朵训练数据
├── flowers_eval.py # 对花朵分类训练模型的评估脚本,对inception_eval.py的封装
├── flowers_train.py # 对花朵分类的训练脚本,对inception_train.py的封装
├── image_processing.py #处理单张图片的库,支持多个线程并行和预处理图片。
├── imagenet_data.py # 使用DataSet管理的ImageNet训练数据
├── imagenet_distributed_train.py #支持分布式系统进行ImageNet训练的库,对inception_distributed_train.py的封装
├── imagenet_eval.py # 对ImageNet数据集训练模型的评估脚本
├── imagenet_train.py #对ImageNet数据集的训练脚本
├── inception_distributed_train.py # 支持分布式系统进行inception的网络的训练
├── inception_eval.py # inception网络训练模型的评估验证库
├── inception_model.py # 构建inception v3网络的模型在数据集上
├── inception_train.py # inception网络训练脚本库
└── slim #Tensorflow中一个轻量级的包含设计,训练和评估模型的代码库,本文不作讨论。
复制代码
本文仅对inception_train.py(此脚本的后续更新已经转移到slim代码库中,参考注意事项)的核心代码进行分析,其余文件请参考源代码。网络
标志参数以下:
train_dir: 用来写入事件日志和检查点(checkpoint),即训练产生的events.out.xxx和model.ckpt-xxxx的文件,默认值'/tmp/imagenet_train’。
max_steps: 训练最大的步数,默认值10000000。
subset: 描述是训练仍是验证。默认值是'train' 。架构
用于管理运行tensorflow使用的硬件
num_gpus: 管理用于运行tensorflow的硬件,该参数规定使用的GPU数量,默认值为1。
log_device_placement: 设置是否记录设备,默认值是False。app
用于管理训练的类型
fine_tune: 管理训练类型,若是设置将随机初始化最后一层权重,以便在新任务上训练网络。默认值是False,便可以在预训练模型上继续训练。
pretrained_model_checkpoint_path: 在一个新的训练任务开始时指定预训练模型存放的路径。curl
下面是关于学习速率的调整参数,这些参数的调整在很大程度上依赖于硬件架构,批大小以及对模型体系结构规范的更改。选择一个精细调整的学习率是须要一些实验的经验过程的。
initial_learning_rate: 初始学习速率。默认值是0.1。
num_epochs_per_decay: 学习速率衰减的调整周期。
learning_rate_decay_factor: 学习速率调整的参数因子。机器学习
函数: _tower_loss
用于计算训练模型单个塔上的总损失。在训练时程序会将批量图片任务进行拆分,一个批量的图片拆分到不一样的塔上。即若是batch_size = 32,num_gpus = 2,那么每一个塔就会处理16张图像。
1,使用inception构建网络推理图。异步
with tf.variable_scope(tf.get_variable_scope(), reuse=reuse_variables):
logits = inception.inference(images, num_classes, for_training=True,
restore_logits=restore_logits,
scope=scope)
复制代码
2,构建推理图中计算损失的部分。
split_batch_size = images.get_shape().as_list()[0]
inception.loss(logits, labels, batch_size=split_batch_size)
复制代码
3,仅组装当前塔中的全部损失。
losses = tf.get_collection(slim.losses.LOSSES_COLLECTION, scope)
复制代码
其中slim来自inception中slim目录中的losses.py文件。这个方法获取网络的全部损失值。其中,LOSSES_COLLECTION = '_losses'
4,计算当前塔的全部损失。
regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
total_loss = tf.add_n(losses + regularization_losses, name='total_loss')
复制代码
在损失函数上加上正则项是防止过拟合的一个重要方法,经过获取tf.GraphKeys.REGULARIZATION_LOSSES集合中的全部变量得到正则化的损失值。
5,调整参数,初始衰减速率为0.9,计算全部损失的移动平均值和总损失。
loss_averages = tf.train.ExponentialMovingAverage(0.9, name='avg')
loss_averages_op = loss_averages.apply(losses + [total_loss])
复制代码
经过tf.train.ExponentialMovingAverage函数建立移动平均而更新参数,控制模型的更新速度。将全部的loss存储在一个全局变量(GraphKeys.MOVING_AVERAGE_VARIABLES)中,再经过apply对每个变量进行每一次的迭代移动平均计算。
函数:train 在数据集上进行训练。
#建立一个变量global_step来计算train调用的数量。这等于处理的批次数* FLAGS.num_gpus。
global_step = tf.get_variable(
'global_step', [],
initializer=tf.constant_initializer(0), trainable=False)
复制代码
#计算得到学习速率的调整方案。
num_batches_per_epoch = (dataset.num_examples_per_epoch() / FLAGS.batch_size)
decay_steps = int(num_batches_per_epoch * FLAGS.num_epochs_per_decay)
复制代码
#根据步数以指数方式衰减学习速率。
lr = tf.train.exponential_decay(FLAGS.initial_learning_rate,
global_step,
decay_steps,
FLAGS.learning_rate_decay_factor,
staircase=True)
复制代码
#使用RMSProp算法建立一个执行梯度降低的优化器。
opt = tf.train.RMSPropOptimizer(lr, RMSPROP_DECAY,
momentum=RMSPROP_MOMENTUM,
epsilon=RMSPROP_EPSILON)
复制代码
#获取ImageNet的图像和标签,并在GPU之间拆分批处理。
split_batch_size = int(FLAGS.batch_size / FLAGS.num_gpus)
复制代码
#覆盖预处理线程的数量,以解决塔数量增长的问题。
num_preprocess_threads = FLAGS.num_preprocess_threads * FLAGS.num_gpus
images, labels = image_processing.distorted_inputs(
dataset,
num_preprocess_threads=num_preprocess_threads)
复制代码
#Dataset标签集中的类数加1.标签0保留给(未使用的)后台类。
num_classes = dataset.num_classes() + 1
复制代码
#拆分塔的图像和标签批次。
images_splits = tf.split(axis=0, num_or_size_splits=FLAGS.num_gpus, value=images)
labels_splits = tf.split(axis=0, num_or_size_splits=FLAGS.num_gpus, value=labels)
复制代码
#计算每一个模型塔的梯度。
#强制全部变量驻留在CPU上,计算ImageNet模型的一个塔的损失,此函数构造整个ImageNet模型,但在全部塔中共享变量。
with slim.arg_scope([slim.variables.variable], device='/cpu:0'):
loss = _tower_loss(images_splits[i], labels_splits[i], num_classes,
scope, reuse_variables)
复制代码
#重用下一个塔的变量。
reuse_variables = True
复制代码
#保留最终塔的摘要。
summaries = tf.get_collection(tf.GraphKeys.SUMMARIES, scope)
复制代码
#仅保留最终塔的批量标准化更新操做。理想状况下,咱们应该从全部塔中获取更新,但这些统计数据累积得很是快,所以咱们能够忽略其余塔的统计数据,而不会形成重大损失。
batchnorm_updates = tf.get_collection(slim.ops.UPDATE_OPS_COLLECTION, scope)
复制代码
#计算此塔上ImageNet批量数据的梯度。
grads = opt.compute_gradients(loss)
复制代码
#跟踪全部塔的梯度。
tower_grads.append(grads)
复制代码
#计算每一个梯度的平均值。请注意,这是全部塔开始同步的地方。
grads = _average_gradients(tower_grads)
复制代码
#添加摘要以跟踪学习率。
summaries.append(tf.summary.scalar('learning_rate', lr))
复制代码
#添加渐变的直方图。
for grad, var in grads:
if grad is not None:
summaries.append(
tf.summary.histogram(var.op.name + '/gradients', grad))
复制代码
#应用渐变来调整共享变量。
apply_gradient_op = opt.apply_gradients(grads, global_step=global_step)
复制代码
#为可训练变量添加直方图。
for var in tf.trainable_variables():
summaries.append(tf.summary.histogram(var.op.name, var))
复制代码
#跟踪全部可训练变量的移动平均值。维护BatchNormalization全局统计信息的“双倍平均值”。这比须要的更复杂,可是使用它与以前的模型向后兼容。
variable_averages = tf.train.ExponentialMovingAverage(
inception.MOVING_AVERAGE_DECAY, global_step)
variables_to_average = (tf.trainable_variables() + tf.moving_average_variables())
variables_averages_op = variable_averages.apply(variables_to_average)
复制代码
#将全部更新分组到一个训练中。
batchnorm_updates_op = tf.group(*batchnorm_updates)
train_op = tf.group(apply_gradient_op, variables_averages_op, batchnorm_updates_op)
复制代码
#建立一个保存器。
saver = tf.train.Saver(tf.global_variables())
复制代码
#从最后的塔摘要中构建摘要操做。
summary_op = tf.summary.merge(summaries)
复制代码
#构建一个初始化操做以在下面运行。
init = tf.global_variables_initializer()
复制代码
#开始在Graph上运行操做。必须将allow_soft_placement设置为True才能在GPU上构建塔,由于某些操做系统没有GPU实现。
sess = tf.Session(config=tf.ConfigProto(
allow_soft_placement=True,
log_device_placement=FLAGS.log_device_placement))
sess.run(init)
if FLAGS.pretrained_model_checkpoint_path:
…
variables_to_restore = tf.get_collection(slim.variables.VARIABLES_TO_RESTORE)
restorer = tf.train.Saver(variables_to_restore)
restorer.restore(sess, FLAGS.pretrained_model_checkpoint_path)
…
复制代码
#启动队列运行。
tf.train.start_queue_runners(sess=sess)
# 建立写入器
summary_writer = tf.summary.FileWriter(FLAGS.train_dir, graph=sess.graph)
for step in range(FLAGS.max_steps):
…
# 执行本步的训练操做
start_time = time.time()
_, loss_value = sess.run([train_op, loss])
…
# 每100步更新一次摘要信息
if step % 100 == 0:
summary_str = sess.run(summary_op)
summary_writer.add_summary(summary_str, step)
# 周期的保存checkpoint文件,这里是5000步执行一次
if step % 5000 == 0 or (step + 1) == FLAGS.max_steps:
checkpoint_path = os.path.join(FLAGS.train_dir, 'model.ckpt')
saver.save(sess, checkpoint_path, global_step=step)
复制代码
理解train方法后便可对网络进行微整。
实战参考Inception的 README 文档,本文只介绍其中的4个部分: ###如何在新任务上对预训练模型进行微调
在调用训练方法前,必须对图片和标签数据进行预处理,即将一个新的数据集转换为分片的TFRecord格式,每一个条目都是一个序列化的tf.Example proto结构。代码库提供了一个脚本,演示如何为5个标签上分布的几千幅花卉图像的小数据集作到这一点。
daisy, dandelion, roses, sunflowers, tulips
代码库提供自动脚本(download_and_preprocess_flowers.sh)下载数据集并将其转换为TFRecord格式。与ImageNet数据集很是类似,TFRecord格式中的每条记录都是序列化的tf.Example proto结构,其条目包括JPEG编码的字符串和整数标签。有关详细信息,请参阅parse_example_proto。
该脚本只需几分钟便可运行,具体取决于您的网络链接速度如下载和处理图像。您的硬盘须要200MB的免费存储空间(这比完整的500GB+的2012 ImageNet数据集少太多了)。在这里咱们选择DATA_DIR = / tmp / flowers-data /做为这样一个位置,但随意编辑。
# 设置flower数据存储位置
FLOWERS_DATA_DIR=/tmp/flowers-data/
# 构建预处理脚本
cd tensorflow-models/inception
bazel
build //inception:download_and_preprocess_flowers
# 运行脚本下载并处理数据
bazel-bin/inception/download_and_preprocess_flowers "${FLOWERS_DATA_DIR}"
复制代码
若是脚本成功运行,终端输出的最后一行应以下所示:
2016-02-24 20:42:25.067551: Finished writing all 3170 images in data set.
复制代码
当脚本结束时,将在DATA_DIR中找到2个用于训练和验证文件的分片。这些文件相似train-?????-of-00002和validation-?????-of-00002,分别表明训练数据集和验证数据集。
注意:
若是准备自定义图像数据集,则须要在自定义数据集上调用build_image_data.py。
另外,能够选择下载代码库提供的预训练模型
# 指定下载模型要存储的路径
INCEPTION_MODEL_DIR=$HOME/inception-v3-model
mkdir -p ${INCEPTION_MODEL_DIR}
cd ${INCEPTION_MODEL_DIR}
# 经过curl命令下载模型压缩包
curl -O http://download.tensorflow.org/models/image/imagenet/inception-v3-2016-03-01.tar.gz
tar xzf inception-v3-2016-03-01.tar.gz
# 将会在目录中建立一个名为inception-v3的目录,并包含下面的文件
> ls inception-v3
README.txt
checkpoint
model.ckpt-157585
复制代码
如今可使用花朵数据集对预先训练好的Inception v3模型进行微调。
准备在花朵数据集上微调预先训练好的Inception-v3模型,须要修改训练脚本的2个参数:
- pretrained_model_checkpoint_path: 指向预先训练的Inception-v3模型的路径。若是指定了此标志,它将在脚本开始训练以前从检查点加载整个模型。
- fine_tune: 一个布尔值,指示最后一个分类层是应该随机初始化仍是恢复。若是您但愿从检查点继续训练预先训练好的模型,则能够将此标志设置为false。若是将此标志设置为true,则能够从头开始培训新的分类层。
综合起来,可使用如下命令从新训练花卉数据集上的预先训练的Inception-v3模型。
# 经过bazel构建flowers_train网络,该网络在源码上封装了对inception_train的调用。
cd tensorflow-models/inception
bazel build //inception:flowers_train
# 设置下载好的预训练的模型路径.
MODEL_PATH="${INCEPTION_MODEL_DIR}/inception-v3/model.ckpt-157585"
# 设置数据保存的路径,该数据已是TFRecord文件格式
FLOWERS_DATA_DIR=/tmp/flowers-data/
# 设置保存训练中输出的事件日志和检查点数据
TRAIN_DIR=/tmp/flowers_train/
# 经过flowers_train网络开始使用预训练的模型从新训练花朵数据,fine_tune设置为True。
bazel-bin/inception/flowers_train --train_dir="${TRAIN_DIR}"
--data_dir="${FLOWERS_DATA_DIR}"
--pretrained_model_checkpoint_path="${MODEL_PATH}"
--fine_tune=True
--initial_learning_rate=0.001
--input_queue_memory_factor=1
复制代码
在培训过程当中增长了一些额外选项。
训练脚本只会报告损失。要评估微调模型的质量,您须要运行验证脚本flowers_eval:
# 开始构建flowers_eval模型
cd tensorflow-models/inception
bazel build //inception:flowers_eval
# 设置训练中输出的事件日志和检查点的目录
TRAIN_DIR=/tmp/flowers_train/
# 设置训练数据集所在目录,该数据集是TFRecord文件格式
FLOWERS_DATA_DIR=/tmp/flowers-data/
# 设定保存验证结果日志文件的目录
EVAL_DIR=/tmp/flowers_eval/
# 经过flowers_eval开始验证flowers_train训练的结果
bazel-bin/inception/flowers_eval
--eval_dir="${EVAL_DIR}"
--data_dir="${FLOWERS_DATA_DIR}"
--subset=validation
--num_examples=500
--checkpoint_dir="${TRAIN_DIR}"
--input_queue_memory_factor=1
--run_once
复制代码
训练中发如今模型运行2000步后,评估的精确度达到大约93.4%。
Successfully loaded model from /tmp/flowers/model.ckpt-1999 at step=1999.
2016-03-01 16:52:51.761219: starting evaluation on (validation).
2016-03-01 16:53:05.450419: [20 batches out of 20] (36.5 examples/sec; 0.684sec/batch)
2016-03-01 16:53:05.450471: precision @ 1 = 0.9340 recall @ 5 = 0.9960 [500 examples]
复制代码
使用该模型提供的现有脚原本构建用于训练或微调的新数据集。主要脚本是build_image_data.py。 简而言之,这个脚本须要一个结构化的图像目录,并将其转换为可由Inception模型读取的分片TFRecord。 具体来讲,您须要建立一个指定结构的训练图像目录,这些图像位于TRAIN_DIR和 VALIDATION_DIR中,其排列方式以下:
$TRAIN_DIR/dog/image0.jpeg
$TRAIN_DIR/dog/image1.jpg
$TRAIN_DIR/dog/image2.png
...
$TRAIN_DIR/cat/weird-image.jpeg
$TRAIN_DIR/cat/my-image.jpeg
$TRAIN_DIR/cat/my-image.JPG
...
$VALIDATION_DIR/dog/imageA.jpeg
$VALIDATION_DIR/dog/imageB.jpg
$VALIDATION_DIR/dog/imageC.png
...
$VALIDATION_DIR/cat/weird-image.PNG
$VALIDATION_DIR/cat/that-image.jpg
$VALIDATION_DIR/cat/cat.JPG
...
复制代码
注意:该脚本将附加一个索引为0的额外背景类,所以您的类标签范围从0到num_labels。使用上面的例子,从build_image_data.py生成的相应类标签以下所示:
0
1 dog
2 cat
复制代码
TRAIN_DIR和VALIDATION_DIR中的每一个子目录对应于驻留在该子目录内的图像的惟一标签,图像多是JPEG或PNG图像,目前不支持其余图像类型。 数据安排在这个目录结构中,能够在数据上运行build_image_data.py来生成分片的TFRecord数据集。 build_image_data.py的注释中描述了tf.Example中包含的完整信息列表。 要运行build_image_data.py,能够运行如下命令行:
# 设置生成TFRecord文件的目录
OUTPUT_DIRECTORY=$HOME/my-custom-data/
# 构建脚本build_image_data
cd tensorflow-models/inception
bazel
build //inception:build_image_data
# 运行脚本进行转化
bazel-bin/inception/build_image_data
--train_directory="${TRAIN_DIR}"
--validation_directory="${VALIDATION_DIR}"
--output_directory="${OUTPUT_DIRECTORY}"
--labels_file="${LABELS_FILE}"
--train_shards=128
--validation_shards=24
--num_threads=8
复制代码
OUTPUT_DIRECTORY是分片TFRecords的位置。
LABELS_FILE将是一个由脚本读取的文本文件,该文件提供了全部标签的列表。例如,在鲜花数据集的状况下, LABELS_FILE包含如下数据:
daisy
dandelion
roses
sunflowers
tulips
请注意,每一个标签的每一行都与模型中最终分类器中的条目相对应。也就是说,雏菊对应于条目1的分类器;蒲公英是条目2等。咱们跳过标签0做为背景类。 运行此脚本后,将生成以下所示的文件:
$TRAIN_DIR/train-00000-of-00128
$TRAIN_DIR/train-00001-of-00128
...
$TRAIN_DIR/train-00127-of-00128
and
$VALIDATION_DIR/validation-00000-of-00024
$VALIDATION_DIR/validation-00001-of-00024
...
$VALIDATION_DIR/validation-00023-of-00024
复制代码
其中128和24分别是为每一个数据集指定的分片数。目标是选择碎片的数量,使每一个碎片大约有1024个图像。一旦创建了这个数据集,就能够在这个数据集上训练或微调一个Inception模型。 另外,若是您使用训练脚本,请修改flowers_data.py中的num_classes()和num_examples_per_epoch()以与新建的数据对应。
模型架构和训练过程严重依赖于用来训练模型的硬件。若是你想在你的机器上训练或微调这个模型,你须要调整和经验地肯定一套适合你的设置的训练超参数。
大约5-10个超参数控制网络训练的速度。除了--batch_size和–num_gpus以外,在inception_train.py中定义了几个常量,它们规定了学习任务。
RMSPROP_DECAY = 0.9 # RMSProp算法的衰减项.
MOMENTUM = 0.9 # RMSProp算法的Momentum值.
RMSPROP_EPSILON = 1.0 # RMSProp算法的Epsilon项.
INITIAL_LEARNING_RATE = 0.1 # 学习速录初始化时的值.
NUM_EPOCHS_PER_DECAY = 30.0 # 学习速率开始衰减的时期Epochs.
LEARNING_RATE_DECAY_FACTOR = 0.16 # 学习速率衰减因子.
复制代码
在训练中下面参数的调整对结果有较大的影响。
训练这个模型在CPU和GPU方面有很大的内存需求,与CPU内存相比,GPU内存相对较小。两个项目决定了GPU内存使用量——模型架构和批量大小(batch_size)。假设您保持模型架构不变,训练对GPU需求的惟一控制参数就是批量大小。
“一个很好的经验法则是尝试使用尽量大的批量大小以适应GPU。”
若是用完GPU内存,请下降--batch_size或在工做机上使用更多GPU。该模型在GPU之间执行批量分割,所以N个GPU能够处理N倍于1个GPU的批量。 该模型也须要大量的CPU内存。Inception调整了这个模型来使用大约20GB的CPU内存。所以,得到大约40GB的CPU内存将是理想的。
若是这不可行,能够经过下降——input_queue_memory_factor来调低模型的内存需求。相对于跨–num_preprocess_threads线程的主要训练对图像进行异步预处理。
预处理的图像存储在队列中,其中每一个GPU执行出队操做以接收批量图像。 为了保证数据的良好序列,咱们维护一个1024 x input_queue_memory_factor图像的大型队列。对于当前的模型架构,这至关于大约4GB的CPU内存。 能够经过下降input_queue_memory_factor以减小内存占用量。但大幅下降此值可能会致使模型在从头开始训练时预测精度略低。
有关更多详细信息,请参阅image_processing.py中的注释。
引用:
1.Inception
2.Rethinking the Inception Architecture for Computer Vision
3.An analysis of deep neural network models for practical applications
4.ImageNet 是机器学习中用于训练图像识别系统的经常使用学术数据集。
5.Inception的模型架构图以下:
注意:
对于Research中开源的Inception代码库,谷歌的开发者们将大部分的后续改进工做转移到了 slim 代码库中。便可以在 slim 中找到此代码库的最新版本,持续学习能够参考。