2022升级—TypeScript系统入门到项目实战完结无密

#1

download:2022升级—TypeScript系统入门到项目实战完结无密

Tricks帮助你提高调试Pytorch的效率。
指导阅读
好的工具和工作习惯可以大大提高工作效率。
每个深度学习项目都不一样。无论你有多少经验,你总会遇到新的挑战和意想不到的行为。你在项目中使用的技能和思维方式将决定你能多快找到并解决这些阻碍你成功的障碍。
从实用的角度来看,深度学习项目是从代码开始的。一开始组织起来很容易,但是随着项目复杂度的增加,在调试和完整性检查上花费的时间会越来越多。令人惊讶的是,很多都可以自动完成。在这篇文章中,我将告诉你如何去做。

找出你的训练损失没有减少的原因。
实现自动模型验证和异常检测。
使用PyTorch Lightning节省宝贵的调试时间。
招数二:记录训练数据的直方图。
总是检查输入数据的范围是很重要的。如果模型权重和数据是非常不同的量级,则在极端情况下可能导致没有或非常低的学习进度和数值不稳定。例如,当数据扩展以错误的顺序应用或忘记规范化时,就会发生这种情况。在我们的例子中是这样吗?我们应该能够通过打印最小值和最大值来找出答案。但是等等!这不是一个好的解决方案,因为它会不必要地污染代码,并在需要时花费太多时间来重复它。更好的方法:写一个回调类来帮我们做!
类输入监视器(pl。回拨):

def on_train_batch_start(self,trainer,pl_module,batch,batch_idx,dataloader_idx):
if(batch _ idx+1)% trainer . log _ every _ n _ steps = = 0:
x,y =批次
logger =培训师
logger . experience . add _ histogram(" input “,x,global _ step = trainer . global _ step)
logger . experience . add _ histogram(” target ",y,global _ step = trainer . global _ step)

#像这样使用回调:
model = LitClassifier()
培训师= pl。培训师(gpus = 1,回调=[InputMonitor()])
trainer.fit(型号)
复制代码
一个简单的回调,将训练数据的直方图记录到TensorBoard。
PyTorchlighting中的回调可以保存任何可以注入训练器的代码。在进入训练步骤之前,计算输入数据的直方图。将此函数封装到回调类中有以下优点:

它与你的研究代码是分开的,没有必要修改你的LightningModule!
它是可移植的,因此可以在未来的项目中重用,只需要修改两行代码:导入回调,然后将其传递给Trainer。
可以通过子类化或者结合其他回调来扩展。

现在有了新的回调函数,我们可以打开TensorBoard并切换到“直方图”选项卡来检查训练数据的分布:

在目标范围[0,9]中,这是正确的,因为MNIST有一个10位的类,但图像的值在-130和-127之间,这是错误的!我们很快发现第41行规范化中有一个问题:
转变。Normalize(128,1) #错误的规范化
复制代码
这两个数字应该是输入数据(在我们的例子中是图像中的像素)的平均值和标准差。为了解决这个问题,我们添加了真实平均值和标准偏差,并命名了参数以使其更加清晰:
转变。归一化(平均值=0.1307,标准差=0.3081)
复制代码
我们可以查这些数字,因为它们是已知的。对于自己的数据集,你得自己去计算。
归一化后像素的平均值为0,标准差为1,就像分类器的权重一样。我们可以通过看TensorBoard的直方图来确认这一点。
技巧3:检测正向传播中的异常
在解决了标准化问题后,我们现在也可以在TensorBoard中获得预期的直方图。可惜损失并没有减少。还有一个问题。我知道数据是正确的,并且开始寻找错误的一个好地方是网络的前向路径。一个常见的误差源是张量形状的操作,如置换、整形、视图、平坦等。,或应用于一维的操作,如softmax。当这些函数应用于错误的大小或错误的顺序时,我们通常会得到形状不匹配的错误,但情况并非总是如此!这些错误很难追踪。
让我们来看看一种能让我们快速检测出这些错误的技术。

快速检查模型是否在批处理中混合数据。
想法很简单:如果我们改变第n个输入样本,它应该只影响第n个输出。如果其他输出i≠n也发生变化,模型就会混数据,这就不好了!实施该测试的一种可靠方法是计算所有输入的第n个输出的梯度。对于所有i≠n的渐变必须为零(以上动画中的红色),对于i = n的渐变必须非零(以上动画中的绿色)。如果满足这些条件,模型就通过了测试。以下是n = 3时的实现:
#用所有输入检查第n个小批量样品的梯度
n = 3

1.输入批次需要梯度

example_input = torch.rand(5,1,28,28,requires_grad=True)

2.通过模型运行批处理

输出=模型(示例_输入)

3.计算第n个输出样本的虚拟损耗并反向传播

输出[n]。abs()。sum()。向后()

4.检查样本I上的梯度!= n都是零!

#健全性检查:如果这没有返回0,您有一个bug!
i = 0
example_input.grad[i]。abs()。sum()。项目()
复制代码
下面是同样的闪电回调:
类CheckBatchGradient(pl。回拨):

定义on_train_start(自我、教练、模型):
n = 0

示例输入=模型.示例输入阵列.至(模型.设备)
example _ input . requires _ grad = True

零grad()
输出=模型(示例_输入)
输出[n]。abs()。sum()。向后()

zero _ grad _ inds = list(range(example _ input . size(0)))
零梯度指数

if example _ input . grad[zero _ grad _ inds]。abs()。sum()。item() > 0
raise RuntimeError(“您的模型混合了批处理维度中的数据!”)

#像这样使用回调:
model = LitClassifier()
培训师= pl。训练器(gpus = 1,回调=[CheckBatchGradient()])
trainer.fit(型号)
复制代码
当这个测试应用于LitClassifer时,您可以立即发现它混合了数据。既然我们知道我们要找的是什么,我们很快就在正向传输中发现了一个错误。第35行中的Softmax应用于错误的尺寸:
output = F.log_softmax(x,dim=0)
复制代码
应该是:
output = F.log_softmax(x,dim=1)
复制代码
好了,分类器工作了!并且训练和验证损失迅速减少。
摘要
编写好的代码从组织开始。PyTorch Lightning通过删除围绕训练周期工程、检查点保存、日志记录等的样板代码来处理这一部分。剩下的就是实际的研究代码:模型、优化和数据加载。如果事情没有按照我们预期的方式运行,很可能是这三部分代码中的某一部分有错误。在这篇博文中,我们实现了两个回调来帮助我们1)监控进入模型的数据,以及2)验证我们的网络中的层不会在批处理维度中混合数据。回调的概念是向现有算法添加任意逻辑的一种非常优雅的方式。一旦实现,通过修改两行代码就可以很容易地集成到一个新项目中。