code: def main():
      args = parse_args()
  
      # Sending telemetry. Tracking the example usage helps us better allocate resources to maintain them. The
      # information sent is the one passed as arguments along with your Python/PyTorch versions.
      send_example_telemetry(
          "run_image_classification_no_trainer", args
      )
  
      # Initialize the accelerator. We will let the accelerator handle device placement for us in this example.
      # If we're using tracking, we also need to initialize it here and it will by default pick up all supported trackers
      # in the environment
      accelerator_log_kwargs = {}
  
      if args.with_tracking:
          accelerator_log_kwargs["log_with"] = args.report_to
          accelerator_log_kwargs["logging_dir"] = args.output_dir
  
      accelerator = Accelerator(
          gradient_accumulation_steps=args.gradient_accumulation_steps,
          **accelerator_log_kwargs,
      )
  
      logger.info(accelerator.state)
      # Make one log on every process with the configuration for debugging.
      logging.basicConfig(
          format="%(asctime)s - %(levelname)s - %(name)s - %(message)s",
          datefmt="%m/%d/%Y %H:%M:%S",
          level=logging.INFO,
      )
      logger.info(accelerator.state, main_process_only=False)
      if accelerator.is_local_main_process:
          datasets.utils.logging.set_verbosity_warning()
          transformers.utils.logging.set_verbosity_info()
      else:
          datasets.utils.logging.set_verbosity_error()
          transformers.utils.logging.set_verbosity_error()
  
      # If passed along, set the training seed now.
      if args.seed is not None:
          set_seed(args.seed)
  
      # Handle the repository creation
      if accelerator.is_main_process:
          if args.push_to_hub:
              if args.hub_model_id is None:
                  repo_name = get_full_repo_name(
                      Path(args.output_dir).name, token=args.hub_token
                  )
              else:
                  repo_name = args.hub_model_id
              repo = Repository(args.output_dir, clone_from=repo_name)
  
              with open(
                  os.path.join(args.output_dir, ".gitignore"), "w+"
              ) as gitignore:
                  if "step_*" not in gitignore:
                      gitignore.write("step_*\n")
                  if "epoch_*" not in gitignore:
                      gitignore.write("epoch_*\n")
          elif args.output_dir is not None:
              os.makedirs(args.output_dir, exist_ok=True)
      accelerator.wait_for_everyone()
  
      # Get the datasets: you can either provide your own training and evaluation files (see below)
      # or specify a Dataset from the hub (the dataset will be downloaded automatically from the datasets Hub).
  
      # In distributed training, the load_dataset function guarantees that only one local process can concurrently
      # download the dataset.
      if args.dataset_name is not None:
          # Downloading and loading a dataset from the hub.
          dataset = load_dataset(
              args.dataset_name, task="image-classification"
          )
      else:
          data_files = {}
          if args.train_dir is not None:
              data_files["train"] = os.path.join(args.train_dir, "**")
          if args.validation_dir is not None:
              data_files["validation"] = os.path.join(
                  args.validation_dir, "**"
              )
          dataset = load_dataset(
              "imagefolder",
              data_files=data_files,
              cache_dir=args.cache_dir,
              task="image-classification",
          )
          # See more about loading custom images at
          # https://huggingface.co/docs/datasets/v2.0.0/en/image_process#imagefolder.
  
      # If we don't have a validation split, split off a percentage of train as validation.
      args.train_val_split = (
          None
          if "validation" in dataset.keys()
          else args.train_val_split
      )
      if (
          isinstance(args.train_val_split, float)
          and args.train_val_split > 0.0
      ):
          split = dataset["train"].train_test_split(
              args.train_val_split
          )
          dataset["train"] = split["train"]
          dataset["validation"] = split["test"]
  
      # Prepare label mappings.
      # We'll include these in the model's config to get human readable labels in the Inference API.
      labels = dataset["train"].features["labels"].names
      label2id = {label: str(i) for i, label in enumerate(labels)}
      id2label = {str(i): label for i, label in enumerate(labels)}
  
      # Load pretrained model and feature extractor
      #
      # In distributed training, the .from_pretrained methods guarantee that only one local process can concurrently
      # download model & vocab.
      config = AutoConfig.from_pretrained(
          args.model_name_or_path,
          num_labels=len(labels),
          i2label=id2label,
          label2id=label2id,
          finetuning_task="image-classification",
      )
      feature_extractor = AutoFeatureExtractor.from_pretrained(
          args.model_name_or_path
      )
      model = AutoModelForImageClassification.from_pretrained(
          args.model_name_or_path,
          from_tf=bool(".ckpt" in args.model_name_or_path),
          config=config,
          ignore_mismatched_sizes=args.ignore_mismatched_sizes,
      )
  
      # Preprocessing the datasets
  
      # Define torchvision transforms to be applied to each image.
      normalize = Normalize(
          mean=feature_extractor.image_mean,
          std=feature_extractor.image_std,
      )
      train_transforms = Compose(
          [
              RandomResizedCrop(feature_extractor.size),
              RandomHorizontalFlip(),
              ToTensor(),
              normalize,
          ]
      )
      val_transforms = Compose(
          [
              Resize(feature_extractor.size),
              CenterCrop(feature_extractor.size),
              ToTensor(),
              normalize,
          ]
      )
  
      def preprocess_train(example_batch):
          """Apply _train_transforms across a batch."""
          example_batch["pixel_values"] = [
              train_transforms(image.convert("RGB"))
              for image in example_batch["image"]
          ]
          return example_batch
  
      def preprocess_val(example_batch):
          """Apply _val_transforms across a batch."""
          example_batch["pixel_values"] = [
              val_transforms(image.convert("RGB"))
              for image in example_batch["image"]
          ]
          return example_batch
  
      with accelerator.main_process_first():
          if args.max_train_samples is not None:
              dataset["train"] = (
                  dataset["train"]
                  .shuffle(seed=args.seed)
                  .select(range(args.max_train_samples))
              )
          # Set the training transforms
          train_dataset = dataset["train"].with_transform(
              preprocess_train
          )
          if args.max_eval_samples is not None:
              dataset["validation"] = (
                  dataset["validation"]
                  .shuffle(seed=args.seed)
                  .select(range(args.max_eval_samples))
              )
          # Set the validation transforms
          eval_dataset = dataset["validation"].with_transform(
              preprocess_val
          )
  
      # DataLoaders creation:
      def collate_fn(examples):
          pixel_values = torch.stack(
              [example["pixel_values"] for example in examples]
          )
          labels = torch.tensor(
              [example["labels"] for example in examples]
          )
          return {"pixel_values": pixel_values, "labels": labels}
  
      train_dataloader = DataLoader(
          train_dataset,
          shuffle=True,
          collate_fn=collate_fn,
          batch_size=args.per_device_train_batch_size,
      )
      eval_dataloader = DataLoader(
          eval_dataset,
          collate_fn=collate_fn,
          batch_size=args.per_device_eval_batch_size,
      )
  
      # Optimizer
      # Split weights in two groups, one with weight decay and the other not.
      no_decay = ["bias", "LayerNorm.weight"]
      optimizer_grouped_parameters = [
          {
              "params": [
                  p
                  for n, p in model.named_parameters()
                  if not any(nd in n for nd in no_decay)
              ],
              "weight_decay": args.weight_decay,
          },
          {
              "params": [
                  p
                  for n, p in model.named_parameters()
                  if any(nd in n for nd in no_decay)
              ],
              "weight_decay": 0.0,
          },
      ]
      optimizer = torch.optim.AdamW(
          optimizer_grouped_parameters, lr=args.learning_rate
      )
  
      # Scheduler and math around the number of training steps.
      overrode_max_train_steps = False
      num_update_steps_per_epoch = math.ceil(
          len(train_dataloader) / args.gradient_accumulation_steps
      )
      if args.max_train_steps is None:
          args.max_train_steps = (
              args.num_train_epochs * num_update_steps_per_epoch
          )
          overrode_max_train_steps = True
  
      lr_scheduler = get_scheduler(
          name=args.lr_scheduler_type,
          optimizer=optimizer,
          num_warmup_steps=args.num_warmup_steps
          * args.gradient_accumulation_steps,
          num_training_steps=args.max_train_steps
          * args.gradient_accumulation_steps,
      )
  
      # Prepare everything with our `accelerator`.
      (
          model,
          optimizer,
          train_dataloader,
          eval_dataloader,
          lr_scheduler,
      ) = accelerator.prepare(
          model,
          optimizer,
          train_dataloader,
          eval_dataloader,
          lr_scheduler,
      )
  
      # We need to recalculate our total training steps as the size of the training dataloader may have changed.
      num_update_steps_per_epoch = math.ceil(
          len(train_dataloader) / args.gradient_accumulation_steps
      )
      if overrode_max_train_steps:
          args.max_train_steps = (
              args.num_train_epochs * num_update_steps_per_epoch
          )
      # Afterwards we recalculate our number of training epochs
      args.num_train_epochs = math.ceil(
          args.max_train_steps / num_update_steps_per_epoch
      )
  
      # Figure out how many steps we should save the Accelerator states
      checkpointing_steps = args.checkpointing_steps
      if (
          checkpointing_steps is not None
          and checkpointing_steps.isdigit()
      ):
          checkpointing_steps = int(checkpointing_steps)
  
      # We need to initialize the trackers we use, and also store our configuration.
      # The trackers initializes automatically on the main process.
      if args.with_tracking:
          experiment_config = vars(args)
          # TensorBoard cannot log Enums, need the raw value
          experiment_config["lr_scheduler_type"] = experiment_config[
              "lr_scheduler_type"
          ].value
          accelerator.init_trackers(
              "image_classification_no_trainer", experiment_config
          )
  
      # Get the metric function
      metric = evaluate.load("accuracy")
  
      # Train!
      total_batch_size = (
          args.per_device_train_batch_size
          * accelerator.num_processes
          * args.gradient_accumulation_steps
      )
  
      logger.info("***** Running training *****")
      logger.info(f"  Num examples = {len(train_dataset)}")
      logger.info(f"  Num Epochs = {args.num_train_epochs}")
      logger.info(
          f"  Instantaneous batch size per device = {args.per_device_train_batch_size}"
      )
      logger.info(
          f"  Total train batch size (w. parallel, distributed & accumulation) = {total_batch_size}"
      )
      logger.info(
          f"  Gradient Accumulation steps = {args.gradient_accumulation_steps}"
      )
      logger.info(
          f"  Total optimization steps = {args.max_train_steps}"
      )
      # Only show the progress bar once on each machine.
      progress_bar = tqdm(
          range(args.max_train_steps),
          disable=not accelerator.is_local_main_process,
      )
      completed_steps = 0
      starting_epoch = 0
      # Potentially load in the weights and states from a previous save
      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)
              path = os.path.basename(args.resume_from_checkpoint)
          else:
              # Get the most recent checkpoint
              dirs = [
                  f.name for f in os.scandir(os.getcwd()) if f.is_dir()
              ]
              dirs.sort(key=os.path.getctime)
              path = dirs[
                  -1
              ]  # Sorts folders by date modified, most recent checkpoint is the last
          # Extract `epoch_{i}` or `step_{i}`
          training_difference = os.path.splitext(path)[0]
  
          if "epoch" in training_difference:
              starting_epoch = (
                  int(training_difference.replace("epoch_", "")) + 1
              )
              resume_step = None
          else:
              resume_step = int(
                  training_difference.replace("step_", "")
              )
              starting_epoch = resume_step // len(train_dataloader)
              resume_step -= starting_epoch * len(train_dataloader)
  
      for epoch in range(starting_epoch, args.num_train_epochs):
          model.train()
          if args.with_tracking:
              total_loss = 0
          for step, batch in enumerate(train_dataloader):
              # We need to skip steps until we reach the resumed step
              if (
                  args.resume_from_checkpoint
                  and epoch == starting_epoch
              ):
                  if resume_step is not None and step < resume_step:
                      completed_steps += 1
                      continue
  
              with accelerator.accumulate(model):
                  outputs = model(**batch)
                  loss = outputs.loss
                  # We keep track of the loss at each epoch
                  if args.with_tracking:
                      total_loss += loss.detach().float()
                  accelerator.backward(loss)
                  optimizer.step()
                  lr_scheduler.step()
                  optimizer.zero_grad()
  
              # Checks if the accelerator has performed an optimization step behind the scenes
              if accelerator.sync_gradients:
                  progress_bar.update(1)
                  completed_steps += 1
  
              if isinstance(checkpointing_steps, int):
                  if completed_steps % checkpointing_steps == 0:
                      output_dir = f"step_{completed_steps }"
                      if args.output_dir is not None:
                          output_dir = os.path.join(
                              args.output_dir, output_dir
                          )
                      accelerator.save_state(output_dir)
  
                      if (
                          args.push_to_hub
                          and epoch < args.num_train_epochs - 1
                      ):
                          accelerator.wait_for_everyone()
                          unwrapped_model = accelerator.unwrap_model(
                              model
                          )
                          unwrapped_model.save_pretrained(
                              args.output_dir,
                              is_main_process=accelerator.is_main_process,
                              save_function=accelerator.save,
                          )
                          if accelerator.is_main_process:
                              feature_extractor.save_pretrained(
                                  args.output_dir
                              )
                              repo.push_to_hub(
                                  commit_message=f"Training in progress {completed_steps} steps",
                                  blocking=False,
                                  auto_lfs_prune=True,
                              )
  
              if completed_steps >= args.max_train_steps:
                  break
  
          model.eval()
          for step, batch in enumerate(eval_dataloader):
              with torch.no_grad():
                  outputs = model(**batch)
              predictions = outputs.logits.argmax(dim=-1)
              predictions, references = accelerator.gather_for_metrics(
                  (predictions, batch["labels"])
              )
              metric.add_batch(
                  predictions=predictions,
                  references=references,
              )
  
          eval_metric = metric.compute()
          logger.info(f"epoch {epoch}: {eval_metric}")
  
          if args.with_tracking:
              accelerator.log(
                  {
                      "accuracy": eval_metric,
                      "train_loss": total_loss.item()
                      / len(train_dataloader),
                      "epoch": epoch,
                      "step": completed_steps,
                  },
                  step=completed_steps,
              )
  
          if args.push_to_hub and epoch < args.num_train_epochs - 1:
              accelerator.wait_for_everyone()
              unwrapped_model = accelerator.unwrap_model(model)
              unwrapped_model.save_pretrained(
                  args.output_dir,
                  is_main_process=accelerator.is_main_process,
                  save_function=accelerator.save,
              )
              if accelerator.is_main_process:
                  feature_extractor.save_pretrained(args.output_dir)
                  repo.push_to_hub(
                      commit_message=f"Training in progress epoch {epoch}",
                      blocking=False,
                      auto_lfs_prune=True,
                  )
  
          if args.checkpointing_steps == "epoch":
              output_dir = f"epoch_{epoch}"
              if args.output_dir is not None:
                  output_dir = os.path.join(args.output_dir, output_dir)
              accelerator.save_state(output_dir)
  
      if args.with_tracking:
          accelerator.end_training()
  
      if args.output_dir is not None:
          accelerator.wait_for_everyone()
          unwrapped_model = accelerator.unwrap_model(model)
          unwrapped_model.save_pretrained(
              args.output_dir,
              is_main_process=accelerator.is_main_process,
              save_function=accelerator.save,
          )
          if accelerator.is_main_process:
              feature_extractor.save_pretrained(args.output_dir)
              if args.push_to_hub:
                  repo.push_to_hub(
                      commit_message="End of training",
                      auto_lfs_prune=True,
                  )
  
      if args.output_dir is not None:
          with open(
              os.path.join(args.output_dir, "all_results.json"), "w"
          ) as f:
              json.dump({"eval_accuracy": eval_metric["accuracy"]}, f)
  
imports: import argparse
  import json
  import logging
  import math
  import os
  from pathlib import Path
  import datasets
  import torch
  from datasets import load_dataset
  from torch.utils.data import DataLoader
  from torchvision.transforms import CenterCrop, Compose, Normalize, RandomHorizontalFlip, RandomResizedCrop, Resize, ToTensor
  from tqdm.auto import tqdm
  import evaluate
  import transformers
  from accelerate import Accelerator
  from accelerate.logging import get_logger
  from accelerate.utils import set_seed
  from huggingface_hub import Repository
  from transformers import AutoConfig, AutoFeatureExtractor, AutoModelForImageClassification, SchedulerType, get_scheduler
  from transformers.utils import check_min_version, get_full_repo_name, send_example_telemetry
  from transformers.utils.versions import require_version
label_desc: Use image node_id 2 for calling a global function with example usage: main() and returns: example_batch, example_batch, dict