Model templates#7636
Conversation
bff5bbd to
d661133
Compare
0355f30 to
1bd4ae9
Compare
fe0fdeb to
83f9a1e
Compare
e82579b to
4a602db
Compare
1bff00e to
ee998fb
Compare
sgugger
left a comment
There was a problem hiding this comment.
This super cool!
I mainly have comments on some docstrings not updated to the new standards (Et tu Brute).
|
|
||
| def run(self): | ||
| # Ensure that there is no other `cookiecutter-template-xxx` directory in the current working directory | ||
| directories = [directory for directory in os.listdir() if "cookiecutter-template-" in directory[:22]] |
There was a problem hiding this comment.
Any reason not to use == in the test?
|
|
||
| MODEL_NAMES_MAPPING = OrderedDict( | ||
| [ | ||
| # Add cased model names here |
There was a problem hiding this comment.
| # Add cased model names here | |
| # Add full (and cased) model names here |
| @@ -0,0 +1,91 @@ | |||
| # Using the `cookiecutter` to generate models | |||
There was a problem hiding this comment.
The "the" is weird. Either "Using cookiecutter to generate models" or "Using the cookiecutter templates to generate models"
| encoder_intermediate_dim (:obj:`int`, `optional`, defaults to 4096): | ||
| Dimensionality of the "intermediate" (often named feed-forward) layer in decoder. | ||
| {% endif -%} | ||
| hidden_act (:obj:`str` or :obj:`function`, optional, defaults to "gelu"): |
There was a problem hiding this comment.
| hidden_act (:obj:`str` or :obj:`function`, optional, defaults to "gelu"): | |
| hidden_act (:obj:`str` or :obj:`function`, `optional`, defaults to :obj:`"gelu"`): |
| {% endif -%} | ||
| hidden_act (:obj:`str` or :obj:`function`, optional, defaults to "gelu"): | ||
| The non-linear activation function (function or string) in the encoder and pooler. | ||
| If string, "gelu", "relu", "swish" and "gelu_new" are supported. |
There was a problem hiding this comment.
| If string, "gelu", "relu", "swish" and "gelu_new" are supported. | |
| If string, :obj:`"gelu"`, :obj:`"relu"`, :obj:`"selu"` and :obj:`"gelu_new"` are supported. |
| Position outside of the sequence are not taken into account for computing the loss. | ||
| end_positions (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`): | ||
| Labels for position (index) of the end of the labelled span for computing the token classification loss. | ||
| Positions are clamped to the length of the sequence (`sequence_length`). |
There was a problem hiding this comment.
| Positions are clamped to the length of the sequence (`sequence_length`). | |
| Positions are clamped to the length of the sequence (:obj:`sequence_length`). |
|
|
||
|
|
||
| # Public API | ||
| def _get_shape(t): |
There was a problem hiding this comment.
Should this be after public API since it's private?
| r""" | ||
| start_positions (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`): | ||
| Labels for position (index) of the start of the labelled span for computing the token classification loss. | ||
| Positions are clamped to the length of the sequence (`sequence_length`). |
There was a problem hiding this comment.
| Positions are clamped to the length of the sequence (`sequence_length`). | |
| Positions are clamped to the length of the sequence (:obj:`sequence_length`). |
| Position outside of the sequence are not taken into account for computing the loss. | ||
| end_positions (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`): | ||
| Labels for position (index) of the end of the labelled span for computing the token classification loss. | ||
| Positions are clamped to the length of the sequence (`sequence_length`). |
There was a problem hiding this comment.
| Positions are clamped to the length of the sequence (`sequence_length`). | |
| Positions are clamped to the length of the sequence (:obj:`sequence_length`). |
| from .configuration_{{cookiecutter.lowercase_modelname}} import {{cookiecutter.uppercase_modelname}}_PRETRAINED_CONFIG_ARCHIVE_MAP, {{cookiecutter.camelcase_modelname}}Config | ||
| # End. | ||
|
|
||
| # Below: "# Add cased model names here" |
There was a problem hiding this comment.
If name is changed in the corresponding file, this line should be adapted.
|
|
||
|
|
||
| logger = logging.get_logger(__name__) | ||
| logger.setLevel(logging.INFO) |
There was a problem hiding this comment.
is that a leftover or should this be merged?
| ``` | ||
| modelname [LysBERT]: | ||
| uppercase_modelname [LYSBERT]: | ||
| lowercase_modelname [<model_name>]: |
There was a problem hiding this comment.
model_name or lys_bert ?
Excited to have Lysbert in the library soon!
|
|
||
| Choose if your model is an encoder-decoder, or an encoder-only architecture. | ||
|
|
||
| If your model is an encoder-only architecture, the generated architecture will be based on the BERT model. |
There was a problem hiding this comment.
Should we base "decoder-only" a.k.a. GPT2 also on BERT for now? or just leave them out?
| intermediate_size (:obj:`int`, optional, defaults to 3072): | ||
| Dimensionality of the "intermediate" (i.e., feed-forward) layer in the Transformer encoder. | ||
| {% else -%} | ||
| encoder_layers (:obj:`int`, `optional`, defaults to 12): |
There was a problem hiding this comment.
can we go for num_encoder_layers similar to num_hidden_layers and same for decoder_attention_heads => num_decoder_attention_heads?
| max_position_embeddings (:obj:`int`, optional, defaults to 512): | ||
| The maximum sequence length that this model might ever be used with. | ||
| Typically set this to something large just in case (e.g., 512 or 1024 or 2048). | ||
| type_vocab_size (:obj:`int`, optional, defaults to 2): |
There was a problem hiding this comment.
Is type_vocab_size actually used for Encoder-Decoder? I don't think this param is used in Bart
There was a problem hiding this comment.
maybe add a if-else here as well if possible
| Dimensionality of the "intermediate" (i.e., feed-forward) layer in the Transformer encoder. | ||
| {% else -%} | ||
| encoder_layers (:obj:`int`, `optional`, defaults to 12): | ||
| Number of encoder layers, 6 are used for the `bart-base` model. |
There was a problem hiding this comment.
maybe delete the "6 are used for the bart-base model part"
| encoder_layers (:obj:`int`, `optional`, defaults to 12): | ||
| Number of encoder layers, 6 are used for the `bart-base` model. | ||
| decoder_layers (:obj:`int`, `optional`, defaults to 12): | ||
| Number of decoder layers, 6 are used for the `bart-base` model. |
There was a problem hiding this comment.
same here bart-base model should be removed probably
| hidden_dropout_prob=0.1, | ||
| attention_probs_dropout_prob=0.1, | ||
| max_position_embeddings=512, | ||
| type_vocab_size=2, |
There was a problem hiding this comment.
I'd throw this out for encoder-decoder type_vocab_size - there is currently no encoder-decoder model that uses this param
| return self.{{cookiecutter.lowercase_modelname}}.encoder | ||
|
|
||
| def get_output_embeddings(self): | ||
| return _make_linear_from_emb(self.{{cookiecutter.lowercase_modelname}}.shared) # make it on the fly |
There was a problem hiding this comment.
this is not the good way of getting the output embedding. A nn.Embedding class should not be instantiated each time the function is called but rather tied in the very beginning at __init__ this should be changed in Bart as well. But I can update this part later if you want
| "use_cache": use_cache, # change this to avoid caching (presumably for debugging) | ||
| } | ||
|
|
||
| def adjust_logits_during_generation(self, logits, cur_len, max_length): |
There was a problem hiding this comment.
very Bart-specific function that I'd probably throw out here, but I think it's okey for now!
| layer_state[self.cache_key] = { | ||
| "prev_key": k.view(bsz, self.num_heads, -1, self.head_dim), | ||
| "prev_value": v.view(bsz, self.num_heads, -1, self.head_dim), | ||
| "prev_key_padding_mask": key_padding_mask if not static_kv else None, |
There was a problem hiding this comment.
masks should not be in the cache - can update this part of the code though as well
patrickvonplaten
left a comment
There was a problem hiding this comment.
Amazing tool! Excited to try it out on a new model.
I think some BART code should be different for new encoder-decoder models, e.g.
- Encoder and Decoder should each be a
PretrainedModelon its own so that these models can be used as stand-alone models. - The caching is overly complex in Bart at the moment (attention_masks don't need to be cached...)
But I can take care of these things after the PR is merged
This PR adds a
cookiecutter-based utility to generate configuration/modeling/tokenization files, the test suites and the statements across the library necessary for adding a new model.This PR's goal is to make adding a new model way simpler, by having a simple CLI request information, generate files, that will then need to be edited to implement the changes relative to BERT. The test suites are implemented and run.
Left to do:
add_new_model.pyfileto_replacefile.Possible improvements:
token_type_idsFor reviewers
If you review this PR, the simplest would be to review the
add_new_model.pyfile, and to generate model files using the utility:And review the generated files.
Reviewing the current files with
{{cookiecutter.lowercase_modelname}}doesn't seem reviewer-friendly to me.