如何使用tensorboard无法使用

转载请注明作者:
Github工程地址:
欢迎star,有问题可以到讨论
官方教程:
TensorFlow自带的一个强大的可视化工具
这是TensorFlow在MNIST实验数据上得到
Event: 展示训练过程中的统计数据(最值,均值等)变化情况
Image: 展示训练过程中记录的图像
Audio: 展示训练过程中记录的音频
Histogram: 展示训练过程中记录的数据的分布图
在运行过程中,记录结构化的数据
运行一个本地服务器,监听6006端口
请求时,分析记录的数据,绘制
在构建graph的过程中,记录你想要追踪的Tensor
with tf.name_scope('output_act'):
hidden = tf.nn.relu6(tf.matmul(reshape, output_weights[0]) + output_biases)
tf.histogram_summary('output_act', hidden)
histogram_summary用于生成分布图,也可以用scalar_summary记录存数值
使用scalar_summary的时候,tag和tensor的shape要一致
name_scope可以不写,但是当你需要在Graph中体现tensor之间的包含关系时,就要写了,像下面这样:
with tf.name_scope('input_cnn_filter'):
with tf.name_scope('input_weight'):
input_weights = tf.Variable(tf.truncated_normal(
[patch_size, patch_size, num_channels, depth], stddev=0.1), name='input_weight')
variable_summaries(input_weights, 'input_cnn_filter/input_weight')
with tf.name_scope('input_biases'):
input_biases = tf.Variable(tf.zeros([depth]), name='input_biases')
variable_summaries(input_weights, 'input_cnn_filter/input_biases')
在Graph中会体现为一个input_cnn_filter,可以点开,里面有weight和biases
用summary系列函数记录后,Tensorboard会根据graph中的依赖关系在Graph标签中展示对应的图结构
官网封装了一个函数,可以调用来记录很多跟某个Tensor相关的数据:
def variable_summaries(var, name):
&&&Attach a lot of summaries to a Tensor.&&&
with tf.name_scope('summaries'):
mean = tf.reduce_mean(var)
tf.scalar_summary('mean/' + name, mean)
with tf.name_scope('stddev'):
stddev = tf.sqrt(tf.reduce_sum(tf.square(var - mean)))
tf.scalar_summary('sttdev/' + name, stddev)
tf.scalar_summary('max/' + name, tf.reduce_max(var))
tf.scalar_summary('min/' + name, tf.reduce_min(var))
tf.histogram_summary(name, var)
只有这样记录国max和min的Tensor才会出现在Event里面
Graph的最后要写一句这个,给session回调
merged = tf.merge_all_summaries()
Session 中调用
构造两个writer,分别在train和valid的时候写数据:
train_writer = tf.train.SummaryWriter(summary_dir + '/train',
session.graph)
valid_writer = tf.train.SummaryWriter(summary_dir + '/valid')
这里的summary_dir存放了运行过程中记录的数据,等下启动服务器要用到
构造run_option和run_meta,在每个step运行session时进行设置:
summary, _, l, predictions =
session.run([merged, optimizer, loss, train_prediction], options=run_options, feed_dict=feed_dict)
注意要把merged拿回来,并且设置options
在每次训练时,记一次:
train_writer.add_summary(summary, step)
在每次验证时,记一次:
valid_writer.add_summary(summary, step)
达到一定训练次数后,记一次meta做一下标记
train_writer.add_run_metadata(run_metadata, 'step%03d' % step)
查看可视化结果
启动TensorBoard服务器:
python安装路径/python TensorFlow安装路径/tensorflow/tensorboard/tensorboard.py --logdir=path/to/log-directory
注意这个python必须是安装了TensorFlow的python,tensorboard.py必须制定路径才能被python找到,logdir必须是前面创建两个writer时使用的路径
比如我的是:
/home/cwh/anaconda2/envs/tensorflow/bin/python /home/cwh/anaconda2/envs/tensorflow/lib/python2.7/site-packages/tensorflow/tensorboard/tensorboard.py --logdir=~/coding/python/GDLnotes/src/convnet/summary
使用python
然后在浏览器输入
就可以访问到tensorboard的结果
强迫症踩坑后记
之前我的cnn代码里有valid_prediction,所以画出来的graph有两条分支,不太清晰,所以只留了train一个分支
多用with,进行包裹,这样才好看,正如官网说的,你的summary代码决定了你的图结构
不是所有的tensor都有必要记录,但是Variable和placeholder最好都用summary记录一下,也是为了好看
由于有了gradient的计算,所以与gradient计算相关的都会被拎出来,下次试一下用其他optimizer
我的CNN TensorBoard代码:
觉得我的文章对您有帮助的话,不妨点个?
土豪可以打赏支持,一分也是爱:
阅读(...) 评论()TensorFlow初学者指南:如何为机器学习项目创建合适的文件架构
在这篇文章中,作者根据自己的经验为 TensorFlow 初学者给出了设计文件、文件夹架构的建议。在管理自己的项目时,这会是非常有帮助的。在机器学习中,设计正确的文件架构并不简单。我自己在几个项目上纠结过此问题之后,我开始寻找简单的模式,并希望其能覆盖大部分在读代码或自己编代码时遇到的使用案例。在此文章中,我会分享我自己的发现。声明:该文章更像是建议,而非明确的指导,但我感觉挺成功的。该文章意在为初学者提供起点,可能会引发一些讨论。因为一开始我想要为自己的工作设计文件架构,我想我能分享下这方面的内容。如果你有更好的文件架构理论,可以留言分享。总需要得到什么?想下在你做机器学习的时候,你必须要做的是什么?需要编写一个模型该模型(至少)有两个不同的阶段:训练阶段和推论阶段(成果)需要为该模型输入数据集(训练阶段)可能也需要为它输入单个元素(推论阶段)需要调整它的超参数精调超参数,需要模型是可配置的,并创造一个类似「API」的存在,至少能让你推动配置的运行训练结果需要好的文件夹(folder)架构(以便于浏览并轻易的记住每个实验)需要用图表示一些指标,比如损失或准确率(在训练以及成果阶段)想要这些图能够轻易地被搜索到想要能够复制所做的任何实验甚至在训练阶段希望跳回前面,以检查模型在构造文件和文件夹时,很容易就会忘记以上这些。此外,可能还有其他需求我并未列出。下面,让我们寻找一些最好的实践。整体文件夹架构一图胜千言:文件架构README 文件:大部分人可能使用 Github,所以请花费些时间,写一个至少包含以下选项的好的 markdown:安装、使用、测试、有用的链接,来记录要直接放进 repository 的大型文件。main.py 文件:独特的 endpoint,简单。下面会有更详细的介绍。你也可以用两个文档做为变形(train.py/infer.py)。但在我看来不必要,它通常用来为每个文件建立两个 API。数据文件夹:创造一个文件夹,并放进一个脚本来下载数据集。如果需要,让脚本很好地适配数据文件夹,例如:如果没有的话,脚本可以创造 trian/val/test 子文件夹。模型文件夹:该文件夹用来放模型文件。我认为不只有一种方式可处理这个文件夹,你可以为每个模型或每个模型类别写个文件,甚至可以有一个子文件夹。只要保持一致就行。__init__ file:下面我会对该文件介绍更多,但它是一个 python 助手(helper),能让你更容易找到模型,且简化了模型文件夹的复杂度。basic_model.py 文件:下面也会对此有所详介。我认为 TensorFlow 中的大部分模型能共享一个通用架构,后文我会解释自己的选择以及原因。hysearch 文件夹:该文件夹用来存放任何做自定义超参数搜索的助手。如果你使用函数库,可能就不需要它,但大多时候你总需要自定义些东西。保持这些功能的纯粹与单独性,以便于能简单地进行测试。测试文件夹:测试文件夹,当然是用来测试的。你会测试它们,对吧?结果文件夹:很明显,该文件夹是用来放结果的。TensorFlow 中更多有关如何提供 TensorBorad 的子文件夹架构的信息,下面很有所介绍。注释:请在结果文件夹中添加一个「.gitkeep」文件和为「.gitignore」文件添加一个文件夹。因为你也许不希望将所有试验都放到 Github 上,并需要避免代码在首次安装时因为文件夹丢失而中断。这些都是十分基础的。当然,也许还需要添加其他文件夹,但那些都能归结到这一基本集中。通过将良好的 README 和其他 bash 脚本作为辅助。任何人希望使用你的资源库(repository)都可以通过「Install」命令和「Usage」命令复制你的研究。基本模型正如我所说的,我最终意识到模型中的模式是通过 TF 工程化的东西。这一点引领着我我设计了一个非常简单的类(class),其可以由我未来的模型所扩展。我并不是继承类别(class inheritance)的热衷者,但我也不是永远清晰复写一段相同代码的热衷者。当你在进行机器学习项目时,模型通过你使用的框架共享了许多相似之处。所以我试图找到一个避免继承的(inheritance)已知香蕉问题(banana problem)的实现,这是通过让一个继承尽可能地深而达到。要完全清楚,我们需要将这一类别作为以后模型的顶部父级类别(top parent),令你模型的构建在一行使用一个变元(one argument):配置(the configuration)。为了更进一步理解,我们将为你直接展示注释文件(commented file):import os, copyimport tensorflow as tfclass BasicAgent(object): & &# To build your model, you only to pass a &configuration& which is a dictionary & &def __init__(self, config): & & & &# I like to keep the best HP found so far inside the model itself & & & &# This is a mechanism to load the best HP and override the configuration & & & &if config['best']: & & & & & &config.update(self.get_best_config(config['env_name'])) & & & & & & & & & &# I make a `deepcopy` of the configuration before using it & & & &# to avoid any potential mutation when I iterate asynchronously over configurations & & & &self.config = copy.deepcopy(config) & & & &if config['debug']: # This is a personal check i like to do & & & & & &print('config', self.config) & & & &# When working with NN, one usually initialize randomly & & & &# and you want to be able to reproduce your initialization so make sure & & & &# you store the random seed and actually use it in your TF graph (tf.set_random_seed() for example) & & & &self.random_seed = self.config['random_seed'] & & & &# All models share some basics hyper parameters, this is the section where we & & & &# copy them into the model & & & &self.result_dir = self.config['result_dir'] & & & &self.max_iter = self.config['max_iter'] & & & &self.lr = self.config['lr'] & & & &self.nb_units = self.config['nb_units'] & & & &# etc. & & & & & & & &# Now the child Model needs some custom parameters, to avoid any & & & &# inheritance hell with the __init__ function, the model
& & & &# will override this function completely & & & &self.set_agent_props() & & & &# Again, child Model should provide its own build_grap function & & & &self.graph = self.build_graph(tf.Graph()) & & & &# Any operations that should be in the graph but are common to all models & & & &# can be added this way, here & & & &with self.graph.as_default(): & & & & & &self.saver = tf.train.Saver( & & & & & & & &max_to_keep=50, & & & & & &) & & & & & & & &# Add all the other common code for the initialization here & & & &gpu_options = tf.GPUOptions(allow_growth=True) & & & &sessConfig = tf.ConfigProto(gpu_options=gpu_options) & & & &self.sess = tf.Session(config=sessConfig, graph=self.graph) & & & &self.sw = tf.summary.FileWriter(self.result_dir, self.sess.graph) & & & & & & & &# This function is not always common to all models, that's why it's again & & & &# separated from the __init__ one & & & &self.init() & & & &# At the end of this function, you want your model to be ready! & &def set_agent_props(self): & & & &# This function is here to be overriden completely. & & & &# When you look at your model, you want to know exactly which custom options it needs. & & & &pass & &def get_best_config(self): & & & &# This function is here to be overriden completely. & & & &# It returns a dictionary used to update the initial configuration (see __init__) & & & &return {}
& &@staticmethod & &def get_random_config(fixed_params={}): & & & &# Why static? Because you want to be able to pass this function to other processes & & & &# so they can independently generate random configuration of the current model & & & &raise Exception('The get_random_config function must be overriden by the agent') & &def build_graph(self, graph): & & & &raise Exception('The build_graph function must be overriden by the agent') & &def infer(self): & & & &raise Exception('The infer function must be overriden by the agent') & &def learn_from_epoch(self): & & & &# I like to separate the function to train per epoch and the function to train globally & & & &raise Exception('The learn_from_epoch function must be overriden by the agent') & &def train(self, save_every=1): & & & &# This function is usually common to all your models, Here is an example: & & & &for epoch_id in range(0, self.max_iter): & & & & & &self.learn_from_epoch() & & & & & &# If you don't want to save during training, you can just pass a negative number & & & & & &if save_every & 0 and epoch_id % save_every == 0: & & & & & & & &self.save() & &def save(self): & & & &# This function is usually common to all your models, Here is an example: & & & &global_step_t = tf.train.get_global_step(self.graph) & & & &global_step, episode_id = self.sess.run([global_step_t, self.episode_id]) & & & &if self.config['debug']: & & & & & &print('Saving to %s with global_step %d' % (self.result_dir, global_step)) & & & &self.saver.save(self.sess, self.result_dir + '/agent-ep_' + str(episode_id), global_step) & & & &# I always keep the configuration that & & & &if not os.path.isfile(self.result_dir + '/config.json'): & & & & & &config = self.config & & & & & &if 'phi' in config: & & & & & & & &del config['phi'] & & & & & &with open(self.result_dir + '/config.json', 'w') as f: & & & & & & & &json.dump(self.config, f) & &def init(self): & & & &# This function is usually common to all your models & & & &# but making separate than the __init__ function allows it to be overidden cleanly & & & &# this is an example of such a function & & & &checkpoint = tf.train.get_checkpoint_state(self.result_dir) & & & &if checkpoint is None: & & & & & &self.sess.run(self.init_op) & & & &else: & & & & & &if self.config['debug']: & & & & & & & &print('Loading the model from folder: %s' % self.result_dir) & & & & & &self.saver.restore(self.sess, checkpoint.model_checkpoint_path) & &def infer(self): & & & &# This function is usually common to all your models & & & &pass & & & &基本模型文件一些注释:关于我配置的「最佳」属性:人们通常在没有模型最优超参数的情况下传送代码,有人知道为什么吗?随机函数是静态的,因为你不想实例化(instantiate)你的模型以访问它,但为什么要将其添加到模型本身呢?因为它通常与模型自定义参数绑定。注意,这个函数必须是纯粹的(pure),这样才能根据需要复杂化。示例 init 函数是最简单的版本,它会加载现存文件夹或(如果&result_dir&为空)使用&init_op&随机初始化。The __init__ script你能在文件夹结构看到初始化脚本(The __init__ script),其和机器学习并没有什么关联。但该脚本是令你的代码对你或其他人更加易读的简单方式。该脚本通过添加几行代码令任何模型类别都能从命名空间 models 直接可读取:所以你能在代码任一处输入:from models import MyModel,该代码行能导入模型而不用管模型的文件夹路径有多么深。这里有一个脚本案例来实现这一任务:from models.basic_model import BasicModelfrom agents.other_model import SomeOtherModel__all__ = [ & &&BasicModel&, & &&SomeOtherModel&]def make_model(config, env): & &if config['model_name'] in __all__: & & & &return globals()[config['model_name']](config, env) & &else: & & & &raise Exception('The model name %s does not exist' % config['model_name'])def get_model_class(config): & &if config['model_name'] in __all__: & & & &return globals()[config['model_name']] & &else: & & & &raise Exception('The model name %s does not exist' % config['model_name'])这并没有多高端,但我发现这一脚本十分有用,所以我把它加到本文中了。API 外壳(The shell API)我们有一个全局一致的文件夹架构和一个很好的基础类别来构建我们的模型,一个好的 python 脚本很容易加载我们的类(class),但是设计「shell API」,特别是其默认值是同样重要的。因为与机器学习研究交互的主要结束点就是你使用任何工具的外壳(shell),程序外壳是你实验的基石。你想要做的最后一件事就是调整你代码中的硬编码值来迭代这些实验,所以你需要从外壳中直接访问所有的超参数。同样你还需要访问所有其他参数,就像结果索引或 stage (HP search/Training/inferring) 等那样。同样为了更进一步理解,我们将为你直接展示注释文件(commented file):import os, jsonimport tensorflow as tf# See the __init__ script in the models folder# `make_models` is a helper function to load any models you havefrom models import make_models from hpsearch import hyperband, randomsearch# I personally always like to make my paths absolute# to be independent from where the python binary is calleddir = os.path.dirname(os.path.realpath(__file__))# I won't dig into TF interaction with the shell, feel free to explore the documentationflags = tf.app.flags# Hyper-parameters search configurationflags.DEFINE_boolean('fullsearch', False, 'Perform a full search of hyperparameter space ex:(hyperband -& lr search -& hyperband with best lr)')flags.DEFINE_boolean('dry_run', False, 'Perform a dry_run (testing purpose)')flags.DEFINE_integer('nb_process', 4, 'Number of parallel process to perform a HP search')# fixed_params is a trick I use to be able to fix some parameters inside the model random function# For example, one might want to explore different models fixing the learning rate, see the basic_model get_random_config functionflags.DEFINE_string('fixed_params', &{}&, 'JSON inputs to fix some params in a HP search, ex: \'{&lr&: 0.001}\'')# Agent configurationflags.DEFINE_string('model_name', 'DQNAgent', 'Unique name of the model')flags.DEFINE_boolean('best', False, 'Force to use the best known configuration')flags.DEFINE_float('initial_mean', 0., 'Initial mean for NN')flags.DEFINE_float('initial_stddev', 1e-2, 'Initial standard deviation for NN')flags.DEFINE_float('lr', 1e-3, 'The learning rate of SGD')flags.DEFINE_float('nb_units', 20, 'Number of hidden units in Deep learning agents')# Environment configurationflags.DEFINE_boolean('debug', False, 'Debug mode')flags.DEFINE_integer('max_iter', 2000, 'Number of training step')flags.DEFINE_boolean('infer', False, 'Load an agent for playing')# This is very important for TensorBoard# each model will end up in its own unique folder using time module# Obviously one can also choose to name the output folderflags.DEFINE_string('result_dir', dir + '/results/' + flags.FLAGS.model_name + '/' + str(int(time.time())), 'Name of the directory to store/log the model (if it exists, the model will be loaded from it)')# Another important point, you must provide an access to the random seed# to be able to fully reproduce an experimentflags.DEFINE_integer('random_seed', random.randint(0, sys.maxsize), 'Value of random seed')def main(_): & &config = flags.FLAGS.__flags.copy() & &# fixed_params must be a string to be passed in the shell, let's use JSON & &config[&fixed_params&] = json.loads(config[&fixed_params&]) & &if config['fullsearch']: & & & &# Some code for HP search ... & &else: & & & &model = make_model(config) & & & &if config['infer']: & & & & & &# Some code for inference ... & & & &else: & & & & & &# Some code for training ...if __name__ == '__main__': &tf.app.run()以上就是本文想要描述的,我们希望它能帮助新入门者辅助研究,我们同样也欢迎自由评论或提问。在文章最后,作者还列出了一批有关 TensorFlow 文章,感兴趣的读者可通过英文原文查看。原文链接:https://blog.metaflow.fr/tensorflow-a-proposal-of-good-practices-for-files-folders-and-models-architecture-f
声明:本文由机器之心编译出品,原文来自MetaFlow,作者Morgan,,机器之心对于违规侵权者保有法律追诉权。
网站转载请在文章开头粗体注明:本文转载自机器之心,标明作者,并附上本文链接。微信公众号转载请在开头粗体注明:本文转载自机器之心,标明作者,并设置阅读原文链接为本文链接,微博转载请附上本文链接并@机器之心synced。网站和微信转载具体文章后需来信至邮箱说明,备注转载文章标题、转载的微信号名称和转载日期。机器之心只接受如上几种转载方式,其余均视为侵权,如需商业合作请致信。
参与成员:
李亚洲蒋思源
同步到新浪微博
李亚洲 说点什么吧,让大家都能了解你。
为何机器不能像人类一样思考? 日TensorFlow 运作方式入门 | TensorFlow 官方文档中文版
1. 新手入门
2. 完整教程
3. 进阶指南
6. API DOC
6.1. Cc API
6.2. Images API
6.3. Python API
TensorFlow运作方式入门
代码:
本篇教程的目的,是向大家展示如何利用TensorFlow使用(经典)MNIST数据集训练并评估一个用于识别手写数字的简易前馈神经网络(feed-forward neural network)。我们的目标读者,是有兴趣使用TensorFlow的资深机器学习人士。
因此,撰写该系列教程并不是为了教大家机器学习领域的基础知识。
在学习本教程之前,请确保您已按照教程中的要求,完成了安装。
教程使用的文件
本教程引用如下文件:
文件
目的
构建一个完全连接(fully connected)的MINST模型所需的代码。
利用下载的数据集训练构建好的MNIST模型的主要代码,以数据反馈字典(feed dictionary)的形式作为输入模型。
只需要直接运行fully_connected_feed.py文件,就可以开始训练:
python fully_connected_feed.py
准备数据
MNIST是机器学习领域的一个经典问题,指的是让机器查看一系列大小为28x28像素的手写数字灰度图像,并判断这些图像代&#x中的哪一个数字。
更多相关信息,请查阅
或者。
下载
在run_training()方法的一开始,input_data.read_data_sets()函数会确保你的本地训练文件夹中,已经下载了正确的数据,然后将这些数据解压并返回一个含有DataSet实例的字典。
data_sets = input_data.read_data_sets(FLAGS.train_dir, FLAGS.fake_data)
注意:fake_data标记是用于单元测试的,读者可以不必理会。
数据集
目的
data_sets.train
55000个图像和标签(labels),作为主要训练集。
data_sets.validation
5000个图像和标签,用于迭代验证训练准确度。
data_sets.test
10000个图像和标签,用于最终测试训练准确度(trained accuracy)。
了解更多数据有关信息,请查阅此系列教程的
部分.
输入与占位符(Inputs and Placeholders)
placeholder_inputs()函数将生成两个操作,定义传入图表中的shape参数,shape参数中包括batch_size值,后续还会将实际的训练用例传入图表。
images_placeholder = tf.placeholder(tf.float32, shape=(batch_size,
IMAGE_PIXELS))
labels_placeholder = tf.placeholder(tf.int32, shape=(batch_size))
在训练循环(training loop)的后续步骤中,传入的整个图像和标签数据集会被切片,以符合每一个操作所设置的batch_size值,占位符操作将会填补以符合这个batch_size值。然后使用feed_dict参数,将数据传入sess.run()函数。
构建图表 (Build the Graph)
在为数据创建占位符之后,就可以运行mnist.py文件,经过三阶段的模式函数操作:inference(), loss(),和training()。图表就构建完成了。
1.inference() —— 尽可能地构建好图表,满足促使神经网络向前反馈并做出预测的要求。
2.loss() —— 往inference图表中添加生成损失(loss)所需要的操作(ops)。
3.training() —— 往损失图表中添加计算并应用梯度(gradients)所需的操作。
推理(Inference)
inference()函数会尽可能地构建图表,做到返回包含了预测结果(output prediction)的Tensor。
它接受图像占位符为输入,在此基础上借助ReLu(Rectified Linear Units)激活函数,构建一对完全连接层(layers),以及一个有着十个节点(node)、指明了输出logtis模型的线性层。
每一层都创建于一个唯一的之下,创建于该作用域之下的所有元素都将带有其前缀。
with tf.name_scope(&hidden1&) as scope:
在定义的作用域中,每一层所使用的权重和偏差都在实例中生成,并且包含了各自期望的shape。
weights = tf.Variable(
tf.truncated_normal([IMAGE_PIXELS, hidden1_units],
stddev=1.0 / math.sqrt(float(IMAGE_PIXELS))),
name=&weights&)
biases = tf.Variable(tf.zeros([hidden1_units]),
name=&biases&)
例如,当这些层是在hidden1作用域下生成时,赋予权重变量的独特名称将会是&hidden1/weights&。
每个变量在构建时,都会获得初始化操作(initializer ops)。
在这种最常见的情况下,通过函数初始化权重变量,给赋予的shape则是一个二维tensor,其中第一个维度代表该层中权重变量所连接(connect from)的单元数量,第二个维度代表该层中权重变量所连接到的(connect to)单元数量。对于名叫hidden1的第一层,相应的维度则是[IMAGE_PIXELS, hidden1_units],因为权重变量将图像输入连接到了hidden1层。tf.truncated_normal初始函数将根据所得到的均值和标准差,生成一个随机分布。
然后,通过函数初始化偏差变量(biases),确保所有偏差的起始值都是0,而它们的shape则是其在该层中所接到的(connect to)单元数量。
图表的三个主要操作,分别是两个操作,它们中嵌入了隐藏层所需的;以及logits模型所需的另外一个tf.matmul。三者依次生成,各自的tf.Variable实例则与输入占位符或下一层的输出tensor所连接。
hidden1 = tf.nn.relu(tf.matmul(images, weights) + biases)
hidden2 = tf.nn.relu(tf.matmul(hidden1, weights) + biases)
logits = tf.matmul(hidden2, weights) + biases
最后,程序会返回包含了输出结果的logitsTensor。
损失(Loss)
loss()函数通过添加所需的损失操作,进一步构建图表。
首先,labels_placeholer中的值,将被编码为一个含有1-hot values的Tensor。例如,如果类标识符为“3”,那么该值就会被转换为:
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
batch_size = tf.size(labels)
labels = tf.expand_dims(labels, 1)
indices = tf.expand_dims(tf.range(0, batch_size, 1), 1)
concated = tf.concat(1, [indices, labels])
onehot_labels = tf.sparse_to_dense(
concated, tf.pack([batch_size, NUM_CLASSES]), 1.0, 0.0)
之后,又添加一个操作,用来比较inference()函数与1-hot标签所输出的logits Tensor。
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits,
onehot_labels,
name=&xentropy&)
然后,使用函数,计算batch维度(第一维度)下交叉熵(cross entropy)的平均值,将将该值作为总损失。
loss = tf.reduce_mean(cross_entropy, name=&xentropy_mean&)
最后,程序会返回包含了损失值的Tensor。
注意:交叉熵是信息理论中的概念,可以让我们描述如果基于已有事实,相信神经网络所做的推测最坏会导致什么结果。更多详情,请查阅博文《可视化信息理论》()
训练
training()函数添加了通过梯度下降(gradient descent)将损失最小化所需的操作。
首先,该函数从loss()函数中获取损失Tensor,将其交给,后者在与SummaryWriter(见下文)配合使用时,可以向事件文件(events file)中生成汇总值(summary values)。在本篇教程中,每次写入汇总值时,它都会释放损失Tensor的当前值(snapshot value)。
tf.scalar_summary(loss.op.name, loss)
接下来,我们实例化一个,负责按照所要求的学习效率(learning rate)应用梯度下降法(gradients)。
optimizer = tf.train.GradientDescentOptimizer(FLAGS.learning_rate)
之后,我们生成一个变量用于保存全局训练步骤(global training step)的数值,并使用函数更新系统中的三角权重(triangle weights)、增加全局步骤的操作。根据惯例,这个操作被称为 train_op,是TensorFlow会话(session)诱发一个完整训练步骤所必须运行的操作(见下文)。
global_step = tf.Variable(0, name=&global_step&, trainable=False)
train_op = optimizer.minimize(loss, global_step=global_step)
最后,程序返回包含了训练操作(training op)输出结果的Tensor。
训练模型
一旦图表构建完毕,就通过fully_connected_feed.py文件中的用户代码进行循环地迭代式训练和评估。
图表
在run_training()这个函数的一开始,是一个Python语言中的with命令,这个命令表明所有已经构建的操作都要与默认的全局实例关联起来。
with tf.Graph().as_default():
tf.Graph实例是一系列可以作为整体执行的操作。TensorFlow的大部分场景只需要依赖默认图表一个实例即可。
利用多个图表的更加复杂的使用场景也是可能的,但是超出了本教程的范围。
会话
完成全部的构建准备、生成全部所需的操作之后,我们就可以创建一个,用于运行图表。
sess = tf.Session()
另外,也可以利用with代码块生成Session,限制作用域:
with tf.Session() as sess:
Session函数中没有传入参数,表明该代码将会依附于(如果还没有创建会话,则会创建新的会话)默认的本地会话。
生成会话之后,所有tf.Variable实例都会立即通过调用各自初始化操作中的函数进行初始化。
init = tf.initialize_all_variables()
sess.run(init)
方法将会运行图表中与作为参数传入的操作相对应的完整子集。在初次调用时,init操作只包含了变量初始化程序。图表的其他部分不会在这里,而是在下面的训练循环运行。
训练循环
完成会话中变量的初始化之后,就可以开始训练了。
训练的每一步都是通过用户代码控制,而能实现有效训练的最简单循环就是:
for step in xrange(max_steps):
sess.run(train_op)
但是,本教程中的例子要更为复杂一点,原因是我们必须把输入的数据根据每一步的情况进行切分,以匹配之前生成的占位符。
向图表提供反馈
执行每一步时,我们的代码会生成一个反馈字典(feed dictionary),其中包含对应步骤中训练所要使用的例子,这些例子的哈希键就是其所代表的占位符操作。
fill_feed_dict函数会查询给定的DataSet,索要下一批次batch_size的图像和标签,与占位符相匹配的Tensor则会包含下一批次的图像和标签。
images_feed, labels_feed = data_set.next_batch(FLAGS.batch_size)
然后,以占位符为哈希键,创建一个Python字典对象,键值则是其代表的反馈Tensor。
feed_dict = {
images_placeholder: images_feed,
labels_placeholder: labels_feed,
这个字典随后作为feed_dict参数,传入sess.run()函数中,为这一步的训练提供输入样例。
检查状态
在运行sess.run函数时,要在代码中明确其需要获取的两个值:[train_op, loss]。
for step in xrange(FLAGS.max_steps):
feed_dict = fill_feed_dict(data_sets.train,
images_placeholder,
labels_placeholder)
_, loss_value = sess.run([train_op, loss],
feed_dict=feed_dict)
因为要获取这两个值,sess.run()会返回一个有两个元素的元组。其中每一个Tensor对象,对应了返回的元组中的numpy数组,而这些数组中包含了当前这步训练中对应Tensor的值。由于train_op并不会产生输出,其在返回的元祖中的对应元素就是None,所以会被抛弃。但是,如果模型在训练中出现偏差,loss Tensor的值可能会变成NaN,所以我们要获取它的值,并记录下来。
假设训练一切正常,没有出现NaN,训练循环会每&#x个训练步骤,就打印一行简单的状态文本,告知用户当前的训练状态。
if step % 100 == 0:
print &Step %d: loss = %.2f (%.3f sec)& % (step, loss_value, duration)
状态可视化
为了释放所使用的事件文件(events file),所有的即时数据(在这里只有一个)都要在图表构建阶段合并至一个操作(op)中。
summary_op = tf.merge_all_summaries()
在创建好会话(session)之后,可以实例化一个,用于写入包含了图表本身和即时数据具体值的事件文件。
summary_writer = tf.train.SummaryWriter(FLAGS.train_dir,
graph_def=sess.graph_def)
最后,每次运行summary_op时,都会往事件文件中写入最新的即时数据,函数的输出会传入事件文件读写器(writer)的add_summary()函数。。
summary_str = sess.run(summary_op, feed_dict=feed_dict)
summary_writer.add_summary(summary_str, step)
事件文件写入完毕之后,可以就训练文件夹打开一个TensorBoard,查看即时数据的情况。
注意:了解更多如何构建并运行TensorBoard的信息,请查看相关教程。
保存检查点(checkpoint)
为了得到可以用来后续恢复模型以进一步训练或评估的检查点文件(checkpoint file),我们实例化一个。
saver = tf.train.Saver()
在训练循环中,将定期调用方法,向训练文件夹中写入包含了当前所有可训练变量值得检查点文件。
saver.save(sess, FLAGS.train_dir, global_step=step)
这样,我们以后就可以使用方法,重载模型的参数,继续训练。
saver.restore(sess, FLAGS.train_dir)
评估模型
每隔一千个训练步骤,我们的代码会尝试使用训练数据集与测试数据集,对模型进行评估。do_eval函数会被调用三次,分别使用训练数据集、验证数据集合测试数据集。
print &Training Data Eval:&
do_eval(sess,
eval_correct,
images_placeholder,
labels_placeholder,
data_sets.train)
print &Validation Data Eval:&
do_eval(sess,
eval_correct,
images_placeholder,
labels_placeholder,
data_sets.validation)
print &Test Data Eval:&
do_eval(sess,
eval_correct,
images_placeholder,
labels_placeholder,
data_sets.test)
注意,更复杂的使用场景通常是,先隔绝data_sets.test测试数据集,只有在大量的超参数优化调整(hyperparameter tuning)之后才进行检查。但是,由于MNIST问题比较简单,我们在这里一次性评估所有的数据。
构建评估图表(Eval Graph)
在打开默认图表(Graph)之前,我们应该先调用get_data(train=False)函数,抓取测试数据集。
test_all_images, test_all_labels = get_data(train=False)
在进入训练循环之前,我们应该先调用mnist.py文件中的evaluation函数,传入的logits和标签参数要与loss函数的一致。这样做事为了先构建Eval操作。
eval_correct = mnist.evaluation(logits, labels_placeholder)
evaluation函数会生成
操作,如果在K个最有可能的预测中可以发现真的标签,那么这个操作就会将模型输出标记为正确。在本文中,我们把K的值设置为1,也就是只有在预测是真的标签时,才判定它是正确的。
eval_correct = tf.nn.in_top_k(logits, labels, 1)
评估图表的输出(Eval Output)
之后,我们可以创建一个循环,往其中添加feed_dict,并在调用sess.run()函数时传入eval_correct操作,目的就是用给定的数据集评估模型。
for step in xrange(steps_per_epoch):
feed_dict = fill_feed_dict(data_set,
images_placeholder,
labels_placeholder)
true_count += sess.run(eval_correct, feed_dict=feed_dict)
true_count变量会累加所有in_top_k操作判定为正确的预测之和。接下来,只需要将正确测试的总数,除以例子总数,就可以得出准确率了。
precision = float(true_count) / float(num_examples)
Num examples: %d
Num correct: %d
Precision @ 1: %0.02f& % (
num_examples, true_count, precision)
原文:
翻译:
校对:

我要回帖

更多关于 google服务框架 的文章

 

随机推荐