Заполнение списка пакетов вручную с помощью маркера huggingface

#pytorch #huggingface-transformers #huggingface-tokenizers

Вопрос:

У меня возникли трудности с пониманием tokenizer.pad метода из библиотеки трансформаторов huggingface. Чтобы оптимизировать обучение, я выполняю маркировку в наборе данных таким образом, чтобы во время загрузки данных не выполнялось никаких сложных операций. Мой набор данных выглядит так:

 class DatasetTokenized(Dataset):

    def __init__(self, data: pd.DataFrame, text_column: str,
                 label_columns: List[str], tokenizer_name: str):
        super(DatasetTokenized, self).__init__()

        self.data = data
        self.text_column = text_column
        self.label_columns = label_columns
        self.tokenizer = BertTokenizer.from_pretrained(tokenizer_name)
        self.tokenized_data = self.tokenize_data(data)

    def __len__(self) -> int:
        return len(self.tokenized_data)

    def __getitem__(self, index: int) -> Dict:
        return self.tokenized_data[index]

    def tokenize_data(self, data: pd.DataFrame):
        tokenized_data = []

        print('Tokenizing data:')
        for _, row in tqdm(data.iterrows(), total=len(data)):

            text = row[self.text_column]
            labels = row[self.label_columns]
            encoding = self.tokenizer(text,
                                      add_special_tokens=True,
                                      max_length=512,
                                      padding=False,
                                      truncation=True,
                                      return_attention_mask=True,
                                      return_tensors='pt')

            tokenized_data.append({
                'text': text,
                'encoding': encoding,
                'labels': torch.FloatTensor(labels)
            })

        return tokenized_data
 

и мой коллатор выглядит так:

 class BertCollatorTokenized:

    def __init__(self, tokenizer_name: str):
        super(BertCollatorTokenized, self).__init__()

        self.tokenizer = BertTokenizer.from_pretrained(tokenizer_name)

    def __call__(self, batch: List[Any]):
        text, encodings, labels = zip(
            *[[sample['text'], sample['encoding'], sample['labels']]
              for sample in batch])

        encodings = list(encodings)
        encodings = self.tokenizer.pad(encodings,
                                       max_length=512,
                                       padding='longest',
                                       return_tensors='pt')

        return {
            'text': text,
            'input_ids': encodings['input_ids'],
            'attention_mask': encodings['attention_mask'],
            'labels': torch.FloatTensor(labels)
        }
 

Я подтвердил, что encodings это список BatchEncoding того, что требуется tokenizer.pad . Однако я получаю следующую ошибку:

Ошибка значения: Не удается создать тензор, вам, вероятно, следует активировать усечение и/или заполнение с помощью «заполнение=Истина «»усечение=Истина», чтобы иметь пакетные тензоры одинаковой длины.

Что немного сбивает с толку, поскольку в этом и должен быть весь смысл использования tokenizer.pad . У кого-нибудь есть представление о том, что происходит?

Комментарии:

1. Кодовая база HuggingFace в полном беспорядке, что плохого в использовании собственных факельных операций для pad? Если вы хотите придерживаться реализации HF, может ли это быть тот случай, который вам нужен encode , а не tokenize в DatasetTokenized.tokenize_data ?

2. Я использую __call__ метод токенизатора, который в фоновом режиме вызовет encode или batch_encode автоматически. Нет ничего плохого в использовании собственных функций факела, но я хотел выяснить, как это сделать с помощью API HF.

3. Ты прав, я неправильно понял (извинения).