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