






"""simple docstring"""





import argparse
import os

import evaluate
import torch
from datasets import load_dataset
from torch.optim import AdamW
from torch.utils.data import DataLoader
from transformers import AutoModelForSequenceClassification, AutoTokenizer, get_linear_schedule_with_warmup, set_seed

from accelerate import Accelerator, DistributedType


########################################################################
# This is a fully working simple example to use Accelerate,
# specifically showcasing the checkpointing capability,
# and builds off the `nlp_example.py` script.
#
# This example trains a Bert base model on GLUE MRPC
# in any of the following settings (with the same script):
#   - single CPU or single GPU
#   - multi GPUS (using PyTorch distributed mode)
#   - (multi) TPUs
#   - fp16 (mixed-precision) or fp32 (normal precision)
#
# To help focus on the differences in the code, building `DataLoaders`
# was refactored into its own function.
# New additions from the base script can be found quickly by
# looking for the # New Code # tags
#
# To run it in each of these various modes, follow the instructions
# in the readme for examples:
# https://github.com/huggingface/accelerate/tree/main/examples
#
########################################################################

UpperCamelCase					=     16
UpperCamelCase					=     32






def 							A(    snake_case_		,  snake_case_ = 16						):
       """simple docstring"""





       lowercase__:							Optional[Any]         =     AutoTokenizer.from_pretrained("bert-base-cased"						)
       lowercase__:							Tuple         =     load_dataset("glue"		,  "mrpc"						)

       def tokenize_function(snake_case_						):
              # max_length=None => use the model max length (it's actually the default)
              lowercase__:							Dict         =     tokenizer(examples["sentence1"]		,  examples["sentence2"]		,  truncation=snake_case_		,  max_length=snake_case_						)
              return outputs

       # Apply the method we just defined to all the examples in all the splits of the dataset
       # starting with the main process first:
       with accelerator.main_process_first():
              lowercase__:							List[Any]         =     datasets.map(
                  snake_case_		,  batched=snake_case_		,  remove_columns=["idx", "sentence1", "sentence2"]		,  )

       # We also rename the 'label' column to 'labels' which is the expected name for labels by the models of the
       # transformers library
       lowercase__:							List[Any]         =     tokenized_datasets.rename_column("label"		,  "labels"						)

       def collate_fn(snake_case_						):
              # On TPU it's best to pad everything to the same length or training will be very slow.
              lowercase__:							Optional[int]         =     128 if accelerator.distributed_type == DistributedType.TPU else None
              # When using mixed precision we want round multiples of 8/16
              if accelerator.mixed_precision == "fp8":
                     lowercase__:							str         =     16
              elif accelerator.mixed_precision != "no":
                     lowercase__:							int         =     8
              else:
                     lowercase__:							Tuple         =     None

              return tokenizer.pad(
                  snake_case_		,  padding="longest"		,  max_length=snake_case_		,  pad_to_multiple_of=snake_case_		,  return_tensors="pt"		,  )

       # Instantiate dataloaders.
       lowercase__:							Any         =     DataLoader(
           tokenized_datasets["train"]		,  shuffle=snake_case_		,  collate_fn=snake_case_		,  batch_size=snake_case_						)
       lowercase__:							Optional[Any]         =     DataLoader(
           tokenized_datasets["validation"]		,  shuffle=snake_case_		,  collate_fn=snake_case_		,  batch_size=snake_case_						)

       return train_dataloader, eval_dataloader


# For testing only
if os.environ.get("""TESTING_MOCKED_DATALOADERS""", None) == "1":
  from accelerate.test_utils.training import mocked_dataloaders

  UpperCamelCase					=     mocked_dataloaders  # noqa: F811






def 							A(    snake_case_		,  snake_case_						):
       """simple docstring"""





       if os.environ.get("TESTING_MOCKED_DATALOADERS"		,  snake_case_						) == "1":
              lowercase__:							List[Any]         =     2
       # Initialize accelerator
       lowercase__:							List[Any]         =     Accelerator(cpu=args.cpu		,  mixed_precision=args.mixed_precision						)
       # Sample hyper-parameters for learning rate, batch size, seed and a few other HPs
       lowercase__:							Any         =     config["lr"]
       lowercase__:							Dict         =     int(config["num_epochs"]						)
       lowercase__:							str         =     int(config["seed"]						)
       lowercase__:							int         =     int(config["batch_size"]						)

       # New Code #
       # Parse out whether we are saving every epoch or after a certain number of batches
       if hasattr(args.checkpointing_steps		,  "isdigit"						):
              if args.checkpointing_steps == "epoch":
                     lowercase__:							List[Any]         =     args.checkpointing_steps
              elif args.checkpointing_steps.isdigit():
                     lowercase__:							List[str]         =     int(args.checkpointing_steps						)
              else:
                     raise ValueError(
                         F"""Argument `checkpointing_steps` must be either a number or `epoch`. `{args.checkpointing_steps}` passed."""						)
       else:
              lowercase__:							Dict         =     None

       set_seed(snake_case_						)

       lowercase__    ,      lowercase__:							Any         =     get_dataloaders(snake_case_		,  snake_case_						)
       lowercase__:							Any         =     evaluate.load("glue"		,  "mrpc"						)

       # If the batch size is too big we use gradient accumulation
       lowercase__:							int         =     1
       if batch_size > MAX_GPU_BATCH_SIZE and accelerator.distributed_type != DistributedType.TPU:
              lowercase__:							int         =     batch_size // MAX_GPU_BATCH_SIZE
              lowercase__:							Dict         =     MAX_GPU_BATCH_SIZE

       # Instantiate the model (we build the model here so that the seed also control new weights initialization)
       lowercase__:							str         =     AutoModelForSequenceClassification.from_pretrained("bert-base-cased"		,  return_dict=snake_case_						)

       # We could avoid this line since the accelerator is set with `device_placement=True` (default value).
       # Note that if you are placing tensors on devices manually, this line absolutely needs to be before the optimizer
       # creation otherwise training will not work on TPU (`accelerate` will kindly throw an error to make us aware of that).
       lowercase__:							Optional[int]         =     model.to(accelerator.device						)

       # Instantiate optimizer
       lowercase__:							Any         =     AdamW(params=model.parameters()		,  lr=snake_case_						)

       # Instantiate scheduler
       lowercase__:							Dict         =     get_linear_schedule_with_warmup(
           optimizer=snake_case_		,  num_warmup_steps=100		,  num_training_steps=(len(snake_case_						) * num_epochs) // gradient_accumulation_steps		,  )

       # Prepare everything
       # There is no specific order to remember, we just need to unpack the objects in the same order we gave them to the
       # prepare method.
       lowercase__    ,      lowercase__    ,      lowercase__    ,      lowercase__    ,      lowercase__:							List[str]         =     accelerator.prepare(
           snake_case_		,  snake_case_		,  snake_case_		,  snake_case_		,  snake_case_						)

       # New Code #
       # We need to keep track of how many total steps we have iterated over
       lowercase__:							Optional[Any]         =     0
       # We also need to keep track of the stating epoch so files are named properly
       lowercase__:							List[Any]         =     0

       # We need to load the checkpoint back in before training here with `load_state`
       # The total number of epochs is adjusted based on where the state is being loaded from,
       # as we assume continuation of the same training script
       if args.resume_from_checkpoint:
              if args.resume_from_checkpoint is not None or args.resume_from_checkpoint != "":
                     accelerator.print(F"""Resumed from checkpoint: {args.resume_from_checkpoint}"""						)
                     accelerator.load_state(args.resume_from_checkpoint						)
                     lowercase__:							Union[str, Any]         =     os.path.basename(args.resume_from_checkpoint						)
              else:
                     # Get the most recent checkpoint
                     lowercase__:							List[Any]         =     [f.name for f in os.scandir(os.getcwd()						) if f.is_dir()]
                     dirs.sort(key=os.path.getctime						)
                     lowercase__:							List[Any]         =     dirs[-1]  # Sorts folders by date modified, most recent checkpoint is the last
              # Extract `epoch_{i}` or `step_{i}`
              lowercase__:							Union[str, Any]         =     os.path.splitext(snake_case_						)[0]

              if "epoch" in training_difference:
                     lowercase__:							Any         =     int(training_difference.replace("epoch_"		,  ""						)						) + 1
                     lowercase__:							List[Any]         =     None
              else:
                     lowercase__:							Optional[Any]         =     int(training_difference.replace("step_"		,  ""						)						)
                     lowercase__:							List[str]         =     resume_step // len(snake_case_						)
                     resume_step -= starting_epoch * len(snake_case_						)

    # Now we train the model
       for epoch in range(snake_case_		,  snake_case_						):
              model.train()
              # New Code #
              if args.resume_from_checkpoint and epoch == starting_epoch and resume_step is not None:
                     # We need to skip steps until we reach the resumed step
                     lowercase__:							int         =     accelerator.skip_first_batches(snake_case_		,  snake_case_						)
                     overall_step += resume_step
              else:
                     # After the first iteration though, we need to go back to the original dataloader
                     lowercase__:							Any         =     train_dataloader
              for step, batch in enumerate(snake_case_						):
                     # We could avoid this line since we set the accelerator with `device_placement=True`.
                     batch.to(accelerator.device						)
                     lowercase__:							Optional[int]         =     model(**snake_case_						)
                     lowercase__:							str         =     outputs.loss
                     lowercase__:							str         =     loss / gradient_accumulation_steps
                     accelerator.backward(snake_case_						)
                     if step % gradient_accumulation_steps == 0:
                            optimizer.step()
                            lr_scheduler.step()
                            optimizer.zero_grad()
                     # New Code #
                     overall_step += 1

                     # New Code #
                     # We save the model, optimizer, lr_scheduler, and seed states by calling `save_state`
                     # These are saved to folders named `step_{overall_step}`
                     # Will contain files: "pytorch_model.bin", "optimizer.bin", "scheduler.bin", and "random_states.pkl"
                     # If mixed precision was used, will also save a "scalar.bin" file
                     if isinstance(snake_case_		,  snake_case_						):
                            lowercase__:							int         =     F"""step_{overall_step}"""
                            if overall_step % checkpointing_steps == 0:
                                   if args.output_dir is not None:
                                          lowercase__:							List[Any]         =     os.path.join(args.output_dir		,  snake_case_						)
                                   accelerator.save_state(snake_case_						)

              model.eval()
              for step, batch in enumerate(snake_case_						):
                     # We could avoid this line since we set the accelerator with `device_placement=True` (the default).
                     batch.to(accelerator.device						)
                     with torch.no_grad():
                            lowercase__:							Optional[Any]         =     model(**snake_case_						)
                     lowercase__:							Optional[int]         =     outputs.logits.argmax(dim=-1						)
                     lowercase__    ,      lowercase__:							Dict         =     accelerator.gather_for_metrics((predictions, batch["labels"])						)
                     metric.add_batch(
                         predictions=snake_case_		,  references=snake_case_		,  )

              lowercase__:							List[str]         =     metric.compute()
              # Use accelerator.print to print only on the main process.
              accelerator.print(F"""epoch {epoch}:"""		,  snake_case_						)

              # New Code #
              # We save the model, optimizer, lr_scheduler, and seed states by calling `save_state`
              # These are saved to folders named `epoch_{epoch}`
              # Will contain files: "pytorch_model.bin", "optimizer.bin", "scheduler.bin", and "random_states.pkl"
              # If mixed precision was used, will also save a "scalar.bin" file
              if checkpointing_steps == "epoch":
                     lowercase__:							Tuple         =     F"""epoch_{epoch}"""
                     if args.output_dir is not None:
                            lowercase__:							Optional[Any]         =     os.path.join(args.output_dir		,  snake_case_						)
                     accelerator.save_state(snake_case_						)






def 							A(    ):
       """simple docstring"""





       lowercase__:							List[Any]         =     argparse.ArgumentParser(description="Simple example of training script."						)
       parser.add_argument(
           "--mixed_precision"		,  type=snake_case_		,  default=snake_case_		,  choices=["no", "fp16", "bf16", "fp8"]		,  help="Whether to use mixed precision. Choose"
           "between fp16 and bf16 (bfloat16). Bf16 requires PyTorch >= 1.10."
           "and an Nvidia Ampere GPU."		,  )
       parser.add_argument("--cpu"		,  action="store_true"		,  help="If passed, will train on the CPU."						)
       parser.add_argument(
           "--checkpointing_steps"		,  type=snake_case_		,  default=snake_case_		,  help="Whether the various states should be saved at the end of every n steps, or 'epoch' for each epoch."		,  )
       parser.add_argument(
           "--output_dir"		,  type=snake_case_		,  default="."		,  help="Optional save directory where all checkpoint folders will be stored. Default is the current working directory."		,  )
       parser.add_argument(
           "--resume_from_checkpoint"		,  type=snake_case_		,  default=snake_case_		,  help="If the training should continue from a checkpoint folder."		,  )
       lowercase__:							str         =     parser.parse_args()
       lowercase__:							Optional[Any]         =     {"lr": 2E-5, "num_epochs": 3, "seed": 42, "batch_size": 16}
       training_function(snake_case_		,  snake_case_						)


if __name__ == "__main__":
  main()














"""simple docstring"""





import argparse
import json
import re
import string
import sys
from collections import Counter






def 							A(    snake_case_						):
       """simple docstring"""





       def remove_articles(snake_case_						):
              return re.sub(r"\b(a|an|the)\b"		,  " "		,  snake_case_						)

       def white_space_fix(snake_case_						):
              return " ".join(text.split()						)

       def remove_punc(snake_case_						):
              lowercase__:							str         =     set(string.punctuation						)
              return "".join(ch for ch in text if ch not in exclude						)

       def lower(snake_case_						):
              return text.lower()

       return white_space_fix(remove_articles(remove_punc(lower(snake_case_						)						)						)						)






def 							A(    snake_case_		,  snake_case_						):
       """simple docstring"""





       lowercase__:							Dict         =     normalize_answer(snake_case_						).split()
       lowercase__:							List[str]         =     normalize_answer(snake_case_						).split()
       lowercase__:							Optional[int]         =     Counter(snake_case_						) & Counter(snake_case_						)
       lowercase__:							Any         =     sum(common.values()						)
       if num_same == 0:
              return 0
       lowercase__:							Any         =     1.0 * num_same / len(snake_case_						)
       lowercase__:							List[Any]         =     1.0 * num_same / len(snake_case_						)
       lowercase__:							int         =     (2 * precision * recall) / (precision + recall)
       return fa






def 							A(    snake_case_		,  snake_case_						):
       """simple docstring"""





       return normalize_answer(snake_case_						) == normalize_answer(snake_case_						)






def 							A(    snake_case_		,  snake_case_		,  snake_case_						):
       """simple docstring"""





       lowercase__:							int         =     []
       for ground_truth in ground_truths:
              lowercase__:							str         =     metric_fn(snake_case_		,  snake_case_						)
              scores_for_ground_truths.append(snake_case_						)
       return max(snake_case_						)






def 							A(    snake_case_		,  snake_case_						):
       """simple docstring"""





       lowercase__:							Optional[int]         =     0
       for article in dataset:
              for paragraph in article["paragraphs"]:
                     for qa in paragraph["qas"]:
                            total += 1
                            if qa["id"] not in predictions:
                                   lowercase__:							Union[str, Any]         =     "Unanswered question " + qa["id"] + " will receive score 0."
                                   print(snake_case_		,  file=sys.stderr						)
                                   continue
                            lowercase__:							List[Any]         =     [x["text"] for x in qa["answers"]]
                            lowercase__:							Optional[Any]         =     predictions[qa["id"]]
                            exact_match += metric_max_over_ground_truths(snake_case_		,  snake_case_		,  snake_case_						)
                            fa += metric_max_over_ground_truths(snake_case_		,  snake_case_		,  snake_case_						)

       lowercase__:							Union[str, Any]         =     1_00.0 * exact_match / total
       lowercase__:							str         =     1_00.0 * fa / total

       return {"exact_match": exact_match, "f1": fa}


if __name__ == "__main__":
  UpperCamelCase					=     """1.1"""
  UpperCamelCase					=     argparse.ArgumentParser(description="""Evaluation for SQuAD """ + expected_version)
  parser.add_argument("""dataset_file""", help="""Dataset file""")
  parser.add_argument("""prediction_file""", help="""Prediction File""")
  UpperCamelCase					=     parser.parse_args()
  with open(args.dataset_file) as dataset_file:
    UpperCamelCase					=     json.load(dataset_file)
    if dataset_json["version"] != expected_version:
      print(
          """Evaluation expects v-""" + expected_version + """, but got dataset with v-""" + dataset_json["""version"""],
          file=sys.stderr,
      )
    UpperCamelCase					=     dataset_json["""data"""]
  with open(args.prediction_file) as prediction_file:
    UpperCamelCase					=     json.load(prediction_file)
  print(json.dumps(evaluate(dataset, predictions)))






