



"""simple docstring"""






import os
import posixpath
import uuid
from dataclasses import dataclass
from typing import TYPE_CHECKING, Iterable, List, Optional, Tuple, Union

import numpy as np
import pyarrow as pa

import datasets
from datasets.arrow_writer import ArrowWriter, ParquetWriter
from datasets.config import MAX_SHARD_SIZE
from datasets.filesystems import (
    is_remote_filesystem,
    rename,
)
from datasets.iterable_dataset import _BaseExamplesIterable
from datasets.utils.py_utils import convert_file_size_to_int


lowerCAmelCase__        =				datasets.utils.logging.get_logger(__name__)

if TYPE_CHECKING:
   import pyspark






@dataclass
class        __snake_case       (	datasets.BuilderConfig):
  snake_case__				:   Optional[datasets.Features]  			=						None






def        snake_case_  (      A_					:		"pyspark.sql.DataFrame",				A_					:		List[int],				):


       '''simple docstring'''





       import pyspark

       def generate_fn():
              _lowerCamelCase						:				Any    			= df.select('''*''',				pyspark.sql.functions.spark_partition_id().alias('''part_id'''						)						)
              for partition_id in partition_order:
                     _lowerCamelCase						:				List[str]    			= df_with_partition_id.select('''*'''						).where(F'''part_id = {partition_id}'''						).drop('''part_id'''						)
                     _lowerCamelCase						:				Optional[Any]    			= partition_df.collect()
                     _lowerCamelCase						:				int    			= 0
                     for row in rows:
                            yield F'''{partition_id}_{row_id}''', row.asDict()
                            row_id += 1

       return generate_fn






class        __snake_case       (	_BaseExamplesIterable):




  def __init__( self     :						List[str]						,					__lowerCAmelCase     :						"pyspark.sql.DataFrame"						,					__lowerCAmelCase     :						List[str]=None						,					):






         """simple docstring"""






         _lowerCamelCase						:				int    			= df
         _lowerCamelCase						:				Union[str, Any]    			= partition_order or range(self.df.rdd.getNumPartitions()		)
         _lowerCamelCase						:				str    			= _generate_iterable_examples(self.df						,					self.partition_order		)




  def __iter__( self     :						Optional[int]		):






         """simple docstring"""






         yield from self.generate_examples_fn()




  def 						SCREAMING_SNAKE_CASE				( self     :						List[Any]						,					__lowerCAmelCase     :						np.random.Generator		):






         """simple docstring"""






         _lowerCamelCase						:				List[str]    			= list(range(self.df.rdd.getNumPartitions()		)		)
         generator.shuffle(__lowerCAmelCase		)
         return SparkExamplesIterable(self.df						,					partition_order=__lowerCAmelCase		)




  def 						SCREAMING_SNAKE_CASE				( self     :						List[str]						,					__lowerCAmelCase     :						int						,					__lowerCAmelCase     :						int		):






         """simple docstring"""






         _lowerCamelCase						:				List[Any]    			= self.split_shard_indices_by_worker(__lowerCAmelCase						,					__lowerCAmelCase		)
         return SparkExamplesIterable(self.df						,					partition_order=__lowerCAmelCase		)




  @property
  def 						SCREAMING_SNAKE_CASE				( self     :						Optional[int]		):






         """simple docstring"""






         return len(self.partition_order		)






class        __snake_case       (	datasets.DatasetBuilder):
  snake_case__				:   Dict  			=						SparkConfig




  def __init__( self     :						str						,					__lowerCAmelCase     :						"pyspark.sql.DataFrame"						,					__lowerCAmelCase     :						str = None						,					__lowerCAmelCase     :						str = None						,					**__lowerCAmelCase     :						str						,					):






         """simple docstring"""






         import pyspark

         _lowerCamelCase						:				Union[str, Any]    			= pyspark.sql.SparkSession.builder.getOrCreate()
         _lowerCamelCase						:				Tuple    			= df
         _lowerCamelCase						:				Tuple    			= working_dir

         super().__init__(
             cache_dir=__lowerCAmelCase						,					config_name=str(self.df.semanticHash()		)						,					**__lowerCAmelCase						,					)




  def 						SCREAMING_SNAKE_CASE				( self     :						str		):






         """simple docstring"""






         def create_cache_and_write_probe(__lowerCAmelCase     :						Optional[int]		):
                # makedirs with exist_ok will recursively create the directory. It will not throw an error if directories
                # already exist.
                os.makedirs(self._cache_dir						,					exist_ok=__lowerCAmelCase		)
                _lowerCamelCase						:				str    			= os.path.join(self._cache_dir						,					'''fs_test''' + uuid.uuida().hex		)
                # Opening the file in append mode will create a new file unless it already exists, in which case it will not
                # change the file contents.
                open(__lowerCAmelCase						,					'''a'''		)
                return [probe_file]

         if self._spark.conf.get('''spark.master'''						,					''''''		).startswith('''local'''		):
                return

         # If the cluster is multi-node, make sure that the user provided a cache_dir and that it is on an NFS
         # accessible to the driver.
         # TODO: Stream batches to the driver using ArrowCollectSerializer instead of throwing an error.
         if self._cache_dir:
                _lowerCamelCase						:				Union[str, Any]    			= (
                    self._spark.sparkContext.parallelize(range(1		)						,					1		).mapPartitions(__lowerCAmelCase		).collect()
                )
                if os.path.isfile(probe[0]		):
                       return

         raise ValueError(
             '''When using Dataset.from_spark on a multi-node cluster, the driver and all workers should be able to access cache_dir'''		)




  def 						SCREAMING_SNAKE_CASE				( self     :						str		):






         """simple docstring"""






         return datasets.DatasetInfo(features=self.config.features		)




  def 						SCREAMING_SNAKE_CASE				( self     :						List[Any]						,					__lowerCAmelCase     :						datasets.download.download_manager.DownloadManager		):






         """simple docstring"""






         return [datasets.SplitGenerator(name=datasets.Split.TRAIN		)]




  def 						SCREAMING_SNAKE_CASE				( self     :						int						,					__lowerCAmelCase     :						str		):






         """simple docstring"""






         import pyspark

         def get_arrow_batch_size(__lowerCAmelCase     :						Union[str, Any]		):
                for batch in it:
                       yield pa.RecordBatch.from_pydict({'''batch_bytes''': [batch.nbytes]}		)

         _lowerCamelCase						:				Optional[int]    			= self.df.count()
         _lowerCamelCase						:				Optional[Any]    			= df_num_rows if df_num_rows <= 1_0_0 else 1_0_0
         # Approximate the size of each row (in Arrow format) by averaging over a max-100-row sample.
         _lowerCamelCase						:				Union[str, Any]    			= (
             self.df.limit(__lowerCAmelCase		)
             .repartition(1		)
             .mapInArrow(__lowerCAmelCase						,					'''batch_bytes: long'''		)
             .agg(pyspark.sql.functions.sum('''batch_bytes'''		).alias('''sample_bytes'''		)		)
             .collect()[0]
             .sample_bytes
             / sample_num_rows
         )
         _lowerCamelCase						:				Any    			= approx_bytes_per_row * df_num_rows
         if approx_total_size > max_shard_size:
                # Make sure there is at least one row per partition.
                _lowerCamelCase						:				Union[str, Any]    			= min(__lowerCAmelCase						,					int(approx_total_size / max_shard_size		)		)
                _lowerCamelCase						:				List[str]    			= self.df.repartition(__lowerCAmelCase		)




  def 						SCREAMING_SNAKE_CASE				( self     :						List[str]						,					__lowerCAmelCase     :						str						,					__lowerCAmelCase     :						str						,					__lowerCAmelCase     :						int						,					):






         """simple docstring"""






         import pyspark

         _lowerCamelCase						:				Dict    			= ParquetWriter if file_format == '''parquet''' else ArrowWriter
         _lowerCamelCase						:				Optional[Any]    			= os.path.join(self._working_dir						,					os.path.basename(__lowerCAmelCase		)		) if self._working_dir else fpath
         _lowerCamelCase						:				Tuple    			= file_format == '''parquet'''

         # Define these so that we don't reference self in write_arrow, which will result in a pickling error due to
         # pickling the SparkContext.
         _lowerCamelCase						:				int    			= self.config.features
         _lowerCamelCase						:				Union[str, Any]    			= self._writer_batch_size
         _lowerCamelCase						:				Optional[int]    			= self._fs.storage_options

         def write_arrow(__lowerCAmelCase     :						Optional[int]		):
                # Within the same SparkContext, no two task attempts will share the same attempt ID.
                _lowerCamelCase						:				int    			= pyspark.TaskContext().taskAttemptId()
                _lowerCamelCase						:				Optional[int]    			= next(__lowerCAmelCase						,					__lowerCAmelCase		)
                if first_batch is None:
                       # Some partitions might not receive any data.
                       return pa.RecordBatch.from_arrays(
                           [[task_id], [0], [0]]						,					names=['''task_id''', '''num_examples''', '''num_bytes''']						,					)
                _lowerCamelCase						:				Tuple    			= 0
                _lowerCamelCase						:				Optional[Any]    			= writer_class(
                    features=__lowerCAmelCase						,					path=working_fpath.replace('''SSSSS'''						,					f'''{shard_id:05d}'''		).replace('''TTTTT'''						,					f'''{task_id:05d}'''		)						,					writer_batch_size=__lowerCAmelCase						,					storage_options=__lowerCAmelCase						,					embed_local_files=__lowerCAmelCase						,					)
                _lowerCamelCase						:				Dict    			= pa.Table.from_batches([first_batch]		)
                writer.write_table(__lowerCAmelCase		)
                for batch in it:
                       if max_shard_size is not None and writer._num_bytes >= max_shard_size:
                              _lowerCamelCase			,    _lowerCamelCase						:				Union[str, Any]    			= writer.finalize()
                              writer.close()
                              yield pa.RecordBatch.from_arrays(
                                  [[task_id], [num_examples], [num_bytes]]						,					names=['''task_id''', '''num_examples''', '''num_bytes''']						,					)
                              shard_id += 1
                              _lowerCamelCase						:				Dict    			= writer_class(
                                  features=writer._features						,					path=working_fpath.replace('''SSSSS'''						,					f'''{shard_id:05d}'''		).replace('''TTTTT'''						,					f'''{task_id:05d}'''		)						,					writer_batch_size=__lowerCAmelCase						,					storage_options=__lowerCAmelCase						,					embed_local_files=__lowerCAmelCase						,					)
                       _lowerCamelCase						:				int    			= pa.Table.from_batches([batch]		)
                       writer.write_table(__lowerCAmelCase		)

                if writer._num_bytes > 0:
                       _lowerCamelCase			,    _lowerCamelCase						:				List[str]    			= writer.finalize()
                       writer.close()
                       yield pa.RecordBatch.from_arrays(
                           [[task_id], [num_examples], [num_bytes]]						,					names=['''task_id''', '''num_examples''', '''num_bytes''']						,					)

                if working_fpath != fpath:
                       for file in os.listdir(os.path.dirname(__lowerCAmelCase		)		):
                              _lowerCamelCase						:				List[Any]    			= os.path.join(os.path.dirname(__lowerCAmelCase		)						,					os.path.basename(__lowerCAmelCase		)		)
                              shutil.move(__lowerCAmelCase						,					__lowerCAmelCase		)

         _lowerCamelCase						:				Any    			= (
             self.df.mapInArrow(__lowerCAmelCase						,					'''task_id: long, num_examples: long, num_bytes: long'''		)
             .groupBy('''task_id'''		)
             .agg(
                 pyspark.sql.functions.sum('''num_examples'''		).alias('''total_num_examples'''		)						,					pyspark.sql.functions.sum('''num_bytes'''		).alias('''total_num_bytes'''		)						,					pyspark.sql.functions.count('''num_bytes'''		).alias('''num_shards'''		)						,					pyspark.sql.functions.collect_list('''num_examples'''		).alias('''shard_lengths'''		)						,					)
             .collect()
         )
         for row in stats:
                yield row.task_id, (row.total_num_examples, row.total_num_bytes, row.num_shards, row.shard_lengths)




  def 						SCREAMING_SNAKE_CASE				( self     :						Any						,					__lowerCAmelCase     :						"datasets.SplitGenerator"						,					__lowerCAmelCase     :						str = "arrow"						,					__lowerCAmelCase     :						Optional[Union[str, int]] = None						,					__lowerCAmelCase     :						Optional[int] = None						,					**__lowerCAmelCase     :						List[Any]						,					):






         """simple docstring"""






         self._validate_cache_dir()

         _lowerCamelCase						:				Union[str, Any]    			= convert_file_size_to_int(max_shard_size or MAX_SHARD_SIZE		)
         self._repartition_df_if_needed(__lowerCAmelCase		)
         _lowerCamelCase						:				str    			= not is_remote_filesystem(self._fs		)
         _lowerCamelCase						:				List[Any]    			= os.path.join if is_local else posixpath.join

         _lowerCamelCase						:				Optional[int]    			= '''-TTTTT-SSSSS-of-NNNNN'''
         _lowerCamelCase						:				List[Any]    			= f'''{self.name}-{split_generator.name}{SUFFIX}.{file_format}'''
         _lowerCamelCase						:				List[Any]    			= path_join(self._output_dir						,					__lowerCAmelCase		)

         _lowerCamelCase						:				Union[str, Any]    			= 0
         _lowerCamelCase						:				List[str]    			= 0
         _lowerCamelCase						:				Any    			= 0
         _lowerCamelCase						:				List[str]    			= []
         _lowerCamelCase						:				Union[str, Any]    			= []

         for task_id, content in self._prepare_split_single(__lowerCAmelCase						,					__lowerCAmelCase						,					__lowerCAmelCase		):
                (
                    (
                    _lowerCamelCase
                )			,    (
                    _lowerCamelCase
                )			,    (
                    _lowerCamelCase
                )			,    (
                    _lowerCamelCase
                )			,    
                )						:				Optional[int]    			= content
                if num_bytes > 0:
                       total_num_examples += num_examples
                       total_num_bytes += num_bytes
                       total_shards += num_shards
                       task_id_and_num_shards.append((task_id, num_shards)		)
                       all_shard_lengths.extend(__lowerCAmelCase		)

         _lowerCamelCase						:				Tuple    			= total_num_examples
         _lowerCamelCase						:				Dict    			= total_num_bytes

         # should rename everything at the end
         logger.debug(f'''Renaming {total_shards} shards.'''		)
         if total_shards > 1:
                _lowerCamelCase						:				Any    			= all_shard_lengths

                # Define fs outside of _rename_shard so that we don't reference self in the function, which will result in a
                # pickling error due to pickling the SparkContext.
                _lowerCamelCase						:				Optional[Any]    			= self._fs

                # use the -SSSSS-of-NNNNN pattern
                def _rename_shard(
                    __lowerCAmelCase     :						int						,					__lowerCAmelCase     :						int						,					__lowerCAmelCase     :						int						,					):
                       rename(
                           __lowerCAmelCase						,					fpath.replace('''SSSSS'''						,					f'''{shard_id:05d}'''		).replace('''TTTTT'''						,					f'''{task_id:05d}'''		)						,					fpath.replace('''TTTTT-SSSSS'''						,					f'''{global_shard_id:05d}'''		).replace('''NNNNN'''						,					f'''{total_shards:05d}'''		)						,					)

                _lowerCamelCase						:				Tuple    			= []
                _lowerCamelCase						:				Optional[Any]    			= 0
                for i in range(len(__lowerCAmelCase		)		):
                       _lowerCamelCase			,    _lowerCamelCase						:				Union[str, Any]    			= task_id_and_num_shards[i]
                       for shard_id in range(__lowerCAmelCase		):
                              args.append([task_id, shard_id, global_shard_id]		)
                              global_shard_id += 1
                self._spark.sparkContext.parallelize(__lowerCAmelCase						,					len(__lowerCAmelCase		)		).map(lambda __lowerCAmelCase		: _rename_shard(*__lowerCAmelCase		)		).collect()
         else:
                # don't use any pattern
                _lowerCamelCase						:				List[Any]    			= 0
                _lowerCamelCase						:				List[str]    			= task_id_and_num_shards[0][0]
                self._rename(
                    fpath.replace('''SSSSS'''						,					f'''{shard_id:05d}'''		).replace('''TTTTT'''						,					f'''{task_id:05d}'''		)						,					fpath.replace(__lowerCAmelCase						,					''''''		)						,					)




  def 						SCREAMING_SNAKE_CASE				( self     :						List[Any]						,					__lowerCAmelCase     :						"datasets.SplitGenerator"						,					):






         """simple docstring"""






         return SparkExamplesIterable(self.df		)




import argparse
import glob
import logging
import os
import time
from argparse import Namespace

import numpy as np
import torch
from lightning_base import BaseTransformer, add_generic_args, generic_train
from torch.utils.data import DataLoader, TensorDataset

from transformers import glue_compute_metrics as compute_metrics
from transformers import glue_convert_examples_to_features as convert_examples_to_features
from transformers import glue_output_modes, glue_tasks_num_labels
from transformers import glue_processors as processors


UpperCAmelCase	      = logging.getLogger(__name__)







class        A_   (			__lowerCamelCase   ):




	'''simple docstring'''


	_UpperCamelCase     :     Optional[int]							 =       """sequence-classification"""





	def __init__(       self		,    snake_case       ):
		if type(snake_case       ) == dict:
			lowercase       =    Namespace(**snake_case       )
		lowercase       =    glue_output_modes[hparams.task]
		lowercase       =    glue_tasks_num_labels[hparams.task]

		super().__init__(snake_case		,    snake_case		,    self.mode       )





	def 	SCREAMING_SNAKE_CASE__						(       self		,    **snake_case       ):
		return self.model(**snake_case       )





	def 	SCREAMING_SNAKE_CASE__						(       self		,    snake_case		,    snake_case       ):
		lowercase       =    {'input_ids': batch[0], 'attention_mask': batch[1], 'labels': batch[3]}

		if self.config.model_type not in ["distilbert", "bart"]:
			lowercase       =    batch[2] if self.config.model_type in ['bert', 'xlnet', 'albert'] else None

		lowercase       =    self(**snake_case       )
		lowercase       =    outputs[0]

		lowercase       =    self.trainer.lr_schedulers[0]['scheduler']
		lowercase       =    {'loss': loss, 'rate': lr_scheduler.get_last_lr()[-1]}
		return {"loss": loss, "log": tensorboard_logs}





	def 	SCREAMING_SNAKE_CASE__						(       self       ):
		lowercase       =    self.hparams
		lowercase       =    processors[args.task]()
		lowercase       =    processor.get_labels()

		for mode in ["train", "dev"]:
			lowercase       =    self._feature_file(snake_case       )
			if os.path.exists(snake_case       ) and not args.overwrite_cache:
				logger.info('Loading features from cached file %s'		,    snake_case       )
			else:
				logger.info('Creating features from dataset file at %s'		,    args.data_dir       )
				lowercase       =    (
				    processor.get_dev_examples(args.data_dir       )
				    if mode == 'dev'
				    else processor.get_train_examples(args.data_dir       )
				)
				lowercase       =    convert_examples_to_features(
				    snake_case		,    self.tokenizer		,    max_length=args.max_seq_length		,    label_list=self.labels		,    output_mode=args.glue_output_mode		,    )
				logger.info('Saving features into cached file %s'		,    snake_case       )
				torch.save(snake_case		,    snake_case       )





	def 	SCREAMING_SNAKE_CASE__						(       self		,    snake_case		,    snake_case		,    snake_case = False       ):
		lowercase       =    'dev' if mode == 'test' else mode

		lowercase       =    self._feature_file(snake_case       )
		logger.info('Loading features from cached file %s'		,    snake_case       )
		lowercase       =    torch.load(snake_case       )
		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       )
		lowercase       =    torch.tensor([f.token_type_ids for f in features]		,    dtype=torch.long       )
		if self.hparams.glue_output_mode == "classification":
			lowercase       =    torch.tensor([f.label for f in features]		,    dtype=torch.long       )
		elif self.hparams.glue_output_mode == "regression":
			lowercase       =    torch.tensor([f.label for f in features]		,    dtype=torch.float       )

		return DataLoader(
		    TensorDataset(snake_case		,    snake_case		,    snake_case		,    snake_case       )		,    batch_size=snake_case		,    shuffle=snake_case		,    )





	def 	SCREAMING_SNAKE_CASE__						(       self		,    snake_case		,    snake_case       ):
		lowercase       =    {'input_ids': batch[0], 'attention_mask': batch[1], 'labels': batch[3]}

		if self.config.model_type not in ["distilbert", "bart"]:
			lowercase       =    batch[2] if self.config.model_type in ['bert', 'xlnet', 'albert'] else None

		lowercase       =    self(**snake_case       )
		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 	SCREAMING_SNAKE_CASE__						(       self		,    snake_case       ):
		lowercase       =    torch.stack([x['val_loss'] for x in outputs]       ).mean().detach().cpu().item()
		lowercase       =    np.concatenate([x['pred'] for x in outputs]		,    axis=0       )

		if self.hparams.glue_output_mode == "classification":
			lowercase       =    np.argmax(snake_case		,    axis=1       )
		elif self.hparams.glue_output_mode == "regression":
			lowercase       =    np.squeeze(snake_case       )

		lowercase       =    np.concatenate([x['target'] for x in outputs]		,    axis=0       )
		lowercase       =    [[] for _ in range(out_label_ids.shape[0]       )]
		lowercase       =    [[] for _ in range(out_label_ids.shape[0]       )]

		lowercase       =    {**{'val_loss': val_loss_mean}, **compute_metrics(self.hparams.task		,    snake_case		,    snake_case       )}

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





	def 	SCREAMING_SNAKE_CASE__						(       self		,    snake_case       ):
		lowercase  ,					lowercase  ,					lowercase       =    self._eval_end(snake_case       )
		lowercase       =    ret['log']
		return {"val_loss": logs["val_loss"], "log": logs, "progress_bar": logs}





	def 	SCREAMING_SNAKE_CASE__						(       self		,    snake_case       ):
		lowercase  ,					lowercase  ,					lowercase       =    self._eval_end(snake_case       )
		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 	SCREAMING_SNAKE_CASE__						(       snake_case		,    snake_case       ):
		BaseTransformer.add_model_specific_args(snake_case		,    snake_case       )
		parser.add_argument(
		    '--max_seq_length'		,    default=128		,    type=snake_case		,    help=(
		        'The maximum total input sequence length after tokenization. Sequences longer '
		        'than this will be truncated, sequences shorter will be padded.'
		    )		,    )

		parser.add_argument(
		    '--task'		,    default=''		,    type=snake_case		,    required=snake_case		,    help='The GLUE task to run'		,    )
		parser.add_argument(
		    '--gpus'		,    default=0		,    type=snake_case		,    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






def 							UpperCAmelCase_		(							):
	lowercase       =    argparse.ArgumentParser()
	add_generic_args(__SCREAMING_SNAKE_CASE ,							os.getcwd()							)
	lowercase       =    GLUETransformer.add_model_specific_args(__SCREAMING_SNAKE_CASE ,							os.getcwd()							)
	lowercase       =    parser.parse_args()

	# If output_dir not provided, a folder will be generated in pwd
	if args.output_dir is None:
		lowercase       =    os.path.join(
		    './results' ,							F'''{args.task}_{time.strftime('%Y%m%d_%H%M%S'							)}''' ,							)
		os.makedirs(args.output_dir							)

	lowercase       =    GLUETransformer(__SCREAMING_SNAKE_CASE							)
	lowercase       =    generic_train(__SCREAMING_SNAKE_CASE ,							__SCREAMING_SNAKE_CASE							)

	# Optionally, predict on dev set and write to output_dir
	if args.do_predict:
		lowercase       =    sorted(glob.glob(os.path.join(args.output_dir ,							'checkpoint-epoch=*.ckpt'							) ,							recursive=__SCREAMING_SNAKE_CASE							)							)
		lowercase       =    model.load_from_checkpoint(checkpoints[-1]							)
		return trainer.test(__SCREAMING_SNAKE_CASE							)


if __name__ == "__main__":
	main()

