RuntimeError: `lengths` array must be sorted in decreasing order when `enforce_sorted` is True. - Pytorch
 It have been 5 hours sitting here getting the same error:
RuntimeError: `lengths` array must be sorted in decreasing order when `enforce_sorted` is True. You can pass `enforce_sorted=False` to pack_padded_sequence and/or pack_sequence to sidestep this requirement if you do not need ONNX exportability.

I'm working on this simple sentiment classification task using RNN in pytorch. I'm loading the my custom data using torchtext. I'm loading it from a json file which looks as follows:
{&quot;reviewText&quot;: &quot;Da Silva takes the divine by ....&quot;, &quot;overall&quot;: 4.0, &quot;summary&quot;: &quot;An amazing first novel&quot;}

I created my field as follows. And i created a pre-processing get_sentiment() function that convert overalls that are greater than 2 to 1 0 otherwise:
get_sentiment = lambda x: 1 if x &gt;=3 else 0

TEXT = data.Field(tokenize = 'spacy',
                  tokenizer_language = 'en_core_web_sm',
                  include_lengths=True
                  )
LABEL = data.Field(sequential=False, use_vocab=False, preprocessing=get_sentiment)

fields = {
    'reviewText': ('review', TEXT),
    'overall': ('sentiment', LABEL)
}

I loaded the data:
train_data, test_data = data.TabularDataset.splits(
    path=&quot;/content/&quot;,
    train=&quot;Books_small_10000.json&quot;,
    test=&quot;Books_small.json&quot;,
    format=&quot;json&quot;,
    fields=fields
)

I built the vocabularies:
MAX_VOCAB_SIZE = 25_000

TEXT.build_vocab(
    train_data,
    max_size = MAX_VOCAB_SIZE,
    vectors = &quot;glove.6B.100d&quot;,
    unk_init = torch.Tensor.normal_
)

LABEL.build_vocab(train_data)

I created my iterators.
BATCH_SIZE = 64

train_iterator, validation_iterator, test_iterator = data.BucketIterator.splits(
    (train_data, validation_data, test_data),
    device = device,
    batch_size = BATCH_SIZE,
    sort_key = lambda x: len(x.review),
)

This is how my Model looks.
class AmazonLSTMRNN(nn.Module):
  def __init__(self, vocab_size, embedding_size, hidden_size, output_size, num_layers
               , bidirectional, dropout, pad_idx):
    super(AmazonLSTMRNN, self).__init__()

    self.embedding = nn.Embedding(vocab_size, embedding_dim=embedding_size, padding_idx=pad_idx)
    self.lstm = nn.LSTM(embedding_size, hidden_size=hidden_size, 
                        bidirectional=bidirectional, num_layers=num_layers,
                        dropout=dropout)
    self.fc = nn.Linear(hidden_size * 2, out_features=output_size)
    self.dropout = nn.Dropout(dropout)

  def forward(self, text, text_lengths):
    embedded = self.dropout(self.embedding(text))
    packed_embedded = nn.utils.rnn.pack_padded_sequence(embedded, text_lengths.to('cpu'))
    packed_output, (h_0, c_0) = self.rnn(packed_embedded)
    output, output_lengths = nn.utils.rnn.pad_packed_sequence(packed_output)
    h_0 = self.dropout(torch.cat((h_0[-2,:,:], h_0[-1,:,:]), dim = 1))
    return self.fc(h_0)


INPUT_DIM = len(TEXT.vocab) # # 25002
EMBEDDING_DIM = 100
HIDDEN_DIM = 256
OUTPUT_DIM = 1
N_LAYERS = 2
BIDIRECTIONAL = True
DROPOUT = 0.5
PAD_IDX = TEXT.vocab.stoi[TEXT.pad_token] # 0
amazon_model = AmazonLSTMRNN(INPUT_DIM, 
            EMBEDDING_DIM, 
            HIDDEN_DIM, 
            OUTPUT_DIM, 
            N_LAYERS, 
            BIDIRECTIONAL, 
            DROPOUT, 
            PAD_IDX)

criterion = nn.BCEWithLogitsLoss()
optimizer = torch.optim.Adam(amazon_model.parameters())
amazon_model = amazon_model.to(device)
criterion = criterion.to(device)

.....
Training function
def train(model, iterator, optimizer, criterion):
    epoch_loss = 0
    epoch_acc = 0
    model.train()
    for batch in iterator:
        optimizer.zero_grad()
        text, text_lengths = batch.review
        predictions = model(text, text_lengths).squeeze(1)
        loss = criterion(predictions, batch.sentiment)
        acc = accuracy(predictions, batch.sentiment)
        loss.backward()
        optimizer.step()
        epoch_loss += loss.item()
        epoch_acc += acc.item()
    return epoch_loss / len(iterator), epoch_acc / len(iterator)

Training loop.
N_EPOCHS = 5
best_valid_loss = float('inf')
for epoch in range(N_EPOCHS):
    start_time = time.time()
    train_loss, train_acc = train(amazon_model, train_iterator, optimizer, criterion)
    end_time = time.time()
    epoch_mins, epoch_secs = epoch_time(start_time, end_time)
    if valid_loss &lt; best_valid_loss:
        best_valid_loss = valid_loss
        torch.save(amazon_model.state_dict(), 'best-model.pt')
    print(f'Epoch: {epoch+1:02} | Epoch Time: {epoch_mins}m {epoch_secs}s')
    print(f'\tTrain Loss: {train_loss:.3f} | Train Acc: {train_acc*100:.2f}%')

If someone knows where am i wrong please correct me. Any help input will be appreciated.


After some few minutes I found the solution and I was able to get accuracy of aprox ~93% on a single training epoch.
I changed my LABEL field to:
LABEL = data.LabelField(preprocessing=get_sentiment, dtype = torch.float)

Then i changed my AmazonLSTMRNN model in the forward method by adding enforce_sorted=False to the pack_padded_sequence.
The forward method:
 def forward(self, text, text_lengths):
    embedded = self.dropout(self.embedding(text))
    packed_embedded = nn.utils.rnn.pack_padded_sequence(embedded, text_lengths.to('cpu'), enforce_sorted=False)
    packed_output, (h_0, c_0) = self.lstm(packed_embedded)
    output, output_lengths = nn.utils.rnn.pad_packed_sequence(packed_output)
    h_0 = self.dropout(torch.cat((h_0[-2,:,:], h_0[-1,:,:]), dim = 1))
    return self.fc(h_0)

