Skip to content

Model templates#7636

Closed
LysandreJik wants to merge 22 commits into
masterfrom
model-templates
Closed

Model templates#7636
LysandreJik wants to merge 22 commits into
masterfrom
model-templates

Conversation

@LysandreJik

@LysandreJik LysandreJik commented Oct 7, 2020

Copy link
Copy Markdown
Member

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:

  • TensorFlow files
  • Tokenizer files
  • Remove the pooler from the base model
  • Ensure the documentation has the right format + .rst file
  • Clean-up/refactor the add_new_model.py file
  • Clarify and add comments to the "dark arts" parts of this PR, such as the to_replace file.
  • Add encoder-decoder models:
    • Modeling PT file
    • Configuration file
    • Testing the modeling PT file
    • Modeling TF file
    • Testing the modeling TF file
    • Update the RST with the appropriate files
    • Add to all auto + init files
  • Run the CI on generated files
  • Update the LysBERT proposal to something better
  • Do a checklist of things left to do after running the script

Possible improvements:

  • Ask the user whether they want to support token_type_ids

For reviewers

If you review this PR, the simplest would be to review the add_new_model.py file, and to generate model files using the utility:

transformers-cli add_new_model

And review the generated files.
Reviewing the current files with {{cookiecutter.lowercase_modelname}} doesn't seem reviewer-friendly to me.

@LysandreJik
LysandreJik marked this pull request as ready for review October 16, 2020 11:48
@LysandreJik
LysandreJik force-pushed the model-templates branch 2 times, most recently from 0355f30 to 1bd4ae9 Compare October 28, 2020 17:36
@LysandreJik
LysandreJik force-pushed the model-templates branch 2 times, most recently from e82579b to 4a602db Compare November 2, 2020 23:29

@sgugger sgugger left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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]]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to use == in the test?


MODEL_NAMES_MAPPING = OrderedDict(
[
# Add cased model names here

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Add cased model names here
# Add full (and cased) model names here

@@ -0,0 +1,91 @@
# Using the `cookiecutter` to generate models

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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"):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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`).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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`).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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`).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If name is changed in the corresponding file, this line should be adapted.



logger = logging.get_logger(__name__)
logger.setLevel(logging.INFO)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is that a leftover or should this be merged?

```
modelname [LysBERT]:
uppercase_modelname [LYSBERT]:
lowercase_modelname [<model_name>]:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is type_vocab_size actually used for Encoder-Decoder? I don't think this param is used in Bart

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

masks should not be in the cache - can update this part of the code though as well

@patrickvonplaten patrickvonplaten left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 PretrainedModel on 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

@LysandreJik
LysandreJik deleted the model-templates branch April 27, 2022 15:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants