Pytorch Tips

记录一下我在用Pytorch和Python中碰到的一些坑和一些便于处理的Tips。如果您有更好的补充或者实现,欢迎评论呀~

目前本人用的是Pytorch 0.4.1。

1.pytorch中的index_copy_()

其实文档说的很详细了index_copy_()是一个in-place操作,那么这样的操作会在不经意间带来一些奇葩的后果:

因为x[0]=1,所以按照copy的顺序x[1]=x[0]=1,同理x[2]=x[1]=1,所以对于in-place操作我们还是尽可能保证对于x的操作不会影响到x本身。

2.嵌套list拍平(flatten)

3.使用allennl的elmo模块做NER任务

本来觉得NER任务中使用allennlp的ELMO也不过是直接调用Elmo这个类的forward方法即可,但是我的实验结果F1值一直比论文里报的低2个点,本着对于我的调参也不太可能调上去的想法,读了一遍他的Elmo代码以及他的NER配置json,结果才发现他的
num_output_representations 这个参数在NER任务上是1(其实实际上除了SQuAD,别的大部分实验都是用的1,结果他示例给了个2摔!)。发现坑点后重跑就差不多到了F1=92了,和论文差别不大了。

同时还想记一下的是,我直接听了cleary大爷的建议为了省显存把batch_size尽可能调大,我在调用elmo前加了个句

with torch.no_grad():

但是需要注意的是,这么做其实有个副作用,会不让elmo对于三层表示的加权系数进行调整了,这就导致可能效果会低半个点左右。所以现在能想到的办法是:直接弄出来每层的表示然后在外面算加权的,也就是把源码里那套东西放到外面计算一遍,这样可能就需要把之前内部的相应参数给禁用掉(没有找到什么方便的得到每层参数的接口,可能看的不是很细致,需要等放寒假了再看看)。当然如果你看一下allennlp内部用来算的加权系数的weight可能猛一看会很吃惊居然初始化为0,这怎么算梯度啊,但其实往下看会发现他过了个softmax操作,其实假如with no_grad()后我感觉上是相当于均值了。

4.Multi-head attention中如何把all_head_size分到各个head

看Bert的pytorch代码看到的,

new_x_shape得到一个[batch,seq_len,num_att_heads,att_head_size]的列表,然后view(*)表示按照这个列表分散各个维度,最后permute调整一下head在前面。

5.When should I use nn.ModuleList and when should I use nn.Sequential?

6.判断空白字符

7.ModuleList的Tips

最近重点看了看Bert的源码,发现他的stack transformer是用一个叫nn.ModuleList的方法得到的,觉得很奇怪就是个列表啊,后来才发现一些用处:比如我们要通过model.named_parameters()得到模型参数的名字,如果用py自带的list就无法得到list里面的内容了,必须要用ModuleList包裹一下。

8.model.zero_grad() or optimizer.zero_grad()

如果代码写成

optimizer = optim.Optimizer(model.parameters())

那么这两者没什么区别,因为看一下optimizer这个类的zero_grad()方法就是for了一遍放进来的所有参数清空其梯度。但是因此当放进来的参数和model不同,或者说只有一部分的话,那么这两者就不同了。model.zero_grad()清空所有模型参数梯度,而optimizer.zero_grad()清空优化器内部的。

9.统计doc中sentence的分布并排序(也可以扩展到句词)

10. random两个一一对应的等长序列

往往需要同时随机排列一下两个一一对应的序列,例如input和label。虽说我基本上是把他们放到dataset里面,然后随机一个排列去取数据。但是发现了一种别的做法,记录一下:

11.reverse tensor in pytorch

python可以[::-1]来倒序一个list,pytorch里可以这么对tensor进行操作。

上面生成了一个倒序列表,然后index_select一下就好了。

发表评论

电子邮件地址不会被公开。 必填项已用*标注