Thank you very much for the response. I took your advice and changed the code accordingly. You can see it below:
(Everything up until the rnn definition is the same)
inputs = embeds(input_seq)
print("Inputs shape:", inputs.shape) --> #(batch_size, seq_len)

output, hx = rnn(inputs)
print("output shape:", output.shape)
print("hx shape: ", hx.shape)

fc = nn.Linear(HIDDEN_DIM * 2, OUTPUT_DIM)

predictions = fc(output)

avg_pool = nn.AvgPool1d(seq_len, stride=seq_len)

predictions = predictions.view(predictions.shape[0], 1, -1)
predictions = avg_pool(predictions)
predictions = predictions.squeeze(1)
predictions = predictions.view(1,-1)
predictions = predictions.squeeze(0)

print("Predictions:", predictions, predictions.shape)
print("Labels: ", labels)

with torch.no_grad():
    criterion = nn.BCEWithLogitsLoss()
    loss = criterion(predictions, labels)
    print('Loss:',loss)

I was able to get my desired output but I wonder if I had to go through all this trouble of squeezing and viewing. Correct me if I am wrong but getting the desired output or computing the loss isnt supposed to be this difficult right? Please let me know if I am doing this correctly. Thanks