点击上方“小白学视觉”,选择加"星标"或“置顶

重磅干货,第一时间送达

导读

TensorFlow代码很难调试,这个大家已达成共识,不过,就算是难,也还是需要调试的,毕竟谁也没有把握不出bug,看看这篇文章能不能让你减轻一点调试时的痛苦。

当讨论在tensorflow上编写代码时,总是将其与PyTorch进行比较,讨论框架有多复杂,以及为什么要使用tf.contrib的某些部分,做得太烂了。此外,我认识很多数据科学家,他们只用Github上已有的repo来用tensorflow。对这个框架持这种态度的原因是非常不同的,但是今天让我们关注更实际的问题:调试用tensorflow编写的代码并理解它的主要特性。

核心抽象

  • 计算图。第一个抽象是计算图tf.Graph,它使框架能够处理惰性评估模式(不是立即执行,这是“传统”命令式Python编程实现的)。基本上,这种方法允许程序员创建tf.Tensor(边)和tf.Operation (节点),它不是立即计算的,而是在执行图形时才计算的。这种构造机器学习模型的方法在许多框架中都很常见(例如,在Apache Spark中使用了类似的思想),并且具有不同的优缺点,这在编写和运行代码时表现得非常明显。最主要和最重要的优点是,数据流图可以很容易地实现并行性和分布式执行,而无需显式地使用multiprocessing 模块。在实践中,编写良好的tensorflow模型在启动时立即使用所有核心的资源,而不需要任何额外的配置。

    然而,这个工作流的一个非常明显的缺点是,一旦你构建图的时候,没有用提供的输入来运行,你就不能确保它不会崩溃。它肯定会崩溃。此外,除非你已经执行了图形,否则你无法估计它的运行时间。

    计算图的主要组成部分是图集合和图结构。严格地说,图的结构是前面讨论的特定的节点集和边集,而图集合是可以逻辑地分组的变量集。例如,检索图形的可训练变量的常用方法是'tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES)

  • 会话 。第二个抽象与第一个抽象高度相关,并且有更复杂的解释:tensorflow会话的tf.Session用于客户端程序和c++运行时之间的连接(如你所知,tensorflow是用c++编写的)。为什么是c++ ?答案是,通过这种语言实现的数学运算可以得到很好的优化,因此,计算图运算可以得到很好的处理。

    如果你正在使用低级的tensorflow API(大多数Python开发人员都在使用),则tensorflow session将作为上下文管理器调用:with tf.Session() as sess:。没有参数传递给构造函数(如前一个示例)的会话仅使用本地机器的资源和默认的tensorflow图,但它也可以通过分布式tensorflow运行时访问远程设备。在实践中,如果没有会话,计算图就不能存在(没有会话,它就不能执行),而会话总是有一个指向全局图的指针。

    深入研究运行会话的细节,值得注意的主要一点是它的语法:tf.Session.run()。它可以作为张量、操作或类张量对象的参数获取(或获取列表)。另外,可以传递feed_dict(这个可选参数是tf.placeholder的对象及其值)以及一组选项。

实验中一些可能的问题以及可能的解决方案

  1. 会话加载并通过预先训练的模型进行预测。这就是瓶颈,我花了几周的时间来理解、调试和修复它。我想高度关注这个问题,并描述两种重新加载预训练模型(图和会话)并使用它的可能技术。

    首先,当我们谈论加载模型时,我们真正的意思是什么?当然,为了做到这一点,我们需要事先训练并保存它。后者通常是通过tf.train.Saver.save完成的。因此,我们有3个二进制文件.index.meta.data-00000-of-00001,其中包含恢复会话和图所需的所有数据。

    要加载以这种方式保存的模型,需要通过tf.train.import_meta_graph() (参数是.meta的文件)来恢复。按照前一段描述的步骤之后,所有变量(包括所谓的“隐藏”变量,稍后将讨论)都将被移植到当前图中。检索某个有自己名字的张量(记住,它可能不同于你初始化它时使用的张量,这取决于创建张量的范围和操作的结果)应该执行graph.get_tensor_by_name()。这是第一种方法。

    第二种方法更显式,也更难实现(对于我一直在使用的模型的架构,我还没有成功用起来),它的主要思想是将图的边(张量)显式地保存到.npy.npz文件中,然后将它们加载回图中(并根据创建它们的范围分配适当的名称)。这种方法的问题在于它有两个巨大的缺点:首先,当模型架构变得非常复杂时,它也变得很难控制和保存所有的权重矩阵。其次,有一种“隐藏的”张量,它是在没有显式初始化的情况下创建的。例如,当你创建 tf.nn.rnn_cell.BasicLSTMCell时。它创建了所有需要的权值和偏差来实现LSTM cell。变量名也是自动分配的。

    这种行为看起来还可以,但实际上,在很多情况下,并不是很好用。这种方法的主要问题是,当你查看图的集合时,看到一堆变量,你不知道它们的来源,你实际上不知道应该保存什么以及在哪里加载它们。坦率地说,很难将隐藏变量放到图中正确的位置并适当地操作它们。

  2. 在没有任何警告的情况下两次创建同名张量(通过自动添加_index结尾)。我认为这个问题不像前一个问题那么重要,但是这个问题确实困扰着我,因为它会导致很多图执行错误。为了更好地解释这个问题,我们来看一下这个例子。

    例如,你用tf.get_variable(name=’char_embeddings’, dtype=…)来创建张量。然后保存它并在新会话中加载。你已经忘记了这个变量是可训练的,并通过tf.get_variable()以相同的方式再次创建了它。在图执行过程中,会发生的这样的错误:FailedPreconditionError (see above for traceback): Attempting to use uninitialized value char_embeddings_2。原因是,你已经创建了一个空变量,但是并没有将它放到模型的适当的位置,而实际上只要它已经包含在计算图中,就可以放到模型的某个地方。

    正如你所看到的,由于开发人员创建了同名张量两次(甚至Windows也会这样做),所以没有出现错误或警告。也许这一点只对我很重要,但这是tensorflow的特性,我并不喜欢它的这个行为。

  3. 在编写单元测试和其他问题时手动重置图。由于许多原因,测试用tensorflow编写的代码总是很困难。第一个— 也是最明显的一个,已经在这一段的开头提到过了,可能听起来很傻,但对我来说,让人很恼火。由于在运行期间访问的所有模块的所有张量只有一个默认的tensorflow图,因此不可能在不重置这个图的情况下,使用不同的参数(例如)测试相同的功能。它只是一行代码tf.reset_default_graph(),但是知道它应该写在大多数方法的顶部,这个解决方案就变成了某种恶作剧,当然,一个明显的代码复制示例。我还没有发现任何可能的方法处理这个问题(除了使用reuse参数,我们将在后面讨论),只要所有的张量与默认图并没有办法隔离(当然,可以有一个单独的tensorflow图方法,但在我看来这不是最佳实践)。

    为tensorflow写单元测试的代码也困扰我很多的事情,在这种情况下,计算图的一部分是不应该被执行的(里面有张量未初始化,因为模型没有训练)。但是,计算图本身并不知道我们应该测试什么。我的意思是 self.assertEqual()的参数不清楚(我们应该测试输出张量的名称或它们的形状吗?如果形状为None呢?如果张量的名字或形状不足以得出这个结论,那该怎么办?)。在我的例子中,我只是简单地断言张量的名称、形状和维数,但是我确信,在不执行图的情况下,只检查这部分功能是不合理的。

  4. 混淆张量的名字。很多人会说这个关于tensorflow的评论是一种另外的抱怨方式,但是我们并不能说出来在做了某种运算之后得到的张量的名字是什么。我的意思是,名称bidirectional_rnn/bw/bw/while/Exit_4:0清楚吗?对我来说,绝对不清楚。我得到这个张量是对动态双向RNN的后向单元进行某种操作的结果,但是如果没有显式地调试代码,就无法知道执行了哪些操作以及操作的顺序。另外,索引的结尾也不太好理解,只要你想知道数字4是从哪里来的,就需要阅读tensorflow文档并深入研究计算图。

    前面讨论的“隐藏”变量的情况也是一样的:为什么这里有biaskernel名称?也许这是我的水平不够,但是这样的调试案例对我来说很不自然。

  5. tf.AUTO_REUSE,可训练的变量,重新编译的库和其他的东西。这个列表的最后,我们看一些小的细节,这些细节只有在错误中才能学习到。第一件事是reuse=tf.AUTO_REUSE参数的作用域,它允许自动处理已经创建的变量,如果它们已经存在,就不会创建两次。事实上,在许多情况下,它可以解决本段第二点所述的问题。但是,在实践中,这个参数应该谨慎使用,并且只有在开发人员知道代码的某些部分需要运行两次或多次时才使用。

    第二点是可训练变量,这里最重要的一点是:所有的张量在默认情况下都是可训练的。有时这可能是一个头痛的行为,因为有时候我们并不想要所有的张量都可训练,但是又很容易忘记,他们是都可以训练的。

    第三件事只是一个优化技巧,我建议每个人都这么做:几乎在所有情况下,当你使用通过pip安装的包时,你都会收到这样的警告:Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX AVX2。如果你看到这类消息,最好卸载tensorflow,然后使用你喜欢的选项通过bazel重新编译它。这样做的主要好处是计算速度的提高和更好的总体性能。

总结

我希望这篇文章能够对那些正在开发他们的第一个tensorflow模型的数据科学家有所帮助,他们正在努力解决框架中某些部分的不明显的行为,这些行为很难理解,而且调试起来相当复杂。要点我想说的是,使用这个库工作的时候,犯一些错误也不是坏事(对于其他的事情也是一样的),这可以让我们多问些问题,深入查看文档和调试每一行代码,这样也是很好的。

就像跳舞或游泳一样,任何事情都需要练习,我希望我能让这种练习变得更愉快和有趣。

下载1:OpenCV-Contrib扩展模块中文版教程

在「小白学视觉」公众号后台回复:扩展模块中文教程即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。

下载2:Python视觉实战项目52讲

在「小白学视觉」公众号后台回复:Python视觉实战项目即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。

下载3:OpenCV实战项目20讲

在「小白学视觉」公众号后台回复:OpenCV实战项目20讲即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。

交流群

欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~

正确debug的TensorFlow的姿势相关推荐

  1. 我的AI之路(5)--如何选择和正确安装跟Tensorflow版本对应的CUDA和cuDNN版本

    最新的Tensorflow和CUDA cuDNN的对应关系可以从这里找到: https://tensorflow.google.cn/install/source https://tensorflow ...

  2. 计算机正确的坐姿教案,《正确的坐立走姿势》教学设计

    <正确的坐立走姿势>教学设计 一.教学目标 知识与技能:知道坐立走的姿势可以表现出人的精神面貌,正确的姿势有利于健康. 行为与习惯:生活中站有站相.坐有坐相,养成良好的习惯. 情感与态度: ...

  3. 怎么正确使用电动升降桌调节姿势

    已经有越来越多的人会因为长时间地久坐办公以及没有得到合理地调节,从而导致腰椎.脊椎.眼睛等身体部位出现伤痛问题.所以,市面上站立交替式地电动升降桌成为了许多人在选择办公桌时的首要考虑产品,人性化地设计 ...

  4. 如何同时GET√5斤网易味央猪肉和正确的APP IM开发姿势?

    年底了 ... CTO 产品Wong 程序猿 ... 过冬的食物屯了没? 还在发愁找不到 实用有逼格的礼物 送亲友? 号称没吃过猪肉还没见过猪跑的你 尝过网易味央猪肉的味道不? 那可是 猪肉中的爱马仕 ...

  5. 360安全卫士电脑版_教你降服“流氓头子”正确打开360安全卫士的姿势,还你电脑流畅体验...

    最近老哥家的电脑经常出问题 原因是熊孩子玩儿完电脑,最后总是一堆莫名其妙的流氓软件占据桌面的半壁江山 然后恢复电脑流畅运行的任务,就交到我这个"懂电脑"的人手里. 如此反复两次,脾 ...

  6. 第1期-软件测试-简历-正确编写测试简历的姿势

    大家好,今天我们这期来讲,如何写一份合格的测试简历(上). 在这期我会说一下,编写简历的原则和技巧:简历是面试第一道关卡,因为hr每天会收到很多简历,那么hr就会快速的审阅每份简历,只有你的简历中亮点 ...

  7. 从 Android 静音看正确的查bug的姿势?

    0.写在前面 没抢到小马哥的红包,无心回家了,回公司写篇文章安慰下自己TT..话说年关难过,bug多多,时间久了难免头昏脑热,不辨朝暮,难识乾坤...艾玛,扯远了,话说谁没踩过坑,可视大家都是如何从坑 ...

  8. 从 Android 静音看正确的查找 bug 的姿势

    0.写在前面 没抢到小马哥的红包,无心回家了,回公司写篇文章安慰下自己TT..话说年关难过,bug多多,时间久了难免头昏脑热,不辨朝暮,难识乾坤...艾玛,扯远了,话说谁没踩过坑,可视大家都是如何从坑 ...

  9. 正确的LeetCode刷题姿势!

    名师 带你刷爆LeetCode 算法知识 讲解+训练 免费0元报名参加 在讲到 AI 算法工程师时,大部分同学关注点都在高大上的模型,一线优秀的项目.但大家往往忽略了一点,人工智能的模型.项目最终还是 ...

最新文章

  1. Centos7.2部署各类服务
  2. python写扫雷脚本_Python自动扫雷实现方法
  3. 硒品牌谋定功能性农业-农业大健康·万祥军:践行健康中国
  4. JZOJ 100035. 【NOIP2017提高A组模拟7.10】区间
  5. [css] ui设计中px、pt、ppi、dpi、dp、sp之间的关系?
  6. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(二)让物体动起来②
  7. 基于JAVA+SpringBoot+Vue+Mybatis+MYSQL的微信小程序便利店购物系统
  8. docker-maven-plugin 推送镜像到 docker-hub
  9. Retrofit使用教程(一)- Retrofit入门详解
  10. [微信小程序]搜索功能实现,搜索框样式
  11. word 添加手写签名
  12. 最大公约数,最小公倍数的求法
  13. 安卓AndroidStudio设计计算器实现简单的计算
  14. 手机话费充值和手机流量充值 API
  15. 【PyG 教程】PyG 自定义构造 GNN
  16. 正则表达式提取字符串全部汉字或者全部英文
  17. 天才小毒妃 第842章 真真是够了
  18. ZYNQ图像处理(4)——灰度图像转二值化图像
  19. python文件开头第一行设置utf-8编码
  20. Java实现比赛打分,去掉最小值及最大值,求平均值

热门文章

  1. 如何用Python实现超级玛丽的界面和状态机?
  2. 宝宝都能看懂的机器学习世界
  3. 两亿多用户,六大业务场景,知乎AI用户模型服务性能如何优化?
  4. NIPS | 谷歌AI大军来袭,看450多名员工如何横扫今年大会
  5. 一文讲述如何将预测范式引入到机器学习模型中
  6. Java高并发之设计模式,设计思想
  7. 用漫画了解 Linux 内核到底长啥样!
  8. 一图胜千言!数据可视化多维讲解
  9. 一份超详细的数据科学路线图!
  10. 深度学习之Pytorch基础教程!