Keras LSTM不平衡多分类模型全预测单一类别问题排查求助
Let’s dive straight into the fundamental problems with your setup that are leading to this all-class-3 prediction behavior—no hyperparameter tuning needed to fix these:
1. Critical Input Feature Dimension Mismatch
Your training data X_train has a shape of (400, 20, 17) (meaning 17 features per timestep), but your model defines nb_features = 18 and uses input_shape=(timestamps, nb_features). This mismatch is a showstopper:
- Keras will either silently pad your input with zeros to reach 18 features (corrupting your actual data) or throw an error (depending on your setup). Either way, the model can’t learn meaningful patterns from misaligned input.
- Fix: Update
nb_features = 17to match your real data dimensions.
2. Misused TimeDistributed(Dense(1)) Wastes Temporal Information
You set return_sequences=True on your LSTM, which outputs a full sequence of (batch_size, 20, 50) (50 hidden units per timestep). But then you apply TimeDistributed(Dense(1)), which crunches each timestep’s 50-dimensional output down to 1 dimension. After flattening, you’re left with only 20 features per sample—this discards nearly all the temporal context the LSTM extracted.
- Fix: Remove the
TimeDistributedandFlattenlayers by disablingreturn_sequences=True(use the LSTM’s final timestep output directly):
If you want to keep sequential outputs, replacemodel = Sequential() model.add(LSTM(units=hidden_neurons, input_shape=(timestamps, nb_features), dropout=0.2, recurrent_dropout=0.2)) model.add(Dropout(0.2)) model.add(Dense(units=nb_classes, activation='softmax'))TimeDistributed(Dense(1))with another LSTM layer instead.
3. Disabled Shuffling Creates Severe Class Bias
You set shuffle=False in model.fit(). If your training data is ordered by class (e.g., all class 0 first, then class 1, ..., finally class 3), the model will learn each class sequentially and overwrite its prior knowledge—ending up heavily biased toward the last class it trained on (class 3). Even if your data isn’t strictly ordered, not shuffling means the model sees non-representative batches, leading to poor generalization.
- Fix: Set
shuffle=Trueto randomize training data order every epoch.
4. Unnecessary Rounding in Metric Calculation
In your Metrics callback, you’re rounding softmax outputs before taking argmax:
val_predict = np.argmax((np.asarray(self.model.predict(self.validation_data[0]))).round(), axis=1)
Softmax outputs are probabilities—rounding can turn valid low-confidence predictions into all zeros, leading to incorrect argmax results. This isn’t the main issue here, but it’s a bug that will skew your metrics.
- Fix: Remove the
.round()call:val_predict = np.argmax(np.asarray(self.model.predict(self.validation_data[0])), axis=1)
Fix these four issues first, and you’ll see your model start to distinguish between classes without needing any hyperparameter tweaks.
内容的提问来源于stack exchange,提问作者ScalaBoy

