9.6. Краткая реализация рекуррентных нейронных сетей

Как и большинство наших реализаций с нуля, Section 9.5 была создана, чтобы пролить свет на то, как работает каждый компонент. Однако, когда вы ежедневно используете RNN или пишете код для продакшена, вам захочется больше полагаться на библиотеки, которые сокращают как время разработки (за счёт предоставления кода для распространённых моделей и функций), так и время вычислений (за счёт тщательной оптимизации этих библиотечных реализаций). В этом разделе мы покажем, как реализовать ту же языковую модель более эффективно, используя высокоуровневый API, предоставляемый вашим фреймворком глубокого обучения. Как и прежде, мы начнём с загрузки набора данных The Time Machine.

import torch
from torch import nn
from torch.nn import functional as F
from d2l import torch as d2l

9.6.1. Определение модели

Определим следующий класс, используя RNN, реализованную с помощью высокоуровневых API.

class RNN(d2l.Module):  #@save
    """The RNN model implemented with high-level APIs."""
    def __init__(self, num_inputs, num_hiddens):
        super().__init__()
        self.save_hyperparameters()
        self.rnn = nn.RNN(num_inputs, num_hiddens)

    def forward(self, inputs, H=None):
        return self.rnn(inputs, H)

Наследуя класс RNNLMScratch из Section 9.5, следующий класс RNNLM определяет полную языковую модель на основе RNN. Обратите внимание, что нам необходимо создать отдельный полносвязный выходной слой.

class RNNLM(d2l.RNNLMScratch):  #@save
    """The RNN-based language model implemented with high-level APIs."""
    def init_params(self):
        self.linear = nn.LazyLinear(self.vocab_size)

    def output_layer(self, hiddens):
        return self.linear(hiddens).swapaxes(0, 1)

9.6.2. Обучение и предсказание

Перед обучением модели давайте сделаем предсказание с моделью, инициализированной случайными весами. Поскольку мы ещё не обучали сеть, она будет выдавать бессмысленные предсказания.

data = d2l.TimeMachine(batch_size=1024, num_steps=32)
rnn = RNN(num_inputs=len(data.vocab), num_hiddens=32)
model = RNNLM(rnn, vocab_size=len(data.vocab), lr=1)
model.predict('it has', 20, data.vocab)

Далее мы обучим нашу модель, используя высокоуровневый API.

trainer = d2l.Trainer(max_epochs=100, gradient_clip_val=1, num_gpus=1)
trainer.fit(model, data)

По сравнению с Section 9.5 эта модель демонстрирует сопоставимую перплексию, но работает быстрее благодаря оптимизированным реализациям. Как и ранее, мы можем генерировать предсказанные токены, опираясь на заданную префиксную строку.

model.predict('it has', 20, data.vocab, d2l.try_gpu())

9.6.3. Резюме

Высокоуровневые API во фреймворках глубокого обучения предоставляют реализации стандартных рекуррентных нейронных сетей. Эти библиотеки позволяют избежать траты времени на повторную реализацию стандартных моделей. Кроме того, реализации во фреймворках часто высоко оптимизированы, что обеспечивает значительный (вычислительный) прирост производительности по сравнению с реализациями, написанными с нуля.

9.6.4. Упражнения

  1. Можно ли заставить модель RNN переобучаться, используя высокоуровневые API?

  2. Реализуйте авторегрессионную модель Section 9.1 с помощью рекуррентной нейронной сети.

Обсуждения