10.6 Kodavimo ir dekodavimo architektūra

Bendrosiose sekos į seką problemose, tokiose kaip mašininis vertimas (10.5 skyrelis), įvestys ir išvestys yra kintamo ilgio ir nesulygiuotos. Standartinis tokių duomenų tvarkymo metodas yra suprojektuoti kodavimo ir dekodavimo architektūrą (10.6.1 pav.), sudarytą iš dviejų pagrindinių komponentų: kodavimo bloko (angl. encoder), kuris kaip įvestį priima kintamo ilgio seką, ir dekodavimo bloko (angl. decoder), veikiančio kaip sąlyginis kalbos modelis, priimančio užkoduotą įvestį ir tikslinės sekos kairįjį kontekstą bei prognozuojančio kitą tikslinės sekos teksto vienetą.

Kodavimo ir dekodavimo architektūra.

10.6.1 pav. Kodavimo ir dekodavimo architektūra.

Paimkime kaip pavyzdį mašininį vertimą iš anglų į prancūzų kalbą. Turint įvesties seką anglų kalba: „They“, „are“, „watching“, „.“, ši kodavimo ir dekodavimo architektūra pirmiausia užkoduoja kintamo ilgio įvestį į būseną, tada dekoduoja būseną, kad sugeneruotų išverstą seką, teksto vienetas po teksto vieneto, kaip išvestį: „Ils“, „regardent“, „.“. Kadangi kodavimo ir dekodavimo architektūra sudaro skirtingų sekos į seką modelių pagrindą vėlesniuose skyreliuose, šiame skyrelyje ši architektūra paverčiama sąsaja, kuri bus įgyvendinta vėliau.

from d2l import mxnet as d2l
from mxnet.gluon import nn
from d2l import torch as d2l
from torch import nn
from d2l import tensorflow as d2l
import tensorflow as tf
from d2l import jax as d2l
from flax import linen as nn

10.6.1 (Kodavimo blokas)

Kodavimo bloko sąsajoje tik nurodome, kad kodavimo blokas kaip įvestį X priima kintamo ilgio sekas. Įgyvendinimą pateiks bet kuris modelis, paveldintis šią bazinę Encoder klasę.

class Encoder(nn.Block):  #@save
    """The base encoder interface for the encoder--decoder architecture."""
    def __init__(self):
        super().__init__()

    # Later there can be additional arguments (e.g., length excluding padding)
    def forward(self, X, *args):
        raise NotImplementedError
class Encoder(nn.Module):  #@save
    """The base encoder interface for the encoder--decoder architecture."""
    def __init__(self):
        super().__init__()

    # Later there can be additional arguments (e.g., length excluding padding)
    def forward(self, X, *args):
        raise NotImplementedError
class Encoder(tf.keras.layers.Layer):  #@save
    """The base encoder interface for the encoder--decoder architecture."""
    def __init__(self):
        super().__init__()

    # Later there can be additional arguments (e.g., length excluding padding)
    def call(self, X, *args):
        raise NotImplementedError
class Encoder(nn.Module):  #@save
    """The base encoder interface for the encoder--decoder architecture."""
    def setup(self):
        raise NotImplementedError

    # Later there can be additional arguments (e.g., length excluding padding)
    def __call__(self, X, *args):
        raise NotImplementedError

10.6.2 Dekodavimo blokas

Toliau pateiktoje dekodavimo bloko sąsajoje pridedame papildomą metodą init_state, kad kodavimo bloko išvestį (enc_all_outputs) paverstume užkoduota būsena. Atkreipkite dėmesį, kad šis žingsnis gali reikalauti papildomų įvesčių, tokių kaip galiojantis įvesties ilgis, paaiškintas 10.5 skyrelis. Kad kintamo ilgio seką sugeneruotume teksto vienetas po teksto vieneto, kiekvieną kartą dekodavimo blokas gali atvaizduoti įvestį (pvz., ankstesniu laiko žingsniu sugeneruotą teksto vienetą) ir užkoduotą būseną į išvesties teksto vienetą dabartiniu laiko žingsniu.

class Decoder(nn.Block):  #@save
    """The base decoder interface for the encoder--decoder architecture."""
    def __init__(self):
        super().__init__()

    # Later there can be additional arguments (e.g., length excluding padding)
    def init_state(self, enc_all_outputs, *args):
        raise NotImplementedError

    def forward(self, X, state):
        raise NotImplementedError
class Decoder(nn.Module):  #@save
    """The base decoder interface for the encoder--decoder architecture."""
    def __init__(self):
        super().__init__()

    # Later there can be additional arguments (e.g., length excluding padding)
    def init_state(self, enc_all_outputs, *args):
        raise NotImplementedError

    def forward(self, X, state):
        raise NotImplementedError
class Decoder(tf.keras.layers.Layer):  #@save
    """The base decoder interface for the encoder--decoder architecture."""
    def __init__(self):
        super().__init__()

    # Later there can be additional arguments (e.g., length excluding padding)
    def init_state(self, enc_all_outputs, *args):
        raise NotImplementedError

    def call(self, X, state):
        raise NotImplementedError
class Decoder(nn.Module):  #@save
    """The base decoder interface for the encoder--decoder architecture."""
    def setup(self):
        raise NotImplementedError

    # Later there can be additional arguments (e.g., length excluding padding)
    def init_state(self, enc_all_outputs, *args):
        raise NotImplementedError

    def __call__(self, X, state):
        raise NotImplementedError

10.6.3 Kodavimo ir dekodavimo blokų sujungimas

Tiesioginio sklidimo metu kodavimo bloko išvestis naudojama užkoduotai būsenai sukurti, o ši būsena toliau naudojama dekodavimo bloko kaip viena iš jo įvesčių.

class EncoderDecoder(d2l.Classifier):  #@save
    """The base class for the encoder--decoder architecture."""
    def __init__(self, encoder, decoder):
        super().__init__()
        self.encoder = encoder
        self.decoder = decoder

    def forward(self, enc_X, dec_X, *args):
        enc_all_outputs = self.encoder(enc_X, *args)
        dec_state = self.decoder.init_state(enc_all_outputs, *args)
        # Return decoder output only
        return self.decoder(dec_X, dec_state)[0]
class EncoderDecoder(d2l.Classifier):  #@save
    """The base class for the encoder--decoder architecture."""
    def __init__(self, encoder, decoder):
        super().__init__()
        self.encoder = encoder
        self.decoder = decoder

    def call(self, enc_X, dec_X, *args):
        enc_all_outputs = self.encoder(enc_X, *args, training=True)
        dec_state = self.decoder.init_state(enc_all_outputs, *args)
        # Return decoder output only
        return self.decoder(dec_X, dec_state, training=True)[0]
class EncoderDecoder(d2l.Classifier):  #@save
    """The base class for the encoder--decoder architecture."""
    encoder: nn.Module
    decoder: nn.Module
    training: bool

    def __call__(self, enc_X, dec_X, *args):
        enc_all_outputs = self.encoder(enc_X, *args, training=self.training)
        dec_state = self.decoder.init_state(enc_all_outputs, *args)
        # Return decoder output only
        return self.decoder(dec_X, dec_state, training=self.training)[0]

Kitame skyrelyje pamatysime, kaip taikyti RNN projektuojant sekos į seką modelius, pagrįstus šia kodavimo ir dekodavimo architektūra.

10.6.4 Santrauka

Kodavimo ir dekodavimo architektūros gali tvarkyti įvestis ir išvestis, kurios abi yra kintamo ilgio sekos, todėl tinka sekos į seką problemoms, tokioms kaip mašininis vertimas. Kodavimo blokas kaip įvestį priima kintamo ilgio seką ir paverčia ją fiksuotos formos būsena. Dekodavimo blokas fiksuotos formos užkoduotą būseną atvaizduoja į kintamo ilgio seką.

10.6.5 Pratimai

  1. Tarkime, kad kodavimo ir dekodavimo architektūrai įgyvendinti naudojame neuroninius tinklus. Ar kodavimo ir dekodavimo blokai turi būti to paties tipo neuroniniai tinklai?
  2. Be mašininio vertimo, ar galite sugalvoti kitą taikymą, kuriame galima taikyti kodavimo ir dekodavimo architektūrą?

Diskusijos

Diskusijos

Diskusijos

Diskusijos