





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
_snake_case  :    Optional[int]						    =  False
_snake_case  :    Union[str, Any]						    =  False

def   a_    ( lowerCAmelCase_      :			Namespace	):
   return TrainCommand(__a	)




class 				_UpperCAmelCase    (    lowercase__    ):

  """simple docstring"""


  @staticmethod
  def 				lowercase		(				lowerCAmelCase_ :		ArgumentParser     )							->						Optional[int]:
     __lowerCAmelCase								=	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=3_2					,  help='Batch size for training.'     )
     train_parser.add_argument('--valid_batch_size'					,  type=_a					,  default=6_4					,  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-08					,  help='Epsilon for Adam optimizer.'     )
     train_parser.set_defaults(func=_a     )






  def __init__(				self :		int					,  lowerCAmelCase_ :		Namespace     )							->						Union[str, Any]:
     __lowerCAmelCase								=	logging.get_logger('transformers-cli/training'     )

     __lowerCAmelCase								=	'tf' if is_tf_available() else 'torch'

     os.makedirs(args.output					,  exist_ok=_a     )
     __lowerCAmelCase								=	args.output

     __lowerCAmelCase								=	args.column_label
     __lowerCAmelCase								=	args.column_text
     __lowerCAmelCase								=	args.column_id

     self.logger.info(f"""Loading {args.task} pipeline for {args.model}"""     )
     if args.task == "text_classification":
        __lowerCAmelCase								=	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}"""     )
     __lowerCAmelCase								=	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					,  )
     __lowerCAmelCase								=	None
     if args.validation_data:
        self.logger.info(f"""Loading validation dataset from {args.validation_data}"""     )
        __lowerCAmelCase								=	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					,  )

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






  def 				lowercase		(				self :		Any     )							->						Tuple:






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






  def 				lowercase		(				self :		Tuple     )							->						Any:
     raise NotImplementedError






  def 				lowercase		(				self :		List[str]     )							->						Tuple:
     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     )



'''simple docstring'''







import numpy as np

from transformers import BatchFeature
from transformers.testing_utils import require_tf, require_torch

from .test_feature_extraction_common import FeatureExtractionSavingTestMixin







class UpperCAmelCase__	( lowercase__	):





  """simple docstring"""

  __UpperCAmelCase				:				Union[str, Any]   =					None
  __UpperCAmelCase				:				List[Any]   =					None


  @property
  def   __lowercase		(		self      :     Dict       ):


     '''simple docstring'''






     return self.feat_extract_tester.prepare_feat_extract_dict()


  def   __lowercase		(		self      :     str       ):


     '''simple docstring'''






     _a				:	Dict			=   self.feature_extraction_class(**self.feat_extract_dict       )
     self.assertTrue(hasattr(_a							,'feature_size'       )       )
     self.assertTrue(hasattr(_a							,'sampling_rate'       )       )
     self.assertTrue(hasattr(_a							,'padding_value'       )       )


  def   __lowercase		(		self      :     int       ):


     '''simple docstring'''






     _a				:	Any			=   self.feat_extract_tester.prepare_inputs_for_common()
     _a				:	str			=   self.feature_extraction_class(**self.feat_extract_dict       )
     _a				:	int			=   feat_extract.model_input_names[0]

     _a				:	List[Any]			=   BatchFeature({input_name: speech_inputs}       )

     self.assertTrue(all(len(_a       ) == len(_a       ) for x, y in zip(_a							,processed_features[input_name]       )       )       )

     _a				:	Any			=   self.feat_extract_tester.prepare_inputs_for_common(equal_length=_a       )
     _a				:	Union[str, Any]			=   BatchFeature({input_name: speech_inputs}							,tensor_type='np'       )

     _a				:	Union[str, Any]			=   processed_features[input_name]

     if len(batch_features_input.shape       ) < 3:
        _a				:	Optional[int]			=   batch_features_input[:, :, None]

     self.assertTrue(
         batch_features_input.shape
         == (self.feat_extract_tester.batch_size, len(speech_inputs[0]       ), self.feat_extract_tester.feature_size)       )


  @require_torch
  def   __lowercase		(		self      :     Any       ):


     '''simple docstring'''






     _a				:	List[Any]			=   self.feat_extract_tester.prepare_inputs_for_common(equal_length=_a       )
     _a				:	Dict			=   self.feature_extraction_class(**self.feat_extract_dict       )
     _a				:	int			=   feat_extract.model_input_names[0]

     _a				:	str			=   BatchFeature({input_name: speech_inputs}							,tensor_type='pt'       )

     _a				:	str			=   processed_features[input_name]

     if len(batch_features_input.shape       ) < 3:
        _a				:	str			=   batch_features_input[:, :, None]

     self.assertTrue(
         batch_features_input.shape
         == (self.feat_extract_tester.batch_size, len(speech_inputs[0]       ), self.feat_extract_tester.feature_size)       )


  @require_tf
  def   __lowercase		(		self      :     int       ):


     '''simple docstring'''






     _a				:	int			=   self.feat_extract_tester.prepare_inputs_for_common(equal_length=_a       )
     _a				:	Dict			=   self.feature_extraction_class(**self.feat_extract_dict       )
     _a				:	Tuple			=   feat_extract.model_input_names[0]

     _a				:	int			=   BatchFeature({input_name: speech_inputs}							,tensor_type='tf'       )

     _a				:	Optional[int]			=   processed_features[input_name]

     if len(batch_features_input.shape       ) < 3:
        _a				:	Optional[Any]			=   batch_features_input[:, :, None]

     self.assertTrue(
         batch_features_input.shape
         == (self.feat_extract_tester.batch_size, len(speech_inputs[0]       ), self.feat_extract_tester.feature_size)       )


  def   __lowercase		(		self      :     Dict							,_a      :     Any=False       ):


     '''simple docstring'''






     def _inputs_have_equal_length(_a      :     Tuple       ):
        _a				:	Tuple			=   len(input[0]       )
        for input_slice in input[1:]:
           if len(_a       ) != length:
              return False
        return True

     def _inputs_are_equal(_a      :     Optional[Any]							,_a      :     Union[str, Any]       ):
        if len(_a       ) != len(_a       ):
           return False

        for input_slice_a, input_slice_a in zip(_a							,_a       ):
           if not np.allclose(np.asarray(_a       )							,np.asarray(_a       )							,atol=1E-3       ):
              return False
        return True

     _a				:	int			=   self.feature_extraction_class(**self.feat_extract_dict       )
     _a				:	Tuple			=   self.feat_extract_tester.prepare_inputs_for_common(numpify=_a       )
     _a				:	Union[str, Any]			=   feat_extract.model_input_names[0]

     _a				:	Tuple			=   BatchFeature({input_name: speech_inputs}       )

     _a				:	str			=   self.feat_extract_tester.seq_length_diff
     _a				:	Dict			=   self.feat_extract_tester.max_seq_length + pad_diff
     _a				:	Dict			=   self.feat_extract_tester.min_seq_length
     _a				:	Optional[Any]			=   self.feat_extract_tester.batch_size
     _a				:	Tuple			=   self.feat_extract_tester.feature_size

     # test padding for List[int] + numpy
     _a				:	int			=   feat_extract.pad(_a							,padding=_a       )
     _a				:	List[Any]			=   input_a[input_name]

     _a				:	Tuple			=   feat_extract.pad(_a							,padding='longest'       )
     _a				:	Any			=   input_a[input_name]

     _a				:	Optional[Any]			=   feat_extract.pad(_a							,padding='max_length'							,max_length=len(speech_inputs[-1]       )       )
     _a				:	List[str]			=   input_a[input_name]

     _a				:	List[str]			=   feat_extract.pad(_a							,padding='longest'							,return_tensors='np'       )
     _a				:	str			=   input_a[input_name]

     # max_length parameter has to be provided when setting `padding="max_length"`
     with self.assertRaises(_a       ):
        feat_extract.pad(_a							,padding='max_length'       )[input_name]

     _a				:	int			=   feat_extract.pad(
         _a							,padding='max_length'							,max_length=_a							,return_tensors='np'       )
     _a				:	Optional[int]			=   input_a[input_name]

     self.assertFalse(_inputs_have_equal_length(_a       )       )
     self.assertTrue(_inputs_have_equal_length(_a       )       )
     self.assertTrue(_inputs_have_equal_length(_a       )       )
     self.assertTrue(_inputs_are_equal(_a							,_a       )       )
     self.assertTrue(len(input_a[0]       ) == pad_min_length       )
     self.assertTrue(len(input_a[1]       ) == pad_min_length + pad_diff       )
     self.assertTrue(input_a.shape[:2] == (batch_size, len(input_a[0]       ))       )
     self.assertTrue(input_a.shape[:2] == (batch_size, pad_max_length)       )

     if feature_size > 1:
        self.assertTrue(input_a.shape[2] == input_a.shape[2] == feature_size       )

     # test padding for `pad_to_multiple_of` for List[int] + numpy
     _a				:	Tuple			=   feat_extract.pad(_a							,pad_to_multiple_of=10       )
     _a				:	List[str]			=   input_a[input_name]

     _a				:	str			=   feat_extract.pad(_a							,padding='longest'							,pad_to_multiple_of=10       )
     _a				:	Tuple			=   input_a[input_name]

     _a				:	Optional[int]			=   feat_extract.pad(
         _a							,padding='max_length'							,pad_to_multiple_of=10							,max_length=_a       )
     _a				:	Any			=   input_a[input_name]

     _a				:	Optional[int]			=   feat_extract.pad(
         _a							,padding='max_length'							,pad_to_multiple_of=10							,max_length=_a							,return_tensors='np'							,)
     _a				:	Dict			=   input_a[input_name]

     self.assertTrue(all(len(_a       ) % 10 == 0 for x in input_a       )       )
     self.assertTrue(_inputs_are_equal(_a							,_a       )       )

     _a				:	List[str]			=   pad_max_length if pad_max_length % 10 == 0 else (pad_max_length // 10 + 1) * 10
     self.assertTrue(all(len(_a       ) == expected_mult_pad_length for x in input_a       )       )
     self.assertEqual(input_a.shape[:2]							,(batch_size, expected_mult_pad_length)       )

     if feature_size > 1:
        self.assertTrue(input_a.shape[2] == feature_size       )

     # Check padding value is correct
     _a				:	Any			=   (np.ones(self.feat_extract_tester.feature_size       ) * feat_extract.padding_value).sum()
     self.assertTrue(
         abs(np.asarray(input_a[0]       )[pad_min_length:].sum() - padding_vector_sum * (pad_max_length - pad_min_length)       )
         < 1E-3       )
     self.assertTrue(
         abs(
             np.asarray(input_a[1]       )[pad_min_length + pad_diff :].sum()
             - padding_vector_sum * (pad_max_length - pad_min_length - pad_diff)       )
         < 1E-3       )
     self.assertTrue(
         abs(
             np.asarray(input_a[2]       )[pad_min_length + 2 * pad_diff :].sum()
             - padding_vector_sum * (pad_max_length - pad_min_length - 2 * pad_diff)       )
         < 1E-3       )
     self.assertTrue(
         abs(input_a[0, pad_min_length:].sum() - padding_vector_sum * (pad_max_length - pad_min_length)       ) < 1E-3       )
     self.assertTrue(
         abs(input_a[0, pad_min_length:].sum() - padding_vector_sum * (expected_mult_pad_length - pad_min_length)       )
         < 1E-3       )


  def   __lowercase		(		self      :     List[Any]							,_a      :     Optional[int]=False       ):


     '''simple docstring'''






     def _inputs_have_equal_length(_a      :     List[str]       ):
        _a				:	Union[str, Any]			=   len(input[0]       )
        for input_slice in input[1:]:
           if len(_a       ) != length:
              return False
        return True

     def _inputs_are_equal(_a      :     List[str]							,_a      :     List[str]       ):
        if len(_a       ) != len(_a       ):
           return False

        for input_slice_a, input_slice_a in zip(_a							,_a       ):
           if not np.allclose(np.asarray(_a       )							,np.asarray(_a       )							,atol=1E-3       ):
              return False
        return True

     _a				:	Dict			=   self.feature_extraction_class(**self.feat_extract_dict       )
     _a				:	str			=   self.feat_extract_tester.prepare_inputs_for_common(numpify=_a       )
     _a				:	Any			=   feat_extract.model_input_names[0]

     _a				:	List[Any]			=   BatchFeature({input_name: speech_inputs}       )

     # truncate to smallest
     _a				:	Union[str, Any]			=   feat_extract.pad(
         _a							,padding='max_length'							,max_length=len(speech_inputs[0]       )							,truncation=_a       )
     _a				:	str			=   input_a[input_name]

     _a				:	List[str]			=   feat_extract.pad(_a							,padding='max_length'							,max_length=len(speech_inputs[0]       )       )
     _a				:	Tuple			=   input_a[input_name]

     self.assertTrue(_inputs_have_equal_length(_a       )       )
     self.assertFalse(_inputs_have_equal_length(_a       )       )

     # truncate to smallest with np
     _a				:	Dict			=   feat_extract.pad(
         _a							,padding='max_length'							,max_length=len(speech_inputs[0]       )							,return_tensors='np'							,truncation=_a							,)
     _a				:	Any			=   input_a[input_name]

     _a				:	List[Any]			=   feat_extract.pad(
         _a							,padding='max_length'							,max_length=len(speech_inputs[0]       )							,return_tensors='np'       )
     _a				:	int			=   input_a[input_name]

     self.assertTrue(_inputs_have_equal_length(_a       )       )
     self.assertTrue(input_a.shape[1] == len(speech_inputs[0]       )       )

     # since truncation forces padding to be smaller than longest input
     # function can't return `np.ndarray`, but has to return list
     self.assertFalse(_inputs_have_equal_length(_a       )       )

     # truncate to middle
     _a				:	Dict			=   feat_extract.pad(
         _a							,padding='max_length'							,max_length=len(speech_inputs[1]       )							,truncation=_a							,return_tensors='np'							,)
     _a				:	List[Any]			=   input_a[input_name]

     _a				:	Tuple			=   feat_extract.pad(
         _a							,padding='max_length'							,max_length=len(speech_inputs[1]       )							,truncation=_a       )
     _a				:	Tuple			=   input_a[input_name]

     _a				:	Tuple			=   feat_extract.pad(
         _a							,padding='max_length'							,max_length=len(speech_inputs[1]       )							,return_tensors='np'       )
     _a				:	Dict			=   input_a[input_name]

     self.assertTrue(input_a.shape[1] == len(speech_inputs[1]       )       )
     self.assertTrue(_inputs_have_equal_length(_a       )       )
     self.assertTrue(_inputs_have_equal_length(_a       )       )
     self.assertTrue(_inputs_are_equal(_a							,_a       )       )

     # since truncation forces padding to be smaller than longest input
     # function can't return `np.ndarray`, but has to return list
     self.assertFalse(_inputs_have_equal_length(_a       )       )
     self.assertTrue(len(input_a[-1]       ) == len(speech_inputs[-1]       )       )

     # padding has to be max_length when setting `truncation=True`
     with self.assertRaises(_a       ):
        feat_extract.pad(_a							,truncation=_a       )[input_name]

     # padding has to be max_length when setting `truncation=True`
     with self.assertRaises(_a       ):
        feat_extract.pad(_a							,padding='longest'							,truncation=_a       )[input_name]

     # padding has to be max_length when setting `truncation=True`
     with self.assertRaises(_a       ):
        feat_extract.pad(_a							,padding='longest'							,truncation=_a       )[input_name]

     # max_length parameter has to be provided when setting `truncation=True` and padding="max_length"
     with self.assertRaises(_a       ):
        feat_extract.pad(_a							,padding='max_length'							,truncation=_a       )[input_name]

     # test truncation for `pad_to_multiple_of` for List[int] + numpy
     _a				:	Optional[Any]			=   12
     _a				:	List[Any]			=   feat_extract.pad(
         _a							,padding='max_length'							,max_length=len(speech_inputs[0]       )							,pad_to_multiple_of=_a							,truncation=_a							,)
     _a				:	Tuple			=   input_a[input_name]

     _a				:	str			=   feat_extract.pad(
         _a							,padding='max_length'							,max_length=len(speech_inputs[0]       )							,pad_to_multiple_of=_a							,)
     _a				:	List[Any]			=   input_a[input_name]

     # retrieve expected_length as multiple of pad_to_multiple_of
     _a				:	List[Any]			=   len(speech_inputs[0]       )
     if expected_length % pad_to_multiple_of != 0:
        _a				:	Union[str, Any]			=   ((len(speech_inputs[0]       ) // pad_to_multiple_of) + 1) * pad_to_multiple_of

     self.assertTrue(len(input_a[0]       ) == expected_length       )
     self.assertTrue(_inputs_have_equal_length(_a       )       )
     self.assertFalse(_inputs_have_equal_length(_a       )       )


  def   __lowercase		(		self      :     Union[str, Any]       ):


     '''simple docstring'''






     self._check_padding(numpify=_a       )


  def   __lowercase		(		self      :     Tuple       ):


     '''simple docstring'''






     self._check_padding(numpify=_a       )


  def   __lowercase		(		self      :     Dict       ):


     '''simple docstring'''






     self._check_truncation(numpify=_a       )


  def   __lowercase		(		self      :     str       ):


     '''simple docstring'''






     self._check_truncation(numpify=_a       )


  @require_torch
  def   __lowercase		(		self      :     Dict       ):


     '''simple docstring'''






     _a				:	Any			=   self.feature_extraction_class(**self.feat_extract_dict       )
     _a				:	List[Any]			=   self.feat_extract_tester.prepare_inputs_for_common()
     _a				:	Union[str, Any]			=   feat_extract.model_input_names[0]

     _a				:	Optional[int]			=   BatchFeature({input_name: speech_inputs}       )

     _a				:	List[Any]			=   feat_extract.pad(_a							,padding='longest'							,return_tensors='np'       )[input_name]
     _a				:	List[str]			=   feat_extract.pad(_a							,padding='longest'							,return_tensors='pt'       )[input_name]

     self.assertTrue(abs(input_np.astype(np.floataa       ).sum() - input_pt.numpy().astype(np.floataa       ).sum()       ) < 1E-2       )


  @require_tf
  def   __lowercase		(		self      :     int       ):


     '''simple docstring'''






     _a				:	List[str]			=   self.feature_extraction_class(**self.feat_extract_dict       )
     _a				:	Optional[Any]			=   self.feat_extract_tester.prepare_inputs_for_common()
     _a				:	Dict			=   feat_extract.model_input_names[0]

     _a				:	Optional[Any]			=   BatchFeature({input_name: speech_inputs}       )

     _a				:	Dict			=   feat_extract.pad(_a							,padding='longest'							,return_tensors='np'       )[input_name]
     _a				:	Any			=   feat_extract.pad(_a							,padding='longest'							,return_tensors='tf'       )[input_name]

     self.assertTrue(abs(input_np.astype(np.floataa       ).sum() - input_tf.numpy().astype(np.floataa       ).sum()       ) < 1E-2       )


  def   __lowercase		(		self      :     Union[str, Any]       ):


     '''simple docstring'''






     _a				:	str			=   self.feat_extract_dict
     _a				:	List[Any]			=   True
     _a				:	Optional[int]			=   self.feature_extraction_class(**_a       )
     _a				:	List[Any]			=   self.feat_extract_tester.prepare_inputs_for_common()
     _a				:	Tuple			=   [len(_a       ) for x in speech_inputs]
     _a				:	int			=   feat_extract.model_input_names[0]

     _a				:	Optional[Any]			=   BatchFeature({input_name: speech_inputs}       )

     _a				:	str			=   feat_extract.pad(_a							,padding='longest'							,return_tensors='np'       )
     self.assertIn('attention_mask'							,_a       )
     self.assertListEqual(list(processed.attention_mask.shape       )							,list(processed[input_name].shape[:2]       )       )
     self.assertListEqual(processed.attention_mask.sum(-1       ).tolist()							,_a       )


  def   __lowercase		(		self      :     int       ):


     '''simple docstring'''






     _a				:	Any			=   self.feat_extract_dict
     _a				:	Tuple			=   True
     _a				:	Optional[int]			=   self.feature_extraction_class(**_a       )
     _a				:	Dict			=   self.feat_extract_tester.prepare_inputs_for_common()
     _a				:	Dict			=   [len(_a       ) for x in speech_inputs]
     _a				:	Union[str, Any]			=   feat_extract.model_input_names[0]

     _a				:	Any			=   BatchFeature({input_name: speech_inputs}       )
     _a				:	List[Any]			=   min(_a       )

     _a				:	Dict			=   feat_extract.pad(
         _a							,padding='max_length'							,max_length=_a							,truncation=_a							,return_tensors='np'       )
     self.assertIn('attention_mask'							,_a       )
     self.assertListEqual(
         list(processed_pad.attention_mask.shape       )							,[processed_pad[input_name].shape[0], max_length]       )
     self.assertListEqual(
         processed_pad.attention_mask[:, :max_length].sum(-1       ).tolist()							,[max_length for x in speech_inputs]       )



