What is curious is that the validation loss seems to converge 10 times faster than the training loss.
To better understand what is going on, could you:

Do validation at a higher frequency ; for example at validate = 20

Try to train it without dropout… Just to see if something changes

By the way, a nn.Dropout() layer has no parameters. So you can define a single layer instead of seven : self.dp = nn.Dropout(droprate)
And in forward call this layer multiple times : x = self.dp(x).