Train and Eval

We use the task of sentiment analysis to give a detailed introduction. And we employ Trainer for a fast training and evaluation.

Load and Process Data

Load Data

We can call the function load() from dataset to load the IMDB dataset. And then the method will return the training set and the testing set of the IMDB dataset.

The code of loading data is as follows:

from mindnlp.dataset import load

imdb_train, imdb_test = load('imdb', shuffle=True)

Process and Split Data

First we obtain the embeddings and the vocabulary, by calling the function from_pretrained() from Glove:

from mindnlp.modules import Glove

embedding, vocab = Glove.from_pretrained('6B', 100, special_tokens=["<unk>", "<pad>"], dropout=0.5)

And then we initialize the tokenizer by instantiating the class BasicTokenizer:

from mindnlp.transforms import BasicTokenizer

tokenizer = BasicTokenizer(True)

Next, we apply the method process() to get the processed training set, by passing the obtained training set, tokenizer, vocabulary and so on into this method:

from mindnlp.dataset import process

imdb_train = process('imdb', imdb_train, tokenizer=tokenizer, vocab=vocab, \
                    bucket_boundaries=[400, 500], max_len=600, drop_remainder=True)

Finally, we employ the method split() to split the processed training set, thus getting a new training set and a validation set:

imdb_train, imdb_valid = imdb_train.split([0.7, 0.3])

Define and Train Model

Define and Initialize Network

We introduce the pre-defined network layers from MindSpore and MindNLP to construct our network.

Use mindspore.nn.LSTM, mindspore.nn.Dense, mindspore.nn.Sigmoid, mindspore.nn.Dropout of MindSpore, and Seq2vecModel, RNNEncoder of MindNLP to construct our model. And apply mindspore.common.initializer.Uniform and mindspore.common.initializer.HeUniform of MindSpore to initialize the weight and bias of the network we construct.

The code of defining and initializing the network is as follows:

import math

from mindspore import nn
from mindspore import ops
from mindspore.common.initializer import Uniform, HeUniform

from mindnlp.modules import RNNEncoder
from mindnlp.abc import Seq2vecModel

class Head(nn.Cell):
    """
    Head for Sentiment Classification model
    """
    def __init__(self, hidden_dim, output_dim, dropout):
        super().__init__()
        weight_init = HeUniform(math.sqrt(5))
        bias_init = Uniform(1 / math.sqrt(hidden_dim * 2))
        self.fc = nn.Dense(hidden_dim * 2, output_dim, weight_init=weight_init, bias_init=bias_init)
        self.sigmoid = nn.Sigmoid()
        self.dropout = nn.Dropout(p=dropout)

    def construct(self, context):
        context = ops.concat((context[-2, :, :], context[-1, :, :]), axis=1)
        context = self.dropout(context)
        return self.sigmoid(self.fc(context))

class SentimentClassification(Seq2vecModel):
    """
    Sentiment Classification model
    """
    def __init__(self, encoder, head):
        super().__init__(encoder, head)
        self.encoder = encoder
        self.head = head

    def construct(self, text):
        _, (hidden, _), _ = self.encoder(text)
        output = self.head(hidden)
        return output

hidden_size = 256
output_size = 1
num_layers = 2
bidirectional = True
drop = 0.5

lstm_layer = nn.LSTM(100, hidden_size, num_layers=num_layers, batch_first=True,
                    dropout=drop, bidirectional=bidirectional)

sentiment_encoder = RNNEncoder(embedding, lstm_layer)

sentiment_head = Head(hidden_size, output_size, drop)

net = SentimentClassification(sentiment_encoder, sentiment_head)

Define Loss Function and Optimizer

A loss function is needed when we train the model. We use mindspore.nn.BCELoss provided by MindSpore to define a loss function:

loss = nn.BCELoss(reduction='mean')

After that, define the optimizer required for running the model by calling mindspore.nn.Adam and passing the trainable parameters of the model into it:

optimizer = nn.Adam(net.trainable_params(), learning_rate=0.001)

Define Callbacks

Defining callbacks plays an important role in training models with MindNLP. It helps to add some extra operations to the training process.

For example, we can add BestModelCallback for saving and loading the best model. Or we can use CheckpointCallback for saving the checkpoint. There are also other callbacks for early stop and timing.

When customizing the callbacks we need, we could first initialize the corresponding classes of callbacks, and then declare a callback list of the callbacks we initialized before. Just like:

from mindnlp.engine.callbacks.timer_callback import TimerCallback
from mindnlp.engine.callbacks.earlystop_callback import EarlyStopCallback
from mindnlp.engine.callbacks.best_model_callback import BestModelCallback

timer_callback_epochs = TimerCallback(print_steps=2)
earlystop_callback = EarlyStopCallback(patience=2)
bestmodel_callback = BestModelCallback(save_path='save/callback/best_model', auto_load=True)

callbacks = [timer_callback_epochs, earlystop_callback, bestmodel_callback]

Define Metrics

It is necessary to evaluate the model using one or more metrics. We choose Accuracy to be the metric of the model:

from mindnlp.engine.metrics import Accuracy

metric = Accuracy()

Train and Evaluate Model

After defining the network, the loss function, the optimizer, the callbacks and the metrics, we employ Trainer to train and evaluate the model defined above.

More specifically, when we train the model, we should pass these parameters into Trainer:

  • network: the network to be trained.

  • train_dataset: the dataset for training the model.

  • eval_dataset: the dataset for evaluating the model.

  • metrics: the metrics used for model evaluation.

  • epochs: the total number of training iterations.

  • loss_fn: the loss function.

  • optimizer: the optimizer for updating the trainable parameters.

  • callbacks: the additional operations executed when training.

The example code of training and evaluating the model is as follows:

from mindnlp.engine.trainer import Trainer

trainer = Trainer(network=net, train_dataset=imdb_train, eval_dataset=imdb_valid, metrics=metric,
                    epochs=5, loss_fn=loss, optimizer=optimizer, callbacks=callbacks)

trainer.run(tgt_columns="label")