




import argparse
import json
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
from accelerate.utils.deepspeed import DummyOptim, DummyScheduler


__A								=       16
__A								=       32







def      lowerCamelCase_						(			UpperCamelCase__							: Accelerator					,	UpperCamelCase__							: int = 16					,	UpperCamelCase__							: str = "bert-base-cased" )	->			Union[str, Any]:





				"""simple docstring"""


				__lowerCamelCase									=       AutoTokenizer.from_pretrained(UpperCamelCase_ )
				__lowerCamelCase									=       load_dataset('glue'					,	'mrpc' )

				def tokenize_function(UpperCamelCase__							: Optional[int] ):
								# max_length=None => use the model max length (it's actually the default)
								__lowerCamelCase									=       tokenizer(examples['sentence1']					,	examples['sentence2']					,	truncation=UpperCamelCase_					,	max_length=UpperCamelCase_ )
								return outputs

				# Apply the method we just defined to all the examples in all the splits of the dataset
				__lowerCamelCase									=       datasets.map(
				    UpperCamelCase_					,	batched=UpperCamelCase_					,	remove_columns=['idx', 'sentence1', 'sentence2']					,	load_from_cache_file=UpperCamelCase_ )

				# We also rename the 'label' column to 'labels' which is the expected name for labels by the models of the
				# transformers library
				__lowerCamelCase									=       tokenized_datasets.rename_column('label'					,	'labels' )

				def collate_fn(UpperCamelCase__							: Optional[int] ):
								# On TPU it's best to pad everything to the same length or training will be very slow.
								if accelerator.distributed_type == DistributedType.TPU:
												return tokenizer.pad(UpperCamelCase_					,	padding='max_length'					,	max_length=128					,	return_tensors='pt' )
								return tokenizer.pad(UpperCamelCase_					,	padding='longest'					,	return_tensors='pt' )

				# Instantiate dataloaders.
				__lowerCamelCase									=       DataLoader(
				    tokenized_datasets['train']					,	shuffle=UpperCamelCase_					,	collate_fn=UpperCamelCase_					,	batch_size=UpperCamelCase_ )
				__lowerCamelCase									=       DataLoader(
				    tokenized_datasets['validation']					,	shuffle=UpperCamelCase_					,	collate_fn=UpperCamelCase_					,	batch_size=UpperCamelCase_ )

				return train_dataloader, eval_dataloader







def      lowerCamelCase_						(			UpperCamelCase__							: Optional[Any]					,	UpperCamelCase__							: Optional[int]					,	UpperCamelCase__							: List[str]					,	UpperCamelCase__							: str )	->			Tuple:





				"""simple docstring"""


				model.eval()
				__lowerCamelCase									=       0
				for step, batch in enumerate(UpperCamelCase_ ):
								# We could avoid this line since we set the accelerator with `device_placement=True`.
								batch.to(accelerator.device )
								with torch.no_grad():
												__lowerCamelCase									=       model(**UpperCamelCase_ )
								__lowerCamelCase									=       outputs.logits.argmax(dim=-1 )
								# It is slightly faster to call this once, than multiple times
								__lowerCamelCase			,		__lowerCamelCase									=       accelerator.gather(
								    (predictions, batch['labels']) )  # If we are in a multiprocess environment, the last batch has duplicates
								if accelerator.use_distributed:
												if step == len(UpperCamelCase_ ) - 1:
																__lowerCamelCase									=       predictions[: len(eval_dataloader.dataset ) - samples_seen]
																__lowerCamelCase									=       references[: len(eval_dataloader.dataset ) - samples_seen]
												else:
																samples_seen += references.shape[0]
								metric.add_batch(
								    predictions=UpperCamelCase_					,	references=UpperCamelCase_					,	)

				__lowerCamelCase									=       metric.compute()
				return eval_metric["accuracy"]







def      lowerCamelCase_						(			UpperCamelCase__							: int					,	UpperCamelCase__							: List[str] )	->			Dict:





				"""simple docstring"""


				__lowerCamelCase									=       Accelerator()

				# Sample hyper-parameters for learning rate, batch size, seed and a few other HPs
				__lowerCamelCase									=       config['lr']
				__lowerCamelCase									=       int(config['num_epochs'] )
				__lowerCamelCase									=       int(config['seed'] )
				__lowerCamelCase									=       int(config['batch_size'] )
				__lowerCamelCase									=       args.model_name_or_path

				set_seed(UpperCamelCase_ )
				__lowerCamelCase			,		__lowerCamelCase									=       get_dataloaders(UpperCamelCase_					,	UpperCamelCase_					,	UpperCamelCase_ )

				# Instantiate the model (we build the model here so that the seed also control new weights initialization)
				__lowerCamelCase									=       AutoModelForSequenceClassification.from_pretrained(UpperCamelCase_					,	return_dict=UpperCamelCase_ )

				# Instantiate optimizer
				__lowerCamelCase									=       (
				    AdamW
				    if accelerator.state.deepspeed_plugin is None
				    or 'optimizer' not in accelerator.state.deepspeed_plugin.deepspeed_config
				    else DummyOptim
				)
				__lowerCamelCase									=       optimizer_cls(params=model.parameters()					,	lr=UpperCamelCase_ )

				if accelerator.state.deepspeed_plugin is not None:
								__lowerCamelCase									=       accelerator.state.deepspeed_plugin.deepspeed_config[
								    'gradient_accumulation_steps'
								]
				else:
								__lowerCamelCase									=       1
				__lowerCamelCase									=       (len(UpperCamelCase_ ) * num_epochs) // gradient_accumulation_steps

				# Instantiate scheduler
				if (
				    accelerator.state.deepspeed_plugin is None
				    or "scheduler" not in accelerator.state.deepspeed_plugin.deepspeed_config
				):
								__lowerCamelCase									=       get_linear_schedule_with_warmup(
								    optimizer=UpperCamelCase_					,	num_warmup_steps=0					,	num_training_steps=UpperCamelCase_					,	)
				else:
								__lowerCamelCase									=       DummyScheduler(UpperCamelCase_					,	total_num_steps=UpperCamelCase_					,	warmup_num_steps=0 )

				# 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.
				__lowerCamelCase			,		__lowerCamelCase			,		__lowerCamelCase			,		__lowerCamelCase			,		__lowerCamelCase									=       accelerator.prepare(
				    UpperCamelCase_					,	UpperCamelCase_					,	UpperCamelCase_					,	UpperCamelCase_					,	UpperCamelCase_ )

				# We need to keep track of how many total steps we have iterated over
				__lowerCamelCase									=       0
				# We also need to keep track of the stating epoch so files are named properly
				__lowerCamelCase									=       0
				__lowerCamelCase									=       evaluate.load('glue'					,	'mrpc' )
				__lowerCamelCase									=       num_epochs

				if args.partial_train_epoch is not None:
								__lowerCamelCase									=       args.partial_train_epoch

				if args.resume_from_checkpoint:
								accelerator.load_state(args.resume_from_checkpoint )
								__lowerCamelCase									=       args.resume_from_checkpoint.split('epoch_' )[1]
								__lowerCamelCase									=       ''
								for char in epoch_string:
												if char.isdigit():
																state_epoch_num += char
												else:
																break
								__lowerCamelCase									=       int(UpperCamelCase_ ) + 1
								__lowerCamelCase									=       evaluation_loop(UpperCamelCase_					,	UpperCamelCase_					,	UpperCamelCase_					,	UpperCamelCase_ )
								accelerator.print('resumed checkpoint performance:'					,	UpperCamelCase_ )
								accelerator.print('resumed checkpoint\'s scheduler\'s lr:'					,	lr_scheduler.get_lr()[0] )
								accelerator.print('resumed optimizers\'s lr:'					,	optimizer.param_groups[0]['lr'] )
								with open(os.path.join(args.output_dir					,	F"""state_{starting_epoch-1}.json""" )					,	'r' ) as f:
												__lowerCamelCase									=       json.load(UpperCamelCase_ )
												assert resumed_state["accuracy"] == accuracy, "Accuracy mismatch, loading from checkpoint failed"
												assert (
												    resumed_state["lr"] == lr_scheduler.get_lr()[0]
												), "Scheduler learning rate mismatch, loading from checkpoint failed"
												assert (
												    resumed_state["optimizer_lr"] == optimizer.param_groups[0]["lr"]
												), "Optimizer learning rate mismatch, loading from checkpoint failed"
												assert resumed_state["epoch"] == starting_epoch - 1, "Epoch mismatch, loading from checkpoint failed"
												return

    # Now we train the model
				__lowerCamelCase									=       {}
				for epoch in range(UpperCamelCase_					,	UpperCamelCase_ ):
								model.train()
								for step, batch in enumerate(UpperCamelCase_ ):
												__lowerCamelCase									=       model(**UpperCamelCase_ )
												__lowerCamelCase									=       outputs.loss
												__lowerCamelCase									=       loss / gradient_accumulation_steps
												accelerator.backward(UpperCamelCase_ )
												if step % gradient_accumulation_steps == 0:
																optimizer.step()
																lr_scheduler.step()
																optimizer.zero_grad()

												overall_step += 1
								__lowerCamelCase									=       F"""epoch_{epoch}"""
								__lowerCamelCase									=       os.path.join(args.output_dir					,	UpperCamelCase_ )
								accelerator.save_state(UpperCamelCase_ )
								__lowerCamelCase									=       evaluation_loop(UpperCamelCase_					,	UpperCamelCase_					,	UpperCamelCase_					,	UpperCamelCase_ )
								__lowerCamelCase									=       accuracy
								__lowerCamelCase									=       lr_scheduler.get_lr()[0]
								__lowerCamelCase									=       optimizer.param_groups[0]['lr']
								__lowerCamelCase									=       epoch
								__lowerCamelCase									=       overall_step
								accelerator.print(F"""epoch {epoch}:"""					,	UpperCamelCase_ )

								accelerator.wait_for_everyone()
								if accelerator.is_main_process:
												with open(os.path.join(args.output_dir					,	F"""state_{epoch}.json""" )					,	'w' ) as f:
																json.dump(UpperCamelCase_					,	UpperCamelCase_ )







def      lowerCamelCase_						(			)	->			Union[str, Any]:





				"""simple docstring"""


				__lowerCamelCase									=       argparse.ArgumentParser(description='Simple example of training script tracking peak GPU memory usage.' )
				parser.add_argument(
				    '--model_name_or_path'					,	type=UpperCamelCase_					,	default='bert-base-cased'					,	help='Path to pretrained model or model identifier from huggingface.co/models.'					,	required=UpperCamelCase_					,	)
				parser.add_argument(
				    '--output_dir'					,	type=UpperCamelCase_					,	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=UpperCamelCase_					,	default=UpperCamelCase_					,	help='If the training should continue from a checkpoint folder.'					,	)
				parser.add_argument(
				    '--partial_train_epoch'					,	type=UpperCamelCase_					,	default=UpperCamelCase_					,	help='If passed, the training will stop after this number of epochs.'					,	)
				parser.add_argument(
				    '--num_epochs'					,	type=UpperCamelCase_					,	default=2					,	help='Number of train epochs.'					,	)
				__lowerCamelCase									=       parser.parse_args()
				__lowerCamelCase									=       {'lr': 2E-5, 'num_epochs': args.num_epochs, 'seed': 42, 'batch_size': 16}

				training_function(UpperCamelCase_					,	UpperCamelCase_ )


if __name__ == "__main__":
					main()







'''simple docstring'''

import shutil
import tempfile
import unittest
from unittest.mock import patch

from transformers import (
    DefaultFlowCallback,
    IntervalStrategy,
    PrinterCallback,
    ProgressCallback,
    Trainer,
    TrainerCallback,
    TrainingArguments,
    is_torch_available,
)
from transformers.testing_utils import require_torch


if is_torch_available():
			from transformers.trainer import DEFAULT_CALLBACKS

			from .test_trainer import RegressionDataset, RegressionModelConfig, RegressionPreTrainedModel

class 							a__( snake_case__     ):






			def __init__(     self						)							->							Dict:
					snake_case__	     =[]






			def 						_lowercase  (     self					,   _UpperCAmelCase					,   _UpperCAmelCase					,   _UpperCAmelCase					,   **_UpperCAmelCase						)							->							List[str]:
					self.events.append('on_init_end'						)






			def 						_lowercase  (     self					,   _UpperCAmelCase					,   _UpperCAmelCase					,   _UpperCAmelCase					,   **_UpperCAmelCase						)							->							Dict:
					self.events.append('on_train_begin'						)






			def 						_lowercase  (     self					,   _UpperCAmelCase					,   _UpperCAmelCase					,   _UpperCAmelCase					,   **_UpperCAmelCase						)							->							Optional[Any]:
					self.events.append('on_train_end'						)






			def 						_lowercase  (     self					,   _UpperCAmelCase					,   _UpperCAmelCase					,   _UpperCAmelCase					,   **_UpperCAmelCase						)							->							int:
					self.events.append('on_epoch_begin'						)






			def 						_lowercase  (     self					,   _UpperCAmelCase					,   _UpperCAmelCase					,   _UpperCAmelCase					,   **_UpperCAmelCase						)							->							List[str]:
					self.events.append('on_epoch_end'						)






			def 						_lowercase  (     self					,   _UpperCAmelCase					,   _UpperCAmelCase					,   _UpperCAmelCase					,   **_UpperCAmelCase						)							->							Optional[int]:
					self.events.append('on_step_begin'						)






			def 						_lowercase  (     self					,   _UpperCAmelCase					,   _UpperCAmelCase					,   _UpperCAmelCase					,   **_UpperCAmelCase						)							->							str:
					self.events.append('on_step_end'						)






			def 						_lowercase  (     self					,   _UpperCAmelCase					,   _UpperCAmelCase					,   _UpperCAmelCase					,   **_UpperCAmelCase						)							->							List[Any]:
					self.events.append('on_evaluate'						)






			def 						_lowercase  (     self					,   _UpperCAmelCase					,   _UpperCAmelCase					,   _UpperCAmelCase					,   **_UpperCAmelCase						)							->							Dict:
					self.events.append('on_predict'						)






			def 						_lowercase  (     self					,   _UpperCAmelCase					,   _UpperCAmelCase					,   _UpperCAmelCase					,   **_UpperCAmelCase						)							->							Any:
					self.events.append('on_save'						)






			def 						_lowercase  (     self					,   _UpperCAmelCase					,   _UpperCAmelCase					,   _UpperCAmelCase					,   **_UpperCAmelCase						)							->							Tuple:
					self.events.append('on_log'						)






			def 						_lowercase  (     self					,   _UpperCAmelCase					,   _UpperCAmelCase					,   _UpperCAmelCase					,   **_UpperCAmelCase						)							->							List[Any]:
					self.events.append('on_prediction_step'						)





@require_torch
class 							a__( unittest.TestCase     ):






			def 						_lowercase  (     self						)							->							Optional[Any]:
					snake_case__	     =tempfile.mkdtemp()






			def 						_lowercase  (     self						)							->							List[str]:
					shutil.rmtree(self.output_dir						)






			def 						_lowercase  (     self					,   _UpperCAmelCase=0					,   _UpperCAmelCase=0					,   _UpperCAmelCase=64					,   _UpperCAmelCase=64					,   _UpperCAmelCase=None					,   _UpperCAmelCase=False					,   **_UpperCAmelCase						)							->							int:
					# disable_tqdm in TrainingArguments has a flaky default since it depends on the level of logging. We make sure
					# its set to False since the tests later on depend on its value.
					snake_case__	     =RegressionDataset(length=_UpperCAmelCase						)
					snake_case__	     =RegressionDataset(length=_UpperCAmelCase						)
					snake_case__	     =RegressionModelConfig(a=_UpperCAmelCase					,   b=_UpperCAmelCase						)
					snake_case__	     =RegressionPreTrainedModel(_UpperCAmelCase						)

					snake_case__	     =TrainingArguments(self.output_dir					,   disable_tqdm=_UpperCAmelCase					,   report_to=[]					,   **_UpperCAmelCase						)
					return Trainer(
					    _UpperCAmelCase					,   _UpperCAmelCase					,   train_dataset=_UpperCAmelCase					,   eval_dataset=_UpperCAmelCase					,   callbacks=_UpperCAmelCase					,   )






			def 						_lowercase  (     self					,   _UpperCAmelCase					,   _UpperCAmelCase						)							->							Optional[Any]:
					self.assertEqual(len(_UpperCAmelCase						)					,   len(_UpperCAmelCase						)						)

					# Order doesn't matter
					snake_case__	     =sorted(_UpperCAmelCase					,   key=lambda _UpperCAmelCase						: cb.__name__ if isinstance(_UpperCAmelCase					,   _UpperCAmelCase						) else cb.__class__.__name__						)
					snake_case__	     =sorted(_UpperCAmelCase					,   key=lambda _UpperCAmelCase						: cb.__name__ if isinstance(_UpperCAmelCase					,   _UpperCAmelCase						) else cb.__class__.__name__						)

					for cba, cba in zip(_UpperCAmelCase					,   _UpperCAmelCase						):
							if isinstance(_UpperCAmelCase					,   _UpperCAmelCase						) and isinstance(_UpperCAmelCase					,   _UpperCAmelCase						):
									self.assertEqual(_UpperCAmelCase					,   _UpperCAmelCase						)
							elif isinstance(_UpperCAmelCase					,   _UpperCAmelCase						) and not isinstance(_UpperCAmelCase					,   _UpperCAmelCase						):
									self.assertEqual(_UpperCAmelCase					,   cba.__class__						)
							elif not isinstance(_UpperCAmelCase					,   _UpperCAmelCase						) and isinstance(_UpperCAmelCase					,   _UpperCAmelCase						):
									self.assertEqual(cba.__class__					,   _UpperCAmelCase						)
							else:
									self.assertEqual(_UpperCAmelCase					,   _UpperCAmelCase						)






			def 						_lowercase  (     self					,   _UpperCAmelCase						)							->							Any:
					snake_case__	     =['on_init_end', 'on_train_begin']
					snake_case__	     =0
					snake_case__	     =len(trainer.get_eval_dataloader()						)
					snake_case__	     =['on_prediction_step'] * len(trainer.get_eval_dataloader()						) + ['on_log', 'on_evaluate']
					for _ in range(trainer.state.num_train_epochs						):
							expected_events.append('on_epoch_begin'						)
							for _ in range(_UpperCAmelCase						):
									step += 1
									expected_events += ["on_step_begin", "on_step_end"]
									if step % trainer.args.logging_steps == 0:
											expected_events.append('on_log'						)
									if trainer.args.evaluation_strategy == IntervalStrategy.STEPS and step % trainer.args.eval_steps == 0:
											expected_events += evaluation_events.copy()
									if step % trainer.args.save_steps == 0:
											expected_events.append('on_save'						)
							expected_events.append('on_epoch_end'						)
							if trainer.args.evaluation_strategy == IntervalStrategy.EPOCH:
									expected_events += evaluation_events.copy()
					expected_events += ["on_log", "on_train_end"]
					return expected_events






			def 						_lowercase  (     self						)							->							Optional[int]:
					snake_case__	     =self.get_trainer()
					snake_case__	     =DEFAULT_CALLBACKS.copy() + [ProgressCallback]
					self.check_callbacks_equality(trainer.callback_handler.callbacks					,   _UpperCAmelCase						)

					# Callbacks passed at init are added to the default callbacks
					snake_case__	     =self.get_trainer(callbacks=[MyTestTrainerCallback]						)
					expected_callbacks.append(_UpperCAmelCase						)
					self.check_callbacks_equality(trainer.callback_handler.callbacks					,   _UpperCAmelCase						)

					# TrainingArguments.disable_tqdm controls if use ProgressCallback or PrinterCallback
					snake_case__	     =self.get_trainer(disable_tqdm=_UpperCAmelCase						)
					snake_case__	     =DEFAULT_CALLBACKS.copy() + [PrinterCallback]
					self.check_callbacks_equality(trainer.callback_handler.callbacks					,   _UpperCAmelCase						)






			def 						_lowercase  (     self						)							->							Optional[Any]:
					snake_case__	     =DEFAULT_CALLBACKS.copy() + [ProgressCallback]
					snake_case__	     =self.get_trainer()

					# We can add, pop, or remove by class name
					trainer.remove_callback(_UpperCAmelCase						)
					expected_callbacks.remove(_UpperCAmelCase						)
					self.check_callbacks_equality(trainer.callback_handler.callbacks					,   _UpperCAmelCase						)

					snake_case__	     =self.get_trainer()
					snake_case__	     =trainer.pop_callback(_UpperCAmelCase						)
					self.assertEqual(cb.__class__					,   _UpperCAmelCase						)
					self.check_callbacks_equality(trainer.callback_handler.callbacks					,   _UpperCAmelCase						)

					trainer.add_callback(_UpperCAmelCase						)
					expected_callbacks.insert(0					,   _UpperCAmelCase						)
					self.check_callbacks_equality(trainer.callback_handler.callbacks					,   _UpperCAmelCase						)

					# We can also add, pop, or remove by instance
					snake_case__	     =self.get_trainer()
					snake_case__	     =trainer.callback_handler.callbacks[0]
					trainer.remove_callback(_UpperCAmelCase						)
					expected_callbacks.remove(_UpperCAmelCase						)
					self.check_callbacks_equality(trainer.callback_handler.callbacks					,   _UpperCAmelCase						)

					snake_case__	     =self.get_trainer()
					snake_case__	     =trainer.callback_handler.callbacks[0]
					snake_case__	     =trainer.pop_callback(_UpperCAmelCase						)
					self.assertEqual(_UpperCAmelCase					,   _UpperCAmelCase						)
					self.check_callbacks_equality(trainer.callback_handler.callbacks					,   _UpperCAmelCase						)

					trainer.add_callback(_UpperCAmelCase						)
					expected_callbacks.insert(0					,   _UpperCAmelCase						)
					self.check_callbacks_equality(trainer.callback_handler.callbacks					,   _UpperCAmelCase						)






			def 						_lowercase  (     self						)							->							Dict:
					import warnings

					# XXX: for now ignore scatter_gather warnings in this test since it's not relevant to what's being tested
					warnings.simplefilter(action='ignore'					,   category=_UpperCAmelCase						)

					snake_case__	     =self.get_trainer(callbacks=[MyTestTrainerCallback]						)
					trainer.train()
					snake_case__	     =trainer.callback_handler.callbacks[-2].events
					self.assertEqual(_UpperCAmelCase					,   self.get_expected_events(_UpperCAmelCase						)						)

					# Independent log/save/eval
					snake_case__	     =self.get_trainer(callbacks=[MyTestTrainerCallback]					,   logging_steps=5						)
					trainer.train()
					snake_case__	     =trainer.callback_handler.callbacks[-2].events
					self.assertEqual(_UpperCAmelCase					,   self.get_expected_events(_UpperCAmelCase						)						)

					snake_case__	     =self.get_trainer(callbacks=[MyTestTrainerCallback]					,   save_steps=5						)
					trainer.train()
					snake_case__	     =trainer.callback_handler.callbacks[-2].events
					self.assertEqual(_UpperCAmelCase					,   self.get_expected_events(_UpperCAmelCase						)						)

					snake_case__	     =self.get_trainer(callbacks=[MyTestTrainerCallback]					,   eval_steps=5					,   evaluation_strategy='steps'						)
					trainer.train()
					snake_case__	     =trainer.callback_handler.callbacks[-2].events
					self.assertEqual(_UpperCAmelCase					,   self.get_expected_events(_UpperCAmelCase						)						)

					snake_case__	     =self.get_trainer(callbacks=[MyTestTrainerCallback]					,   evaluation_strategy='epoch'						)
					trainer.train()
					snake_case__	     =trainer.callback_handler.callbacks[-2].events
					self.assertEqual(_UpperCAmelCase					,   self.get_expected_events(_UpperCAmelCase						)						)

					# A bit of everything
					snake_case__	     =self.get_trainer(
					    callbacks=[MyTestTrainerCallback]					,   logging_steps=3					,   save_steps=10					,   eval_steps=5					,   evaluation_strategy='steps'					,   )
					trainer.train()
					snake_case__	     =trainer.callback_handler.callbacks[-2].events
					self.assertEqual(_UpperCAmelCase					,   self.get_expected_events(_UpperCAmelCase						)						)

					# warning should be emitted for duplicated callbacks
					with patch('transformers.trainer_callback.logger.warning'						) as warn_mock:
							snake_case__	     =self.get_trainer(
							    callbacks=[MyTestTrainerCallback, MyTestTrainerCallback]					,   )
							assert str(_UpperCAmelCase						) in warn_mock.call_args[0][0]




