You can check several things to improve model accuracy:

Make sure that all 40 classes are distributed proportionally between the train and validation sets. If some classes are absent or underrepresented in the train set, there is no way the model learns how to identify them. Use ‘stratify’ argument in the ‘train_test_split’ and pass target values there.
Normalize input data before passing it to the model (for example use MinMaxScaler from sklearn) or use Keras Normalization layer as the first layer in the model.
Decrease the batch size. Normally it should be somewhere between 32 and 512 depending on the total number of samples in your dataset.
In classification models usually only the last dense layer has softmax activation. All previous layers could have relu or something else. Softmax converts the vector into probabilities, which is done after all other transformations.
Decrease the number of dense layers. Number of units in each layers does not have to be equal to the number of features. Usually some multiple of 2 is used as the number of units and this number decreases with every next dense layer like: 256, 128, 64…

You train the model for 1000 epochs without using a callback. If after this many epochs the model does not show reasonable accuracy, repeating the training 50 times in a loop using the same model and the same input data would not help.
If you want to train several models and select the best run, you should initialize the model at every iteration from scratch (move your make_nn() function into the loop) and probably use different subsets of your data at every training run or at least different random states in splitting the data. For this you can move get_dataset() into the loop and and pass i as a random state.