自然语言处理N天-AllenNLP学习(完整实例,预测论文发表场合-下篇)

新建 Microsoft PowerPoint 演示文稿 (2).jpg

本文基于AllenNLP中文教程,仅作为个人学习记录,作者也是一位骚话博主,和原文对照发现不少骚话蛤蛤蛤
有一篇帖子总结了一下学习处理NLP问题中间的坑。NLP数据预处理要比CV的麻烦很多。

  • 去除停用词,建立词典,加载各种预训练词向量,Sentence -> Word ID -> Word Embedding的过程(Tobias Lee:文本预处理方法小记),其中不仅需要学习pytorch,可能还要学习spacy,NLTK,numpy,pandas,tensorboardX等常用python包。
  • 用到RNN时,还要经过pad,pack,pad的过程,像这样的很多函数在使用时需要有数学基础加上简单的实践,感觉对一个新人来说,高维数据的流动有点抽象,不容易理解。
  • 数据集的读取,tensorboardX的使用。。。。各种东西要学习。在运行别人的代码后打印出信息,不仅看着上档次,而且可以看到很多实用的信息。。。

AllenNLP是在pytorch基础上的封装,它的目标是处理NLP任务,可以减少很多额外的学习。

  • 分词,帮你用spacy,NLTK,或者简单的按空格分词处理。
  • 数据集的读取,它内置了很多数据集的读取,你可以在通过学习它的读取方式,在它的基础上对自己需要的数据集进行读取。 、
  • 在Sentence -> Word ID -> Word Embedding的过程中,Glove,ELMo,BERT等常用的都可以直接使用,需要word,char粒度的都可以。
  • log打印输出,在内置的输出项之外,你可以很方便地加入想要输出的信息。模型的各个组件中的参数都可以存在一个json/jsonnet文件中,修改参数进行实验很方便。

3. 完整实例,预测论文发表场合

第二部分 预测和Demo

在完成构建和训练模型后,需要使用这个模型去做一些事情,这个教程完成

  • 如何使用模型完成一次预测
  • 如何实现一个网络Demo
    教程中将代码放在了Github上,可以选择自己训练或是下载那个模型。

第一步 创建预测器Predictor

模型中最重要的是forward()方法。

    @overrides
    def forward(self,  # type: ignore
                title: Dict[str, torch.LongTensor],
                abstract: Dict[str, torch.LongTensor],
                label: torch.LongTensor = None) -> Dict[str, torch.Tensor]:
        pass

它需要一个Tensor-ized标题和抽象(可能还有一个标签)并返回一些Tensor输出。这对于计算损失函数和性能指标非常有用,但它对于进行预测和提供演示不太有用。我们希望实现的是接受JSON输入并返回JSON结果。
AllenNLP提供一个Predictor抽象类,其中打包了一个模型并精确地实现它。大多数需要Predictor的功能都已经在这个基础类中实现。通畅只需要实现predict_json功能(能够将输入的JSON字典转为AllenNLP的Instance)。因为希望返回Instance,我们使用predict_instace来序列化这个JSON字典。在DatasetReader中已经有了text_to_instance方法,能够从JSON中抽取出我们需要的信息。
有了以上的方法,我们的Predictor会很简单。

@Predictor.register('paper-classifier')
class PaperClassifierPredictor(Predictor):
    # Predictor打包的AcademicPaperClassifier
    def predict_json(self, inputs: JsonDict) -> JsonDict:
        instance = self._json_to_instance(inputs)
        output_dict = self.predict_instance(instance)
        # label_dict will be like {0: "ACL", 1: "AI", ...}
        label_dict = self._model.vocab.get_index_to_token_vocabulary('labels')
        # Convert it to list ["ACL", "AI", ...]
        all_labels = [label_dict[i] for i in range(len(label_dict))]
        output_dict["all_labels"] = all_labels
        return output_dict

    @overrides
    def _json_to_instance(self, json_dict: JsonDict) -> Instance:
        title = json_dict['title']
        abstract = json_dict['paperAbstract']
        return self._dataset_reader.text_to_instance(title=title, abstract=abstract)

每一个Instance都有title和paperAbstract,并将其喂给text_to_instance。在这个例子中,我们同样希望返回一个可能的labels列表。我们首先得到从索引到labels的映射,然后我们将它转​​换为位置0为标签0的列表,依此类推。
predict_json返回一个JSON字典,第一个元素是Instance,第二个元素是一个字典(包括了Model.forward_on_instance的元素),总之就是我们的forward的返回值没有提供的但是我们又需要的东西都放在这里就好啦。
在这里我们只是存储所有可能的标签,其他的东西暂时就不存啦。当然,如果你连标签都用不着,那你就放个空空的字典在这里占位就好啦。

第二步 测试预测器

和前几个类似,我们需要写一个测试看看是否能用。
这里的主要问题是我们的测试将(隐式)需要按名称实例化我们的模型,数据集读取器和预测器,这意味着它们需要在我们的测试运行之前注册。在my_library / predictors /__ init__.py中将它们全部添加为导入,然后在构建predictor_test时只需要导入该包
init.py

# pylint: disable=wildcard-import
from my_library.dataset_readers import *
from my_library.models import *
from my_library.predictors import *

predict_test.py

import my_library

测试很简单,提供输入所要求的JSON格式({title: title, abstract: abstract}),然后在模型中run即可。

# pylint: disable=no-self-use,invalid-name,unused-import
from unittest import TestCase

from pytest import approx
from allennlp.models.archival import load_archive
from allennlp.predictors import Predictor

# required so that our custom model + predictor + dataset reader
# will be registered by name
import my_library

class TestPaperClassifierPredictor(TestCase):
    def test_uses_named_inputs(self):
        # JSON格式输入
        inputs = {
            "title": "Interferring Discourse Relations in Context",
            "paperAbstract": (
                    "We investigate various contextual effects on text "
                    "interpretation, and account for them by providing "
                    "contextual constraints in a logical theory of text "
                    "interpretation. On the basis of the way these constraints "
                    "interact with the other knowledge sources, we draw some "
                    "general conclusions about the role of domain-specific "
                    "information, top-down and bottom-up discourse information "
                    "flow, and the usefulness of formalisation in discourse theory."
            )
        }

        archive = load_archive(r'C:/Users/01/Desktop/allennlp-as-a-library-example-master/tests/fixtures/model.tar.gz')
        predictor = Predictor.from_archive(archive, 'paper-classifier')

        result = predictor.predict_json(inputs)

        label = result.get("label")
        assert label in {'AI', 'ML', 'ACL'}
        all_labels = result.get("all_labels")
        assert all_labels == ['AI', 'ACL', 'ML']

        class_probabilities = result.get("class_probabilities")
        assert class_probabilities is not None
        assert all(cp > 0 for cp in class_probabilities)
        assert sum(class_probabilities) == approx(1.0)

运行命令

allennlp predict tests/fixtures/model.tar.gz tests/fixtures/s2_papers.jsonl --include-package my_library --predictor paper-classifier

使用验证集进行验证。
结果如下,看了一下十篇文本都是ACL,肯定不对,原因可能是我训练集用的是下载的那个训练集,里面的内容不是机器学习这方面的。

prediction:  {"logits": [-0.11413432657718658, 0.43438369035720825, 0.07639823108911514], "class_probabilities": [0.25376972556114197, 0.43919578194618225, 0.3070344030857086], "label": "ACL", "all_labels": ["AI", "ACL", "ML"]}
prediction:  {"logits": [-0.08729098737239838, 0.2393871545791626, -0.04727406054735184], "class_probabilities": [0.29178479313850403, 0.40451735258102417, 0.3036978840827942], "label": "ACL", "all_labels": ["AI", "ACL", "ML"]}
prediction:  {"logits": [-0.06943605840206146, 0.23592156171798706, -0.039462827146053314], "class_probabilities": [0.2951996922492981, 0.4006185531616211, 0.3041817247867584], "label": "ACL", "all_labels": ["AI", "ACL", "ML"]}
prediction:  {"logits": [-0.10107310116291046, 0.24393372237682343, -0.05196814239025116], "class_probabilities": [0.28882285952568054, 0.4078177213668823, 0.3033594489097595], "label": "ACL", "all_labels": ["AI", "ACL", "ML"]}
prediction:  {"logits": [-0.15188564360141754, 0.2519247531890869, -0.07553312927484512], "class_probabilities": [0.27957457304000854, 0.4186685085296631, 0.3017568588256836], "label": "ACL", "all_labels": ["AI", "ACL", "ML"]}
.....

你可能感兴趣的:(自然语言处理N天-AllenNLP学习(完整实例,预测论文发表场合-下篇))