chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
# Neural Machine Translation with Byte-Level Subwords
|
||||
|
||||
https://arxiv.org/abs/1909.03341
|
||||
|
||||
We provide an implementation of byte-level byte-pair encoding (BBPE), taking IWSLT 2017 Fr-En translation as
|
||||
example.
|
||||
|
||||
## Data
|
||||
Get data and generate fairseq binary dataset:
|
||||
```bash
|
||||
bash ./get_data.sh
|
||||
```
|
||||
|
||||
## Model Training
|
||||
Train Transformer model with Bi-GRU embedding contextualization (implemented in `gru_transformer.py`):
|
||||
```bash
|
||||
# VOCAB=bytes
|
||||
# VOCAB=chars
|
||||
VOCAB=bbpe2048
|
||||
# VOCAB=bpe2048
|
||||
# VOCAB=bbpe4096
|
||||
# VOCAB=bpe4096
|
||||
# VOCAB=bpe16384
|
||||
```
|
||||
```bash
|
||||
fairseq-train "data/bin_${VOCAB}" --task translation --user-dir examples/byte_level_bpe/gru_transformer \
|
||||
--arch gru_transformer --encoder-layers 2 --decoder-layers 2 --dropout 0.3 --share-all-embeddings \
|
||||
--optimizer adam --adam-betas '(0.9, 0.98)' \
|
||||
--lr 5e-4 --lr-scheduler inverse_sqrt --warmup-updates 4000 \
|
||||
--criterion label_smoothed_cross_entropy --label-smoothing 0.1 \
|
||||
--log-format 'simple' --log-interval 100 --save-dir "checkpoints/${VOCAB}" \
|
||||
--batch-size 100 --max-update 100000 --update-freq 2
|
||||
```
|
||||
|
||||
## Generation
|
||||
`fairseq-generate` requires bytes (BBPE) decoder to convert byte-level representation back to characters:
|
||||
```bash
|
||||
# BPE=--bpe bytes
|
||||
# BPE=--bpe characters
|
||||
BPE=--bpe byte_bpe --sentencepiece-model-path data/spm_bbpe2048.model
|
||||
# BPE=--bpe sentencepiece --sentencepiece-model data/spm_bpe2048.model
|
||||
# BPE=--bpe byte_bpe --sentencepiece-model-path data/spm_bbpe4096.model
|
||||
# BPE=--bpe sentencepiece --sentencepiece-model data/spm_bpe4096.model
|
||||
# BPE=--bpe sentencepiece --sentencepiece-model data/spm_bpe16384.model
|
||||
```
|
||||
|
||||
```bash
|
||||
fairseq-generate "data/bin_${VOCAB}" --task translation --user-dir examples/byte_level_bpe/gru_transformer \
|
||||
--source-lang fr --gen-subset test --sacrebleu --path "checkpoints/${VOCAB}/checkpoint_last.pt" \
|
||||
--tokenizer moses --moses-target-lang en ${BPE}
|
||||
```
|
||||
When using `fairseq-interactive`, bytes (BBPE) encoder/decoder is required to tokenize input data and detokenize model predictions:
|
||||
```bash
|
||||
fairseq-interactive "data/bin_${VOCAB}" --task translation --user-dir examples/byte_level_bpe/gru_transformer \
|
||||
--path "checkpoints/${VOCAB}/checkpoint_last.pt" --input data/test.fr --tokenizer moses --moses-source-lang fr \
|
||||
--moses-target-lang en ${BPE} --buffer-size 1000 --max-tokens 10000
|
||||
```
|
||||
|
||||
## Results
|
||||
| Vocabulary | Model | BLEU |
|
||||
|:-------------:|:-------------:|:-------------:|
|
||||
| Joint BPE 16k ([Kudo, 2018](https://arxiv.org/abs/1804.10959)) | 512d LSTM 2+2 | 33.81 |
|
||||
| Joint BPE 16k | Transformer base 2+2 (w/ GRU) | 36.64 (36.72) |
|
||||
| Joint BPE 4k | Transformer base 2+2 (w/ GRU) | 35.49 (36.10) |
|
||||
| Joint BBPE 4k | Transformer base 2+2 (w/ GRU) | 35.61 (35.82) |
|
||||
| Joint BPE 2k | Transformer base 2+2 (w/ GRU) | 34.87 (36.13) |
|
||||
| Joint BBPE 2k | Transformer base 2+2 (w/ GRU) | 34.98 (35.43) |
|
||||
| Characters | Transformer base 2+2 (w/ GRU) | 31.78 (33.30) |
|
||||
| Bytes | Transformer base 2+2 (w/ GRU) | 31.57 (33.62) |
|
||||
|
||||
|
||||
## Citation
|
||||
```
|
||||
@misc{wang2019neural,
|
||||
title={Neural Machine Translation with Byte-Level Subwords},
|
||||
author={Changhan Wang and Kyunghyun Cho and Jiatao Gu},
|
||||
year={2019},
|
||||
eprint={1909.03341},
|
||||
archivePrefix={arXiv},
|
||||
primaryClass={cs.CL}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Contact
|
||||
Changhan Wang ([changhan@fb.com](mailto:changhan@fb.com)),
|
||||
Kyunghyun Cho ([kyunghyuncho@fb.com](mailto:kyunghyuncho@fb.com)),
|
||||
Jiatao Gu ([jgu@fb.com](mailto:jgu@fb.com))
|
||||
@@ -0,0 +1,254 @@
|
||||
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||
#
|
||||
# This source code is licensed under the MIT license found in the
|
||||
# LICENSE file in the root directory of this source tree.
|
||||
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import os.path as op
|
||||
from collections import namedtuple
|
||||
from multiprocessing import cpu_count
|
||||
from typing import List, Optional
|
||||
|
||||
import sentencepiece as sp
|
||||
from fairseq.data.encoders.byte_bpe import ByteBPE
|
||||
from fairseq.data.encoders.byte_utils import byte_encode
|
||||
from fairseq.data.encoders.bytes import Bytes
|
||||
from fairseq.data.encoders.characters import Characters
|
||||
from fairseq.data.encoders.moses_tokenizer import MosesTokenizer
|
||||
from fairseq.data.encoders.sentencepiece_bpe import SentencepieceBPE
|
||||
|
||||
|
||||
SPLITS = ["train", "valid", "test"]
|
||||
|
||||
|
||||
def _convert_xml(in_path: str, out_path: str):
|
||||
with open(in_path) as f, open(out_path, "w") as f_o:
|
||||
for s in f:
|
||||
ss = s.strip()
|
||||
if not ss.startswith("<seg"):
|
||||
continue
|
||||
ss = ss.replace("</seg>", "").split('">')
|
||||
assert len(ss) == 2
|
||||
f_o.write(ss[1].strip() + "\n")
|
||||
|
||||
|
||||
def _convert_train(in_path: str, out_path: str):
|
||||
with open(in_path) as f, open(out_path, "w") as f_o:
|
||||
for s in f:
|
||||
ss = s.strip()
|
||||
if ss.startswith("<"):
|
||||
continue
|
||||
f_o.write(ss.strip() + "\n")
|
||||
|
||||
|
||||
def _get_bytes(in_path: str, out_path: str):
|
||||
with open(in_path) as f, open(out_path, "w") as f_o:
|
||||
for s in f:
|
||||
f_o.write(Bytes.encode(s.strip()) + "\n")
|
||||
|
||||
|
||||
def _get_chars(in_path: str, out_path: str):
|
||||
with open(in_path) as f, open(out_path, "w") as f_o:
|
||||
for s in f:
|
||||
f_o.write(Characters.encode(s.strip()) + "\n")
|
||||
|
||||
|
||||
def pretokenize(in_path: str, out_path: str, src: str, tgt: str):
|
||||
Args = namedtuple(
|
||||
"Args",
|
||||
[
|
||||
"moses_source_lang",
|
||||
"moses_target_lang",
|
||||
"moses_no_dash_splits",
|
||||
"moses_no_escape",
|
||||
],
|
||||
)
|
||||
args = Args(
|
||||
moses_source_lang=src,
|
||||
moses_target_lang=tgt,
|
||||
moses_no_dash_splits=False,
|
||||
moses_no_escape=False,
|
||||
)
|
||||
pretokenizer = MosesTokenizer(args)
|
||||
with open(in_path) as f, open(out_path, "w") as f_o:
|
||||
for s in f:
|
||||
f_o.write(pretokenizer.encode(s.strip()) + "\n")
|
||||
|
||||
|
||||
def _convert_to_bchar(in_path_prefix: str, src: str, tgt: str, out_path: str):
|
||||
with open(out_path, "w") as f_o:
|
||||
for lang in [src, tgt]:
|
||||
with open(f"{in_path_prefix}.{lang}") as f:
|
||||
for s in f:
|
||||
f_o.write(byte_encode(s.strip()) + "\n")
|
||||
|
||||
|
||||
def _get_bpe(in_path: str, model_prefix: str, vocab_size: int):
|
||||
arguments = [
|
||||
f"--input={in_path}",
|
||||
f"--model_prefix={model_prefix}",
|
||||
f"--model_type=bpe",
|
||||
f"--vocab_size={vocab_size}",
|
||||
"--character_coverage=1.0",
|
||||
"--normalization_rule_name=identity",
|
||||
f"--num_threads={cpu_count()}",
|
||||
]
|
||||
sp.SentencePieceTrainer.Train(" ".join(arguments))
|
||||
|
||||
|
||||
def _apply_bbpe(model_path: str, in_path: str, out_path: str):
|
||||
Args = namedtuple("Args", ["sentencepiece_model_path"])
|
||||
args = Args(sentencepiece_model_path=model_path)
|
||||
tokenizer = ByteBPE(args)
|
||||
with open(in_path) as f, open(out_path, "w") as f_o:
|
||||
for s in f:
|
||||
f_o.write(tokenizer.encode(s.strip()) + "\n")
|
||||
|
||||
|
||||
def _apply_bpe(model_path: str, in_path: str, out_path: str):
|
||||
Args = namedtuple("Args", ["sentencepiece_model"])
|
||||
args = Args(sentencepiece_model=model_path)
|
||||
tokenizer = SentencepieceBPE(args)
|
||||
with open(in_path) as f, open(out_path, "w") as f_o:
|
||||
for s in f:
|
||||
f_o.write(tokenizer.encode(s.strip()) + "\n")
|
||||
|
||||
|
||||
def _concat_files(in_paths: List[str], out_path: str):
|
||||
with open(out_path, "w") as f_o:
|
||||
for p in in_paths:
|
||||
with open(p) as f:
|
||||
for r in f:
|
||||
f_o.write(r)
|
||||
|
||||
|
||||
def preprocess_iwslt17(
|
||||
root: str,
|
||||
src: str,
|
||||
tgt: str,
|
||||
bpe_size: Optional[int],
|
||||
need_chars: bool,
|
||||
bbpe_size: Optional[int],
|
||||
need_bytes: bool,
|
||||
):
|
||||
# extract bitext
|
||||
in_root = op.join(root, f"{src}-{tgt}")
|
||||
for lang in [src, tgt]:
|
||||
_convert_train(
|
||||
op.join(in_root, f"train.tags.{src}-{tgt}.{lang}"),
|
||||
op.join(root, f"train.{lang}"),
|
||||
)
|
||||
_convert_xml(
|
||||
op.join(in_root, f"IWSLT17.TED.dev2010.{src}-{tgt}.{lang}.xml"),
|
||||
op.join(root, f"valid.{lang}"),
|
||||
)
|
||||
_convert_xml(
|
||||
op.join(in_root, f"IWSLT17.TED.tst2015.{src}-{tgt}.{lang}.xml"),
|
||||
op.join(root, f"test.{lang}"),
|
||||
)
|
||||
# pre-tokenize
|
||||
for lang in [src, tgt]:
|
||||
for split in SPLITS:
|
||||
pretokenize(
|
||||
op.join(root, f"{split}.{lang}"),
|
||||
op.join(root, f"{split}.moses.{lang}"),
|
||||
src,
|
||||
tgt,
|
||||
)
|
||||
# tokenize with BPE vocabulary
|
||||
if bpe_size is not None:
|
||||
# learn vocabulary
|
||||
concated_train_path = op.join(root, "train.all")
|
||||
_concat_files(
|
||||
[op.join(root, "train.moses.fr"), op.join(root, "train.moses.en")],
|
||||
concated_train_path,
|
||||
)
|
||||
bpe_model_prefix = op.join(root, f"spm_bpe{bpe_size}")
|
||||
_get_bpe(concated_train_path, bpe_model_prefix, bpe_size)
|
||||
os.remove(concated_train_path)
|
||||
# apply
|
||||
for lang in [src, tgt]:
|
||||
for split in SPLITS:
|
||||
_apply_bpe(
|
||||
bpe_model_prefix + ".model",
|
||||
op.join(root, f"{split}.moses.{lang}"),
|
||||
op.join(root, f"{split}.moses.bpe{bpe_size}.{lang}"),
|
||||
)
|
||||
# tokenize with bytes vocabulary
|
||||
if need_bytes:
|
||||
for lang in [src, tgt]:
|
||||
for split in SPLITS:
|
||||
_get_bytes(
|
||||
op.join(root, f"{split}.moses.{lang}"),
|
||||
op.join(root, f"{split}.moses.bytes.{lang}"),
|
||||
)
|
||||
# tokenize with characters vocabulary
|
||||
if need_chars:
|
||||
for lang in [src, tgt]:
|
||||
for split in SPLITS:
|
||||
_get_chars(
|
||||
op.join(root, f"{split}.moses.{lang}"),
|
||||
op.join(root, f"{split}.moses.chars.{lang}"),
|
||||
)
|
||||
# tokenize with byte-level BPE vocabulary
|
||||
if bbpe_size is not None:
|
||||
# learn vocabulary
|
||||
bchar_path = op.join(root, "train.bchar")
|
||||
_convert_to_bchar(op.join(root, "train.moses"), src, tgt, bchar_path)
|
||||
bbpe_model_prefix = op.join(root, f"spm_bbpe{bbpe_size}")
|
||||
_get_bpe(bchar_path, bbpe_model_prefix, bbpe_size)
|
||||
os.remove(bchar_path)
|
||||
# apply
|
||||
for lang in [src, tgt]:
|
||||
for split in SPLITS:
|
||||
_apply_bbpe(
|
||||
bbpe_model_prefix + ".model",
|
||||
op.join(root, f"{split}.moses.{lang}"),
|
||||
op.join(root, f"{split}.moses.bbpe{bbpe_size}.{lang}"),
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--root", type=str, default="data")
|
||||
parser.add_argument(
|
||||
"--bpe-vocab",
|
||||
default=None,
|
||||
type=int,
|
||||
help="Generate tokenized bitext with BPE of size K."
|
||||
"Default to None (disabled).",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--bbpe-vocab",
|
||||
default=None,
|
||||
type=int,
|
||||
help="Generate tokenized bitext with BBPE of size K."
|
||||
"Default to None (disabled).",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--byte-vocab",
|
||||
action="store_true",
|
||||
help="Generate tokenized bitext with bytes vocabulary",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--char-vocab",
|
||||
action="store_true",
|
||||
help="Generate tokenized bitext with chars vocabulary",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
preprocess_iwslt17(
|
||||
args.root,
|
||||
"fr",
|
||||
"en",
|
||||
args.bpe_vocab,
|
||||
args.char_vocab,
|
||||
args.bbpe_vocab,
|
||||
args.byte_vocab,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,47 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||
#
|
||||
# This source code is licensed under the MIT license found in the
|
||||
# LICENSE file in the root directory of this source tree.
|
||||
|
||||
PY_BIN_ROOT=
|
||||
|
||||
# PyPI dependency
|
||||
${PY_BIN_ROOT}pip install sentencepiece sacremoses
|
||||
|
||||
# Get data
|
||||
if [ ! -d "data" ]; then
|
||||
mkdir data
|
||||
fi
|
||||
|
||||
if [ ! -f "data/fr-en.tgz" ]; then
|
||||
wget https://wit3.fbk.eu/archive/2017-01-trnted/texts/fr/en/fr-en.tgz -P data
|
||||
tar xvf data/fr-en.tgz -C data
|
||||
fi
|
||||
${PY_BIN_ROOT}python get_bitext.py --bpe-vocab 16384 --byte-vocab --char-vocab
|
||||
for VOCAB_SIZE in 2048 4096; do
|
||||
${PY_BIN_ROOT}python get_bitext.py --bpe-vocab ${VOCAB_SIZE} --bbpe-vocab ${VOCAB_SIZE}
|
||||
done
|
||||
rm -r data/fr-en data/fr-en.tgz
|
||||
|
||||
# Generate binary dataset
|
||||
${PY_BIN_ROOT}/fairseq-preprocess --source-lang fr --target-lang en --destdir data/bin_bpe16384 --joined-dictionary \
|
||||
--workers "$(nproc)" --trainpref data/train.moses.bpe16384 --validpref data/valid.moses.bpe16384 \
|
||||
--testpref data/test.moses.bpe16384
|
||||
|
||||
${PY_BIN_ROOT}/fairseq-preprocess --source-lang fr --target-lang en --destdir data/bin_bytes --joined-dictionary \
|
||||
--workers "$(nproc)" --trainpref data/train.moses.bytes --validpref data/valid.moses.bytes \
|
||||
--testpref data/test.moses.bytes
|
||||
|
||||
${PY_BIN_ROOT}/fairseq-preprocess --source-lang fr --target-lang en --destdir data/bin_chars --joined-dictionary \
|
||||
--workers "$(nproc)" --trainpref data/train.moses.chars --validpref data/valid.moses.chars \
|
||||
--testpref data/test.moses.chars
|
||||
|
||||
for VOCAB_SIZE in 2048 4096; do
|
||||
for TYPE in bbpe bpe; do
|
||||
${PY_BIN_ROOT}/fairseq-preprocess --source-lang fr --target-lang en --destdir "data/bin_${TYPE}${VOCAB_SIZE}" \
|
||||
--joined-dictionary --workers "$(nproc)" --trainpref "data/train.moses.${TYPE}${VOCAB_SIZE}" \
|
||||
--validpref "data/valid.moses.${TYPE}${VOCAB_SIZE}" --testpref "data/test.moses.${TYPE}${VOCAB_SIZE}"
|
||||
done
|
||||
done
|
||||
@@ -0,0 +1,107 @@
|
||||
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||
#
|
||||
# This source code is licensed under the MIT license found in the
|
||||
# LICENSE file in the root directory of this source tree.
|
||||
|
||||
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||
#
|
||||
# This source code is licensed under the MIT license found in the
|
||||
# LICENSE file in the root directory of this source tree.
|
||||
|
||||
import torch.nn as nn
|
||||
import torch.nn.functional as F
|
||||
from fairseq.models import register_model, register_model_architecture
|
||||
from fairseq.models.transformer import TransformerEncoder, TransformerModel
|
||||
|
||||
|
||||
@register_model("gru_transformer")
|
||||
class GRUTransformerModel(TransformerModel):
|
||||
@classmethod
|
||||
def build_encoder(cls, args, src_dict, embed_tokens):
|
||||
return GRUTransformerEncoder(args, src_dict, embed_tokens)
|
||||
|
||||
|
||||
class GRUTransformerEncoder(TransformerEncoder):
|
||||
def __init__(self, args, dictionary, embed_tokens):
|
||||
super().__init__(args, dictionary, embed_tokens)
|
||||
self.emb_ctx = nn.GRU(
|
||||
input_size=embed_tokens.embedding_dim,
|
||||
hidden_size=embed_tokens.embedding_dim // 2,
|
||||
num_layers=1,
|
||||
bidirectional=True,
|
||||
)
|
||||
|
||||
def forward_embedding(self, src_tokens):
|
||||
# embed tokens and positions
|
||||
x = embed = self.embed_scale * self.embed_tokens(src_tokens)
|
||||
if self.embed_positions is not None:
|
||||
x = embed + self.embed_positions(src_tokens)
|
||||
|
||||
# contextualize embeddings
|
||||
x = x.transpose(0, 1)
|
||||
x = self.dropout_module(x)
|
||||
x, _ = self.emb_ctx.forward(x)
|
||||
x = x.transpose(0, 1)
|
||||
|
||||
if self.layernorm_embedding is not None:
|
||||
x = self.layernorm_embedding(x)
|
||||
x = self.dropout_module(x)
|
||||
return x, embed
|
||||
|
||||
|
||||
@register_model_architecture("gru_transformer", "gru_transformer")
|
||||
def gru_transformer_base_architecture(args):
|
||||
args.encoder_embed_path = getattr(args, "encoder_embed_path", None)
|
||||
args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512)
|
||||
args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 2048)
|
||||
args.encoder_layers = getattr(args, "encoder_layers", 6)
|
||||
args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 8)
|
||||
args.encoder_normalize_before = getattr(args, "encoder_normalize_before", False)
|
||||
args.encoder_learned_pos = getattr(args, "encoder_learned_pos", False)
|
||||
args.decoder_embed_path = getattr(args, "decoder_embed_path", None)
|
||||
args.decoder_embed_dim = getattr(args, "decoder_embed_dim", args.encoder_embed_dim)
|
||||
args.decoder_ffn_embed_dim = getattr(
|
||||
args, "decoder_ffn_embed_dim", args.encoder_ffn_embed_dim
|
||||
)
|
||||
args.decoder_layers = getattr(args, "decoder_layers", 6)
|
||||
args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 8)
|
||||
args.decoder_normalize_before = getattr(args, "decoder_normalize_before", False)
|
||||
args.decoder_learned_pos = getattr(args, "decoder_learned_pos", False)
|
||||
args.attention_dropout = getattr(args, "attention_dropout", 0.0)
|
||||
args.activation_dropout = getattr(args, "activation_dropout", 0.0)
|
||||
args.activation_fn = getattr(args, "activation_fn", "relu")
|
||||
args.dropout = getattr(args, "dropout", 0.1)
|
||||
args.adaptive_softmax_cutoff = getattr(args, "adaptive_softmax_cutoff", None)
|
||||
args.adaptive_softmax_dropout = getattr(args, "adaptive_softmax_dropout", 0)
|
||||
args.share_decoder_input_output_embed = getattr(
|
||||
args, "share_decoder_input_output_embed", False
|
||||
)
|
||||
args.share_all_embeddings = getattr(args, "share_all_embeddings", False)
|
||||
args.no_token_positional_embeddings = getattr(
|
||||
args, "no_token_positional_embeddings", False
|
||||
)
|
||||
args.adaptive_input = getattr(args, "adaptive_input", False)
|
||||
args.no_cross_attention = getattr(args, "no_cross_attention", False)
|
||||
args.cross_self_attention = getattr(args, "cross_self_attention", False)
|
||||
args.layer_wise_attention = getattr(args, "layer_wise_attention", False)
|
||||
|
||||
args.decoder_output_dim = getattr(
|
||||
args, "decoder_output_dim", args.decoder_embed_dim
|
||||
)
|
||||
args.decoder_input_dim = getattr(args, "decoder_input_dim", args.decoder_embed_dim)
|
||||
|
||||
args.no_scale_embedding = getattr(args, "no_scale_embedding", False)
|
||||
args.layernorm_embedding = getattr(args, "layernorm_embedding", False)
|
||||
|
||||
|
||||
@register_model_architecture("gru_transformer", "gru_transformer_big")
|
||||
def gru_transformer_big(args):
|
||||
args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1024)
|
||||
args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 4096)
|
||||
args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 16)
|
||||
args.encoder_normalize_before = getattr(args, "encoder_normalize_before", False)
|
||||
args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 1024)
|
||||
args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 4096)
|
||||
args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 16)
|
||||
args.dropout = getattr(args, "dropout", 0.3)
|
||||
gru_transformer_base_architecture(args)
|
||||
Reference in New Issue
Block a user