Boxx:一个旨在提升 Python 代码开发和调试效率的工具库,尤为在计算机视觉领域

介绍一个Python 工具包 boxxhtml

在调试视觉代码时, 基本就是和多维数组打交道, 多维数组有不少的属性,打印起来比较麻烦。 boxx.loga 能够一次性展示出一个数组的大多数属性.
python

💡 Note:git

  • loga 是 "log array" 的缩写, 若 array 里面还含有 naninf, loga 也会一并提示出来。
  • loga 支持许多能够转为 numpy 的数据类型,包括 torch.tensor, mxnet.ndarray, PIL.Image 等。

作计算机视觉,可视化图像和 feature 很是重要。boxx.show 能方便地作可视化。
github


💡 Note: show 会在复杂的数据结构中 找出全部多是图像的矩阵,并一一显示( plt.imshow)出来。 固然, show 也支持 numpytorchmxnetPIL.Image .etc

在开发 CV 代码时,会遇到一些复杂的 dict,list(好比 batch、模型参数)。boxx.tree 能够直观地展现复杂结构。
编程

💡 Note: 在理解和适配别人的代码时,常常用到 treetree 还支持自动从 torch.Dataloader/Dataset 中 sample 一个 batch 来可视化 (P.S. boxx.show 也支持)数组


以上三个工具是我在视觉领域常常用到的工具, 接下来介绍一些通用的 Python 开发调试工具,只要写 Python 代码,均可以用上。浏览器

打印变量是最简单、直接的debug方式, 那能不能更简单?
服务器

💡 Note: boxx.p 使用了 magic method, p/x 便会打印 x 并返回 x。这样即可以在任何地方打印,好比 例子中的 p/randint(0, 3) 就不须要新建变量即可直接打印网络

在函数内运行 p(),便会将函数或 module 内的全部变量名和值一同打印(至关于快捷打印 locals())
数据结构

💡 Note: 在函数内 import boxx.pp() 有相同的效果

许多数状况下, 直接 print 没法得到调试的关键信息。 好比训练 loss 跑飞了, 致使 Bug 的多是 tensor 的尺度/类型不对, 矩阵里有 nan , inf 等状况。我曾遇到过 梯度含有nan 的状况

这时 就必须对矩阵进行分析, 方式有:

  1. 在调试处加上 print(x.mean(), np.hasinf(x),.np.hasnan(x))
  2. 设置断点进行分析

方法1 每改一次调试代码 都要运行整个代码, 不灵活,操做也繁琐。
方法2 中进入和退出 Debug console 比较麻烦,Debug console 自己也不太好用(没有自动补全功能)
boxx.g 提供了一种新的方式,经过 g.name 能够将变量传到当前的 Python 交互终端

变量传到 Python 终端后,就能对变量进行全面分析了,好比 使用 logatree 来分析

💡 Note:

  • gg 的意思是 to Global and log, 和 g 的用法同样, 但 gg 会在传输的同时打印变量.
  • 须要注意, 若是以前在终端中存在同样的变量名称,则变量的值会被新值覆盖.

在函数内运行 g(),便会将函数 (或 module) 内的全部变量一同传到当前的 Python 交互终端

这样 任何错误均可以在终端中复现和分析了。固然, 注意不要覆盖重要的全局变量。

💡 Note: 在函数内 import boxx.gg() 有相同的效果

在实际开发调试中, 函数或 module 内可能含有很是多的变量 但咱们只对几个变量感兴趣, with p, with g, with gg 可使操做只做用于几个感兴趣的变量,只需把变量放入 with 结构中便可 :


💡 Note:

  • with p, with g, with gg 只做用于在 with 结构中进行赋值操做的变量.
  • 若是变量名在 with 前存在于 locals() 中, 同时 id(变量) 没有变化 , with 结构可能没法检测到该变量.

总结一下,boxx 的调试工具能够汇总为一个表

boxx 调试工具矩阵

变量个数 \ 操做 print transport print & transport
单变量 p/x g.name/x gg.name/x
多变量 with p: with g: with gg:
locals() p() g() gg()
locals()_2 import boxx.p import boxx.g import boxx.gg

💡 Note:

  • transport 操做是指 把函数内的变量传送到 Python interactive console 中
  • locals() 指 做用于函数或 module 内的全部变量
  • locals()_2: 当 boxx 未导入时, import boxx.{操做} 能等价于 from boxx import {操做};{操做}()

在学习新框架或适配大佬代码时,常常会使用 print(x), dir(x), help(x), type(x) 来了解某个变量的各方面的信息 (变量多是 值/function/class/module 等),因而我写了一个 boox.what(x) 来全面了解"what is x?":


💡 Note: what(x) 经过打印 x 本身及 x文档, 父类继承关系, 内部结构全部属性 来全面了解 x. 是 help(x) 的补充.


说了这么多调试 再说一下性能调优

测试代码性能时,计时很经常使用, 我写了一个方便的计时工具boxx.timeit 将想要计时的代码块放入 with timeit(): 中就能够计时了:

此外 SnakeViz 是一个很棒的性能分析工具,SnakeViz 可以经过 cProfile 文件,来统计代码的函数调用状况,并可视化出代码的 火焰图。可是, 先生成 cProfile 文件,再运行 SnakeViz 的流程很是繁琐,我把这一套操做封装成了 boxx.performance 来简化流程:

💡 Note: performance 也支持字符串形式的 Python 代码.

现在的数据集都数百上千 GB,在数据清洗和预处理时 要写多进程的 Python 代码 来榨干 CPU 的每个线程得到加速。但我以为 Python 多进程的几个范式都不够方便,我参照 map 的思想和用法把多进程操做封装成 boxx.mapmp 函数(意思是"Map for Mulit Processing"). mapmpmap 有同样的用法, 只需把 map 替换为 mapmp 便可得到多进程加速:


💡 Note:

  • mapmppool 参数来控制进程数目,默认为 CPU 线程数目.
  • 在多进程程序中, 打印进度每每很是麻烦. mapmpprintfreq 参数能解决这个问题.
  • 如同 map 同样,mapmp 支持将多个参数输入函数,如mapmp(add, list_1, list_2)
  • 在 Python 中,多进程代码最好在 __name__ == '__main__' 环境中运行.
  • 若是加速 numpy 程序,请注意 在 MKL 版本的 numpy 中,多进程会更慢, 能够运行 boxx.testNumpyMultiprocessing() 来测试当前环境对多进程 numpy 的友好程度

当要下载 url 形式的数据集或网络爬取图片时,多线程编程对这类高IO操做会颇有用。boxx 还有个多线程版本的 map -- mapmt (意思是 "Map for Mulit Threading")。mapmt 用法和 mapmp 同样, 但没有多进程的诸多限制。


再分享一下我本身在写视觉代码的感觉吧

因为我本身

  1. 写 CV 代码离不开强大的 Qt console for IPython
  2. 受不了远程编辑对网络的依赖和延迟

因此 一直用 Anaconda 自带的 Spyder 做为 Python 开发的 IDE. Spyder 虽然不够强大,但自带的 Qt-IPython, 配合本身写的工具,调试起来仍是比较方便, 顺手。因此, 我开发的工具都尽量地直接, 简洁,上面介绍的大部分工具都支持 func-x 来代替 func(x) 以方便调试时调用。甚至,我还写了一些字符串处理工具,直接在IPython 内使用, 以弥补 Spyder 做为 IDE 的不足。

此外,个人工做流通常是 先在本地开发调试, 用 boxx.sysi 检测运行环境来自动切换运行参数, 本地开发调试 OK 了, 用 rsync 命令 只传改过的 .py 文件到服务器 再来 train。虽然这样传代码比较麻烦, 但开发, 调试起来会方便不少。

以前在实验室一直是本地 GPU 环境调试 比较方便。实习后, 旷厂不提供本地 GPU。我主力是 PyTorch, 为了方便调试 我写了个 boxx.ylth 包,若是检测到没有 CUDA 环境,boxx.ylth 会强行使 .cuda() 和大部分 GPU 操做无效。只要在代码开头 import boxx.ylth 大多数只基于 GPU 的 torch 代码, 能够不经更改 直接在 CPU 上运行和调试。(这操做太暴力 请慎用)


GitHub 主页:github.com/DIYer22/box…

安装:pip install git+https://github.com/DIYer22/boxx (其余安装方法及说明)

教程:boxx 的教程是一个可执行的在线 Notebook。 也就是说,无需下载和运行任何代码,只需浏览器点击下面的连接,就能够在线执行 Notebook 教程中的代码块。
=> 可直接执行的在线教程

最后 特别感谢徐晓栋、吴国栋、范浩强和熊鹏飞对 boxx 提出的建议。

相关文章
相关标签/搜索