Keras自动编码器:验证损失>训练损失-但在测试数据集上表现良好

时间:2019-10-10 18:30:19

标签: python machine-learning keras autoencoder

短内

我已经训练了一个自动编码器,其验证损失始终高于其训练损失(参见附图)。as - Autoencoder我认为这是过度拟合的信号。但是,我的自动编码器在测试数据集上表现良好。我想知道是否:

1)参考下面提供的网络体系结构,任何人都可以提供有关如何减少验证损失的见解(以及尽管存在以下问题,但如何减少验证损失比训练的损失高得多):自动编码器在测试数据集上表现良好);

2)如果训练和验证损失之间确实存在差距(当测试数据集的性能实际上不错时)。

详细信息:

我用Keras(下面的代码)对深层的Autoencoder进行了编码。架构是2001(输入层)-1000-500-200-50-200-500-1000-2001(输出层)。我的样本是时间的一维函数。它们每个都有2001年的时间分量。我有2000个样本,我将其分为1500个用于训练,500个用于测试。在1500个训练样本中,有20%(即300个)用作验证集。我对训练集进行归一化,去除均值并除以标准差。我也使用训练数据集的均值和标准差对测试数据集进行归一化。

我使用Adamax优化器训练自动编码器,并将均方误差作为损失函数。

from tensorflow.keras.layers import Input, Dense, Dropout
from tensorflow.keras.models import Model
from tensorflow.keras import optimizers

import numpy as np
import copy


# data
data = # read my input samples. They are 1d functions of time and I have 2000 of them.
# Each function has 2001 time components

# shuffling data before training
import random
random.seed(4)
random.shuffle(data)

# split training (1500 samples) and testing (500 samples) dataset
X_train = data[:1500]
X_test = data[1500:]

# normalize training and testing set using mean and std deviation of training set
X_mean = X_train.mean()
X_train -= X_mean
X_std = X_train.std()
X_train /= X_std

X_test -= X_mean
X_test /= X_std


### MODEL ###

# Architecture

# input layer
input_shape = [X_train.shape[1]]
X_input = Input(input_shape)

# hidden layers

x = Dense(1000, activation='tanh', name='enc0')(X_input)
encoded = Dense(500, activation='tanh', name='enc1')(x)
encoded_2 = Dense(200, activation='tanh', name='enc2')(encoded)
encoded_3 = Dense(50, activation='tanh', name='enc3')(encoded_2)
decoded_2 = Dense(200, activation='tanh', name='dec2')(encoded_3)
decoded_1 = Dense(500, activation='tanh', name='dec1')(decoded_2)
x2 = Dense(1000, activation='tanh', name='dec0')(decoded_1)

# output layer
decoded = Dense(input_shape[0], name='out')(x2)

# the Model
model = Model(inputs=X_input, outputs=decoded, name='autoencoder')

# optimizer
opt = optimizers.Adamax()
model.compile(optimizer=opt, loss='mse', metrics=['acc'])
print(model.summary())

###################

### TRAINING ###

epochs = 1000
# train the model
history = model.fit(x = X_train, y = X_train,
                    epochs=epochs,
                    batch_size=100,
                    validation_split=0.2)  # using 20% of training samples for validation

# Testing 
prediction = model.predict(X_test)
for i in range(len(prediction)):
    prediction[i] = np.multiply(prediction[i], X_std) + X_mean

loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(epochs)
plt.figure()
plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()
plt.close()

1 个答案:

答案 0 :(得分:3)

  

2)如果训练和验证损失之间确实存在差距(当测试数据集的性能实际上不错时)。

这只是概括性差距,即训练集和验证集之间的表现中的预期差距;引用最近的blog post by Google AI

  

理解泛化的一个重要概念是泛化差距,即模型在训练数据上的性能与在相同分布中得出的未见数据上的性能之间的差异。

  

我认为这是过度拟合的信号。但是,我的Autoencoder在测试数据集上表现良好。

这不是不是,但是原因并不完全是您的想法(更不用说“好”是一个非常主观的术语)。

过度拟合的特征签名是指验证损失开始增加,而训练损失则继续减少,即:

enter image description here

您的图表未显示此类行为;另外,请注意上述曲线(改编自Wikipedia entry on overfitting)中曲线之间的 gap (双关)。

  

尽管自动编码器在测试数据集上表现良好,但验证损失有可能比训练损失高得多

这里绝对没有没有矛盾;请注意,您的训练损失几乎为零,这本身并不一定令人惊讶,但如果验证损失接近零,那肯定会令人惊讶。同样,“好”是一个高度主观的术语。

换句话说,您提供的信息中没有任何内容表明您的模型有问题...