codingutf8 2018 the google ai language team s and the huggingface inc team c 2018 nvidia corporation licensed under the apache license version 2 0 the license you may not use this file except in compliance with the license you may obtain a copy of the license at http www apache orglicenseslicense2 0 unless required by applicable law or agreed to in writing software distributed under the license is distributed on an as is basis without warranties or conditions of any kind either express or implied see the license for the specific language governing permissions and limitations under the license a single trainingtest example for simple sequence classification args guid unique id for the example texta string the untokenized text of the first sequence for single sequence tasks only this sequence must be specified textb optional string the untokenized text of the second sequence only must be specified for sequence pair tasks label optional string the label of the example this should be specified for train and dev examples but not for test examples pairid optional string unique identifier for the pair of sentences a single set of features of data property names are the same names as the corresponding inputs to a model args inputids indices of input sequence tokens in the vocabulary attentionmask mask to avoid performing attention on padding token indices mask values selected in 0 1 usually 1 for tokens that are not masked 0 for masked padded tokens tokentypeids optional segment token indices to indicate first and second portions of the inputs only some models use them label optional label corresponding to the input int for classification problems float for regression problems pairid optional unique identifier for the pair of sentences this will be superseded by a frameworkagnostic approach soon hacklabel indices are swapped in roberta pretrained model make sure only the first process in distributed training processes the dataset and the others will use the cache this will be superseded by a frameworkagnostic approach soon hacklabel indices are swapped in roberta pretrained model processor for the hans data set def gettrainexamplesself datadir see base class return self createexamplesself readtsvos path joindatadir heuristicsevaluationset txt dev def getlabelsself creates examples for the training and dev sets examples for i line in enumeratelines if i 0 continue guid ss settype line0 texta line5 textb line6 pairid line72 if line7 startswithex else line7 label line0 examples appendinputexampleguidguid textatexta textbtextb labellabel pairidpairid return examples def hansconvertexamplestofeatures examples listinputexample labellist liststr maxlength int tokenizer pretrainedtokenizer labelmap label i for i label in enumeratelabellist features for exindex example in tqdm tqdmenumerateexamples descconvert examples to features if exindex 10000 0 logger infowriting example d exindex inputs tokenizer example texta example textb addspecialtokenstrue maxlengthmaxlength paddingmaxlength truncationtrue returnoverflowingtokenstrue label labelmapexample label if example label in labelmap else 0 pairid intexample pairid features appendinputfeaturesinputs labellabel pairidpairid for i example in enumerateexamples 5 logger info example logger infofguid example logger infoffeatures featuresi return features hanstasksnumlabels hans 3 hansprocessors hans hansprocessor coding utf 8 2018 the google ai language team s and the huggingface inc team c 2018 nvidia corporation licensed under the apache license version 2 0 the license you may not use this file except in compliance with the license you may obtain a copy of the license at http www apache org licenses license 2 0 unless required by applicable law or agreed to in writing software distributed under the license is distributed on an as is basis without warranties or conditions of any kind either express or implied see the license for the specific language governing permissions and limitations under the license a single training test example for simple sequence classification args guid unique id for the example text_a string the untokenized text of the first sequence for single sequence tasks only this sequence must be specified text_b optional string the untokenized text of the second sequence only must be specified for sequence pair tasks label optional string the label of the example this should be specified for train and dev examples but not for test examples pairid optional string unique identifier for the pair of sentences a single set of features of data property names are the same names as the corresponding inputs to a model args input_ids indices of input sequence tokens in the vocabulary attention_mask mask to avoid performing attention on padding token indices mask values selected in 0 1 usually 1 for tokens that are not masked 0 for masked padded tokens token_type_ids optional segment token indices to indicate first and second portions of the inputs only some models use them label optional label corresponding to the input int for classification problems float for regression problems pairid optional unique identifier for the pair of sentences this will be superseded by a framework agnostic approach soon hack label indices are swapped in roberta pretrained model make sure only the first process in distributed training processes the dataset and the others will use the cache this will be superseded by a framework agnostic approach soon hack label indices are swapped in roberta pretrained model processor for the hans data set see base class see base class see base class note that we follow the standard three labels for mnli see class transformers data processors utils mnliprocessor but the hans evaluation groups contradiction and neutral into non entailment label 0 while entailment is label 1 creates examples for the training and dev sets loads a data file into a list of inputfeatures args examples list of inputexamples containing the examples label_list list of labels can be obtained from the processor using the processor get_labels method max_length maximum example length tokenizer instance of a tokenizer that will tokenize the examples returns a list of task specific inputfeatures which can be fed to the model
import logging
import os
from dataclasses import dataclass
from typing import List, Optional, Union

import tqdm
from filelock import FileLock

from transformers import (
    BartTokenizer,
    BartTokenizerFast,
    DataProcessor,
    PreTrainedTokenizer,
    RobertaTokenizer,
    RobertaTokenizerFast,
    XLMRobertaTokenizer,
    is_tf_available,
    is_torch_available,
)


logger = logging.getLogger(__name__)


@dataclass(frozen=True)
class InputExample:
    

    guid: str
    text_a: str
    text_b: Optional[str] = None
    label: Optional[str] = None
    pairID: Optional[str] = None


@dataclass(frozen=True)
class InputFeatures:
    

    input_ids: List[int]
    attention_mask: Optional[List[int]] = None
    token_type_ids: Optional[List[int]] = None
    label: Optional[Union[int, float]] = None
    pairID: Optional[int] = None


if is_torch_available():
    import torch
    from torch.utils.data import Dataset

    class HansDataset(Dataset):
        

        features: List[InputFeatures]

        def __init__(
            self,
            data_dir: str,
            tokenizer: PreTrainedTokenizer,
            task: str,
            max_seq_length: Optional[int] = None,
            overwrite_cache=False,
            evaluate: bool = False,
        ):
            processor = hans_processors[task]()

            cached_features_file = os.path.join(
                data_dir,
                "cached_{}_{}_{}_{}".format(
                    "dev" if evaluate else "train",
                    tokenizer.__class__.__name__,
                    str(max_seq_length),
                    task,
                ),
            )
            label_list = processor.get_labels()
            if tokenizer.__class__ in (
                RobertaTokenizer,
                RobertaTokenizerFast,
                XLMRobertaTokenizer,
                BartTokenizer,
                BartTokenizerFast,
            ):
                
                label_list[1], label_list[2] = label_list[2], label_list[1]
            self.label_list = label_list

            
            
            lock_path = cached_features_file + ".lock"
            with FileLock(lock_path):
                if os.path.exists(cached_features_file) and not overwrite_cache:
                    logger.info(f"Loading features from cached file {cached_features_file}")
                    self.features = torch.load(cached_features_file)
                else:
                    logger.info(f"Creating features from dataset file at {data_dir}")

                    examples = (
                        processor.get_dev_examples(data_dir) if evaluate else processor.get_train_examples(data_dir)
                    )

                    logger.info("Training examples: %s", len(examples))
                    self.features = hans_convert_examples_to_features(examples, label_list, max_seq_length, tokenizer)
                    logger.info("Saving features into cached file %s", cached_features_file)
                    torch.save(self.features, cached_features_file)

        def __len__(self):
            return len(self.features)

        def __getitem__(self, i) -> InputFeatures:
            return self.features[i]

        def get_labels(self):
            return self.label_list


if is_tf_available():
    import tensorflow as tf

    class TFHansDataset:
        

        features: List[InputFeatures]

        def __init__(
            self,
            data_dir: str,
            tokenizer: PreTrainedTokenizer,
            task: str,
            max_seq_length: Optional[int] = 128,
            overwrite_cache=False,
            evaluate: bool = False,
        ):
            processor = hans_processors[task]()
            label_list = processor.get_labels()
            if tokenizer.__class__ in (
                RobertaTokenizer,
                RobertaTokenizerFast,
                XLMRobertaTokenizer,
                BartTokenizer,
                BartTokenizerFast,
            ):
                
                label_list[1], label_list[2] = label_list[2], label_list[1]
            self.label_list = label_list

            examples = processor.get_dev_examples(data_dir) if evaluate else processor.get_train_examples(data_dir)
            self.features = hans_convert_examples_to_features(examples, label_list, max_seq_length, tokenizer)

            def gen():
                for ex_index, ex in tqdm.tqdm(enumerate(self.features), desc="convert examples to features"):
                    if ex_index % 10000 == 0:
                        logger.info("Writing example %d of %d" % (ex_index, len(examples)))

                    yield (
                        {
                            "example_id": 0,
                            "input_ids": ex.input_ids,
                            "attention_mask": ex.attention_mask,
                            "token_type_ids": ex.token_type_ids,
                        },
                        ex.label,
                    )

            self.dataset = tf.data.Dataset.from_generator(
                gen,
                (
                    {
                        "example_id": tf.int32,
                        "input_ids": tf.int32,
                        "attention_mask": tf.int32,
                        "token_type_ids": tf.int32,
                    },
                    tf.int64,
                ),
                (
                    {
                        "example_id": tf.TensorShape([]),
                        "input_ids": tf.TensorShape([None, None]),
                        "attention_mask": tf.TensorShape([None, None]),
                        "token_type_ids": tf.TensorShape([None, None]),
                    },
                    tf.TensorShape([]),
                ),
            )

        def get_dataset(self):
            return self.dataset

        def __len__(self):
            return len(self.features)

        def __getitem__(self, i) -> InputFeatures:
            return self.features[i]

        def get_labels(self):
            return self.label_list


class HansProcessor(DataProcessor):
    

    def get_train_examples(self, data_dir):
        
        return self._create_examples(self._read_tsv(os.path.join(data_dir, "heuristics_train_set.txt")), "train")

    def get_dev_examples(self, data_dir):
        
        return self._create_examples(self._read_tsv(os.path.join(data_dir, "heuristics_evaluation_set.txt")), "dev")

    def get_labels(self):
        
        return ["contradiction", "entailment", "neutral"]

    def _create_examples(self, lines, set_type):
        
        examples = []
        for i, line in enumerate(lines):
            if i == 0:
                continue
            guid = "%s-%s" % (set_type, line[0])
            text_a = line[5]
            text_b = line[6]
            pairID = line[7][2:] if line[7].startswith("ex") else line[7]
            label = line[0]
            examples.append(InputExample(guid=guid, text_a=text_a, text_b=text_b, label=label, pairID=pairID))
        return examples


def hans_convert_examples_to_features(
    examples: List[InputExample],
    label_list: List[str],
    max_length: int,
    tokenizer: PreTrainedTokenizer,
):
    

    label_map = {label: i for i, label in enumerate(label_list)}

    features = []
    for ex_index, example in tqdm.tqdm(enumerate(examples), desc="convert examples to features"):
        if ex_index % 10000 == 0:
            logger.info("Writing example %d" % (ex_index))

        inputs = tokenizer(
            example.text_a,
            example.text_b,
            add_special_tokens=True,
            max_length=max_length,
            padding="max_length",
            truncation=True,
            return_overflowing_tokens=True,
        )

        label = label_map[example.label] if example.label in label_map else 0

        pairID = int(example.pairID)

        features.append(InputFeatures(**inputs, label=label, pairID=pairID))

    for i, example in enumerate(examples[:5]):
        logger.info("*** Example ***")
        logger.info(f"guid: {example}")
        logger.info(f"features: {features[i]}")

    return features


hans_tasks_num_labels = {
    "hans": 3,
}

hans_processors = {
    "hans": HansProcessor,
}