Python 培训损失高于验证损失

Python 培训损失高于验证损失,python,tensorflow,keras,Python,Tensorflow,Keras,我试图在Keras中训练一个三变量的虚拟函数回归模型,并使用完全连接的神经网络,我总是得到比验证损失高得多的训练损失 我将数据集分成2/3用于培训,1/3用于验证。我尝试了很多不同的东西: 改变架构 增加更多的神经元 使用正则化 使用不同的批量 训练误差仍然比验证误差高一个数量级: Epoch 5995/6000 4020/4020 [==============================] - 0s 78us/step - loss: 1.2446e-04 - mean_square

我试图在Keras中训练一个三变量的虚拟函数回归模型,并使用完全连接的神经网络,我总是得到比验证损失高得多的训练损失

我将数据集分成2/3用于培训,1/3用于验证。我尝试了很多不同的东西:

  • 改变架构
  • 增加更多的神经元
  • 使用正则化
  • 使用不同的批量
训练误差仍然比验证误差高一个数量级:

Epoch 5995/6000
4020/4020 [==============================] - 0s 78us/step - loss: 1.2446e-04 - mean_squared_error: 1.2446e-04 - val_loss: 1.3953e-05 - val_mean_squared_error: 1.3953e-05
Epoch 5996/6000
4020/4020 [==============================] - 0s 98us/step - loss: 1.2549e-04 - mean_squared_error: 1.2549e-04 - val_loss: 1.5730e-05 - val_mean_squared_error: 1.5730e-05
Epoch 5997/6000
4020/4020 [==============================] - 0s 105us/step - loss: 1.2500e-04 - mean_squared_error: 1.2500e-04 - val_loss: 1.4372e-05 - val_mean_squared_error: 1.4372e-05
Epoch 5998/6000
4020/4020 [==============================] - 0s 96us/step - loss: 1.2500e-04 - mean_squared_error: 1.2500e-04 - val_loss: 1.4151e-05 - val_mean_squared_error: 1.4151e-05
Epoch 5999/6000
4020/4020 [==============================] - 0s 80us/step - loss: 1.2487e-04 - mean_squared_error: 1.2487e-04 - val_loss: 1.4342e-05 - val_mean_squared_error: 1.4342e-05
Epoch 6000/6000
4020/4020 [==============================] - 0s 79us/step - loss: 1.2494e-04 - mean_squared_error: 1.2494e-04 - val_loss: 1.4769e-05 - val_mean_squared_error: 1.4769e-05
这没有道理,请帮忙

编辑:这是完整的代码

我有6000个培训示例

# -*- coding: utf-8 -*-
"""
Created on Mon Feb 26 13:40:03 2018

@author: Michele
"""
#from keras.datasets import reuters
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Dropout, LSTM
from keras import optimizers
import matplotlib.pyplot as plt
import os 
import pylab 
from keras.constraints import maxnorm
from sklearn.model_selection import train_test_split
from keras import regularizers
from sklearn.preprocessing import MinMaxScaler
import math
from sklearn.metrics import mean_squared_error
import keras

# fix random seed for reproducibility
seed=7
np.random.seed(seed)

dataset = np.loadtxt("BabbaX.csv", delimiter=",")
 #split into input (X) and output (Y) variables
#x = dataset.transpose()[:,10:15] #only use power
x = dataset
del(dataset) # delete container
dataset = np.loadtxt("BabbaY.csv", delimiter=",")
 #split into input (X) and output (Y) variables
y = dataset.transpose()
del(dataset) # delete container

 #scale labels from 0 to 1
scaler = MinMaxScaler(feature_range=(0, 1))
y = np.reshape(y, (y.shape[0],1))
y = scaler.fit_transform(y)

lenData=x.shape[0]
x=np.transpose(x)

xtrain=x[:,0:round(lenData*0.67)]
ytrain=y[0:round(lenData*0.67),]
xtest=x[:,round(lenData*0.67):round(lenData*1.0)]
ytest=y[round(lenData*0.67):round(lenData*1.0)]

xtrain=np.transpose(xtrain)
xtest=np.transpose(xtest)    

l2_lambda = 0.1 #reg factor

#sequential type of model
model = Sequential() 
#stacking layers with .add
units=300
#model.add(Dense(units, input_dim=xtest.shape[1], activation='relu', kernel_initializer='normal', kernel_regularizer=regularizers.l2(l2_lambda), kernel_constraint=maxnorm(3)))
model.add(Dense(units, activation='relu', input_dim=xtest.shape[1]))
#model.add(Dropout(0.1))
model.add(Dense(units, activation='relu'))
#model.add(Dropout(0.1))
model.add(Dense(1)) #no activation function should be used for the output layer

rms = optimizers.RMSprop(lr=0.00001, rho=0.9, epsilon=None, decay=0) #It is recommended to leave the parameters
adam = keras.optimizers.Adam(lr=0.00001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=1e-6, amsgrad=False)

#of this optimizer at their default values (except the learning rate, which can be freely tuned).
#adam=keras.optimizers.Adam(lr=0.01, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)

#configure learning process with .compile
model.compile(optimizer=adam, loss='mean_squared_error', metrics=['mse'])

# fit the model (iterate on the training data in batches)
history = model.fit(xtrain, ytrain, nb_epoch=1000, batch_size=round(xtest.shape[0]/100),
              validation_data=(xtest, ytest), shuffle=True, verbose=2)

#extract weights for each layer
weights = [layer.get_weights() for layer in model.layers]

#evaluate on training data set
valuesTrain=model.predict(xtrain)

#evaluate on test data set
valuesTest=model.predict(xtest)

 #invert predictions
valuesTrain = scaler.inverse_transform(valuesTrain)
ytrain = scaler.inverse_transform(ytrain)
valuesTest = scaler.inverse_transform(valuesTest)
ytest = scaler.inverse_transform(ytest)

若训练损失稍高或接近验证损失,则表示模型并没有过度拟合。 始终努力使用最佳特性,以减少过度拟合,提高验证和测试精度。 您经常导致列车损失增加的可能原因可能是您用于培训的功能和数据

请参考以下链接,观察辍学情况下的培训和验证损失: TL;博士: 当模型学习良好且快速时,验证损失可能低于培训损失,因为验证发生在更新的模型上,而培训损失没有任何(无批次)或仅应用了部分(有批次)更新


好吧,我想我知道这里发生了什么。我使用下面的代码来测试这一点

import numpy as np
import keras
from keras.models import Sequential
from keras.layers import Dense
import matplotlib.pyplot as plt

np.random.seed(7)

N_DATA = 6000

x = np.random.uniform(-10, 10, (3, N_DATA))
y = x[0] + x[1]**2 + x[2]**3

xtrain = x[:, 0:round(N_DATA*0.67)]
ytrain = y[0:round(N_DATA*0.67)]

xtest = x[:, round(N_DATA*0.67):N_DATA]
ytest = y[round(N_DATA*0.67):N_DATA]

xtrain = np.transpose(xtrain)
xtest = np.transpose(xtest)

model = Sequential()
model.add(Dense(10, activation='relu', input_dim=3))
model.add(Dense(5, activation='relu'))
model.add(Dense(1))

adam = keras.optimizers.Adam()

# configure learning process with .compile
model.compile(optimizer=adam, loss='mean_squared_error', metrics=['mse'])

# fit the model (iterate on the training data in batches)
history = model.fit(xtrain, ytrain, nb_epoch=50,
                    batch_size=round(N_DATA/100),
                    validation_data=(xtest, ytest), shuffle=False, verbose=2)

plt.plot(history.history['mean_squared_error'])
plt.plot(history.history['val_loss'])
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()
这本质上与您的代码相同,并复制了问题,而这实际上不是问题。简单地改变

history = model.fit(xtrain, ytrain, nb_epoch=50,
                    batch_size=round(N_DATA/100),
                    validation_data=(xtest, ytest), shuffle=False, verbose=2)

因此,不再使用验证数据进行验证,而是再次使用培训数据进行验证,这会导致完全相同的行为。很奇怪,不是吗?不,实际上不是。我认为正在发生的是:

Keras在每个历元上给出的初始
均方误差
是应用梯度之前的损失,而验证发生在应用梯度之后,这是有意义的


对于通常使用NNs的高度随机问题,您看不到这一点,因为数据变化太大,更新的权重根本不足以描述验证数据,对训练数据的轻微过度拟合效应仍然非常强烈,即使在更新权重后,验证损失仍然高于之前的训练损失。这只是我的想法,我可能完全错了。

这可能有很多原因。如果没有更多的细节就不能确定,也许是一些代码?您使用的是退出层吗?您确定没有信息从验证泄漏到培训数据中吗?您好,我已经用几行代码编辑了此消息谢谢。我无法在没有数据的情况下进行测试(但这没关系):您确定在这里显示的测试运行中停用了退出层吗?一般来说,代码的编写似乎有点奇怪,但我无法立即发现错误。你确定数据中没有重复数据吗?我先是从辍学开始的,但我立即得到了第一个奇怪的效果,即训练丢失>val丢失奇怪的书写都是我的错。要测试它,只需在3个变量中生成一个多项式函数,并在加载它之前尝试在预随机化的数据集中拟合它?是的,因此模型做得很好,这使得验证中的MSE小于训练中的MSE,因为新的权重(很好)是直接应用的?是的。它们是在计算了训练损失(用于获得梯度)后应用的。比梯度的应用导致新的权重,这些新的权重用于计算已经小于训练损失的验证损失。我回答了你的问题吗?
history = model.fit(xtrain, ytrain, nb_epoch=50,
                    batch_size=round(N_DATA/100),
                    validation_data=(xtrain, ytrain), shuffle=False, verbose=2)