Добавление слоя softmax в сеть LSTM «замораживает» вывод

#python #deep-learning #pytorch #lstm #softmax

#python #глубокое обучение #pytorch #lstm #softmax

Вопрос:

Я пытался самостоятельно освоить основы RNN с помощью личного проекта на PyTorch. Я хочу создать простую сеть, которая способна предсказывать следующий символ в последовательности (идея в основном из этой статьиhttp://karpathy.github.io/2015/05/21/rnn-effectiveness / но я хотел сделать большую часть материала сам).

Моя идея заключается в следующем: я беру пакет из B входных последовательностей размером n (np массив из n целых чисел), одним горячим способом кодирую их и пропускаю через свою сеть, состоящую из нескольких слоев LSTM, одного полностью подключенного слоя и одного модуля softmax. Затем я сравниваю вывод с целевыми последовательностями, которые являются входными последовательностями, сдвинутыми на шаг вперед.

Моя проблема в том, что когда я включаю слой softmax, вывод одинаков в каждую отдельную эпоху для каждого отдельного пакета. Когда я его не включаю, сеть, похоже, обучается соответствующим образом. Я не могу понять, что не так.

Моя реализация заключается в следующем :

 class Model(nn.Module):
def __init__(self, one_hot_length, dropout_prob, num_units, num_layers):
    
    super().__init__()

    self.LSTM = nn.LSTM(one_hot_length, num_units, num_layers, batch_first = True, dropout = dropout_prob)
    
    self.dropout = nn.Dropout(dropout_prob)
    self.fully_connected = nn.Linear(num_units, one_hot_length)
    self.softmax = nn.Softmax(dim = 1)
    # dim = 1 as the tensor is of shape (batch_size*seq_length, one_hot_length) when entering the softmax unit

def forward_pass(self, input_seq, hc_states):

    output, hc_states = self.LSTM (input_seq, hc_states)
    output = output.view(-1, self.num_units)
    output = self.fully_connected(output) 
    # I simply comment out the next line when I run the network without the softmax layer
    output = self.softmax(output)
    return output, hc_states
  

one_hot_length — это размер моего словаря символов (~ 200, также размер одного вектора с горячим кодированием)
num_units — это количество скрытых блоков в ячейке LSTM, num_layers — количество уровней LSTM в сети.

Внутренняя часть цикла обучения (упрощенная) выглядит следующим образом :

 input, target = next_batches(data, batch_pointer)

input = nn.functional.one_hot(input_seq, num_classes = one_hot_length).float().

for state in hc_states:
    state.detach_()
            
optimizer.zero_grad()
            
output, states = net.forward_pass(input, hc_states)

loss = nn.CrossEntropyLoss(output, target)
loss.backward()
    
nn.utils.clip_grad_norm_(net.parameters(), MaxGradNorm)

optimizer.step()
  

С hc_states кортежем с тензором скрытых состояний и тензором состояний ячеек, входным является тензор размера (B,n,one_hot_length), целевой является (B,n).

Я тренируюсь на действительно небольшом наборе данных (предложения в формате .txt размером ~ 400 КБ), просто чтобы настроить свой код, и выполнил 4 разных запуска с разными параметрами, и каждый раз результат был одинаковым: сеть вообще не обучается, когда у нее есть слой softmax, и тренируется несколько адекватно без него. Я не думаю, что это проблема с тензорными формами, поскольку я почти уверен, что я все проверил.

Мое понимание моей проблемы заключается в том, что я пытаюсь выполнить классификацию, и что обычно нужно поместить единицу softmax в конец, чтобы получить «вероятности» появления каждого символа, но, очевидно, это неправильно.

Есть идеи, которые могут мне помочь? Я также довольно новичок в Pytorch и RNN, поэтому заранее приношу извинения, если моя архитектура / реализация покажется знающему человеку каким-то чудовищем. Не стесняйтесь поправлять меня и заранее благодарите.

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

1. nn.CrossEntropyLoss Сначала меня тоже смутил. Одновременно выполняется logSoftmax и потеря вероятности отрицательного логарифма, поэтому softmax является избыточным. pytorch.org/docs/stable/generated /…

2. О, хорошо, спасибо, я думаю, я должен был более тщательно прочитать документацию. Я думаю, мне это не нужно для моего прямого прохождения. Однако я все еще не до конца понимаю это, потому что, когда я печатаю вывод моего прямого прохода (поэтому, прежде чем вычислять потери) Я ясно вижу, что вывод тот же. Есть ли у вас какие-либо идеи, почему добавление слоя softmax после слоя FC может вызвать такую проблему? Большое вам спасибо в любом случае