第一把Pytorch实现LSTM经验总结
LSTM模型简介
整体认识:
-
下图是LSTM模型的基本“细胞”,在处理一个句子时,每个单词都对应一个“细胞”。
具体意义:
-
贯穿 $$C_{t-1}$$ 和 的一条线中包含的信息是连贯的全文/句中蕴含的信息,可以理解为主干内容。
-
LSTM 和普通 RNN 相比, 多出了三个控制器. (输入控制, 输出控制, 忘记控制)
-
更详细的内容请参见:LSTM始祖级博客
-
LSTM有两种 Input->Output 模式,一种是一对一,一种是多对一,如下图:
其中,这里的“多”和“一”指的是输入和输出节点。输入节点在我们这个例子中意味着一句话的几个单词,每个单词都会输出一个hidden层的TensorFlow,而如果我们把每个Tensor都考虑再后续的层中,比如在给句子中的每个单词标注词性的时候,那么就是“多”个单词 -> “多”个输出(打上的标签);而像是句子分类情况下,就是“多”个单词 -> “一”个输出(句子的具体分类)。
采坑笔记(实践)
-
送入DataLoader中的数据一定要是numpy数组,不能是list
-
进入DataLoader中的数据如果有好几层,必须保证每一层都是list不能是numpy。如一个三层数组,最内层inner是np.array,则要做的操作是:np.array(list[list[list(inner), …],…]),否则会报各种奇怪的错误
-
计算loss的criterion中的各个output、label等必须是autograd.Variable变量而不是torch.tensor类型
-
nn.CrossEntropyLoss(output, labels)中的labels的类型必须是torch.LongTensor而不是torch.FloatTensor
-
读取数据最好还是老老实实用Dataloader,否则还是同样的,数据格式可能会出意想不到的错误
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25from torch.utils.data import Dataset
from torch.utils.data import DataLoader
class Beibei(Dataset):
def __init__(self, trainData, train_num, test_num, train=True):
self.train = train
self.train_num = train_num
self.test_num = test_num
if self.train:
self.train_data = trainData[:train_num]
else:
self.test_data = trainData[train_num:train_num+test_num]
def __getitem__(self, index):
if self.train:
sentence, label = self.train_data[index]
else:
sentence, label = self.test_data[index]
send2word = get_wordvecs(sentence=sentence)
return send2word, label
def __len__(self):
if self.train:
return self.train_num
else:
return self.test_num -
注意在一个cell里面定义了函数,有时候会顺便再同一个cell里面定义了一把随意的输入数据测试一把,但是千万记住不要把函数的输入形参搞成了你定义的那个测试量,否则会在暗地里炸的体无完肤
-
数据需要处理的部分最好放在Dataset的类里面返回值处处理,这样会节省空间和内存。如果把这些预处理提前一次性做了,尤其是Word2Vec这种操作,会吃掉大量内存
-
loss.backward(retain_variables=True)#retain_graph=True)的作用:
After
loss.backward
you cannot do anotherloss.backward
unlessretain_variables
is true.In plain words, the backward proc will consume the intermediate saved Tensors (Variables) used for backpropagation unless you explicitly tell PyTorch to retain them.
- 由上述解答可知,retain_variables=True语句确保了用于计算后向传播的中间变量不会在计算中被销毁。
- 又由下可知,目前最好使用的方式是retain_graph=True
It is essentially the same,
retain_variables
argument has been deprecated in favor ofretain_graph
.
-
当batch参数放在第一个时,欲得到一个batch中每个句子的预测中最相近的一个值和其对应的序号:
1
values, indices = torch.max(tensor, 0)
-
LSTM在pytorch中的输入输出信息的顺序是:(sentence,batch,word2vec)这样不太自然,用下列写法可以更正至(batch,sentence,word2vec):
1
self.lstm = nn.LSTM(embedding_dim, hidden_dim, batch_first=False)
我的代码实现:
Many to One
1 | import torch |
Many to many
1 | import torch |
两者最大的差别在于在lstm的输出之后是取output[:,-1,:],即截取一句话的最后一个节点的Hidden层的输出(Many to One),还是要所有的输出,即output.view(-1, self.hidden_dim*20),把batch的维度和sentence的维度打平,把两维降到一维。