自然语言处理N天-AllenNLP学习(设定文档解读)

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

本文基于AllenNLP英文tutorial翻译,其中不少错误,仅作为个人学习记录
有一篇帖子总结了一下学习处理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文件中,修改参数进行实验很方便。

2. A Walk Through AllenNLP

第二部分 实验参数设定

上一节中对训练和评估一个模型有了了解(就是调用JSON、存储模型、评估),这节做的是深入了解实验设定文件,其实就是那个JSON文档。
教程中会解读配置文件的每一节内容,解释所有参数的含义。

初步:Registrable 和 from_params

AllenNLP中大多类继承自Registrable基类,为子类提供了一个命名注册表,这意味着如果有Model,可以这样处理

数据集、实例和域

我们在数据集上训练、评估模型,一个数据集应包含有实例。
在之前标记实验中,每一个数据集是一个包括标记的句子的集合,每一个实例也是标记句子之一。
在标记设置中,每一个实例将包含表示句子的单词/tokens的文本域(textfield)和表示相应词性标记的sequencelabelfield。
如何将句子文本转为数据集?可以使用配置文件指定的DatasetReader。

DatasetReader

第一个需要配置的部分是定义 dataset_reader

  "dataset_reader": {
    "type": "sequence_tagging",
    "word_tag_delimiter": "/",
    "token_indexers": {
      "tokens": {
        "type": "single_id",
        "lowercase_tokens": true
      },
      "token_characters": {
        "type": "characters"
      }
    }
  },

这里我们已经指定我们想要使用DatasetReader的子类“sequence_tagging”。这是SequenceTaggingDatasetReader子类。
这个reader假设一个新行分隔句子的文本文件,其中每个句子看起来像下面的一些“单词标记分隔符”{wtd}和一些“标记分隔符”{td}。

word1{wtd}tag1{td} word2{wtd}tag2{td} ...{td} wordn{wtd}tagn

而我们的数据文件是这样的

The/at detectives/nns placed/vbd Barco/np under/in arrest/nn

就是说,需要指定“/”,回看json中的第二个参数“word_tag_delimiter”

"word_tag_delimiter": "/",

因为源文件中已经进行了分词,这里就不需要指定“token_delimiter”。
如果查看SequenceTaggingDatasetReader.read()的代码,它会将每个句子转换为标记的TextField和标记的SequenceLabelField。
后者不是真正可配置的,但前者需要一个TokenIndexers字典,指示如何将标记转换为数组。
在配置中指定两个token indexers。第一个tokens是一个SingledIdTokenIndexer,只是将每个标记的单词表示为单个整数,下面的lowercase为True,表示忽略大小写。
注意,这里为每个token提供了两种不同的编码。每个编码都有一个名称,在本例中为“tokens”和“token_characters”,这些名称稍后将由模型引用。

    "token_indexers": {
      "tokens": {
        "type": "single_id",
        "lowercase_tokens": true
      },
      "token_characters": {
        "type": "characters"
      }
    }

训练和验证数据

下一个部分是指定用于训练和验证的数据。可以是在本地的,也可以是在网上的地址。

    "train_data_path": "https://allennlp.s3.amazonaws.com/datasets/getting-started/sentences.small.train",
    "validation_data_path": "https://allennlp.s3.amazonaws.com/datasets/getting-started/sentences.small.dev",

模型部分

下一个部分是模型的设置。

  "model": {
    "type": "simple_tagger",

这一段表明要开始设置模型了,使用模型的simple_tagger,对应SimpleTagger模型。
这个模型包括了一个TextFieldEmbedder和一个Seq2SeqEncoder和一个线性层(最后的这个线性层不可配置,所以json里面没有)。

TextFieldEmbedder
  "text_field_embedder": {
    "tokens": {
      "type": "embedding",
      "embedding_dim": 50
    },
    "token_characters": {
      "type": "character_encoding",
      "embedding": {
        "embedding_dim": 8
      },
      "encoder": {
        "type": "cnn",
        "embedding_dim": 8,
        "num_filters": 50,
        "ngram_filter_sizes": [
          5
        ]
      },
      "dropout": 0.2
    }
  },
  • TextField中为每个命名编码都有一个条目。每个条目指定一个TokenEmbedder,指示如何嵌入使用该名称编码的标记。 TextFieldEmbedder的输出是这些嵌入的串联。
  • “token”输入(由输入中的小写单词的整数编码组成)被输入嵌入模块,该嵌入模块将词汇表单词嵌入到50维空间中,如embedding_dim参数所指定的。
  • “token_characters”输入(由每个单词中字符的整数序列编码组成)被输入TokenCharactersEncoder,它将字符嵌入到8维空间中,然后应用使用50个过滤器的CnnEncoder,因此也生成50维输出。可以看到此编码器在训练期间也使用了20%的dropout。
    TextFieldEmbedder输出“tokens”是一个50维向量,与“token_characters”的50维向量连接在一起,也就是说,一个100维向量。

因为TextFields和TextFieldEmbedder的编码都是以这种方式配置的,所以尝试使用不同的单词表示作为模型的输入,在简单的单词嵌入之间切换,与字符级CNN连接的单词嵌入,甚至使用预先训练的模型,用于获取上下文嵌入,而无需更改单行代码。

Seq2SeqEncoder

上一个TextFieldEmbedder输出的数据由这里进行处理。

    "encoder": {
      "type": "lstm",
      "input_size": 100,
      "hidden_size": 100,
      "num_layers": 2,
      "dropout": 0.5,
      "bidirectional": true
    }

注意,这里的input_size是和上面输出的数据维度要一致。

训练模型

剩下的配置文件表明训练过程

  "iterator": {"type": "basic", "batch_size": 32},

使用basiciterator进行迭代,填充我们的数据并使用32个batch完成处理。

  "trainer": {
    "optimizer": "adam",
    "num_epochs": 40,
    "patience": 10,
    "cuda_device": -1
  }

最后,我们将使用其默认参数优化:torch.optim.Adam;
我们将进行40次迭代培训;
如果10个时代没有改善,我们会过早地停止;
我们将在CPU上进行训练。如果你想在GPU上训练,你可以将cuda_device更改为其设备ID。如果你只有一个GPU应该是0。

这是我们的整个实验配置。如果我们想要更改我们的优化器,批量大小,嵌入维度或任何其他超参数,我们需要做的就是修改此配置文件并训练另一个模型。
训练配置始终保存为模型存档的一部分,这意味着您始终可以查看已保存模型的训练方式。

终于翻译完了,这是对上一节的补充。看看就好

你可能感兴趣的:(自然语言处理N天-AllenNLP学习(设定文档解读))