Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Seq2SeqTrainer crash when BatchEncoding data is None #31418

Merged
merged 1 commit into from
Jul 8, 2024

Conversation

iohub
Copy link
Contributor

@iohub iohub commented Jun 14, 2024

What does this PR do?

Fix Seq2SeqTrainer crash when evaluate dataset's labels is None.

  • Reproduction example:

finetune GLM4 model with customize DataCollator and customize Seq2SeqTrainer according to finetune script : https://github.com/THUDM/GLM-4/blob/main/finetune_demo/finetune.py

class DataCollatorForSeq2Seq(_DataCollatorForSeq2Seq):
    def __call__(self, features, return_tensors=None):
        output_ids = ([feature['output_ids'] for feature in features] if 'output_ids' in features[0].keys() else None)
        if output_ids is not None:
            max_output_length = max(len(out) for out in output_ids)
            if self.pad_to_multiple_of is not None:
                max_output_length = (
                        (
                                max_output_length + self.pad_to_multiple_of - 1) //
                        self.pad_to_multiple_of * self.pad_to_multiple_of
                )
            for feature in features:
                remainder = [self.tokenizer.pad_token_id] * (
                        max_output_length - len(feature['output_ids'])
                )
                if isinstance(feature['output_ids'], list):
                    feature['output_ids'] = feature['output_ids'] + remainder
                else:
                    feature['output_ids'] = np.concatenate(
                        [feature['output_ids'], remainder]
                    ).astype(np.int64)
        return super().__call__(features, return_tensors)
class Seq2SeqTrainer(_Seq2SeqTrainer):
    def prediction_step(
            self,
            model: nn.Module,
            inputs: dict[str, Any],
            prediction_loss_only: bool,
            ignore_keys=None,
            **gen_kwargs,
    ) -> tuple[Optional[float], Optional[torch.Tensor], Optional[torch.Tensor]]:
        if self.args.predict_with_generate:
            output_ids = inputs.pop('output_ids')
        input_ids = inputs['input_ids']
        loss, generated_tokens, labels = super().prediction_step(
            model, inputs, prediction_loss_only, ignore_keys, **gen_kwargs
        )
        generated_tokens = generated_tokens[:, input_ids.size()[1]:]
        labels = output_ids
        return loss, generated_tokens, labels
  • Root cause

https://github.com/iohub/transformers/blob/b7672826cad31e30319487af876e608d8af7d37b/src/transformers/data/data_collator.py#L664

        # reintroduce side effects via tokenizer that return respective datatypes for the `return_tensors` argument
        if batch.get("labels", None) is not None:
            if return_tensors == "pt":
                import torch

                batch["labels"] = torch.tensor(batch["labels"], dtype=torch.int64)
            elif return_tensors == "tf":
                import tensorflow as tf

                batch["labels"] = tf.constant(batch["labels"], dtype=tf.int64)
            else:
                batch["labels"] = np.array(batch["labels"], dtype=np.int64)
        else:
            batch["labels"] = None

As the code showed, batch["labels"] = None may cause None value v in BatchEncoding.

    self.data = {k: v.to(device=device) for k, v in self.data.items()}

Before submitting

  • This PR fixes a typo or improves the docs (you can dismiss the other checks if that's the case).
  • Did you read the contributor guideline,
    Pull Request section?
  • Was this discussed/approved via a Github issue or the forum? Please add a link
    to it if that's the case.
  • Did you make sure to update the documentation with your changes? Here are the
    documentation guidelines, and
    here are tips on formatting docstrings.
  • Did you write any new necessary tests?

Who can review?

@amyeroberts

@iohub iohub changed the title fix crash when BatchEncoding data is None Fix Seq2SeqTrainer crash when BatchEncoding data is None Jun 14, 2024
@iohub iohub marked this pull request as draft June 14, 2024 22:20
@iohub iohub marked this pull request as ready for review June 14, 2024 22:29
Copy link
Collaborator

@amyeroberts amyeroberts left a comment

Choose a reason for hiding this comment

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

Thanks for adding!

It doesn't really make sense for something to be None in the BatchEncoding: this is a class we use to bundle together the outputs of the tokenizer and easily convert to different formats. However, as this is a relatively simple change and it comes from one of our examples and data collators I think it should be OK

@amyeroberts
Copy link
Collaborator

@iohub Could you rebase on main to include upstream changes? This should resolve the currently failing CI tests

@iohub
Copy link
Contributor Author

iohub commented Jul 6, 2024

@amyeroberts Thanks for approval. this branch already rebase on upstream main, and CI tests are success.

@amyeroberts amyeroberts merged commit c1cda0e into huggingface:main Jul 8, 2024
20 checks passed
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.

2 participants