博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【译】Effective TensorFlow Chapter11——在TensorFlow中调试模型
阅读量:5973 次
发布时间:2019-06-19

本文共 3095 字,大约阅读时间需要 10 分钟。

本文翻译自: , 如有侵权请联系删除,仅限于学术交流,请勿商用。如有谬误,请联系指出。

与常规python代码相比,TensorFlow的符号特性使的TensorFlow的代码调试变得相对困难。这里我介绍一些TensorFlow附带的工具,使调试更容易。

使用TensorFlow时最常见的错误可能是传递形状错误的张量。许多TensorFlow操作可以在不同秩(rank)和形状(shape)的张量上操作。这在使用API时很方便,但在出现问题时可能会导致额外的麻烦。

例如,考虑下面这个tf.matmul操作,它可以使两个矩阵相乘:

a = tf.random_uniform([2, 3])b = tf.random_uniform([3, 4])c = tf.matmul(a, b)  # c is a tensor of shape [2, 4]复制代码

但是下面这个函数也可以实现矩阵乘法:

a = tf.random_uniform([10, 2, 3])b = tf.random_uniform([10, 3, 4])tf.matmul(a, b)  # c is a tensor of shape [10, 2, 4]复制代码

下面是我们之前在谈到的一个支持广播的添加操作的例子:

a = tf.constant([[1.], [2.]])b = tf.constant([1., 2.])c = a + b  # c is a tensor of shape [2, 2]复制代码

使用tf.assert * 操作验证您的张量

减少不必要行为可能性的一种方法是使用tf.assert *操作验证中间张量的秩(rank)或形状(shape)。

a = tf.constant([[1.], [2.]])b = tf.constant([1., 2.])check_a = tf.assert_rank(a, 1)  # This will raise an InvalidArgumentError exceptioncheck_b = tf.assert_rank(b, 1)with tf.control_dependencies([check_a, check_b]):    c = a + b  # c is a tensor of shape [2, 2]复制代码

请记住,断言节点和其他操作一样都属于TensorFlow中图(Graph)的一部分,如果不进行评估,则会在执行Session.run()期间进行剔除。因此,请确保为断言操作创建显式依赖项,以强制TensorFlow执行它们。

你还可以在运行时使用断言验证张量的值:

check_pos = tf.assert_positive(a)复制代码

有关断言操作的,请参阅官方文档。

使用tf.Print打印张量值

另一个对调试有帮助的内置函数是tf.Print,它可以将给定的张量记录到标准错误堆栈中:

input_copy = tf.Print(input, tensors_to_print_list)复制代码

注意一下,tf.Print函数将其第一个参数的副本作为返回值输出。一种让tf.Print强制运行的方式是将其输出传递给另一个操作去执行。例如,如果我们想在添加它们之前就打印张量a和b的值,我们可以这样做:

a = ...b = ...a = tf.Print(a, [a, b])c = a + b复制代码

或者,我们可以手动定义控件依赖项。

利用tf.compute_gradient_error检查梯度变化的值

并不是TensorFlow中的所有操作都有梯度变化,并且很容易在无意中构建出TensorFlow无法计算梯度变化的图。

让我们来看个例子:

import tensorflow as tfdef non_differentiable_softmax_entropy(logits):    probs = tf.nn.softmax(logits)    return tf.nn.softmax_cross_entropy_with_logits(labels=probs, logits=logits)w = tf.get_variable("w", shape=[5])y = -non_differentiable_softmax_entropy(w)opt = tf.train.AdamOptimizer()train_op = opt.minimize(y)sess = tf.Session()sess.run(tf.global_variables_initializer())for i in range(10000):    sess.run(train_op)print(sess.run(tf.nn.softmax(w)))复制代码

我们正在使用tf.nn.softmax_cross_entropy_with_logits定义一个分类分布上的熵。然后我们使用Adam优化器来找到具有最大熵的权重。如果你通过了信息论的课程,你就会知道均匀分布包含最大熵。所以你预计他的结果应该会是[0.2, 0.2, 0.2, 0.2, 0.2]。但是你执行这段代码的话会得到一个你意想不到的结果:

[ 0.34081486  0.24287023  0.23465775  0.08935683  0.09230034]复制代码

事实证明,tf.nn.softmax_cross_entropy_with_logits对标签有未定义的梯度变化!但是,如果我们不知道这个现象,我们又怎么能发现这个问题呢?

幸运的是,TensorFlow带有一个数值微分器,可用于查找符号梯度误差。让我们看看我们如何使用它:

with tf.Session():    diff = tf.test.compute_gradient_error(w, [5], y, [])    print(diff)复制代码

如果你运行它,你会发现数值和符号之间的差异非常大(我试了下大约为0.06 - 0.1)。

现在让我们更改下我们的函数并再次执行下:

import tensorflow as tfimport numpy as npdef softmax_entropy(logits, dim=-1):    plogp = tf.nn.softmax(logits, dim) * tf.nn.log_softmax(logits, dim)    return -tf.reduce_sum(plogp, dim)w = tf.get_variable("w", shape=[5])y = -softmax_entropy(w)print(w.get_shape())print(y.get_shape())with tf.Session() as sess:    diff = tf.test.compute_gradient_error(w, [5], y, [])    print(diff)复制代码

差异应该在0.0001左右,这个结果看起来好多了。

现在,如果再次使用正确的版本运行优化器,你可以看到最终权重为:

[ 0.2  0.2  0.2  0.2  0.2]复制代码

这就是我们想要的答案。

和是另外两个用于调试的工具,请参阅官方文档以了解更多信息。

转载地址:http://tzdox.baihongyu.com/

你可能感兴趣的文章
SpringBoot上传文件到本服务器 目录与jar包同级
查看>>
python开发_difflib字符串比较
查看>>
被解放的姜戈01 初试天涯
查看>>
三极管工作区在Spectre中的表示
查看>>
HT for Web的HTML5树组件延迟加载技术实现
查看>>
ASP.NET MVC 3 Razor Nested foreach with if statements
查看>>
【Mysql】命令行
查看>>
Asterisk 安装与配置
查看>>
利用日志记录所有LINQ的增,删,改解决方案
查看>>
实例讲解PostSharp(一)
查看>>
graylog 客户端的安装配置
查看>>
CentOS6.4_X86_64 安装Drupal-7.31必须成功版!
查看>>
驱动学习之驱动和应用的接口
查看>>
hbase region split源码分析
查看>>
MySQL备份之分库分表备份脚本
查看>>
Java 与 Netty 实现高性能高并发
查看>>
SurfControl人工智能新突破 领跑反垃圾邮件
查看>>
一个动态ACL的案例
查看>>
linux基础中的基础
查看>>
jquery 表单验证
查看>>