Keras LSTM回归模型对不同视频始终输出相同值的问题
模型测试始终输出相同值的排查方案
问题重现
基于行走视频提取的特征训练LSTM回归模型,目标预测人物快乐程度(输出范围0-1),但测试不同视频时模型始终输出固定值,训练与测试代码如下:
训练代码
list_features,masks=fe.prepare_all_videos() X_train=np.array(list_features) scaler = MinMaxScaler(feature_range=(-1,1)) X_train = scaler.fit_transform(X_train.reshape(X_train.shape[0], -1)).reshape(X_train.shape) X_train = scaler.fit_transform(X_train.reshape(X_train.shape[1], -1)).reshape(X_train.shape) X_train = scaler.fit_transform(X_train.reshape(X_train.shape[2], -1)).reshape(X_train.shape) y_train=f.getListEtichettaFromVideos('happy') y_train=np.array(y_train) y_train = (y_train-min(y_train)) / (max(y_train)-min(y_train)) model = keras.Sequential([ layers.LSTM(32,input_shape=(24,2048)), layers.Dense(16), layers.Dense(1,activation='sigmoid') ]) # Compile neural network model.compile(optimizer='adam', loss='mse') history=model.fit(X_train,y_train,epochs=20,batch_size=16,validation_data=(X_train,y_train))
测试代码
modello=keras.models.load_model('Modello.keras') video=cv2.VideoCapture(path+'VID_TEST_CUT_75.avi') frames=f.getAllFramesFromVideo(video) frames=frames[:24] feature,mask=fe.prepare_single_video(frames) features=np.array(feature) scaler = MinMaxScaler(feature_range=(-1,1)) features = scaler.fit_transform(features.reshape(features.shape[0], -1)).reshape(features.shape) features = scaler.fit_transform(features.reshape(features.shape[1], -1)).reshape(features.shape) features = scaler.fit_transform(features.reshape(features.shape[2], -1)).reshape(features.shape) print(modello.predict(features))
核心问题排查与修复
1. 数据标准化逻辑完全错误
这是导致输出固定值的最直接原因:
- 训练时连续三次调用
fit_transform,每次都会重新计算数据的均值、极值,彻底打乱特征分布,模型无法学到有效规律 - 测试时重新初始化Scaler并调用
fit_transform,用测试数据的分布做标准化,和训练阶段的标准化逻辑完全脱节,导致模型输入分布错乱
修复方案:
- 训练时仅基于训练集做一次标准化,保存Scaler用于测试阶段
- 测试时只能用训练好的Scaler执行
transform,绝对不能重新fit
修改后的训练代码片段:
scaler = MinMaxScaler(feature_range=(-1,1)) # 对样本维度做一次标准化(假设X_train形状为(样本数, 帧数, 特征数)) X_train_flatten = X_train.reshape(X_train.shape[0], -1) scaler.fit(X_train_flatten) X_train = scaler.transform(X_train_flatten).reshape(X_train.shape) # 保存scaler,后续测试用 import joblib joblib.dump(scaler, 'scaler.pkl')
修改后的测试代码片段:
# 加载训练好的scaler scaler = joblib.load('scaler.pkl') features=np.array(feature) # 仅执行transform,禁止fit features_flatten = features.reshape(features.shape[0], -1) features = scaler.transform(features_flatten).reshape(features.shape)
2. 验证集设置无效
训练时validation_data=(X_train,y_train)直接用训练集做验证,无法判断模型泛化能力:
- 若训练集标签分布单一(比如大部分标签集中在某个值),模型会直接学习输出该均值,导致测试时输出固定值
- 无法监控过拟合/欠拟合情况,训练过程完全失控
修复方案:
- 用
train_test_split将训练集划分为训练、验证子集,用独立验证集监控loss变化 - 查看训练曲线:若训练/验证loss都居高不下,说明模型未学到有效特征;若训练loss极低但验证loss极高,说明过拟合
3. 模型结构与损失函数不匹配
- LSTM后的Dense层无激活函数,默认线性激活易导致梯度消失,建议添加
relu激活增强非线性表达 - 输出层用
sigmoid(输出0-1)搭配mse损失,若标签是连续值可保留,但如果标签是离散二分类,建议改用binary_crossentropy
修改后的模型结构:
model = keras.Sequential([ layers.LSTM(32,input_shape=(24,2048)), layers.Dense(16, activation='relu'), # 添加relu激活 layers.Dense(1,activation='sigmoid') ]) # 根据标签类型选择损失函数 model.compile(optimizer='adam', loss='mse')
4. 输入维度一致性检查
测试时需确保输入形状与训练时一致(训练输入为(样本数,24,2048)),单样本测试时需手动增加维度:
# 若features形状为(24,2048),需转为(1,24,2048)匹配模型输入 features = np.expand_dims(features, axis=0) print(modello.predict(features))
内容的提问来源于stack exchange,提问作者Kisegi
相关产品推荐
相关产品推荐

