Pytorch dataloader для предложений - PullRequest
1 голос
/ 29 января 2020

Я собрал небольшой набор данных для классификации двоичного текста, и моя цель - обучить модель с помощью метода, предложенного Сверточные нейронные сети для классификации предложений

Я начал свою реализацию с помощью torch.util.data.Dataset. По сути, каждый образец в моем наборе данных my_data выглядит следующим образом (как пример):

{"words":[0,1,2,3,4],"label":1},
{"words":[4,9,20,30,4,2,3,4,1],"label":0}

Далее я взглянул на Запись пользовательских загрузчиков данных с помощью pytorch : using:

dataloader = DataLoader(my_data, batch_size=2,
                    shuffle=False, num_workers=4)

Я подозреваю, что при перечислении по партии получится что-то следующее:

{"words":[[0,1,2,3,4],[4,9,20,30,4,2,3,4,1]],"labels":[1,0]}

Однако это больше похоже на это:

{"words":[[0,4],[1,9],[2,20],[3,30],[4,4]],"label":[1,0]}

Я думаю, это что-то сделать что они не равны по размеру. Должны ли они быть одинакового размера, и если да, то как мне этого добиться? Для людей, которые разбираются в этой статье, как выглядят ваши тренировочные данные?

edit:

class CustomDataset(Dataset):
def __init__(self, path_to_file, max_size=10, transform=None):

    with open(path_to_file) as f:
        self.data = json.load(f)
    self.transform = transform
    self.vocab = self.build_vocab(self.data)
    self.word2idx, self.idx2word = self.word2index(self.vocab)

def get_vocab(self):
    return self.vocab

def get_word2idx(self):
    return self.word2idx, self.idx2word

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

def __getitem__(self, idx):
    if torch.is_tensor(idx):
        idx = idx.tolist()
    inputs_ = word_tokenize(self.data[idx][0])
    inputs_ = [w for w in inputs_ if w not in stopwords]
    inputs_ = [w for w in inputs_ if w not in punctuation]
    inputs_ = [self.word2idx[w] for w in inputs_]  # convert words to index

    label = {"positive": 1,"negative": 0}
    label_ = label[self.data[idx][1]] #convert label to 0|1

    sample = {"words": inputs_, "label": label_}

    if self.transform:
        sample = self.transform(sample)

    return sample

def build_vocab(self, corpus):
    word_count = {}
    for sentence in corpus:
        tokens = word_tokenize(sentence[0])
        for token in tokens:
            if token not in word_count:
                word_count[token] = 1
            else:
                word_count[token] += 1
    return word_count

def word2index(self, word_count):
    word_index = {w: i for i, w in enumerate(word_count)}
    idx_word = {i: w for i, w in enumerate(word_count)}
    return word_index, idx_word

1 Ответ

1 голос
/ 30 января 2020

Как вы правильно поняли, это в основном проблема разных тензорных форм. К счастью, PyTorch предлагает вам несколько решений различной простоты для достижения желаемого (размеры пакетов> = 1 для образцов текста):

  • Решение самого высокого уровня, вероятно, torchtext, который предоставляет несколько решений для загрузки (пользовательских) наборов данных для задач НЛП. Если вы можете подогнать данные обучения к любому из описанных загрузчиков, это, вероятно, рекомендуемый вариант, так как имеется приличная документация и несколько примеров.
  • Если вы предпочитаете создавать решение, есть отступы такие решения, как torch.nn.utils.rnn.pad_sequence, в сочетании с torch.nn.utils.pack_padded_sequence или их комбинацией ( torch.nn.utils.rnn.pack_sequence . Обычно это позволяет вам гораздо больше гибкости, которая может или не может быть то, что вам нужно.

Лично у меня был хороший опыт использования только pad_sequence, и я пожертвовал немного скорости для гораздо более четкой отладки состояние, и, казалось бы, другие имеют аналогичные рекомендации .

...