当前位置:首页 > 天道酬勤 > 正文内容

csdn免费获取c币(csdn论坛)

张世龙2021年12月21日 13:32天道酬勤1300

作者| hyk_1996

来源| CSDN博客

1. nn.Module.cuda和Tensor.cuda的作用效果不同

无论是模型还是数据,cuda函数都可以实现从CPU到GPU的内存迁移,但其效果不同。

nn.Module:的情况

模型=模型. cuda

模型. cuda

以上两个语句的效果与向model自身的内存迁移相同。

Tensor:的情况

与nn.Module不同,调用tensor.cuda只会返回此tensor对象在GPU内存中的副本,而不会对自身进行任何更改。 因此,必须重新代入tensor。 即,tensor=tensor.cuda。

例:

模型=创建_ a _模型

tensor=torch.zeros ([ 2,3,10,10 ] )。

模型. cuda

tensor.cuda

model(tensor ) #报告错误

tensor=tensor.cuda

model(tensor ) #正常工作

2. PyTorch 0.4计算累积损失的差异

以广泛使用的模式total_loss =loss.data[0]为例。 在Python0.4.0之前,loss是封有(1,)满意信封的变量,但Python0.4.0的loss现在是零维标量。 为标量建立索引是没有意义的(似乎会报告invalid index to scalar variable的错误)。 可以使用loss.item从标量中获取Python的数字。 因此,将改为:

总损耗=损耗.项目

如果在累积损失时未转换为Python数字,则程序的内存使用量可能会增加。 这是因为上式的右侧原本是Python浮点数,但现在是零维令人满意的信封。 结果,总损失将累积满意的信封及其坡度历史记录,生成autograd的大图表,可能会消耗内存和计算资源。

3 .编写不限制3. PyTorch 0.4设备的代码

# # torch.deviceobjectusedthroughoutthisscript

dvice=torch.device (cuda ' if use _ cuda else ' CPU ) ) ) ) )。) ) ) ) ) ) ) ) ) ) ) )。

model=myr nn.to (设备)

# #三叉戟

总损耗=0

输入,目标输入加载器:

输入,目标=输入.到(设备,目标.到)设备) ) )。

hidden=input.new_Zeros(h_shape ) # has the same device dtype as `输入

. #获取丢失和优化

总损耗=损耗.项目

# #测试

with torch.no _ grad : #操作系统跟踪历史记录

输入,目标输入测试加载器:

.

4 .使用4. torch.Tensor.detach

detach的正式说明如下。

返回新张紧器,从当前图形检测。

theresultwillneverrequiregradient

假设有模型a和模型b。 a的输出需要作为b的输入,但在训练时只训练模型b。 可以这样做。

输入-输出-分离

这样就切断了两个计算图的梯度传递,实现了必要的功能。

5.error : UnexpectedBuserrorencounteredinworker.thismightbecausedbyinsufficientsharedmemory (shm )。

发生该错误的情况是在服务器上的docker中执行训练代码时,将batch size设定得过大,shared memory不够的情况。解决方法是将Dataloader的num_workers设为0

6. pytorch的loss函数的参数设定

以CrossEntropyLoss为例。

crossentropyloss (自我,weight=无,size _ average=无,ignore_index=-100,降低=无,降低='电池)

如果reduce=False,则size_average参数无效且为直的

接返回向量形式的 loss,即batch中每个元素对应的loss.

若 reduce = True,那么 loss 返回的是标量:

如果 size_average = True,返回 loss.mean.

如果 size_average = False,返回 loss.sum.

weight : 输入一个1D的权值向量,为各个类别的loss加权,如下公式所示:

ignore_index : 选择要忽视的目标值,使其对输入梯度不作贡献。如果 size_average = True,那么只计算不被忽视的目标的loss的均值。

reduction : 可选的参数有:‘none’ | ‘elementwise_mean’ | ‘sum’, 正如参数的字面意思,不解释。

7. pytorch的可重复性问题

参考这篇博文:

https://blog.csdn.net/hyk_1996/article/details/84307108

8. 多GPU的处理机制

使用多GPU时,应该记住pytorch的处理逻辑是:

1)在各个GPU上初始化模型。

2)前向传播时,把batch分配到各个GPU上进行计算。

3)得到的输出在主GPU上进行汇总,计算loss并反向传播,更新主GPU上的权值。

4)把主GPU上的模型复制到其它GPU上。

9. num_batches_tracked参数

今天读取模型参数时出现了错误

KeyError: 'unexpected key "module.bn1.num_batches_tracked" in state_dict'

经过研究发现,在pytorch 0.4.1及后面的版本里,BatchNorm层新增了num_batches_tracked参数,用来统计训练时的forward过的batch数目,源码如下(pytorch0.4.1):

if self.training and self.track_running_stats:

self.num_batches_tracked += 1

if self.momentum is None: # use cumulative moving average

exponential_average_factor = 1.0 / self.num_batches_tracked.item

else: # use exponential moving average

exponential_average_factor = self.momentum

大概可以看出,这个参数和训练时的归一化的计算方式有关。

因此,我们可以知道该错误是由于训练和测试所用的pytorch版本(0.4.1版本前后的差异)不一致引起的。具体的解决方案是:如果是模型参数(Orderdict格式,很容易修改)里少了num_batches_tracked变量,就加上去,如果是多了就删掉。偷懒的做法是将load_state_dict的strict参数置为False,如下所示:

load_state_dict(torch.load(weight_path), strict=False)

还看到有人直接修改pytorch 0.4.1的源代码把num_batches_tracked参数删掉的,这就非常不建议了。

10. 训练时损失出现nan的问题

最近在训练模型时出现了损失为nan的情况,发现是个大坑。暂时先记录着。

可能导致梯度出现nan的三个原因:

1.梯度爆炸。也就是说梯度数值超出范围变成nan. 通常可以调小学习率、加BN层或者做梯度裁剪来试试看有没有解决。

2.损失函数或者网络设计。比方说,出现了除0,或者出现一些边界情况导致函数不可导,比方说log(0)、sqrt(0).

3.脏数据。可以事先对输入数据进行判断看看是否存在nan.

补充一下nan数据的判断方法:

注意!像nan或者inf这样的数值不能使用 == 或者 is 来判断!为了安全起见统一使用 math.isnan 或者 numpy.isnan 吧。

例如:

import numpy as np

# 判断输入数据是否存在nan

if np.any(np.isnan(input.cpu.numpy)):

print('Input data has NaN!')

# 判断损失是否为nan

if np.isnan(loss.item):

print('Loss value is NaN!')

11. ValueError: Expected more than 1 value per channel when training

当batch里只有一个样本时,再调用batch_norm就会报下面这个错误:

raise ValueError('Expected more than 1 value per channel when training, got input size {}'.format(size))

没有什么特别好的解决办法,在训练前用 num_of_samples % batch_size 算一下会不会正好剩下一个样本。

12. 优化器的weight_decay项导致的隐蔽bug

我们都知道weight_decay指的是权值衰减,即在原损失的基础上加上一个L2惩罚项,使得模型趋向于选择更小的权重参数,起到正则化的效果。但是我经常会忽略掉这一项的存在,从而引发了意想不到的问题。

这次的坑是这样的,在训练一个ResNet50的时候,网络的高层部分layer4暂时没有用到,因此也并不会有梯度回传,于是我就放心地将ResNet50的所有参数都传递给Optimizer进行更新了,想着layer4应该能保持原来的权重不变才对。但是实际上,尽管layer4没有梯度回传,但是weight_decay的作用仍然存在,它使得layer4权值越来越小,趋向于0。后面需要用到layer4的时候,发现输出异常(接近于0),才注意到这个问题的存在。

虽然这样的情况可能不容易遇到,但是还是要谨慎:暂时不需要更新的权值,一定不要传递给Optimizer,避免不必要的麻烦。

(*本文为 AI科技大本营转载文章,转载请联系原作者)

扫描二维码推送至手机访问。

版权声明:本文由花开半夏のブログ发布,如需转载请注明出处。

本文链接:https://www.zhangshilong.cn/work/26346.html

标签: tensor
分享给朋友:

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。