tensorflow cnn怎么训练cnn

热门推荐:
选自Github
机器之心编译
参与:朱思颖、蒋思源
今年 6 月 DeepMind 的一条官方推文里,公布了他们当时运用 PixelCNN 所生成的条件自然场景合成图,并称这种方法将艺术生成模型提升到一个新的水准。DeepMind 运用 PixelCNN 实现条件图像生成的论文也被今年的 NIPS 所收录(见文末附录)。6 个月之后,近日,OpenAI 在 GitHub 公开了 TensorFlow 框架里用 Python3 实现的 PixelCNN 优化版――PixelCNN++的源码,其论文已被 ICLR 2017 接收。
所公开的源码是 PixelCNN++的具体代码实现,是在 TensorFlow 框架里用 Python3 编写的。PixelCNN++的具体阐述在以下论文:
PixelCNN++:A PixelCNN Implementation with Discretized Logistic Mixture Likelihood and Other Modifications, by Tim Salimans, Andrej Karpathy, Xi Chen, Diederik P. Kingma, and Yaroslav Bulatov.
我们的研究是建立在 van der Oord 等人今年 6 月份最初提出来的 PixelCNN(所附论文一)上。PixelCNN 是一类强大的生成模型,它有易处理似然性(tractable likelihood)从而容易进行抽样。其核心的卷积神经网络计算在一个像素值上的概率分布,且受左侧和上侧的像素值约束。下面是在 CIFAR-10 上训练的模型里面的示例样本,其实现了每维度 2.92 bits(van der Oord 等人的 PixelCNN 是 3.03 bits):
来自模型(左)的样品和来自以 CIFAR-10 类标签为约束的模型的样本(右):
此代码支持将我们改进的 PixelCNN 在 CIFAR-10 和 Small ImageNet 上进行多 GPU 训练,并很容易适应额外的数据集。在具有 8 个 Maxwell TITAN X GPU 的机器上进行训练在大约 10 小时内能实现每个维度 3.0 bits,并且需要大约 5 天才能收敛到 2.92 bits。
  开源地址:/openai/pixel-cnn
你需要以下环境运行该代码:
多 GPU 计算机
Numpy, TensorFlow
使用 train.py 脚本进行模型的训练,在 CIFAR-10 上训练默认模型只需要简单键入:
python3 train.py
你可能希望至少可更改 --data_dir 和 --save_dir,它们指向系统下载数据的路径(如果是无效的)和保存点的位置。
我想使用更少的 GPU 进行训练。为了在更少的 GPU 上训练,我们建议使用 CUDA_VISIBLE_DEVICES 缩小 GPU 可用(the visibility of GPUs)数量,然后再运行脚本。不要忘记相应地调制 flag: --nr_gpu。
我想训练自己的数据集。看看 data/ 文件夹中的 DataLoader 类,必须为你自己的数据集写一个类似的数据迭代器,然后代码才能从那边正常运行。
预训练模型检查点(checkpoint)
你可以下载(/pxpp.zip)(/pxpp.zip%EF%BC%89) 中我们已训练的模型(TensorFlow),它在 CIFAR-10 上实现了 2.92bpd。
如果你发现代码很有用,请在你的研究中引用我们:
@inproceedings{Salimans2016PixeCNN,
title={PixelCNN++: A PixelCNN Implementation with Discretized Logistic Mixture Likelihood and Other Modifications},
author={Tim Salimans and Andrej Karpathy and Xi Chen and Diederik P. Kingma and Yaroslav Bulatov},
booktitle={Submitted to ICLR 2017},
year={2016}
  附录:
论文:Conditional Image Generation with PixelCNN Decoders
本研究探索了使用条件图像生成与基于 PixelCNN 架构的新的图像密度模型。该模型可以以任何矢量为条件,包括描述性标签或标签,或由其他网络创建的隐嵌入。当使用来自 ImageNet 数据库的类标签时,该模型能够生成表示不同动物,对象,风景和结构的多样化、形象逼真的场景。当对由未知的面部的单个图像给出的卷积网络产生的嵌入进行调节时,它可以生成不同面部表情,姿势和光照条件下同一个人的各种新肖像。我们还展示了条件 PixelCNN 可以作为图像自动编码器中的强大的解码器。此外,提出的模型中的门控卷积层提高了 PixelCNN 的对数似然度,以匹配 ImageNet 上的 PixelRNN 的最新性能,大大降低了计算成本。
论文:PIXELCNN++: A PIXELCNN IMPLEMENTATION WITH DISCRETIZED LOGISTIC MIXTURE LIKELIHOOD AND OTHER MODIFICATIONS
PixelCNN 是最近提出的一类具有易处理似然性(tractable likelihood)的强大生成模型。本文将讨论我们怎样实现 PixelCNN,同时在 Github 上开源。我们的实现方法包含对原始模型的多个修改,不仅精简了结构,还提高了性能。主要从以下几个角度完成:1. 我们使用像素上的离散逻辑混合似然(discretized logistic mixture likelihood),而不是 256 阶的 softmax 回归(256-way softmax),这能大大加快训练。2. 我们对整个像素而不是 R/G/B 子像素进行约束,从而简化模型结构。3. 我们使用下采样(downsampling)有效地捕获多种分辨率结构。4. 我们引入额外的快捷连接,以进一步加速优化。5. 我们使用 dropout 对模型进行正则化。最后,我们在 CIFAR-10 上呈现最先进的对数似然(log likelihood)结果,以证明这些改进的有用性。
  &本文由机器之心编译,转载请联系本公众号获得授权。
  ?------------------------------------------------
加入机器之心(全职记者/实习生):
投稿或寻求报道:
广告&商务合作:
请先登录再操作
请先登录再操作
微信扫一扫分享至朋友圈
知名IT评论人,曾就职于多家知名IT企业,现是科幻星系创建人
未来在这里发声。
新媒体的实践者、研究者和批判者。
立足终端领域,静观科技变化。深入思考,简单陈述。
智能硬件领域第一自媒体。卷积神经网络
注意: 本教程适用于对Tensorflow有丰富经验的用户,并假定用户有机器学习相关领域的专业知识和经验。
对CIFAR-10 数据集的分类是机器学习中一个公开的基准测试问题,其任务是对一组大小为32x32的RGB图像进行分类,这些图像涵盖了10个类别:
飞机, 汽车, 鸟, 猫, 鹿, 狗, 青蛙, 马, 船以及卡车。
想了解更多信息请参考,以及Alex Krizhevsky写的
本教程的目标是建立一个用于识别图像的相对较小的卷积神经网络,在这一过程中,本教程会:
着重于建立一个规范的网络组织结构,训练并进行评估;
为建立更大规模更加复杂的模型提供一个范例
选择CIFAR-10是因为它的复杂程度足以用来检验TensorFlow中的大部分功能,并可将其扩展为更大的模型。与此同时由于模型较小所以训练速度很快,比较适合用来测试新的想法,检验新的技术。
本教程的重点
CIFAR-10 教程演示了在TensorFlow上构建更大更复杂模型的几个种重要内容:
相关核心数学对象,如、、以及;
训练过程中一些网络行为的,这些行为包括输入图像、损失情况、网络行为的分布情况以及梯度;
算法学习参数的的计算函数,以及在评估阶段使用这些平均值提高预测性能;
实现了一种机制,使得随着时间的推移而递减;
为输入数据设计预存取,将磁盘延迟和高开销的图像预处理操作与模型分离开来处理;
我们也提供了模型的多GPU版本,用以表明:
可以配置模型后使其在多个GPU上并行的训练
可以在多个GPU之间共享和更新变量值
我们希望本教程给大家开了个头,使得在Tensorflow上可以为视觉相关工作建立更大型的CNN模型
本教程中的模型是一个多层架构,由卷积层和非线性层(nonlinearities)交替多次排列后构成。这些层最终通过全连通层对接到softmax分类器上。这一模型除了最顶部的几层外,基本跟提出的模型一致。
在一个GPU上经过几个小时的训练后,该模型最高可以达到86%的精度。细节请查看的描述以及代码。模型中包含了1,068,298个学习参数,对一副图像进行分类大概需要19.5M个乘加操作。
本教程的代码位于.
读取本地CIFAR-10的二进制文件格式的内容。
建立CIFAR-10的模型。
在CPU或GPU上训练CIFAR-10的模型。
在多GPU上训练CIFAR-10的模型。
评估CIFAR-10模型的预测性能。
CIFAR-10 模型
CIFAR-10 网络模型部分的代码位于
完整的训练图中包含约765个操作。但是我们发现通过下面的模块来构造训练图可以最大限度的提高代码复用率:
包括inputs()
、 distorted_inputs()等一些操作,分别用于读取CIFAR的图像并进行预处理,做为后续评估和训练的输入;
包括inference()等一些操作,用于进行统计计算,比如在提供的图像进行分类;
adds operations that perform inference, i.e. classification, on supplied images.
包括loss() and train()等一些操作,用于计算损失、计算梯度、进行变量更新以及呈现最终结果。
输入模型是通过 inputs() 和distorted_inputs()函数建立起来的,这2个函数会从CIFAR-10二进制文件中读取图片文件,由于每个图片的存储字节数是固定的,因此可以使用函数。更多的关于Reader类的功能可以查看。
图片文件的处理流程如下:
图片会被统一裁剪到24x24像素大小,裁剪中央区域用于评估或裁剪用于训练;
图片会进行,使得模型对图片的动态范围变化不敏感。
对于训练,我们另外采取了一系列随机变换的方法来人为的增加数据集的大小:
对图像进行;
随机变换;
随机变换;
可以在页的列表中查看所有可用的变换,对于每个原始图我们还附带了一个,以便于在TensorBoard中查看。这对于检查输入图像是否正确十分有用。
从磁盘上加载图像并进行变换需要花费不少的处理时间。为了避免这些操作减慢训练过程,我们在16个独立的线程中并行进行这些操作,这16个线程被连续的安排在一个TensorFlow中。
模型的预测流程由inference()构造,该函数会添加必要的操作步骤用于计算预测值的 logits,其对应的模型组织方式如下所示:
Layer 名称
activation.
activation.
softmax_linear
进行线性变换以输出 logits.
这里有一个由TensorBoard绘制的图形,用于描述模型建立过程中经过的步骤:
练习: inference的输出是未归一化的logits,尝试使用修改网络架构后返回归一化的预测值。
inputs() 和 inference() 函数提供了评估模型时所需的所有构件,现在我们把讲解的重点从构建一个模型转向训练一个模型。
练习: inference() 中的模型跟中描述的CIFAR-10模型有些许不同,其差异主要在于其顶层不是全连接层而是局部连接层,可以尝试修改网络架构来准确的复制全连接模型。
训练一个可进行N维分类的网络的常用方法是使用,又被叫做softmax 回归。Softmax 回归在网络的输出层上附加了一个 nonlinearity,并且计算归一化的预测值和label的的。在正则化过程中,我们会对所有学习变量应用。模型的目标函数是求交叉熵损失和所有权重衰减项的和,loss()函数的返回值就是这个值。
在TensorBoard中使用来查看该值的变化情况:
我们使用标准的梯度下降算法来训练模型(也可以在中看看其他方法),其学习率随时间以指数形式衰减。
train() 函数会添加一些操作使得目标函数最小化,这些操作包括计算梯度、更新学习变量(详细信息请查看)。train() 函数最终会返回一个用以对一批图像执行所有计算的操作步骤,以便训练并更新模型。
开始执行并训练模型
我们已经把模型建立好了,现在通过执行脚本cifar10_train.py来启动训练过程。
python cifar10_train.py
注意: 当第一次在CIFAR-10教程上启动任何任务时,会自动下载CIFAR-10数据集,该数据集大约有160M大小,因此第一次运行时泡杯咖啡小栖一会吧。
你应该可以看到如下类似的输出:
Filling queue with 20000 CIFAR images before starting to train. This will take a few minutes.
11:45:45.927302: step 0, loss = 4.68 (2.0 examples/ 64.221 sec/batch)
11:45:49.133065: step 10, loss = 4.66 (533.8 examples/ 0.240 sec/batch)
11:45:51.397710: step 20, loss = 4.64 (597.4 examples/ 0.214 sec/batch)
11:45:54.446850: step 30, loss = 4.62 (391.0 examples/ 0.327 sec/batch)
11:45:57.152676: step 40, loss = 4.61 (430.2 examples/ 0.298 sec/batch)
11:46:00.437717: step 50, loss = 4.59 (406.4 examples/ 0.315 sec/batch)
脚本会在每10步训练过程后打印出总损失值,以及最后一批数据的处理速度。下面是几点注释:
第一批数据会非常的慢(大概要几分钟时间),因为预处理线程要把20,000个待处理的CIFAR图像填充到重排队列中;
打印出来的损失值是最近一批数据的损失值的均值。请记住损失值是交叉熵和权重衰减项的和;
上面打印结果中关于一批数据的处理速度是在Tesla K40C上统计出来的,如果你运行在CPU上,性能会比此要低;
练习: 当实验时,第一阶段的训练时间有时会非常的长,长到足以让人生厌。可以尝试减少初始化时初始填充到队列中图片数量来改变这种情况。在cifar10.py中搜索NUM_EXAMPLES_PER_EPOCH_FOR_TRAIN并修改之。
cifar10_train.py 会周期性的在中模型中的所有参数,但是不会对模型进行评估。cifar10_eval.py会使用该检查点文件来测试预测性能(详见下面的描述:)。
如果按照上面的步骤做下来,你应该已经开始训练一个CIFAR-10模型了。
cifar10_train.py输出的终端信息中提供了关于模型如何训练的一些信息,但是我们可能希望了解更多关于模型训练时的信息,比如:
损失是真的在减小还是看到的只是噪声数据?
为模型提供的图片是否合适?
梯度、激活、权重的值是否合理?
当前的学习率是多少?
提供了该功能,可以通过cifar10_train.py中的周期性的获取并显示这些数据。
比如我们可以在训练过程中查看local3的激活情况,以及其特征维度的稀疏情况:
相比于总损失,在训练过程中的单项损失尤其值得人们的注意。但是由于训练中使用的数据批量比较小,损失值中夹杂了相当多的噪声。在实践过程中,我们也发现相比于原始值,损失值的移动平均值显得更为有意义。请参阅脚本了解如何实现。
现在可以在另一部分数据集上来评估训练模型的性能。脚本文件cifar10_eval.py对模型进行了评估,利用 inference()函数重构模型,并使用了在评估数据集所有10,000张CIFAR-10图片进行测试。最终计算出的精度为1:N,N=预测值中置信度最高的一项与图片真实label匹配的频次。(It calculates the precision at 1: how often the top prediction matches the true label of the image)。
为了监控模型在训练过程中的改进情况,评估用的脚本文件会周期性的在最新的检查点文件上运行,这些检查点文件是由cifar10_train.py产生。
python cifar10_eval.py
注意:不要在同一块GPU上同时运行训练程序和评估程序,因为可能会导致内存耗尽。尽可能的在其它单独的GPU上运行评估程序,或者在同一块GPU上运行评估程序时先挂起训练程序。
你可能会看到如下所示输出:
08:30:44.391206: precision @ 1 = 0.860
评估脚本只是周期性的返回precision@1 (The script merely returns the precision @ 1 periodically)--在该例中返回的准确率是86%。cifar10_eval.py 同时也返回其它一些可以在TensorBoard中进行可视化的简要信息。可以通过这些简要信息在评估过程中进一步的了解模型。
训练脚本会为所有学习变量计算其,评估脚本则直接将所有学习到的模型参数替换成对应的移动均值。这一替代方式可以在评估过程中提升模型的性能。
练习: 通过precision @ 1测试发现,使用均值参数可以将预测性能提高约3%,在cifar10_eval.py中尝试修改为不采用均值参数的方式,并确认由此带来的预测性能下降。
在多个GPU板卡上训练模型
现代的工作站可能包含多个GPU进行科学计算。TensorFlow可以利用这一环境在多个GPU卡上运行训练程序。
在并行、分布式的环境中进行训练,需要对训练程序进行协调。对于接下来的描述,术语模型拷贝(model replica)特指在一个数据子集中训练出来的模型的一份拷贝。
如果天真的对模型参数的采用异步方式更新将会导致次优的训练性能,这是因为我们可能会基于一个旧的模型参数的拷贝去训练一个模型。但与此相反采用完全同步更新的方式,其速度将会变得和最慢的模型一样慢(Conversely, employing fully synchronous updates will be as slow as the slowest model replica.)。
在具有多个GPU的工作站中,每个GPU的速度基本接近,并且都含有足够的内存来运行整个CIFAR-10模型。因此我们选择以下方式来设计我们的训练系统:
在每个GPU上放置单独的模型副本;
等所有GPU处理完一批数据后再同步更新模型的参数;
下图示意了该模型的结构::
可以看到,每一个GPU会用一批独立的数据计算梯度和估计值。这种设置可以非常有效的将一大批数据分割到各个GPU上。
这一机制要求所有GPU能够共享模型参数。但是众所周知在GPU之间传输数据非常的慢,因此我们决定在CPU上存储和更新所有模型的参数(对应图中绿色矩形的位置)。这样一来,GPU在处理一批新的数据之前会更新一遍的参数。
图中所有的GPU是同步运行的。所有GPU中的梯度会累积并求平均值(绿色方框部分)。模型参数会利用所有模型副本梯度的均值来更新。
在多个设备中设置变量和操作
在多个设备中设置变量和操作时需要做一些特殊的抽象。
我们首先需要把在单个模型拷贝中计算估计值和梯度的行为抽象到一个函数中。在代码中,我们称这个抽象对象为“tower”。对于每一个“tower”我们都需要设置它的两个属性:
在一个tower中为所有操作设定一个唯一的名称。通过添加一个范围前缀来提供该唯一名称。比如,第一个tower中的所有操作都会附带一个前缀tower_0,示例:tower_0/conv1/Conv2D;
在一个tower中运行操作的优先硬件设备。
提供该信息。比如,在第一个tower中的所有操作都位于 device('/gpu:0')范围中,暗含的意思是这些操作应该运行在第一块GPU上;
为了在多个GPU上共享变量,所有的变量都绑定在CPU上,并通过访问。可以查看以了解如何共享变量。
启动并在多个GPU上训练模型
如果你的机器上安装有多块GPU,你可以通过使用cifar10_multi_gpu_train.py脚本来加速模型训练。该脚本是训练脚本的一个变种,使用多个GPU实现模型并行训练。
python cifar10_multi_gpu_train.py --num_gpus=2
训练脚本的输出如下所示:
Filling queue with 20000 CIFAR images before starting to train. This will take a few minutes.
11:45:45.927302: step 0, loss = 4.68 (2.0 examples/ 64.221 sec/batch)
11:45:49.133065: step 10, loss = 4.66 (533.8 examples/ 0.240 sec/batch)
11:45:51.397710: step 20, loss = 4.64 (597.4 examples/ 0.214 sec/batch)
11:45:54.446850: step 30, loss = 4.62 (391.0 examples/ 0.327 sec/batch)
11:45:57.152676: step 40, loss = 4.61 (430.2 examples/ 0.298 sec/batch)
11:46:00.437717: step 50, loss = 4.59 (406.4 examples/ 0.315 sec/batch)
需要注意的是默认的GPU使用数是1,此外,如果你的机器上只有一个GPU,那么所有的计算都只会在一个GPU上运行,即便你可能设置的是N个。
练习: cifar10_train.py中的批处理大小默认配置是128。尝试在2个GPU上运行cifar10_multi_gpu_train.py脚本,并且设定批处理大小为64,然后比较2种方式的训练速度。
你已经完成了CIFAR-10教程。
如果你对开发和训练自己的图像分类系统感兴趣,我们推荐你新建一个基于该教程的分支,并修改其中的内容以建立解决您问题的图像分类系统。
练习: 下载 数据集。新建一个CIFAR-10教程的分支,并将输入数据替换成SVHN。尝试改变网络结构以提高预测性能。
翻译: 校对:Python(5)
TensorFlow(3)
机器学习(11)
文本代码基于TensorFlow 0.12.0版本,使用tf.contrib.learn封装的方法来实现CNN。
从网上借用一张图片来表示一下,是一个有2层hidden layer的CNN。
程序中设置的一些参数是:
卷积层1:kernel_size [5, 5], stride=1, 4个卷积窗口
卷积层2:kernel_size [5, 5], stride=1, 6个卷积窗口
池化层: pool_size [2, 2], stride = 2
全连接层1: 1024个特征
MNIST数据的获取
以往我们获取MINIST的方式是:
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
现在可以:
from tensorflow.contrib import learn
mnist = learn.datasets.load_dataset('mnist')
通过mnist.train, mnist.test, mnist.validation来获得3个数据集,每个数据集里面的方法有(已train为例):
train.images
图片数据,二维数组 (5) dtype=float32
train.labels
图片的分类, 一维数组,每个数值表示图片对应的数字
array([7, 3, 4, …, 5, 6, 8], dtype=uint8)
train.num_examples
train.next_batch
下一批数据
n = train.next_batch
n[0] 是images
n[1]是labels
第一次load MNIST数据的时候,会自动从网上下载,放到当前目录的MNIST-data目录下
第一种加载方式,有一个one-hot参数,此时每个样本的label,返回的是一个长度10的vector,其中只有一个位置是1,其他都是0。 第二种方式,没有这个参数,如果需要的话,得直接调用datasets.mnist.read_data_sets
查看learn.datasets的代码,还可以加载其他一些数据:
DATASETS = {
'iris': base.load_iris,
'boston': base.load_boston,
'mnist': mnist.load_mnist,
'dbpedia': text_datasets.load_dbpedia,
定义卷积层
在tf.contrib.layers里面有convolution2d,conv2d等方法,其实都是convolution方法的别名
convolution(inputs, num_outputs, kernel_size, stride=1, padding='SAME', data_format=None, rate=1, activation_fn=nn.relu, normalizer_fn=None, normalizer_params=None, weights_initializer=initializers.xavier_initializer(), weights_regularizer=None, biases_initializer=init_ops.zeros_initializer, biases_regularizer=None, reuse=None, variables_collections=None, outputs_collections=None, trainable=True, scope=None)
我们自己写卷积运算时要考虑的因素,基本上都体现在这个方法的参数里面了,禁不住佩服一下google的抽象能力。
Adds an N-D convolution followed by an optional batch_norm layer.It is required that 1 &= N &= 3.
这个函数很强大,1到3维的卷积都支持。(我暂时只用过2维)
inputs: 输入变量,是一个N+2维的Tensor
类型要求是一个Tensor,而我们一般训练的数据都是常量(比如mnist,load以后得到是python的数据类型,不是tf的),所以需要把用tf的方法做一下转换,比如tf.reshape
为什么是N+2维呢,比如图像,除了宽度和高度,实际上还有样本数量和通道数量(如RGB3通道),所以多了2维。
inputs的格式,由date_format这个参数来觉得,比如2维,有NHWC和NCHW两种。N是样本数量,H高度,W宽度,C通道数。
num_outputs: 卷积filter的数量,或者说提取的特征数量,比如5,10
kernel_size: 卷积核的大小,是N个参数的list,比如二维图像,可以时候[10,10],如果参数值相同,用一个整数来表示也可以;
stride: 卷积步长,同样是N个参数的序列,或者都相等的话,用一个整数来表示,默认是1.
padding: 字符串格式,默认SAME,可选’VALID’。(想问:这两个效果上有多大差异?)
data_format: 字符串,指定inputs的格式
一维数据:”NWC” (default) and “NCW”
二维数据:”NHWC” (default) and “NCHW”
三维数据:”NDHWC”
也就是,不指定的话,通道数都是最后一个参数。
rate: a sequence of N positive integers specifying the dilation rate to use for a’trous convolution. Can be a single integer to specify the same value for all spatial dimensions. (暂时没看到其作用)
activation_fn: 激活函数,默认relu
normalizer_fn: normalization function to use instead of biases.(没用过,不知道起作用)
normalizer_params: normalization function parameters.
weights_initializer: 这不用说了,有默认值,估计用默认的就可以了。
weights_regularizer:
Optional regularizer for the weights.(没明白为什么需要这个)
biases_initializer: 有默认值,一般也就不用指定。
biases_regularizer: …
reuse: whether or not the layer and its variables should be reused. To be able to reuse the layer scope must be given. 应该都需要reuse吧,所以这个参数默认为True更好,现在是None。
variables_collections: 怎么用暂时不太明白,但应该不用指定也可以;
outputs_collections: 同上;
trainable: If True also add variables to the graph collection GraphKeys.TRAINABLE_VARIABLES,默认是True。 (这个是不是说在fit的时候需要设为True,evaluate和predict的时候为false?)
scope: 也即是variable_scope, 如果用多个卷积层的话,需要设置这个参数,以便把每一次的weight和bias区别出来。
我们在对MNIST做卷积的时候,只要指定inputs, num_outputs, kernel_size, scope这几个参数就可以了,比如:
conv1 = tf.contrib.layers.conv2d(inputs, 4, [5, 5], 'conv_layer1')
#stride默认1,weights和biases也都是默认的
TODO:卷积的结果是多少维的数据?
定义池化层
可以用 tf.contrib.layers.max_pool2d或者tf.contrib.layers.avg_pool2d
max_pool2d(inputs, kernel_size, stride=2, padding=’VALID’, data_format=DATA_FORMAT_NHWC, outputs_collections=None, scope=None)
inputs: 就是卷积的输出了;
kernel_size:
是不是叫pool_size更贴切。[kernel_height, kernel_width]或者是一个整数;
[stride_height, stride_width],不过文档上说目前这两个值必须一样
padding: 这里默认是VALID,和卷积默认不一样,为什么要这样呢?
data_format: 注意和卷积用的一样哦;
outputs_collections: …
scope: pooling的时候没有参数,需要scope吗?
pool1 = tf.contrib.layers.max_pool2d(conv1, [2, 2], padding='SAME')
定义全连接层
tf.contrib.layers下有可用的全连接方法:
fully_connected(inputs, num_outputs, activation_fn=nn.relu, normalizer_fn=None, normalizer_params=None, weights_initializer=initializers.xavier_initializer(), weights_regularizer=None, biases_initializer=init_ops.zeros_initializer, biases_regularizer=None, reuse=None, variables_collections=None, outputs_collections=None, trainable=True, scope=None)
看这个函数,参数和卷积很多地方是一样的,
我们可以这样用:
fc = tf.contrib.layers.fully_connected(inputs, 1024, scope='fc_layer')
唯一需要注意的是这里的inputs参数,一般是二维的形式[batch_size, depth],而前面卷积的结果,一般是[batch_size, height, width, channels]的形式,所以需要做一个flatten操作后再传给fully_connected。
一般在fc之后还会做dropout,可以用如下方法:
dropout(inputs, keep_prob=0.5, noise_shape=None, is_training=True, outputs_collections=None, scope=None)
参数的意义很明显,其中is_training需要注意一下,在训练的时候传True,其他情况下传False。
定义logits
全连接之后,一般就是用softmax做分类,然后定义loss,就可以训练了。但是看官方的例子,softmax前还加了一步,计算叫logits的东西,代码里面的说明是:
We don’t apply softmax here because
tf.nn.softmax_cross_entropy_with_logits accepts the unscaled logits
and performs the softmax internally for efficiency.
为什么要这样暂时不太明白,但是依样画葫芦,定义logtis本身很简单,做一个线性变换,把FC的结果映射到分类的数量上:
def inference(x, num_class):
with tf.variable_scope('softmax'):
dtype = x.dtype.base_dtype
init_mean = 0.0
init_stddev = 0.0
weights = tf.get_variable('weights',
[x.get_shape()[1], num_class], initializer=init_ops.random_normal_initializer(init_mean, init_stddev, dtype=dtype), dtype=dtype)
biases = tf.get_variable('bias', [num_class], initializer=init_ops.random_normal_initializer(init_mean, init_stddev, dtype=dtype), dtype=dtype)
logits = tf.nn.xw_plus_b(x, weights, biases)
return logits
在tf.contrib.losses下有一些预定义的loss函数,比如直接用
softmax_cross_entropy(logits, onehot_labels, weights=_WEIGHT_SENTINEL, label_smoothing=0, scope=None)
注意这里的label是onehot格式的, 我们从mnist获取的label要转换成这个格式。
定义train_op
可以用tf.contrib.layers.optimize_loss,通过传递不同的参数,就可以调用不同的优化方法。
optimize_loss(loss,
global_step,
learning_rate,
optimizer,
gradient_noise_scale=None,
gradient_multipliers=None,
clip_gradients=None,
learning_rate_decay_fn=None,
update_ops=None,
variables=None,
name=None,
summaries=None,
colocate_gradients_with_ops=False):
预定义的optimizer有:
OPTIMIZER_CLS_NAMES = {
"Adagrad": train.AdagradOptimizer,
"Adam": train.AdamOptimizer,
"Ftrl": train.FtrlOptimizer,
"Momentum": train.MomentumOptimizer,
"RMSProp": train.RMSPropOptimizer,
"SGD": train.GradientDescentOptimizer,
所以我们可以这样写:
train_op = tf.contrib.layers.optimize_loss(
loss, tf.contrib.framework.get_global_step(), optimizer='Adagrad', learning_rate=0.1)
model和Estimator
结合上面的内容,就可以定义出model, 从而用Estimator完成训练,预测等功能,完整的程序如下:
import numpy as np
import sklearn.metrics as metrics
import tensorflow as tf
from PIL import Image
from tensorflow.contrib import learn
from tensorflow.contrib.learn import SKCompat
from tensorflow.contrib.learn.python.learn.estimators import model_fn as model_fn_lib
from tensorflow.python.ops import init_ops
IMAGE_SIZE = 28
LOG_DIR = './ops_logs'
mnist = learn.datasets.load_dataset('mnist')
def inference(x, num_class):
with tf.variable_scope('softmax'):
dtype = x.dtype.base_dtype
init_mean = 0.0
init_stddev = 0.0
weight = tf.get_variable('weights',
[x.get_shape()[1], num_class], initializer=init_ops.random_normal_initializer(init_mean, init_stddev, dtype=dtype), dtype=dtype)
biases = tf.get_variable('bias', [num_class], initializer=init_ops.random_normal_initializer(init_mean, init_stddev, dtype=dtype), dtype=dtype)
logits = tf.nn.xw_plus_b(x, weight, biases)
return logits
def model(features, labels, mode):
if mode != model_fn_lib.ModeKeys.INFER:
labels = tf.one_hot(labels, 10, 1, 0)
labels = None
inputs = tf.reshape(features, (-1, IMAGE_SIZE, IMAGE_SIZE, 1))
conv1 = tf.contrib.layers.conv2d(inputs, 4, [5, 5], scope='conv_layer1', activation_fn=tf.nn.tanh);
pool1 = tf.contrib.layers.max_pool2d(conv1, [2, 2], padding='SAME')
conv2 = tf.contrib.layers.conv2d(pool1, 6, [5, 5], scope='conv_layer2', activation_fn=tf.nn.tanh);
pool2 = tf.contrib.layers.max_pool2d(conv2, [2, 2], padding='SAME')
pool2_shape = pool2.get_shape()
pool2_in_flat = tf.reshape(pool2, [pool2_shape[0].value or -1, np.prod(pool2_shape[1:]).value])
fc1 = tf.contrib.layers.fully_connected(pool2_in_flat, 1024, scope='fc_layer1', activation_fn=tf.nn.tanh)
is_training = False
if mode == model_fn_lib.ModeKeys.TRAIN:
is_training = True
dropout = tf.contrib.layers.dropout(fc1, keep_prob=0.5, is_training=is_training, scope='dropout')
logits = inference(dropout, 10)
prediction = tf.nn.softmax(logits)
if mode != model_fn_lib.ModeKeys.INFER:
loss = tf.contrib.losses.softmax_cross_entropy(logits, labels)
train_op = tf.contrib.layers.optimize_loss(
loss, tf.contrib.framework.get_global_step(), optimizer='Adagrad',
learning_rate=0.1)
train_op = None
loss = None
return {'class': tf.argmax(prediction, 1), 'prob': prediction}, loss, train_op
classifier = SKCompat(learn.Estimator(model_fn=model, model_dir=LOG_DIR))
classifier.fit(mnist.train.images, mnist.train.labels, steps=1000, batch_size=300)
predictions = classifier.predict(mnist.test.images)
score = metrics.accuracy_score(mnist.test.labels, predictions['class'])
print('Accuracy: {0:f}'.format(score))
待分析的一些问题
global_step的作用
session到哪儿去了
变量的保存和加载
参数的调优
参考文章:
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:3584次
排名:千里之外
原创:18篇
(1)(6)(5)(13)

我要回帖

更多关于 fast rcnn tensorflow 的文章

 

随机推荐