使用Modules和Models快速搭建自定义模型

modulesmodels 用于构建 fastNLP 所需的神经网络模型,它可以和 torch.nn 中的模型一起使用。 下面我们会分三节介绍编写构建模型的具体方法。

使用 models 中的模型

fastNLP 在 models 模块中内置了如 CNNTextSeqLabeling 等完整的模型,以供用户直接使用。 以文本分类的任务为例,我们从 models 中导入 CNNText 模型,用它进行训练。

from fastNLP.models import CNNText

model_cnn = CNNText((len(vocab),100), num_classes=2, dropout=0.1)

trainer = Trainer(train_data=train_data, dev_data=dev_data, metrics=metric,
                  loss=loss, device=device, model=model_cnn)
trainer.train()

在 iPython 环境输入 model_cnn ,我们可以看到 model_cnn 的网络结构

CNNText(
  (embed): Embedding(
    (embed): Embedding(16292, 100)
    (dropout): Dropout(p=0.0, inplace=False)
  )
  (conv_pool): ConvMaxpool(
    (convs): ModuleList(
      (0): Conv1d(100, 30, kernel_size=(1,), stride=(1,), bias=False)
      (1): Conv1d(100, 40, kernel_size=(3,), stride=(1,), padding=(1,), bias=False)
      (2): Conv1d(100, 50, kernel_size=(5,), stride=(1,), padding=(2,), bias=False)
    )
  )
  (dropout): Dropout(p=0.1, inplace=False)
  (fc): Linear(in_features=120, out_features=2, bias=True)
)

FastNLP 中内置的 models 如下表所示,您可以点击具体的名称查看详细的 API:

名称

介绍

CNNText

使用 CNN 进行文本分类的模型

SeqLabeling

简单的序列标注模型

AdvSeqLabel

更大网络结构的序列标注模型

ESIM

ESIM 模型的实现

StarTransEnc

带 word-embedding的Star-Transformer模 型

STSeqLabel

用于序列标注的 Star-Transformer 模型

STNLICls

用于自然语言推断 (NLI) 的 Star-Transformer 模型

STSeqCls

用于分类任务的 Star-Transformer 模型

BiaffineParser

Biaffine 依存句法分析网络的实现

BiLSTMCRF

使用BiLSTM与CRF进行序列标注

使用 nn.torch 编写模型

FastNLP 完全支持使用 pyTorch 编写的模型,但与 pyTorch 中编写模型的常见方法不同, 用于 fastNLP 的模型中 forward 函数需要返回一个字典,字典中至少需要包含 pred 这个字段。

下面是使用 pyTorch 中的 torch.nn 模块编写的文本分类,注意观察代码中标注的向量维度。 由于 pyTorch 使用了约定俗成的维度设置,使得 forward 中需要多次处理维度顺序

import torch
import torch.nn as nn

class LSTMText(nn.Module):
    def __init__(self, vocab_size, embedding_dim, output_dim, hidden_dim=64, num_layers=2, dropout=0.5):
        super().__init__()

        self.embedding = nn.Embedding(vocab_size, embedding_dim)
        self.lstm = nn.LSTM(embedding_dim, hidden_dim, num_layers=num_layers, bidirectional=True, dropout=dropout)
        self.fc = nn.Linear(hidden_dim * 2, output_dim)
        self.dropout = nn.Dropout(dropout)

    def forward(self, words):
        # (input) words : (batch_size, seq_len)
        words = words.permute(1,0)
        # words : (seq_len, batch_size)

        embedded = self.dropout(self.embedding(words))
        # embedded : (seq_len, batch_size, embedding_dim)
        output, (hidden, cell) = self.lstm(embedded)
        # output: (seq_len, batch_size, hidden_dim * 2)
        # hidden: (num_layers * 2, batch_size, hidden_dim)
        # cell: (num_layers * 2, batch_size, hidden_dim)

        hidden = torch.cat((hidden[-2, :, :], hidden[-1, :, :]), dim=1)
        hidden = self.dropout(hidden)
        # hidden: (batch_size, hidden_dim * 2)

        pred = self.fc(hidden.squeeze(0))
        # result: (batch_size, output_dim)
        return {"pred":pred}

我们同样可以在 iPython 环境中查看这个模型的网络结构

LSTMText(
  (embedding): Embedding(16292, 100)
  (lstm): LSTM(100, 64, num_layers=2, dropout=0.5, bidirectional=True)
  (fc): Linear(in_features=128, out_features=2, bias=True)
  (dropout): Dropout(p=0.5, inplace=False)
)

使用 modules 编写模型

下面我们使用 fastNLP.modules 中的组件来构建同样的网络。由于 fastNLP 统一把 batch_size 放在第一维, 在编写代码的过程中会有一定的便利。

from fastNLP.modules import Embedding, LSTM, MLP

class MyText(nn.Module):
    def __init__(self, vocab_size, embedding_dim, output_dim, hidden_dim=64, num_layers=2, dropout=0.5):
        super().__init__()

        self.embedding = Embedding((vocab_size, embedding_dim))
        self.lstm = LSTM(embedding_dim, hidden_dim, num_layers=num_layers, bidirectional=True)
        self.mlp = MLP([hidden_dim*2,output_dim], dropout=dropout)

    def forward(self, words):
        embedded = self.embedding(words)
        _,(hidden,_) = self.lstm(embedded)
        pred = self.mlp(torch.cat((hidden[-1],hidden[-2]),dim=1))
        return {"pred":pred}

我们自己编写模型的网络结构如下

MyText(
  (embedding): Embedding(
    (embed): Embedding(16292, 100)
    (dropout): Dropout(p=0.0, inplace=False)
  )
  (lstm): LSTM(
    (lstm): LSTM(100, 64, num_layers=2, batch_first=True, bidirectional=True)
  )
  (mlp): MLP(
    (hiddens): ModuleList()
    (output): Linear(in_features=128, out_features=2, bias=True)
    (dropout): Dropout(p=0.5, inplace=False)
  )
)

FastNLP 中包含的各种模块如下表,您可以点击具体的名称查看详细的 API,也可以通过 fastNLP.modules package 进行了解。

名称

介绍

ConvolutionCharEncoder

char级别的卷积 encoder

LSTMCharEncoder

char级别基于LSTM的 encoder

ConvMaxpool

结合了Convolution和Max-Pooling于一体的模块

LSTM

LSTM模块

轻量封装了PyTorch的LSTM

StarTransformer

Star-Transformer 的encoder部分

TransformerEncoder

Transformer的encoder模块,不包含embedding层

VarRNN

Variational Dropout RNN 模块

VarLSTM

Variational Dropout LSTM 模块

VarGRU

Variational Dropout GRU 模块

MaxPool

Max-pooling模块

MaxPoolWithMask

带mask矩阵的max pooling。在做 max-pooling的时候不会考虑mask值为0的位置。

AvgPool

Average-pooling模块

AvgPoolWithMask

带mask矩阵的average pooling。在做 average-pooling的时候不会考虑mask值为0的位置。

MultiHeadAttention

MultiHead Attention 模块

MLP

简单的多层感知器模块

ConditionalRandomField

条件随机场模块

viterbi_decode

给定一个特征矩阵以及转移分数矩阵,计算出最佳的路径以及对应的分数 (与 ConditionalRandomField 配合使用)

allowed_transitions

给定一个id到label的映射表,返回所有可以跳转的列表(与 ConditionalRandomField 配合使用)

TimestepDropout

简单包装过的Dropout 组件