【译】Effective TensorFlow Chapter11——在TensorFlow中调试模型

栏目: 数据库 · 发布时间: 6年前

内容简介:本文翻译自:与常规python代码相比,TensorFlow的符号特性使的TensorFlow的代码调试变得相对困难。这里我介绍一些TensorFlow附带的工具,使调试更容易。使用TensorFlow时最常见的错误可能是传递形状错误的张量。许多TensorFlow操作可以在不同秩(rank)和形状(shape)的张量上操作。这在使用API时很方便,但在出现问题时可能会导致额外的麻烦。
【译】Effective TensorFlow Chapter11——在TensorFlow中调试模型

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

与常规 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 exception
check_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 tf

def 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 tf
import numpy as np

def 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]

复制代码

这就是我们想要的答案。

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


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Introduction to Programming in Java

Introduction to Programming in Java

Robert Sedgewick、Kevin Wayne / Addison-Wesley / 2007-7-27 / USD 89.00

By emphasizing the application of computer programming not only in success stories in the software industry but also in familiar scenarios in physical and biological science, engineering, and appli......一起来看看 《Introduction to Programming in Java》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具