基于visual studio single step debug 如何单步调试TensorFlow源码

背景:

由于最近的几个项目中在使用TensorFlow,但是一直使用python API,使得写代码的过程渐渐的成为了“调包”的过程,程序员也渐渐成为了“调包侠”。

想深入学习TensorFlow,但是其源码比较大又太复杂,没有好的学习方法,没有好的师傅领进门,常常让人感觉到无从下手。

之前喜欢在IDE下调试源码,这样既能加深对代码的理解,又能提升学习的效率;一直喜欢侯捷那句“源码面前,了无秘密”。

我是老王,出于对技术的极致追求,使用TensorFlow的时候总想窥探其底层的秘密,所以耗费大量的精力开发出了适合学习TensorFlow的可调试工具。

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

学习的方式没有好坏之分,只有适合与不适合的方法。

关键词:TensorBoard 、可视化监督、tf.Print 、TensorFlow 、tfdbg

为什么需要调试

通过单步调试,查看堆栈信息和变量实时值,胜过任何资深讲师的讲解

Tensorflow的学习困惑:
虽然tensorflow是开源的
但是,学习tensorflow的方法只能是用各种源代码阅读工具(Source Insight)
进行源码级的阅读、理解、分析代码间的关系流程,
由于tensorflow是基于C++开发,各种模板(template)类(class)具有可继承性,
一个基类会派生出多个子类型,每个子类型才是真正要实现的功能,
这给学习人员带来了很大的挑战性;目前,网上提供的调试方法大致有:

1、使用 TensorBoard 可视化进行监督
2、使用 tf.Print 操作输出变量值
3、使用CLI TensorFlow 调试工具tfdbg
4、Other…..

把这些调试工具能运行起来,学习和使用这些调试工具都需要花费大量的时间,
本人(王工)在使用的时候也有“力不从心”的感觉。

	众所周知,在用C/C++语言编程这个领域,最优的开发调试环境IDE当属于Microsoft Visual Studio/ VC6.0工具

 

为学习而开发工具:

     为了从底层彻底掌握和使用tensorflow-r1.8-CPU(不支持GPU)这个项目

我本人(王工)经历了三个月的亲身学习和调试。

tensorflow-r1.8-CPU经过我编译之后,包含中间的临时文件,*.obj文件等,

占用了26G的硬盘空间,把这些代码*.h,*.cc文件进行编译并生成带有调试信息的*.lib,

共占用了11G的硬盘空间,下面是库 VS2019-tensorflow-r1.8-CPU-Debug 的截图:

 

 

工具包含内容:

1、VS2019-tensorflow-r1.8-CPU整个工程文件 

说明:

        此文件是基于vs2019编译出的带有Debug信息的TensorFlow可调试库。

意味着可以在windows平台下使用vs2019单步调试TensorFlow的源码。

 

单步调试概览:

 

2、调试样例

 

multibox_detector_test示例:

 /**********************************************************************

* * TensorFlow C++多盒对象检测演示

本演示基于 [使用深度神经网络进行扩展对象检测],,并使用该multibox_model.pb文件,检测图像中包含的对象:用于实时人员检测和跟踪相机预览。

*********************************************************************/

演示源图如下surfers.jpg:

经过示例的运行结果图:

输出信息:

========================wyx demo的调试输出=================

2020-09-16 15:20:52.399710:  Tensor<type: uint8 shape: [228,480,3] values: [[160 140 149]]...>

2020-09-16 15:20:52.412927:  ===== Top 5 Detections ======

2020-09-16 15:20:52.426605:  Detection 0: L:324.406 T:76.3239 R:373.032 B:214.923 (635) score: 0.239021

2020-09-16 15:20:52.444433:  Detection 1: L:332.595 T:76.064 R:372.239 B:204.336 (523) score: 0.237581

2020-09-16 15:20:52.470445:  Detection 2: L:143.498 T:86.0459 R:187.015 B:195.247 (387) score: 0.173919

2020-09-16 15:20:52.525309:  Detection 3: L:144.457 T:86.2542 R:185.335 B:165.518 (219) score: 0.1659

2020-09-16 15:20:52.568824:  Detection 4: L:306.302 T:76.0753 R:370.994 B:217.478 (634) score: 0.160769* ****************************/

 

load_pre_trained_recognize_objects_test示例:

/**********************************************************************

* tensorflow C++图像分类提取演示

此示例演示如何加载预先训练的 TensorFlow 网络并使用它

进行分类提取,以识别出图像是属于以下1000种对象中哪一种类型:

dummy

tench

goldfish

大白鲨

虎鲨

hammerhead

electric ray

stingray

cock

hen

ostrich

*********************************************************************/

输入图片文件: tensorflow_demo_release\label_image\data\grace_hopper.jpg

经过运算,输出分类的结果如下:

/******************************************************

    result:

    military uniform 0.834305

    mortarboard 0.0218694

    academic gown 0.0103581

    pickelhaube 0.00800818

    bulletproof vest 0.0053509

    军装 0.834305

        砂浆板 0.0218694

        学术礼服 0.0103581

        皮克尔豪贝 0.00800818

        防弹背心 0.0053509

******************************************************/

 

通过以上两个调试样例,你可以学习到detector和 recognize的更多细节,

从而进一步根据需求去修改它们

 

core_framework_all_test演示工程介绍:

      包含以下24个单个子示例,你可以单步调试,方便对单个模块进行深入理解,单步运行每个功能的细节.

 

transform_graph_test演示工程:

       包含以下25个单个子示例,你可以单步调试,方便对单个模块进行深入理解,单步运行每个功能的细节.

 

transform_graph_test测试案例功能简介

  • 1-1 .测试Conv2D操作的文件:fold_batch_norms_test.cc位于          transform_graph_test\transform_graph_test\test_cc\fold_batch_norms_test.cc
  • 1-2 TestFoldBatchNormsConv2D 该测试案例展示了手工建立一个op(操作)Conv2D的计算节点,
  • 手工将节点参数赋初值,然后调用root.ToGraphDef()函数
  • 将节点的网表转换成GraphDef类型,最后,根据转换后的网表建立一个session,
  • 并调用TF_ASSERT_OK(session->Run({}, {"output"}, {}, &original_outputs));执行运算.
  • 示例代码如下:
Tensor input_data(DT_FLOAT, TensorShape({1, 1, 6, 2}));
    test::FillValues<float>(&input_data, {1.0f, 4.0f, 2.0f, 5.0f, 3.0f, 6.0f, -1.0f, -4.0f, -2.0f, -5.0f, -3.0f, -6.0f});
    Output input_op =  Const(root.WithOpName("input_op"), Input::Initializer(input_data));
    Tensor weights_data(DT_FLOAT, TensorShape({1, 2, 2, 2}));
    test::FillValues<float>(&weights_data,{1.0f, 2.0f, 3.0f, 4.0f, 0.1f, 0.2f, 0.3f, 0.4f});
    Output weights_op =Const(root.WithOpName("weights_op"), Input::Initializer(weights_data));
    Output conv_op = Conv2D(root.WithOpName("conv_op"), input_op, weights_op,{1, 1, 1, 1}, "VALID");
    Tensor mul_values_data(DT_FLOAT, TensorShape({2}));
    test::FillValues<float>(&mul_values_data, {2.0f, 3.0f});
    Output mul_values_op = Const(root.WithOpName("mul_values"),Input::Initializer(mul_values_data));
    Output mul_op = Mul(root.WithOpName("output"), conv_op, mul_values_op);

    GraphDef original_graph_def;
    TF_ASSERT_OK(root.ToGraphDef(&original_graph_def));

    std::unique_ptr<Session> original_session(NewSession(SessionOptions()));
    TF_ASSERT_OK(original_session->Create(original_graph_def));
    std::vector<Tensor> original_outputs;
    TF_ASSERT_OK(original_session->Run({}, {"output"}, {}, &original_outputs));transform_graph_test.cc

调试的跟踪:

调试图1:

调试图2:

查看变量versions的当前值

调试图3:

查看op_def变量的当前值

调试图4:

查看DeviceMgr->devices变量的当前值

调试图5:

查看director_session->client_graph变量的当前值

调试图6:

查看真正执行DeepConv2D()函数调试及堆栈变量的查看图:

调试图_7

transform_graph_test.png,用函数ReadTextProto()

读取一个*.pbtxt模型文件

然后解析成GraphDef类型的调试及内部变量和堆栈的查看.

最后,工程演示就先介绍到此,其它的演示就不再一一赘述了。

上述调试可以带你,洞悉每个step运行的变量值,跟踪函数的执行变量值。


如何获取此工具:

百度下载链接:链接:https://pan.baidu.com/s/1HkSznXLps30ymes6OzHWOQ 
提取码:1234

作者:王工,联系方式:
电话:13510160446,微信同号(时间:周一到周六,9:00~17:00)

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值