



import json
import os
import subprocess
import unittest
from ast import literal_eval

import pytest
from parameterized import parameterized, parameterized_class

from . import is_sagemaker_available


if is_sagemaker_available():
				from sagemaker import Session, TrainingJobAnalytics
				from sagemaker.huggingface import HuggingFace

@pytest.mark.skipif(
    literal_eval(os.getenv("""TEST_SAGEMAKER"""			,"""False""")) is not True			,reason="""Skipping test because should only be run when releasing minor transformers version"""			,)
@pytest.mark.usefixtures("""sm_env""")
@parameterized_class(
    [
        {
            """framework""": """pytorch""",
            """script""": """run_glue_model_parallelism.py""",
            """model_name_or_path""": """roberta-large""",
            """instance_type""": """ml.p3dn.24xlarge""",
            """results""": {"""train_runtime""": 1_6_0_0, """eval_accuracy""": 0.3, """eval_loss""": 1.2},
        },
        {
            """framework""": """pytorch""",
            """script""": """run_glue.py""",
            """model_name_or_path""": """roberta-large""",
            """instance_type""": """ml.p3dn.24xlarge""",
            """results""": {"""train_runtime""": 1_6_0_0, """eval_accuracy""": 0.3, """eval_loss""": 1.2},
        },
    ])
class  __snake_case      (   unittest.TestCase):







							'''simple docstring'''






							def _a      (							self		):
											if self.framework == "pytorch":
															subprocess.run(
															    F'''cp ./examples/pytorch/text-classification/run_glue.py {self.env.test_path}/run_glue.py'''.split()  ,  encoding="""utf-8"""  ,  check=a_  ,  )
											assert hasattr(self  ,  """env"""		)


							def _a      (							self  ,  a_		):
											# configuration for running training on smdistributed Model Parallel
											a__				      =		{
											    """enabled""": True,
											    """processes_per_host""": 8,
											}
											a__				      =		{
											    """enabled""": True,
											    """parameters""": {
											        """microbatches""": 4,
											        """placement_strategy""": """spread""",
											        """pipeline""": """interleaved""",
											        """optimize""": """speed""",
											        """partitions""": 4,
											        """ddp""": True,
											    },
											}

											a__				      =		{"""smdistributed""": {"""modelparallel""": smp_options}, """mpi""": mpi_options}

											a__				      =		"""trainer""" if self.script == """run_glue.py""" else """smtrainer"""
											# creates estimator
											return HuggingFace(
											    entry_point=self.script  ,  source_dir=self.env.test_path  ,  role=self.env.role  ,  image_uri=self.env.image_uri  ,  base_job_name=F'''{self.env.base_job_name}-{instance_count}-smp-{name_extension}'''  ,  instance_count=a_  ,  instance_type=self.instance_type  ,  debugger_hook_config=a_  ,  hyperparameters={
											        **self.env.hyperparameters,
											        """model_name_or_path""": self.model_name_or_path,
											        """max_steps""": 500,
											    }  ,  metric_definitions=self.env.metric_definitions  ,  distribution=a_  ,  py_version="""py36"""  ,  )


							def _a      (							self  ,  a_		):
											TrainingJobAnalytics(a_		).export_csv(F'''{self.env.test_path}/{job_name}_metrics.csv'''		)







							@parameterized.expand([(1,)]		)
							def _a      (							self  ,  a_		):
											# create estimator
											a__				      =		self.create_estimator(a_		)

											# run training
											estimator.fit()

											# result dataframe
											a__				      =		TrainingJobAnalytics(estimator.latest_training_job.name		).dataframe()

											# extract kpis
											a__				      =		list(result_metrics_df[result_metrics_df.metric_name == """eval_accuracy"""]["""value"""]		)
											a__				      =		list(result_metrics_df[result_metrics_df.metric_name == """eval_loss"""]["""value"""]		)
											# get train time from SageMaker job, this includes starting, preprocessing, stopping
											a__				      =		(
											    Session().describe_training_job(estimator.latest_training_job.name		).get("""TrainingTimeInSeconds"""  ,  999_999		)
											)

											# assert kpis
											assert train_runtime <= self.results["train_runtime"]
											assert all(t >= self.results["""eval_accuracy"""] for t in eval_accuracy		)
											assert all(t <= self.results["""eval_loss"""] for t in eval_loss		)

											# dump tests result into json file to share in PR
											with open(F'''{estimator.latest_training_job.name}.json'''  ,  """w"""		) as outfile:
															json.dump({"""train_time""": train_runtime, """eval_accuracy""": eval_accuracy, """eval_loss""": eval_loss}  ,  a_		)






import os
from argparse import ArgumentParser, Namespace

from ..data import SingleSentenceClassificationProcessor as Processor
from ..pipelines import TextClassificationPipeline
from ..utils import is_tf_available, is_torch_available, logging
from . import BaseTransformersCLICommand


if not is_tf_available() and not is_torch_available():
	raise RuntimeError("""At least one of PyTorch or TensorFlow 2.0+ should be installed to use CLI training""")

# TF training parameters
UpperCAmelCase							 =					False
UpperCAmelCase							 =					False

def 			A_      (	__a     :				Namespace		):

				"""simple docstring"""
				return TrainCommand(__a		)




class  __snake_case      (   SCREAMING_SNAKE_CASE):







							'''simple docstring'''






							@staticmethod
							def _a      (							a_		):
											a__				      =		parser.add_parser("""train"""  ,  help="""CLI tool to train a model on a task."""		)

											train_parser.add_argument(
											    """--train_data"""  ,  type=a_  ,  required=a_  ,  help="""path to train (and optionally evaluation) dataset as a csv with tab separated labels and sentences."""  ,  )
											train_parser.add_argument(
											    """--column_label"""  ,  type=a_  ,  default=0  ,  help="""Column of the dataset csv file with example labels."""		)
											train_parser.add_argument(
											    """--column_text"""  ,  type=a_  ,  default=1  ,  help="""Column of the dataset csv file with example texts."""		)
											train_parser.add_argument(
											    """--column_id"""  ,  type=a_  ,  default=2  ,  help="""Column of the dataset csv file with example ids."""		)
											train_parser.add_argument(
											    """--skip_first_row"""  ,  action="""store_true"""  ,  help="""Skip the first row of the csv file (headers)."""		)

											train_parser.add_argument("""--validation_data"""  ,  type=a_  ,  default=""""""  ,  help="""path to validation dataset."""		)
											train_parser.add_argument(
											    """--validation_split"""  ,  type=a_  ,  default=0.1  ,  help="""if validation dataset is not provided, fraction of train dataset to use as validation dataset."""  ,  )

											train_parser.add_argument("""--output"""  ,  type=a_  ,  default="""./"""  ,  help="""path to saved the trained model."""		)

											train_parser.add_argument(
											    """--task"""  ,  type=a_  ,  default="""text_classification"""  ,  help="""Task to train the model on."""		)
											train_parser.add_argument(
											    """--model"""  ,  type=a_  ,  default="""bert-base-uncased"""  ,  help="""Model's name or path to stored model."""		)
											train_parser.add_argument("""--train_batch_size"""  ,  type=a_  ,  default=32  ,  help="""Batch size for training."""		)
											train_parser.add_argument("""--valid_batch_size"""  ,  type=a_  ,  default=64  ,  help="""Batch size for validation."""		)
											train_parser.add_argument("""--learning_rate"""  ,  type=a_  ,  default=3E-5  ,  help="""Learning rate."""		)
											train_parser.add_argument("""--adam_epsilon"""  ,  type=a_  ,  default=1E-0_8  ,  help="""Epsilon for Adam optimizer."""		)
											train_parser.set_defaults(func=a_		)


							def __init__(							self  ,  a_		):
											a__				      =		logging.get_logger("""transformers-cli/training"""		)

											a__				      =		"""tf""" if is_tf_available() else """torch"""

											os.makedirs(args.output  ,  exist_ok=a_		)
											a__				      =		args.output

											a__				      =		args.column_label
											a__				      =		args.column_text
											a__				      =		args.column_id

											self.logger.info(F'''Loading {args.task} pipeline for {args.model}'''		)
											if args.task == "text_classification":
															a__				      =		TextClassificationPipeline.from_pretrained(args.model		)
											elif args.task == "token_classification":
															raise NotImplementedError
											elif args.task == "question_answering":
															raise NotImplementedError

											self.logger.info(F'''Loading dataset from {args.train_data}'''		)
											a__				      =		Processor.create_from_csv(
											    args.train_data  ,  column_label=args.column_label  ,  column_text=args.column_text  ,  column_id=args.column_id  ,  skip_first_row=args.skip_first_row  ,  )
											a__				      =		None
											if args.validation_data:
															self.logger.info(F'''Loading validation dataset from {args.validation_data}'''		)
															a__				      =		Processor.create_from_csv(
															    args.validation_data  ,  column_label=args.column_label  ,  column_text=args.column_text  ,  column_id=args.column_id  ,  skip_first_row=args.skip_first_row  ,  )

											a__				      =		args.validation_split
											a__				      =		args.train_batch_size
											a__				      =		args.valid_batch_size
											a__				      =		args.learning_rate
											a__				      =		args.adam_epsilon


							def _a      (							self		):
											if self.framework == "tf":
															return self.run_tf()
											return self.run_torch()


							def _a      (							self		):
											raise NotImplementedError







							def _a      (							self		):
											self.pipeline.fit(
											    self.train_dataset  ,  validation_data=self.valid_dataset  ,  validation_split=self.validation_split  ,  learning_rate=self.learning_rate  ,  adam_epsilon=self.adam_epsilon  ,  train_batch_size=self.train_batch_size  ,  valid_batch_size=self.valid_batch_size  ,  )

											# Save trained pipeline
											self.pipeline.save_pretrained(self.output		)

