我又回来了,Pytorch的学习也是为了熟悉AllenNLP结构,所以,在完成基础tutorial之后又折回来继续学AllenNLP。四月份的目标是复现那篇论文中的结构并使用Finetuning完成Transformer。
今天开始AllenNLP入门的第二部分How-to。总共包括七个小节。
如何使用json配置向导如何使用Lazy Data训练模型- How to train and use a Transformer-based ELMo
- How to Debug Your AllenNLP Code
- How to visualize model internals (BETA)
- Using pre-trained ELMo representations
- Using span representations
3. 如何训练并使用一个Transformer ELMo
在第三节,学习训练一个Transformer ELMo。ELMo是AllenNLP的成名之作,在2018年的NAACL上,outstanding paper award。
首先,什么是EMLo?
ELMo
近年来,研究人员通过文本上下文信息分析获得更好的词向量。ELMo是其中的翘楚,在多个任务、多个数据集上都有显著的提升。所以,它是目前最好用的词向量,the-state-of-the-art的方法。
ELMo的优势
- ELMo能够学习到词汇用法的复杂性,比如语法、语义。
- ELMo能够学习不同上下文情况下的词汇多义性。
ELMo模型基于大量文本,从深层的双向语言模型(deep bidirectional language model)中的内部状态(internal state)学习而来的。其效果如下:
- Textual entailment: stanford natural language inference (SNLI)数据集上提升了1.4%。
- Question answering: 在stanford question answering dataset (SQuAD)数据集上提升了4.2%,将ELMo加入到之前的state-of-the-art的ensemble模型中,提升了10%。
- Semantic role labeling: 比之前的state-of-the-art模型提高了3.2%,将ELMo加入到之前的state-of-the-art的单模型中,提升了1.2%。
- Coreference resolution: 比之前的state-of-the-art模型提高了3.2%,将ELMo加入到之前的state-of-the-art的ensemble模型中,提升了1.6%。
- Named entity extraction: 在CoNLL 2003 NER task数据机上提高了2.06%
- Sentiment analysis: 比之前的state-of-the-art模型提高了3.3%,将ELMo加入到之前的state-of-the-art模型中,提升了1%。
以下进入正文。
本文描述的是如何通过AllenNLP训练并使用一个基于Transformer的ELMo。模型使用该模型是Peters等人在Dissecting Contextual Word Embeddings:Architecture and Representation中描述的端口。
3.1 训练
3.1.1 先从这个地址获取数据
数据比较大,下载的时候先去处理其他部分。
3.1.2 获取词汇
Avoid creating garbage namespace.
rm vocab-2016-09-10.txt
echo 'labels\ntags' > non_padded_namespaces.txt
allennlp train training_config/bidirectional_language_model.jsonnet --serialization-dir output_path
3.1.4 等待
需要等待好些天,而且这个模型的训练只进行了4次迭代
3.1.5 评价
评估。这里有一个问题,就是我们放弃3个句子太长时间(否则我们会耗尽GPU内存)。如果我们想要正式报告这个数字(在论文或类似文件中),我们需要以不同的方式处理这个问题。
评价命令
看到这里是不是心凉了,作者很皮,其实AllenNLP已经有训练好的模型,虽然是英文的……
3.2 使用AllenNLP已有的Transformer ELMo模型
"text_field_embedder": {
"token_embedders": {
"elmo": {
"type": "elmo_token_embedder",
"options_file":
"weight_file":
"do_layer_norm": false,
"dropout": 0.5
}
}
},
替换为
"text_field_embedder": {
"token_embedders": {
"elmo": {
"type": "bidirectional_lm_token_embedder",
"archive_file": std.extVar('BIDIRECTIONAL_LM_ARCHIVE_PATH'),
"dropout": 0.2,
"bos_eos_tokens": ["<S>", "</S>"],
"remove_bos_eos": true,
"requires_grad": false
}
}
},
会发现,在type部分改为bidirectional_lm_token_embedder。那么是不是可以直接调用呢?
3.3 直接调用 BidirectionalLanguageModelTokenEmbedder
当然可以,用户可以直接调用 bidirectional_lm_token_embedder。
from allennlp.modules.token_embedders.bidirectional_language_model_token_embedder import BidirectionalLanguageModelTokenEmbedder
from allennlp.data.token_indexers.elmo_indexer import ELMoTokenCharactersIndexer
from allennlp.data.tokenizers.token import Token
import torch
lm_model_file = "output_path/model.tar.gz"
sentence = "It is raining in Seattle ."
tokens = [Token(word) for word in sentence.split()]
lm_embedder = BidirectionalLanguageModelTokenEmbedder(
archive_file=lm_model_file,
dropout=0.2,
bos_eos_tokens=["<S>", "</S>"],
remove_bos_eos=True,
requires_grad=False
)
indexer = ELMoTokenCharactersIndexer()
vocab = lm_embedder._lm.vocab
character_indices = indexer.tokens_to_indices(tokens, vocab, "elmo")["elmo"]
# Batch of size 1
indices_tensor = torch.LongTensor([character_indices])
# Embed and extract the single element from the batch.
embeddings = lm_embedder(indices_tensor)[0]
for word_embedding in embeddings:
print(word_embedding)
这里缺少数据加载和批处理机制,如果要使用的话还需要增加。