import torch
from torch.utils.data import Dataset, DataLoader
from torch.nn.utils.rnn import pad_sequence
texts = [
[5, 9, 12, 34, 23, 76, 89], # len = 7
[2, 45, 23], # len = 3
[12, 56, 78, 90, 43, 22, 11, 8], # len = 8
[65, 12, 99, 54], # len = 4
[3, 7, 8, 5, 1, 4, 6, 10, 11], # len = 9
]
labels = [0, 1, 0, 2, 1]
class TextDataset(Dataset):
def __init__(self, texts, labels):
# сложите тексты и классы в переменные датасета
self.texts = texts
self.labels = labels
def __len__(self):
# посчитайте размер датасета
return len(self.texts)
def __getitem__(self, idx):
# верните элемент датасета
return {
'text': torch.tensor(self.texts[idx], dtype=torch.long),
'label': torch.tensor(self.labels[idx], dtype=torch.long)
}
def collate_fn(batch):
texts = [item['text'] for item in batch]
labels = [item['label'] for item in batch]
# посчитайте длины текстов в батче
lengths = []
for _ in range(len(texts)):
lengths.append(len(texts[_]))
# отсортируйте тексты и классы по убыванию длины текстов
joined_data = list(zip(lengths, texts, labels))
# joined_data = torch.cat(
# torch.tensor(lengths),
# torch.tensor(texts),
# labels
# )
joined_data.sort(key=lambda x: x[0], reverse=True)
# joined_data = torch.argsort(joined_data, dim=0)
lengths, texts, labels = zip(*joined_data)
# lengths, texts, labels = torch.split(joined_data, 0)
# дополните тексты пэддингом
padded_texts = pad_sequence(texts, batch_first=True, padding_value=0)
# посчитайте маску для батча
masks = (padded_texts != 0).long()
return {
'texts': padded_texts, # (batch_size, max_len)
'masks': masks, # (batch_size, max_len)
'labels': labels, # (batch_size,)
'lengths': lengths
}
dataset = TextDataset(texts, labels)
# создайте объект dataloader с batch_size=3 и реализованным collate_fn
dataloader = DataLoader(dataset, batch_size=3, collate_fn=collate_fn)
# вывод результатов
for batch in dataloader:
print("Texts:\n", batch['texts'])
print("Masks:\n", batch['masks'])
print("Labels:", batch['labels'])
# print("Lengths:", batch['lengths'])
print("=" * 40)