赞
踩
Recurrent Neural Network(RNN),循环神经网络的优势在于能够处理任意长度的输入(或者说流式(strem)输入,插一嘴,博主非常讨厌这种故作玄虚的称呼,似乎显得提出者高大上,实际只能让后来者在单独学习的时候费尽力气)。简单的来说,一句话**“go to bed instead of go mad”**,可以通过分词将这句话分为:['go', 'to', 'bed', 'instead', 'of', 'go', 'mad']
。在这之后,我们可以用一些pretrained的向量对这些单词有一个表示,比如我们可以用GloVe拿到了一个向量的list,里面的向量都是对应位置单词的表示。
在给RNN模型喂的时候,每一个向量都依此送进去跑一下,在这个过程中一些有特殊设计的RNN比如LSTM,GRU这些可能会有一些额外的量被计算出来,但是最终都会拿到一个outputs矩阵,里面储存着每一次计算过程中,对于该次喂进去的单词计算而得的隐层向量。通常而言,我们想要的是最后一个输出的隐层,因为其跑遍了所有的信息,因此我们从某种意义上可以相信其更贴切该句子的表示。
这个数据集是国外友人的电影影评,可以理解成是从豆瓣上面爬下来的数据,经过人工看了之后,分为positive 和 negative两种进行标注。这个可以通过torchtext的api来做,但是这个其实挺蛋疼的。
因为如果按照其官方文档开始的展示来用,得到的train_iter = torchtext.datasets.IMDB(split='train')
,其并不是一个dataset
对象,而是一个奇了八怪的MapperIterDatapipe
。尽管花了好几个小时研究这个东西,最后还是通过遍历的方式把数据全部拿出来,再用复写Dataset, DataLoader
的形式做了一个自己的数据迭代器。
博主最开始在做的时候为了表示单词,直接naive地通过torch.nn.Embedding
随机初始化了一个编码层。虽然在做的时候还想过,这些随机初始化的编码不能表示这些词的意思,但是当时脑子一懵,觉得在这个数据量下可以通过训练的方式不断更新这个编码。但是事实表示年轻了,还是太年轻了,人生宝贵的半天就这么耗过去了。
也在这里提一下关于训练时候loss不降的一种观察角度,如果loss并不是严格不动的,换言之你的optimizer在干活,但是模型的表现一直很差,关于分类任务的输出通常和盲猜的结果相同。这个时候是代码层面错误的几率比较小,应该从模型的整体架构来看。另外一方面,如果loss一直不动都是那个数,那么需要查查是不是哪块的计算图被清掉了。
开源是一个伟大的事情,希望自己未来能开源一些更有价值的东西
import torch import torch.nn as nn import torch.optim as optim import torchtext.vocab.vocab as vocab import torchtext from torchtext import datasets from torch.utils.data import DataLoader,Dataset from collections import Counter, OrderedDict BATCH_SIZE = 32 EPOCHS = 10 SHUFFLE = True DEVICE = 'cuda' if torch.cuda.is_available() else 'cpu' MOST_COMMON_SIZE = 40000 VOCAB_SIZE = MOST_COMMON_SIZE + 2 # unk pad COMMENT_SIZE = 300 EMBED_SIZE = 50 HIDDEN_SIZE = 32 UNK_TOKEN = '<unk>' PAD_TOKEN = '<pad>' imdb_path = 'path_of_dataset' GloVe = torchtext.vocab.GloVe('6B', 50, cache='/home/haolin_li/code/pretrained_models') # 这俩就是上面提到的,Datapipe train_imdb = datasets.IMDB( root = imdb_path, split = 'train' ) test_imdb = datasets.IMDB( root = imdb_path, split = 'test' ) # 把两个Datapipe里面数据全都拿出来 train_source_targets = [] train_source_comments = [] test_source_targets = [] test_source_comments = [] for target, comment in train_imdb: train_source_targets.append(target) train_source_comments.append(comment) for target, comment in test_imdb: test_source_targets.append(target) test_source_comments.append(comment) # 计算词频 word_counter = Counter() tokenizer = torchtext.data.utils.get_tokenizer('basic_english') for comment in train_source_comments: for word in tokenizer(comment): word_counter[word] += 1 # 前十个都是些没啥语义的 of with that 这样的,所以直接去掉 most_common_words = word_counter.most_common(MOST_COMMON_SIZE+10)[10:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。