![](https://img.haomeiwen.com/i14340919/7c77a303b60ea887.jpg)
我又回来了,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
Embeddings from Language Models
以下摘自ELMo最好用词向量Deep Contextualized Word Representations
近年来,研究人员通过文本上下文信息分析获得更好的词向量。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 先从这个地址获取数据
数据比较大,下载的时候先去处理其他部分。
http://www.statmt.org/lm-benchmark/1-billion-word-language-modeling-benchmark-r13output.tar.gz
3.1.2 获取词汇
mkdir vocabulary
export BIDIRECTIONAL_LM_VOCAB_PATH=BIDIRECTIONAL_LM_VOCAB_PATH
aws --no-sign-request s3 cp s3://allennlp/models/elmo/vocab-2016-09-10.txt .
cat vocab-2016-09-10.txt | sed 's/<UNK>/@@UNKNOWN@@/' > tokens.txt
Avoid creating garbage namespace.
rm vocab-2016-09-10.txt
echo 'labels\ntags' > non_padded_namespaces.txt
3.1.3 进行训练
多进程数据集读取器和迭代器使用许多文件描述符,所以在这里增加相关的ulimit以提供帮助。
有关基础问题的说明,请参阅https://pytorch.org/docs/stable/multiprocessing.html#file-descriptor-file-descriptor#。
训练命令
allennlp train training_config/bidirectional_language_model.jsonnet --serialization-dir output_path
3.1.4 等待
需要等待好些天,而且这个模型的训练只进行了4次迭代
3.1.5 评价
评估。这里有一个问题,就是我们放弃3个句子太长时间(否则我们会耗尽GPU内存)。如果我们想要正式报告这个数字(在论文或类似文件中),我们需要以不同的方式处理这个问题。
评价命令
allennlp evaluate --cuda-device 0 -o '{"iterator": {"base_iterator": {"maximum_samples_per_batch": ["num_tokens", 500] }}}' output_path/model.tar.gz $BIDIRECTIONAL_LM_DATA_PATH/heldout-monolingual.tokenized.shuffled/news.en-00000-of-00100
作者列举了4词迭代后的结果,真的是拼,5点多出来,连夜跑的吧。
2018-12-12 05:42:53,711 - INFO - allennlp.commands.evaluate - loss: 3.745238332322373
ipython
In [1]: import math; math.exp(3.745238332322373) # To compute perplexity
Out[1]: 42.3190920245054
看到这里是不是心凉了,作者很皮,其实AllenNLP已经有训练好的模型,虽然是英文的……
3.2 使用AllenNLP已有的Transformer ELMo模型
使用Transformer ELMo与使用常规ELMo基本相同,这篇文档有详细说明。只有一个不同是在text_field_embedder 部分,需要将以下部分进行替换
"text_field_embedder": {
"token_embedders": {
"elmo": {
"type": "elmo_token_embedder",
"options_file": "https://s3-us-west-2.amazonaws.com/allennlp/models/elmo/2x4096_512_2048cnn_2xhighway/elmo_2x4096_512_2048cnn_2xhighway_options.json",
"weight_file": "https://s3-us-west-2.amazonaws.com/allennlp/models/elmo/2x4096_512_2048cnn_2xhighway/elmo_2x4096_512_2048cnn_2xhighway_weights.hdf5",
"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)
这里缺少数据加载和批处理机制,如果要使用的话还需要增加。
网友评论