抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

问题

使用 pytracking 框架的跟踪器, 在训练时控制台无报错, 但也没有任何反应. 强行停止后发现卡在 ltr_trainer.pyenumerate 处, 疑似死循环.

问题处

调试

请按照教程自行调试, 不要直接照我的改.

准备

在调试前, 请确保你是直接运行 project/lib/train/run_training.py 文件, 而不是 project/tracking/train.py. 否则你将无法调试, 你应该在 train.py 里打印出命令行语句, 然后添加到 PyCharm 的运行配置里.

train.py

按照上图打印出运行指令, 修改后的配置如下:

运行配置

复现

CV库会使用多线程来加载图片, 不利于调试, 在 project/experiments 文件夹里修改跟踪器配置文件, 将 NUM_WORKER 改为 0. 注意是你运行的那个配置, 不要改错了.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
TRAIN:
BACKBONE_MULTIPLIER: 0.1
DROP_PATH_RATE: 0.1
BATCH_SIZE: 1
EPOCH: 240
GIOU_WEIGHT: 2.0
L1_WEIGHT: 0.0
GRAD_CLIP_NORM: 0.1
LR: 0.00008
LR_DROP_EPOCH: 192
NUM_WORKER: 0 # 在这里
OPTIMIZER: ADAMW
PRINT_INTERVAL: 10
SCHEDULER:
TYPE: step
DECAY_RATE: 0.1
VAL_EPOCH_INTERVAL: 20
WEIGHT_DECAY: 0.0001
AMP: False

然后运行代码, 等一会儿, 当控制台没有输出后, 直接强制停止. 此时应该已经卡在死循环内. 你会看到控制台有 KeyboardInterrupt 报错,然后顺着这个报错去找死循环位置.

定位死循环

你会在控制台看到以下报错:

报错

点击最底下的, 且位于项目目录内的报错行. 我的报错最后一项恰好在项目目录内, 你的可能不是, 如 site-packages 是库文件, 请直接跳过. 点击后会直接跳转到中断处, 为这一行打断点, 点击左侧的行号即可.

断点

接下来调试运行, 程序暂停在断点处. 如果你的程序没有暂停, 说明你运行的是 project/tracking/train.py, 请查看 准备 一节.

正常情况如下图所示.

程序中断

可以看到现在调用的是 _read_target_visible() 函数, 左下角是调用栈, 可以查看当前线程和变量, 也可以切换到控制台. 多次点击右上角的 “恢复” 按钮(红圈里的), 然后切换到控制台选项卡, 如果每次都在这里中断, 没有进入死循环, 并且控制台没有输出, 说明当前断点位置就在死循环里.

但是这个函数里并没有 while 出现, 说明死循环在外部. 现在转到图片左下角调用栈, 按照从上往下的顺序逐个查看代码. 你只需要查看项目代码, 库文件已经自动变灰, 不用查看.

我在查看到第 3 层时, 发现 while 循环.

第1个while循环

为了判断此处是否是死循环, 我们取消之前的断点, 在此处重新打一个断点, 然后单步运行(F8). 我们发现程序可以正常离开循环, 说明此处不是死循环.

第1个while循环

于是我们在左下角继续查找, 发现第 4 层也是 while 循环. 同理, 我们取消掉之前的断点, 在这一层打一个新断点, 然后单步运行(F8).

第2个while循环

此时我们发现程序无法离开循环, 并且执行到了 except 语句, 说明此处是死循环.

第2个while循环

解决问题

我们发现此处使用了 except 语句, 这会导致控制台没有报错. 现在我们要查看具体的报错, 直接在这里打印即可.

1
2
3
4
5
6
7
import traceback

...
except Exception as ex:
traceback.print_exc()
valid = False
...

打印栈信息

再次运行(现在不用调试了), 控制台会打印出一堆报错. 由于是死循环, 报错会重复打印.

报错

定位至报错点, 打上断点, 进行调试.

定位报错点

现在只需要按照正常流程解决 bug 即可.

解决bug

分析可知此处使用 / 来分割字符串, 但字符串里实际上反斜杠 \, 因此出错, 只需要将代码修改为反斜杠即可解决.

评论