LSTM模型提供了很好的训练,但是测试结果很差,但是看不到过拟合

时间:2018-09-08 10:07:46

标签: python neural-network keras lstm

这是我的数据:

我有500幅录音(随意分为训练,验证和测试集)。每个记录包含一定数量的行,每个对应于1s的EEG段。换句话说,每个记录的长度等于EEG信号的长度(以s为单位)。每行包含22个通道* 22个时间/频率特征= 484个特征+输出标签(0或1)。

所以我要执行二进制分类。

正如许多论文所建议的(请参阅this good paper),对于每个记录,我创建了长度为look_back的序列,以便在考虑“周围”片段特征的情况下预测每个标签。这是代码:

def create_dataset(feat,targ, look_back=1):
   semi_window=math.floor(look_back/2)
   dataX, dataY = [], []
   for i in range(semi_window,len(targ)-semi_window):
       a = feat[i-semi_window:(i+semi_window+1), :]
       dataX.append(a)
       dataY.append(targ[i])
   return np.array(dataX), np.array(dataY)

此函数返回大小为(samples, look_back=time_steps, features=484)的3D数组。

为了处理不平衡的类,我测试了make_imbalance函数以删除实例以保持每个类的实例数量相同,并测试了class_weight参数,该参数在loss函数中考虑了不平衡性。

因此,我使用LSTM模型,并使用EarlyStopping回调参数在验证精度没有增加给定公差的情况下停止运行。

这是我的完整模特:

from sklearn.utils import class_weight
earlystop = EarlyStopping(monitor='val_acc', min_delta=0.001, patience=5, verbose=1, mode='auto')
callbacks_list = [earlystop]
np.random.seed(10)
set_random_seed(30)
rn.seed(50)
# plutôt que faire imbalance qui supprime plic ploc les données, on préfère introduire class_weight et ne pas shuffler les données (ben en fait si..)...
weights = class_weight.compute_class_weight('balanced',np.unique(trainY),trainY)
print (weights)
model = Sequential()
model.add(LSTM(8, input_shape=(look_back, trainX.shape[2]), recurrent_dropout=0.3))
model.add(Dropout(0.3))


model.add(Dense(1, activation='sigmoid'))
print (model.summary())
model.compile(loss='binary_crossentropy', optimizer='adam',metrics=['accuracy'])
model.fit(trainX, trainY, validation_data=(validX, validY), epochs=100, batch_size=32, class_weight=weights, verbose=1 , callbacks=callbacks_list, shuffle=True)  

train_score = model.evaluate(trainX, trainY, batch_size=2048)
print(train_score)
trainPredict = model.predict(trainX)
print(confusion_matrix(trainY, trainPredict.round()))                      

valid_score = model.evaluate(validX, validY, batch_size=2048)
print(valid_score)
validPredict = model.predict(validX)
print(confusion_matrix(validY, validPredict.round()))

test_score = model.evaluate(testX, testY, batch_size=2048)
print(test_score)
testPredict = model.predict(testX)
print(confusion_matrix(testY, testPredict.round()))

我得到了这样的结果:

enter image description here

训练混乱矩阵非常出色,但验证和测试矩阵却很差...

我想这并不过分,因为我的模型很小(一层,...)。而且,我认为该模型是适当的,因为它可以很好地区分(巨大)训练集上的数据...

那么,怎么了?

注意:我确实说过,经典的Keras前馈神经网络也有同样的问题

编辑:这是我绘制学习曲线时得到的:

enter image description here  您会看到,训练精度仍然很高,而验证精度(实际上应该是橙色的“验证”曲线)仍然很低……

编辑:我试图使用XGBoost和SVM分类器,但是我无法获得结果(仍然是相同的行为)

编辑:我试图将数据改组并查看。我得到了很好的结果,但是这有点像海市...楼。的确,我在训练和验证集中都来自相同的录音(不是完全相同,但是非常接近)……是一种作弊。当我向模型展示全新录音时,它崩溃了...所以,我还没有找到解决方法

0 个答案:

没有答案