原文链接: http://chenhao.space/post/a5b86241.html
Pytorch-情感分析
第一步:导入IMDB电影数据集,只有训练集和测试集
import torch
from torchtext import data
SEED = 1234
torch.manual_seed(SEED) # 为CPU设置随机种子
torch.cuda.manual_seed(SEED) #为GPU设置随机种子
# 在程序刚开始加这条语句可以提升一点训练速度,没什么额外开销
torch.backends.cudnn.deterministic = True
# 首先,我们要创建两个Field 对象:这两个对象包含了我们打算如何预处理文本数据的信息。
# spaCy:英语分词器,类似于NLTK库,如果没有传递tokenize参数,则默认只是在空格上拆分字符串。
# torchtext.data.Field : 用来定义字段的处理方法(文本字段,标签字段)
TEXT = data.Field(tokenize='spacy')
#LabelField是Field类的一个特殊子集,专门用于处理标签。
LABEL = data.LabelField(dtype=torch.float)
# 加载IMDB电影评论数据集
from torchtext import datasets
train_data, test_data = datasets.IMDB.splits(TEXT, LABEL)
downloading aclImdb_v1.tar.gz
aclImdb_v1.tar.gz: 100%|██████████| 84.1M/84.1M [00:07<00:00, 11.1MB/s]
# 查看数据集
print(vars(train_data.examples[0]))
{'text': ['This', 'is', 'one', 'of', 'the', 'finest', 'films', 'to', 'come', 'out', 'of', 'Hong', 'Kong', "'s", "'", 'New', 'Wave', "'", 'that', 'began', 'with', 'Tsui', 'Hark', "'s", '"', 'ZU', ':', 'Warriors', 'of', 'Magic', 'Mountain', '"', '.', 'Tsui', 'set', 'a', 'tone', 'for', 'the', 'New', 'Wave', "'s", 'approach', 'to', 'the', 'martial', 'arts', 'film', 'that', 'pretty', 'much', 'all', 'the', 'directors', 'of', 'the', 'New', 'Wave', '(', 'Jackie', 'Chan', ',', 'Sammo', 'Hung', ',', 'Wong', 'Jing', ',', 'Ching', 'Siu', 'Tung', ',', 'etc', '.', ')', 'accepted', 'from', 'then', 'on', 'as', 'a', 'given', ';', 'namely', ',', 'the', 'approach', 'to', 'such', 'films', 'thenceforth', 'would', 'need', 'more', 'than', 'a', 'touch', 'of', 'irony', ',', 'if', 'not', 'outright', 'comedy', '.', '"', 'Burning', 'Paradise', '"', 'put', 'a', 'stop', 'to', 'all', 'that', ',', 'and', 'with', 'a', 'vengeance.<br', '/><br', '/>It', "'s", 'not', 'that', 'there', 'is', "n't", 'humor', 'here', ';', 'but', 'it', 'is', 'a', 'purely', 'human', 'humor', ',', 'as', 'with', 'the', 'aged', 'Buddhist', 'priest', 'at', 'the', 'beginning', 'who', 'somehow', 'manages', 'a', 'quick', 'feel', 'of', 'the', 'nubile', 'young', 'prostitute', 'while', 'hiding', 'in', 'a', 'bundle', 'of', 'straw', '.', 'But', 'this', 'is', 'just', 'as', 'humans', 'are', ',', 'not', 'even', 'Buddhist', 'priests', 'can', 'be', 'saints', 'all', 'the', 'time.<br', '/><br', '/>When', 'irony', 'is', 'at', 'last', 'introduced', 'into', 'the', 'film', ',', 'it', 'is', 'the', 'nastiest', 'possible', ',', 'emanating', 'from', 'the', "'", 'abbot', "'", 'of', 'Red', 'Lotus', 'Temple', ',', 'who', 'is', 'a', 'study', 'in', 'pure', 'nihilism', 'such', 'as', 'has', 'never', 'been', 'recorded', 'on', 'film', 'before', '.', 'He', 'is', 'the', 'very', 'incarnation', 'of', 'Milton', "'s", 'Satan', 'from', '"', 'Paradise', 'Lost', '"', ':', '"', 'Better', 'to', 'rule', 'in', 'Hell', 'than', 'serve', 'in', 'heaven', '!', '"', 'And', 'if', 'he', 'ca', "n't", 'get', 'to', 'Satan', "'s", 'hell', 'soon', 'enough', ',', 'he', "'ll", 'turn', 'the', 'world', 'around', 'him', 'into', 'a', 'living', 'hell', 'he', 'can', 'rule.<br', '/><br', '/>That', "'s", 'the', 'motif', 'underscoring', 'the', 'brutal', 'violence', 'of', 'much', 'of', 'the', 'imagery', 'here', ':', 'It', "'s", 'not', 'that', 'the', 'Abbot', 'just', 'wants', 'to', 'kill', 'people', ';', 'he', 'wants', 'them', 'to', 'despair', ',', 'to', 'feel', 'utterly', 'hopeless', ',', 'to', 'accept', 'his', 'nihilism', 'as', 'all', '-', 'encompassing', 'reality', '.', 'Thus', 'there', "'s", 'a', 'definite', 'sense', 'pervading', 'the', 'Red', 'Temple', 'scenes', 'that', 'there', 'just', 'might', 'not', 'be', 'any', 'other', 'reality', 'outside', 'of', 'the', 'Temple', 'itself', '-', 'it', 'has', 'become', 'all', 'there', 'is', 'to', 'the', 'universe', ',', 'and', 'the', 'Abbot', ',', 'claiming', 'mastery', 'of', 'infinite', 'power', ',', 'is', 'in', 'charge.<br', '/><br', '/>Of', 'course', ',', 'fortunately', ',', 'the', 'film', 'does', "n't", 'end', 'there', '.', 'Though', 'there', 'are', 'losses', ',', 'the', 'human', 'will', 'to', 'be', 'just', 'ordinarily', 'human', 'at', 'last', 'prevails', '.', '(', 'If', 'you', 'want', 'to', 'know', 'how', ',', 'see', 'the', 'film', '!', ')', 'Yet', 'there', 'is', 'no', 'doubt', 'that', ',', 'in', 'viewing', 'this', 'film', ',', 'we', 'visit', 'hell', '.', 'Hopefully', ',', 'we', 'do', 'not', 'witness', 'our', 'own', 'afterlives', ';', 'but', 'we', 'certainly', 'feel', 'chastened', 'by', 'the', 'experience', '-', 'and', 'somehow', 'better', 'for', 'it', 'over', 'all', '.'], 'label': 'pos'}
第二步:将训练集划分为训练集和验证集
- 由于我们现在只有train/test这两个分类,所以我们需要创建一个新的validation set。我们可以使用.split()创建新的分类。
- 默认的数据分割是 70、30,如果我们声明split_ratio,可以改变split之间的比例,split_ratio=0.8表示80%的数据是训练集,20%是验证集。
- 我们还声明random_state这个参数,确保我们每次分割的数据集都是一样的。
import random
# 默认split_ratio=0.7
train_data, valid_data = train_data.split(random_state=random.seed(SEED))
print(f'Number of training examples: {len(train_data)}')
print(f'Number of validation examples: {len(valid_data)}')
print(f'Number of testing examples: {len(test_data)}')
Number of training examples: 17500
Number of validation examples: 7500
Number of testing examples: 25000
第三步:用训练集建立vocabulary,把每个单词映射到一个数字。
- 我们使用最常见的25k个单词来构建我们的单词表,用
max_size
这个参数可以做到这一点。 - 所有其他的单词都用
<unk>
来表示。
# 从预训练的词向量(vectors)中,将当前(corpus语料库)词汇表的词向量抽取出来,构成当前 corpus 的 Vocab(词汇表)
# 预训练的 vectors 来自glove模型,每个单词有100维。glove模型训练的词向量参数来自很大的语料库
# 而我们的电影评论的语料库小一点,所以词向量需要更新,glove的词向量适合用做初始化参数。
TEXT.build_vocab(train_data, max_size=25000, vectors="glove.6B.100d", unk_init=torch.Tensor.normal_)
LABEL.build_vocab(train_data)
.vector_cache/glove.6B.zip: 862MB [00:44, 19.5MB/s]
100%|█████████▉| 399664/400000 [00:19<00:00, 20291.20it/s]
print(f'Unique tokens in TEXT vocabulary: {len(TEXT.vocab)}')
print(f'Unique tokens in LABEL vocabulary: {len(LABEL.vocab)}')
Unique tokens in TEXT vocabulary: 25002
Unique tokens in LABEL vocabulary: 2
print(LABEL.vocab.itos)
['neg', 'pos']
print(LABEL.vocab.stoi)
defaultdict(<function _default_unk_index at 0x7fb5205c2a60>, {'neg': 0, 'pos': 1})
print(TEXT.vocab.stoi)
defaultdict(<function _default_unk_index at 0x7fb5205c2a60>, {'<unk>': 0, '<pad>': 1, 'the': 2, ',': 3, '.': 4, 'and': 5, 'a': 6, 'of': 7, 'to': 8, 'is': 9, 'in': 10, 'I': 11, 'it': 12, 'that': 13, '"': 14, "'s": 15, 'this': 16, '-': 17, '/><br': 18, 'was': 19, 'as': 20, 'with': 21, 'movie': 22, 'for': 23, 'film': 24, 'The': 25, 'but': 26, '(': 27, ')': 28, "n't": 29, 'on': 30, 'you': 31, 'are': 32, 'not': 33, 'have': 34, 'his': 35, 'be': 36, 'he': 37, 'one': 38, 'at': 39, 'by': 40, 'all': 41, '!': 42, 'an': 43, 'who': 44, 'they': 45, 'from': 46, 'like': 47, 'so': 48, 'her': 49, "'": 50, 'about': 51, 'or': 52, 'has': 53, 'It': 54, 'out': 55, 'just': 56, 'do': 57, '?': 58, 'some': 59, 'good': 60, 'more': 61, 'very': 62, 'would': 63, 'up': 64, 'what': 65, 'This': 66, 'there': 67, 'time': 68, 'can': 69, 'when': 70, 'which': 71, 'had': 72, 'she': 73, 'if': 74, 'only': 75, 'story': 76, 'really': 77, 'were': 78, 'their': 79, 'see': 80, 'no': 81, 'even': 82, 'my': 83, 'me': 84, 'did': 85, 'does': 86, '...': 87, 'than': 88, ':': 89, 'much': 90, 'could': 91, 'been': 92, 'get': 93, 'into': 94, 'we': 95, 'well': 96, 'bad': 97, 'people': 98, 'will': 99, 'because': 100, ......,'chieftain': 24995, 'child.<br': 24996, 'childbirth': 24997, 'chilly': 24998, 'chime': 24999, 'chinese': 25000, 'chokes': 25001})
# 语料库单词频率越高,索引越靠前。前两个默认为unk和pad。
print(TEXT.vocab.itos)
['<unk>', '<pad>', 'the', ',', '.', 'and', 'a', 'of', 'to', 'is', 'in', 'I', 'it', 'that', '"', "'s", 'this', '-', '/><br', 'was', 'as', 'with', 'movie', 'for', 'film', 'The', 'but', '(', ')', "n't", 'on', 'you', 'are', 'not', 'have', 'his', 'be', 'he', 'one', 'at', 'by', 'all', '!', 'an', 'who', 'they', 'from', 'like', 'so', 'her', "'", 'about', 'or', 'has', 'It', 'out', 'just', 'do', '?', 'some', 'good', 'more', 'very', 'would', 'up', 'what', 'This', 'there', 'time', 'can', 'when', 'which', 'had', 'she', 'if', &