



'''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


SCREAMING_SNAKE_CASE__          =  logging.getLogger(__name__)


class 					snake_case			(UpperCamelCase ):
       lowerCAmelCase__	:Tuple     =       "token-classification"



       def __init__(					self  ,UpperCAmelCase_   )	->				Any:
           if type(UpperCAmelCase_   ) == dict:
               lowercase__									=    Namespace(**UpperCAmelCase_   )
           lowercase__									=    import_module("tasks"   )
           try:
               lowercase__									=    getattr(UpperCAmelCase_  ,hparams.task_type   )
               lowercase__									=    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__()}'''   )
           lowercase__									=    self.token_classification_task.get_labels(hparams.labels   )
           lowercase__									=    CrossEntropyLoss().ignore_index
           super().__init__(UpperCAmelCase_  ,len(self.labels   )  ,self.mode   )



       def 				_a   (					self  ,**UpperCAmelCase_   )	->				List[Any]:
           return self.model(**UpperCAmelCase_   )



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

           lowercase__									=    self(**UpperCAmelCase_   )
           lowercase__									=    outputs[0]
           # tensorboard_logs = {"loss": loss, "rate": self.lr_scheduler.get_last_lr()[-1]}
           return {"loss": loss}



       def 				_a   (					self   )	->				str:
           lowercase__									=    self.hparams
           for mode in ["train", "dev", "test"]:
               lowercase__									=    self._feature_file(UpperCAmelCase_   )
               if os.path.exists(UpperCAmelCase_   ) and not args.overwrite_cache:
                   logger.info("Loading features from cached file %s"  ,UpperCAmelCase_   )
                   lowercase__									=    torch.load(UpperCAmelCase_   )
               else:
                   logger.info("Creating features from dataset file at %s"  ,args.data_dir   )
                   lowercase__									=    self.token_classification_task.read_examples_from_file(args.data_dir  ,UpperCAmelCase_   )
                   lowercase__									=    self.token_classification_task.convert_examples_to_features(
                       UpperCAmelCase_  ,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=UpperCAmelCase_  ,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"  ,UpperCAmelCase_   )
                   torch.save(UpperCAmelCase_  ,UpperCAmelCase_   )



       def 				_a   (					self  ,UpperCAmelCase_  ,UpperCAmelCase_  ,UpperCAmelCase_ = False   )	->				DataLoader:
           lowercase__									=    self._feature_file(UpperCAmelCase_   )
           logger.info("Loading features from cached file %s"  ,UpperCAmelCase_   )
           lowercase__									=    torch.load(UpperCAmelCase_   )
           lowercase__									=    torch.tensor([f.input_ids for f in features]  ,dtype=torch.long   )
           lowercase__									=    torch.tensor([f.attention_mask for f in features]  ,dtype=torch.long   )
           if features[0].token_type_ids is not None:
               lowercase__									=    torch.tensor([f.token_type_ids for f in features]  ,dtype=torch.long   )
           else:
               lowercase__									=    torch.tensor([0 for f in features]  ,dtype=torch.long   )
               # HACK(we will not use this anymore soon)
           lowercase__									=    torch.tensor([f.label_ids for f in features]  ,dtype=torch.long   )
           return DataLoader(
               TensorDataset(UpperCAmelCase_  ,UpperCAmelCase_  ,UpperCAmelCase_  ,UpperCAmelCase_   )  ,batch_size=UpperCAmelCase_   )



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



       def 				_a   (					self  ,UpperCAmelCase_   )	->				int:
           lowercase__									=    torch.stack([x["val_loss"] for x in outputs]   ).mean()
           lowercase__									=    np.concatenate([x["pred"] for x in outputs]  ,axis=0   )
           lowercase__									=    np.argmax(UpperCAmelCase_  ,axis=2   )
           lowercase__									=    np.concatenate([x["target"] for x in outputs]  ,axis=0   )

           lowercase__									=    dict(enumerate(self.labels   )   )
           lowercase__									=    [[] for _ in range(out_label_ids.shape[0]   )]
           lowercase__									=    [[] 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]]   )

           lowercase__									=    {
               "val_loss": val_loss_mean,
               "accuracy_score": accuracy_score(UpperCAmelCase_  ,UpperCAmelCase_   ),
               "precision": precision_score(UpperCAmelCase_  ,UpperCAmelCase_   ),
               "recall": recall_score(UpperCAmelCase_  ,UpperCAmelCase_   ),
               "f1": fa_score(UpperCAmelCase_  ,UpperCAmelCase_   ),
           }

           lowercase__									=    dict(results.items()   )
           lowercase__									=    results
           return ret, preds_list, out_label_list



       def 				_a   (					self  ,UpperCAmelCase_   )	->				Any:
           # when stable
           lowercase__							,							lowercase__							,							lowercase__									=    self._eval_end(UpperCAmelCase_   )
           lowercase__									=    ret["log"]
           return {"val_loss": logs["val_loss"], "log": logs, "progress_bar": logs}



       def 				_a   (					self  ,UpperCAmelCase_   )	->				Any:
           # updating to test_epoch_end instead of deprecated test_end
           lowercase__							,							lowercase__							,							lowercase__									=    self._eval_end(UpperCAmelCase_   )

           # Converting to the dict required by pl
           # https://github.com/PyTorchLightning/pytorch-lightning/blob/master/\
           # pytorch_lightning/trainer/logging.py#L139
           lowercase__									=    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 				_a   (					UpperCAmelCase_  ,UpperCAmelCase_   )	->				Union[str, Any]:
           # Add NER specific options
           BaseTransformer.add_model_specific_args(UpperCAmelCase_  ,UpperCAmelCase_   )
           parser.add_argument(
               "--task_type"  ,default="NER"  ,type=UpperCAmelCase_  ,help="Task type to fine tune in training (e.g. NER, POS, etc)"   )
           parser.add_argument(
               "--max_seq_length"  ,default=128  ,type=UpperCAmelCase_  ,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=UpperCAmelCase_  ,help="Path to a file containing all labels. If not specified, CoNLL-2003 labels are used."  ,)
           parser.add_argument(
               "--gpus"  ,default=0  ,type=UpperCAmelCase_  ,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__":
 SCREAMING_SNAKE_CASE__          =  argparse.ArgumentParser()
 add_generic_args(parser, os.getcwd())
 SCREAMING_SNAKE_CASE__          =  NERTransformer.add_model_specific_args(parser, os.getcwd())
 SCREAMING_SNAKE_CASE__          =  parser.parse_args()
 SCREAMING_SNAKE_CASE__          =  NERTransformer(args)
 SCREAMING_SNAKE_CASE__          =  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
  SCREAMING_SNAKE_CASE__          =  sorted(glob.glob(os.path.join(args.output_dir, "checkpoint-epoch=*.ckpt"), recursive=True))
  SCREAMING_SNAKE_CASE__          =  model.load_from_checkpoint(checkpoints[-1])
  trainer.test(model)









'''simple docstring'''





import logging
import os
import threading
import time


try:
 import warnings
except ImportError:
 SCREAMING_SNAKE_CASE__          =  None

try:
 import msvcrt
except ImportError:
 SCREAMING_SNAKE_CASE__          =  None

try:
 import fcntl
except ImportError:
 SCREAMING_SNAKE_CASE__          =  None


# Backward compatibility
# ------------------------------------------------
try:
 TimeoutError
except NameError:
 SCREAMING_SNAKE_CASE__          =  OSError


# Data
# ------------------------------------------------
SCREAMING_SNAKE_CASE__          =  [
    "Timeout",
    "BaseFileLock",
    "WindowsFileLock",
    "UnixFileLock",
    "SoftFileLock",
    "FileLock",
]

SCREAMING_SNAKE_CASE__          =  "3.0.12"


SCREAMING_SNAKE_CASE__          =  None




def 							lowerCamelCase	(					):





    '''simple docstring'''


    global _logger
    lowercase__									=    _logger or logging.getLogger(__name__							)
    return _logger


class 					snake_case			(UpperCamelCase ):



       def __init__(					self  ,UpperCAmelCase_   )	->				int:
           lowercase__									=    lock_file
           return None







       def __str__(					self   )	->				Union[str, Any]:
           lowercase__									=    F'''The file lock \'{self.lock_file}\' could not be acquired.'''
           return temp





class 					snake_case			:



       def __init__(					self  ,UpperCAmelCase_   )	->				List[Any]:
           lowercase__									=    lock
           return None



       def __enter__(					self   )	->				Optional[int]:
           return self.lock







       def __exit__(					self  ,UpperCAmelCase_  ,UpperCAmelCase_  ,UpperCAmelCase_   )	->				int:
           self.lock.release()
           return None





class 					snake_case			:



       def __init__(					self  ,UpperCAmelCase_  ,UpperCAmelCase_=-1  ,UpperCAmelCase_=None   )	->				Tuple:
           lowercase__									=    max_filename_length if max_filename_length is not None else 255
           # Hash the filename if it's too long
           lowercase__									=    self.hash_filename_if_too_long(UpperCAmelCase_  ,UpperCAmelCase_   )
           # The path to the lock file.
           lowercase__									=    lock_file

           # The file descriptor for the *_lock_file* as it is returned by the
           # os.open() function.
           # This file lock is only NOT None, if the object currently holds the
           # lock.
           lowercase__									=    None

           # The default timeout value.
           lowercase__									=    timeout

           # We use this lock primarily for the lock counter.
           lowercase__									=    threading.Lock()

           # The lock counter is used for implementing the nested locking
           # mechanism. Whenever the lock is acquired, the counter is increased and
           # the lock is only released, when this value is 0 again.
           lowercase__									=    0
           return None



       @property
       def 				_a   (					self   )	->				List[str]:
           return self._lock_file



       @property
       def 				_a   (					self   )	->				Optional[int]:
           return self._timeout



       @timeout.setter
       def 				_a   (					self  ,UpperCAmelCase_   )	->				Optional[Any]:
           lowercase__									=    float(UpperCAmelCase_   )
           return None



       def 				_a   (					self   )	->				Optional[Any]:
           raise NotImplementedError()



       def 				_a   (					self   )	->				Optional[int]:
           raise NotImplementedError()



       @property
       def 				_a   (					self   )	->				Dict:
           return self._lock_file_fd is not None



       def 				_a   (					self  ,UpperCAmelCase_=None  ,UpperCAmelCase_=0.05   )	->				Optional[Any]:
           # Use the default timeout, if no timeout is provided.
           if timeout is None:
               lowercase__									=    self.timeout

           # Increment the number right at the beginning.
           # We can still undo it, if something fails.
           with self._thread_lock:
               self._lock_counter += 1

           lowercase__									=    id(self   )
           lowercase__									=    self._lock_file
           lowercase__									=    time.time()
           try:
               while True:
                   with self._thread_lock:
                       if not self.is_locked:
                           logger().debug(F'''Attempting to acquire lock {lock_id} on {lock_filename}'''   )
                           self._acquire()

                   if self.is_locked:
                       logger().debug(F'''Lock {lock_id} acquired on {lock_filename}'''   )
                       break
                   elif timeout >= 0 and time.time() - start_time > timeout:
                       logger().debug(F'''Timeout on acquiring lock {lock_id} on {lock_filename}'''   )
                       raise Timeout(self._lock_file   )
                   else:
                       logger().debug(
                           F'''Lock {lock_id} not acquired on {lock_filename}, waiting {poll_intervall} seconds ...'''   )
                       time.sleep(UpperCAmelCase_   )
           except:  # noqa
               # Something did go wrong, so decrement the counter.
               with self._thread_lock:
                   lowercase__									=    max(0  ,self._lock_counter - 1   )

               raise
           return _Acquire_ReturnProxy(lock=self   )



       def 				_a   (					self  ,UpperCAmelCase_=False   )	->				List[Any]:
           with self._thread_lock:
               if self.is_locked:
                   self._lock_counter -= 1

                   if self._lock_counter == 0 or force:
                       lowercase__									=    id(self   )
                       lowercase__									=    self._lock_file

                       logger().debug(F'''Attempting to release lock {lock_id} on {lock_filename}'''   )
                       self._release()
                       lowercase__									=    0
                       logger().debug(F'''Lock {lock_id} released on {lock_filename}'''   )

           return None



       def __enter__(					self   )	->				Dict:
           self.acquire()
           return self



       def __exit__(					self  ,UpperCAmelCase_  ,UpperCAmelCase_  ,UpperCAmelCase_   )	->				int:
           self.release()
           return None



       def __del__(					self   )	->				Union[str, Any]:
           self.release(force=UpperCAmelCase_   )
           return None







       def 				_a   (					self  ,UpperCAmelCase_  ,UpperCAmelCase_   )	->				str:
           lowercase__									=    os.path.basename(UpperCAmelCase_   )
           if len(UpperCAmelCase_   ) > max_length and max_length > 0:
               lowercase__									=    os.path.dirname(UpperCAmelCase_   )
               lowercase__									=    str(hash(UpperCAmelCase_   )   )
               lowercase__									=    filename[: max_length - len(UpperCAmelCase_   ) - 8] + "..." + hashed_filename + ".lock"
               return os.path.join(UpperCAmelCase_  ,UpperCAmelCase_   )
           else:
               return path





class 					snake_case			(UpperCamelCase ):



       def __init__(					self  ,UpperCAmelCase_  ,UpperCAmelCase_=-1  ,UpperCAmelCase_=None   )	->				Dict:
           from .file_utils import relative_to_absolute_path

           super().__init__(UpperCAmelCase_  ,timeout=UpperCAmelCase_  ,max_filename_length=UpperCAmelCase_   )
           lowercase__									=    "\\\\?\\" + relative_to_absolute_path(self.lock_file   )



       def 				_a   (					self   )	->				List[str]:
           lowercase__									=    os.O_RDWR | os.O_CREAT | os.O_TRUNC

           try:
               lowercase__									=    os.open(self._lock_file  ,UpperCAmelCase_   )
           except OSError:
               pass
           else:
               try:
                   msvcrt.locking(UpperCAmelCase_  ,msvcrt.LK_NBLCK  ,1   )
               except OSError:
                   os.close(UpperCAmelCase_   )
               else:
                   lowercase__									=    fd
           return None







       def 				_a   (					self   )	->				Any:
           lowercase__									=    self._lock_file_fd
           lowercase__									=    None
           msvcrt.locking(UpperCAmelCase_  ,msvcrt.LK_UNLCK  ,1   )
           os.close(UpperCAmelCase_   )

           try:
               os.remove(self._lock_file   )
           # Probably another instance of the application
           # that acquired the file lock.
           except OSError:
               pass
           return None





class 					snake_case			(UpperCamelCase ):



       def __init__(					self  ,UpperCAmelCase_  ,UpperCAmelCase_=-1  ,UpperCAmelCase_=None   )	->				int:
           lowercase__									=    os.statvfs(os.path.dirname(UpperCAmelCase_   )   ).f_namemax
           super().__init__(UpperCAmelCase_  ,timeout=UpperCAmelCase_  ,max_filename_length=UpperCAmelCase_   )



       def 				_a   (					self   )	->				List[str]:
           lowercase__									=    os.O_RDWR | os.O_CREAT | os.O_TRUNC
           lowercase__									=    os.open(self._lock_file  ,UpperCAmelCase_   )

           try:
               fcntl.flock(UpperCAmelCase_  ,fcntl.LOCK_EX | fcntl.LOCK_NB   )
           except OSError:
               os.close(UpperCAmelCase_   )
           else:
               lowercase__									=    fd
           return None







       def 				_a   (					self   )	->				int:
           # Do not remove the lockfile:
           #
           #   https://github.com/benediktschmitt/py-filelock/issues/31
           #   https://stackoverflow.com/questions/17708885/flock-removing-locked-file-without-race-condition
           lowercase__									=    self._lock_file_fd
           lowercase__									=    None
           fcntl.flock(UpperCAmelCase_  ,fcntl.LOCK_UN   )
           os.close(UpperCAmelCase_   )
           return None





class 					snake_case			(UpperCamelCase ):



       def 				_a   (					self   )	->				Optional[Any]:
           lowercase__									=    os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_TRUNC
           try:
               lowercase__									=    os.open(self._lock_file  ,UpperCAmelCase_   )
           except OSError:
               pass
           else:
               lowercase__									=    fd
           return None







       def 				_a   (					self   )	->				Tuple:
           os.close(self._lock_file_fd   )
           lowercase__									=    None

           try:
               os.remove(self._lock_file   )
           # The file is already deleted and that's what we want.
           except OSError:
               pass
           return None





SCREAMING_SNAKE_CASE__          =  None

if msvcrt:
 SCREAMING_SNAKE_CASE__          =  WindowsFileLock
elif fcntl:
 SCREAMING_SNAKE_CASE__          =  UnixFileLock
else:
 SCREAMING_SNAKE_CASE__          =  SoftFileLock

 if warnings is not None:
  warnings.warn("only soft file lock is available")




