"""simple docstring"""
import argparse
import glob
import logging
import os
from argparse import Namespace
from importlib import import_module

import numpy as np
import torch
from lightning_base import BaseTransformer, add_generic_args, generic_train
from seqeval.metrics import accuracy_score, fa_score, precision_score, recall_score
from torch.nn import CrossEntropyLoss
from torch.utils.data import DataLoader, TensorDataset
from utils_ner import TokenClassificationTask


lowercase__ 	=     logging.getLogger(__name__)




class        __snake_case	(					__lowerCAmelCase    ):
      a__				=		"""token-classification"""



      def __init__(						self   ,      lowercase)     ->      Any:





        '''simple docstring'''





        if type(lowercase) == dict:
          a__:					Optional[int]      							=     Namespace(**lowercase)
        a__:					Optional[int]      							=     import_module('tasks')
        try:
          a__:					List[Any]      							=     getattr(lowercase   ,      hparams.task_type)
          a__:					TokenClassificationTask      							=     token_classification_task_clazz()
        except AttributeError:
          raise ValueError(
              f'Task {hparams.task_type} needs to be defined as a TokenClassificationTask subclass in {module}. '
              f'Available tasks classes are: {TokenClassificationTask.__subclasses__()}')
        a__:					Dict      							=     self.token_classification_task.get_labels(hparams.labels)
        a__:					List[str]      							=     CrossEntropyLoss().ignore_index
        super().__init__(lowercase   ,      len(self.labels)   ,      self.mode)



      def   lowerCamelCase_       (						self   ,      **lowercase)     ->      str:





        '''simple docstring'''





        return self.model(**lowercase)



      def   lowerCamelCase_       (						self   ,      lowercase   ,      lowercase)     ->      Optional[int]:





        '''simple docstring'''





        a__:					List[Any]      							=     {'input_ids': batch[0], 'attention_mask': batch[1], 'labels': batch[3]}
        if self.config.model_type != "distilbert":
          a__:					List[Any]      							=     (
              batch[2] if self.config.model_type in ['bert', 'xlnet'] else None
          )  # XLM and RoBERTa don"t use token_type_ids

        a__:					List[str]      							=     self(**lowercase)
        a__:					int      							=     outputs[0]
        # tensorboard_logs = {"loss": loss, "rate": self.lr_scheduler.get_last_lr()[-1]}
        return {"loss": loss}



      def   lowerCamelCase_       (						self)     ->      str:





        '''simple docstring'''





        a__:					Tuple      							=     self.hparams
        for mode in ["train", "dev", "test"]:
          a__:					Any      							=     self._feature_file(lowercase)
          if os.path.exists(lowercase) and not args.overwrite_cache:
            logger.info('Loading features from cached file %s'   ,      lowercase)
            a__:					List[Any]      							=     torch.load(lowercase)
          else:
            logger.info('Creating features from dataset file at %s'   ,      args.data_dir)
            a__:					Union[str, Any]      							=     self.token_classification_task.read_examples_from_file(args.data_dir   ,      lowercase)
            a__:					Any      							=     self.token_classification_task.convert_examples_to_features(
                lowercase   ,      self.labels   ,      args.max_seq_length   ,      self.tokenizer   ,      cls_token_at_end=bool(self.config.model_type in ['xlnet'])   ,      cls_token=self.tokenizer.cls_token   ,      cls_token_segment_id=2 if self.config.model_type in ['xlnet'] else 0   ,      sep_token=self.tokenizer.sep_token   ,      sep_token_extra=lowercase   ,      pad_on_left=bool(self.config.model_type in ['xlnet'])   ,      pad_token=self.tokenizer.pad_token_id   ,      pad_token_segment_id=self.tokenizer.pad_token_type_id   ,      pad_token_label_id=self.pad_token_label_id   ,      )
            logger.info('Saving features into cached file %s'   ,      lowercase)
            torch.save(lowercase   ,      lowercase)



      def   lowerCamelCase_       (						self   ,      lowercase   ,      lowercase   ,      lowercase = False)     ->      DataLoader:





        '''simple docstring'''





        a__:					List[Any]      							=     self._feature_file(lowercase)
        logger.info('Loading features from cached file %s'   ,      lowercase)
        a__:					Union[str, Any]      							=     torch.load(lowercase)
        a__:					str      							=     torch.tensor([f.input_ids for f in features]   ,      dtype=torch.long)
        a__:					Dict      							=     torch.tensor([f.attention_mask for f in features]   ,      dtype=torch.long)
        if features[0].token_type_ids is not None:
          a__:					List[Any]      							=     torch.tensor([f.token_type_ids for f in features]   ,      dtype=torch.long)
        else:
          a__:					int      							=     torch.tensor([0 for f in features]   ,      dtype=torch.long)
          # HACK(we will not use this anymore soon)
        a__:					int      							=     torch.tensor([f.label_ids for f in features]   ,      dtype=torch.long)
        return DataLoader(
            TensorDataset(lowercase   ,      lowercase   ,      lowercase   ,      lowercase)   ,      batch_size=lowercase)



      def   lowerCamelCase_       (						self   ,      lowercase   ,      lowercase)     ->      Optional[int]:





        '''simple docstring'''





        """Compute validation""" ""
        a__:					int      							=     {'input_ids': batch[0], 'attention_mask': batch[1], 'labels': batch[3]}
        if self.config.model_type != "distilbert":
          a__:					Dict      							=     (
              batch[2] if self.config.model_type in ['bert', 'xlnet'] else None
          )  # XLM and RoBERTa don"t use token_type_ids
        a__:					str      							=     self(**lowercase)
        a__							,   a__:					int      							=     outputs[:2]
        a__:					Tuple      							=     logits.detach().cpu().numpy()
        a__:					List[str]      							=     inputs['labels'].detach().cpu().numpy()
        return {"val_loss": tmp_eval_loss.detach().cpu(), "pred": preds, "target": out_label_ids}



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





        '''simple docstring'''





        a__:					int      							=     torch.stack([x['val_loss'] for x in outputs]).mean()
        a__:					List[str]      							=     np.concatenate([x['pred'] for x in outputs]   ,      axis=0)
        a__:					Dict      							=     np.argmax(lowercase   ,      axis=2)
        a__:					int      							=     np.concatenate([x['target'] for x in outputs]   ,      axis=0)

        a__:					Optional[Any]      							=     dict(enumerate(self.labels))
        a__:					List[str]      							=     [[] for _ in range(out_label_ids.shape[0])]
        a__:					str      							=     [[] for _ in range(out_label_ids.shape[0])]

        for i in range(out_label_ids.shape[0]):
          for j in range(out_label_ids.shape[1]):
            if out_label_ids[i, j] != self.pad_token_label_id:
              out_label_list[i].append(label_map[out_label_ids[i][j]])
              preds_list[i].append(label_map[preds[i][j]])

        a__:					Union[str, Any]      							=     {
            'val_loss': val_loss_mean,
            'accuracy_score': accuracy_score(lowercase   ,      lowercase),
            'precision': precision_score(lowercase   ,      lowercase),
            'recall': recall_score(lowercase   ,      lowercase),
            'f1': fa_score(lowercase   ,      lowercase),
        }

        a__:					List[str]      							=     dict(results.items())
        a__:					List[str]      							=     results
        return ret, preds_list, out_label_list



      def   lowerCamelCase_       (						self   ,      lowercase)     ->      Optional[int]:





        '''simple docstring'''





        a__							,   a__							,   a__:					List[str]      							=     self._eval_end(lowercase)
        a__:					List[str]      							=     ret['log']
        return {"val_loss": logs["val_loss"], "log": logs, "progress_bar": logs}



      def   lowerCamelCase_       (						self   ,      lowercase)     ->      str:





        '''simple docstring'''





        a__							,   a__							,   a__:					Optional[int]      							=     self._eval_end(lowercase)

        # Converting to the dict required by pl
        # https://github.com/PyTorchLightning/pytorch-lightning/blob/master/\
        # pytorch_lightning/trainer/logging.py#L139
        a__:					List[str]      							=     ret['log']
        # `val_loss` is the key returned by `self._eval_end()` but actually refers to `test_loss`
        return {"avg_test_loss": logs["val_loss"], "log": logs, "progress_bar": logs}



      @staticmethod
      def   lowerCamelCase_       (						lowercase   ,      lowercase)     ->      Any:





        '''simple docstring'''





        BaseTransformer.add_model_specific_args(lowercase   ,      lowercase)
        parser.add_argument(
            '--task_type'   ,      default='NER'   ,      type=lowercase   ,      help='Task type to fine tune in training (e.g. NER, POS, etc)')
        parser.add_argument(
            '--max_seq_length'   ,      default=1_28   ,      type=lowercase   ,      help=(
                'The maximum total input sequence length after tokenization. Sequences longer '
                'than this will be truncated, sequences shorter will be padded.'
            )   ,      )

        parser.add_argument(
            '--labels'   ,      default=''   ,      type=lowercase   ,      help='Path to a file containing all labels. If not specified, CoNLL-2003 labels are used.'   ,      )
        parser.add_argument(
            '--gpus'   ,      default=0   ,      type=lowercase   ,      help='The number of GPUs allocated for this, it is by default 0 meaning none'   ,      )

        parser.add_argument(
            '--overwrite_cache'   ,      action='store_true'   ,      help='Overwrite the cached training and evaluation sets')

        return parser


if __name__ == "__main__":
 lowercase__ 	=     argparse.ArgumentParser()
 add_generic_args(parser, os.getcwd())
 lowercase__ 	=     NERTransformer.add_model_specific_args(parser, os.getcwd())
 lowercase__ 	=     parser.parse_args()
 lowercase__ 	=     NERTransformer(args)
 lowercase__ 	=     generic_train(model, args)

 if args.do_predict:
  # See https://github.com/huggingface/transformers/issues/3159
  # pl use this default format to create a checkpoint:
  # https://github.com/PyTorchLightning/pytorch-lightning/blob/master\
  # /pytorch_lightning/callbacks/model_checkpoint.py#L322
  lowercase__ 	=     sorted(glob.glob(os.path.join(args.output_dir, 'checkpoint-epoch=*.ckpt'), recursive=True))
  lowercase__ 	=     model.load_from_checkpoint(checkpoints[-1])
  trainer.test(model)



"""simple docstring"""
def 						__a       (     _SCREAMING_SNAKE_CASE       )     ->bool:
  return credit_card_number.startswith(('34', '35', '37', '4', '5', '6')       )







def 						__a       (     _SCREAMING_SNAKE_CASE       )     ->bool:
  a__:					Any      							=     credit_card_number
  a__:					Tuple      							=     0
  a__:					List[str]      							=     len(_SCREAMING_SNAKE_CASE       ) - 2
  for i in range(_SCREAMING_SNAKE_CASE		,					-1		,					-2       ):
    #  double the value of every second digit
    a__:					Tuple      							=     int(cc_number[i]       )
    digit *= 2
    # If doubling of a number results in a two digit number
    # i.e greater than 9(e.g., 6 × 2 = 12),
    # then add the digits of the product (e.g., 12: 1 + 2 = 3, 15: 1 + 5 = 6),
    # to get a single digit number.
    if digit > 9:
      digit %= 10
      digit += 1
    a__:					Optional[Any]      							=     cc_number[:i] + str(_SCREAMING_SNAKE_CASE       ) + cc_number[i + 1 :]
    total += digit

  # Sum up the remaining digits
  for i in range(len(_SCREAMING_SNAKE_CASE       ) - 1		,					-1		,					-2       ):
    total += int(cc_number[i]       )

  return total % 10 == 0







def 						__a       (     _SCREAMING_SNAKE_CASE       )     ->bool:
  a__:					Optional[int]      							=     F'{credit_card_number} is an invalid credit card number because'
  if not credit_card_number.isdigit():
    print(F'{error_message} it has nonnumerical characters.'       )
    return False

  if not 13 <= len(_SCREAMING_SNAKE_CASE       ) <= 16:
    print(F'{error_message} of its length.'       )
    return False

  if not validate_initial_digits(_SCREAMING_SNAKE_CASE       ):
    print(F'{error_message} of its first two digits.'       )
    return False

  if not luhn_validation(_SCREAMING_SNAKE_CASE       ):
    print(F'{error_message} it fails the Luhn check.'       )
    return False

  print(F'{credit_card_number} is a valid credit card number.'       )
  return True


if __name__ == "__main__":
 import doctest

 doctest.testmod()
 validate_credit_card_number('4111111111111111')
 validate_credit_card_number('32323')


