程序错误定位
如果报出exception,寻找输出在最下方且是自己项目内的错误位置
比如这里我们看最下面的的一个NullPointerException,标蓝文件定位说明该错误出自我们自己的项目代码,点他定位错误
![在这里插入图片描述](https://img-blog.csdnimg.cn/022d6b8b55ca47c69da8846fd9591e11.png
他提示我自己项目内的类jdbcutils中出现了空指针异常
发现ips为空指针,因为没有将配置文件放在src下,导致配置找不到,所以为null,至此问题就解决了。
之所以为什么是找最下方的,因为在程序堆栈中报错都是从下向上报错,从控制台输出的越靠后,说明在程序堆栈越底部,说明越接近错误真实发生的地方
jupyter note book vscode 版提供了强大的调试功能,分为逐行调试和cell debug
本文章借鉴了https://blog.csdn.net/Nie_Quanxin/article/details/124239699,感谢这位仁兄的分享。
首先升级ipykernel,确保版本不低于6,这个基本每个环境新安装时都要先安装ipykernel,与pip更新一样为每个新建虚拟环境的必做选项。
pip install --upgrade ipykernel
逐行调试,左一,就是断点调试的简化版本,对cell中每一行进行调试
cell断点调试
cell断点调试功能非常强大,除了本cell的可以调试,还能进入其他cell的函数,或其他的py文件。
查看某个变量的值可以使用printf,或将其定义为变量
p1=np.sum(y)/m
鼠标放在变量上也能查看值,外带额外的信息
变量列表
断点调试按钮功能
1.继续按钮:程序快速跳转到下一个断点的位置
2.单步跳过按钮:执行一条语句,如果执行的语句是自定义的函数则直接得出结果,不进入函数(函数是自定义的函数才能进入)
3.单步调试,就是执行一条语句,相比于2不同在于如果该语句执行了函数则会进入函数,调到函数的代码进行一行行地执行。
4.单步跳出:如果在函数中就跳出当前函数,执行完在函数中当前语句后面的所有代码,如果在全局就跳出当前的cell,执行完在cell内在该语句后面的所有代码。
5.重启:重新从头进行调试
6.断开:停止调试
经常会出现的bug
1.在跨cell调试的时候会出现跳入函数时会报错
无法加载源“c:\Users\xx\AppData\Local\Temp\ipykernel_9776\3566846540.py”: source unavailable。
这是因为修改了函数的代码,但是没有重新运行该函数所在的单元导致的错误,正确的方法是要每次修改函数后都应该重新运行该函数所在的单元,这是使用jupyter的一个良好的习惯,每次修改一个cell的代码都要重新执行该cell。
2.调试小箭头消失
这个重启内核就好了
vscode编辑实用快捷键
参考vscode实用快捷键
实用快捷键
快捷键实战(可不看)
- 将class定义如class PartNormalDataset(Dataset):去掉
- ctrl + D实现批量修改,将函数引入的变量全变为全局,ctrl + F里面的局部替换查找在jupyter notebook里不起作用,相当于局部查找操作
源:
def __init__(self,root = './data/shapenetcore_partanno_segmentation_benchmark_v0_normal', npoints=2500, split='train', class_choice=None, normal_channel=False):
修改后
3.使用⇧ shift + ⌃ ctrl + L,将所有self.删去
这个就是cell内全局查找的操作,删除任何位置匹配的,包括注释的,函数内的
4.注:实用快捷键F2,可以修改所有引用位置相同,且名字相同的位置
a=[]
a3=a
a=a
def f():
a=1
修改外面的a话只有函数外的且叫a的能被修改
a1=[]
a3=a1
a1=a1
def f():
a=1
vscode自带的调试功能
1.四个额外的调试选项
可以通过右击来得到
1.单步执行目标:
目前没有发现和上面按钮“继续”有什么区别。
2.跳转到光标处
可以直接跳转到该地点,向前跳转则是直接跳过去,放弃执行中间的所有代码。向后跳转并不会时光回溯,已经做过的操作和得到的变量也不会因为跳到前面的代码而撤销,所有结果都会保留下来。
3.跳转到光标:加强版的断点等于是,只能向前跳,相对于2的向前跳不同的是他会做完中间的代码。
4.内联断点:仅当执行到达与内联断点关联的列时,才会命中内联断点。这在调试在一行中包含多个语句的缩小代码时特别有用。比如for循环,短路运算符等一行代码包含多个表达式时会特别有用。比如下面的例子:
2.添加高级断点
高级断点
可以在某个条件达到时,或某条指令执行到一定次数引起中断,也可以在debug这条指令时输出日志,对于条件循环中非常好用
3.调试控制台
可以在这里在调试中查看所有的变量,也可以更改变量的值之类的,非常的万能,尤其是在封装非常好的代码中查看变量很方便,并且是根据当前debug作用域在动态变化的,不会查看到作用域之外或已被释放的变量,搜寻变量的规则与正常程序是一致的。
深度学习调试的两种方式
1.py 文件debug调试
优点:可以使用跳转到光标,ipynb文件则不行,跳转到光标可以实现代码的回退,如果使用得当
有时ipynb会报显存不足,在py则没有这个
缺点:如果修改代码,要重新执行上面所有操作,上面有比较耗时的操作就很麻烦
2.ipynb文件debug调试
优点:随时查看,随时调试
缺点:对封装性强的比如函数,类调试没有优势
麻烦,最终还要导出py文件作为模块
最后综上还是选择py 文件debug调试比较好,有耗时操作比如训练可以将其注释掉,然后执行其他代码也不影响使用
代码复现标准
**1.dataset:**最后输出的值要是符合要求的
**2.网络:**使用torchinfo要和源代码有相同的info
3.训练:
如果有源码
SEED = 0
torch.manual_seed(SEED)
torch.cuda.manual_seed(SEED)
np.random.seed(SEED)
1.可使用随机种子来使结果可以复现
2.调试看看各个参数结果正不正常
3.指标是否合理,比如某些ious为0,非常低,我要看看是否是合理的,经验证是合理的,说明程序没问题
4.直接看训练几轮看看正确率效果是否有大幅提升(最省事)
其他小知识
1.调试循环运行速度总是比非调试情况下的运行速度慢,所以要比较运行速度需要在非调试状态下进行比较