我最近在使用Keras开发一个深度学习模型时,遇到了非常令人困惑的结果。模型能够随着时间的推移掌握训练数据,但在验证数据上的表现却持续变差。
我知道如果验证准确率在一段时间内上升然后开始下降,说明模型在训练数据上过拟合,但在这种情况下,验证准确率始终在下降。我真的很困惑为什么会这样。有人能提供一些见解,解释可能导致这种情况的原因吗?或者有什么建议可以测试来尝试解决这个问题?
编辑以添加更多信息和代码
好的。我正在构建一个用于进行基本股票预测的模型。通过查看过去40天的开盘价、最高价、最低价、收盘价和交易量,模型试图预测价格是否会在不下降一个平均真实范围的情况下上升两个平均真实范围。我从雅虎财经获取了包含过去30年道琼斯工业平均指数中所有股票这些信息的CSV文件作为输入。模型使用70%的股票进行训练,并使用另外20%的股票进行验证。这大约产生了150,000个训练样本。我目前使用的是一维卷积神经网络,但我还尝试过其他较小的模型(逻辑回归和小型前馈神经网络),结果总是训练和验证损失分歧,或者因为模型过于简单而没有任何学习。
以下是代码:
import numpy as np
from sklearn import preprocessing
from sklearn.metrics import auc, roc_curve, roc_auc_score
from keras.layers import Input, Dense, Flatten, Conv1D, Activation, MaxPooling1D, Dropout, Concatenate
from keras.models import Model
from keras.callbacks import ModelCheckpoint, EarlyStopping, Callback
from keras import backend as K
import matplotlib.pyplot as plt
from random import seed, shuffle
from os import listdir
class roc_auc(Callback):
def on_train_begin(self, logs={}):
self.aucs = []
def on_train_end(self, logs={}):
return
def on_epoch_begin(self, epoch, logs={}):
return
def on_epoch_end(self, epoch, logs={}):
y_pred = self.model.predict(self.validation_data[0])
self.aucs.append(roc_auc_score(self.validation_data[1], y_pred))
if max(self.aucs) == self.aucs[-1]:
model.save_weights("weights.roc_auc.hdf5")
print(" - auc: %0.4f" % self.aucs[-1])
return
def on_batch_begin(self, batch, logs={}):
return
def on_batch_end(self, batch, logs={}):
return
rrr = 2
epochs = 200
batch_size = 64
days_input = 40
seed(42)
X_train = []
X_test = []
y_train = []
y_test = []
files = listdir("Stocks")
total_stocks = len(files)
shuffle(files)
for x, file in enumerate(files):
test = False
if (x+1.0)/total_stocks > 0.7:
test = True
if test:
print("Test -> Stocks/%s" % file)
else:
print("Train -> Stocks/%s" % file)
stock = np.loadtxt(open("Stocks/"+file, "r"), delimiter=",", skiprows=1, usecols = (1,2,3,5,6))
atr = []
last = None
for day in stock:
if last is None:
tr = abs(day[1] - day[2])
atr.append(tr)
else:
tr = max(day[1] - day[2], abs(last[3] - day[1]), abs(last[3] - day[2]))
atr.append((13*atr[-1]+tr)/14)
last = day.copy()
stock = np.insert(stock, 5, atr, axis=1)
for i in range(days_input,stock.shape[0]-1):
input = stock[i-days_input:i, 0:5].copy()
for j, day in enumerate(input):
input[j][1] = (day[1]-day[0])/day[0]
input[j][2] = (day[2]-day[0])/day[0]
input[j][3] = (day[3]-day[0])/day[0]
input[:,0] = input[:,0] / np.linalg.norm(input[:,0])
input[:,1] = input[:,1] / np.linalg.norm(input[:,1])
input[:,2] = input[:,2] / np.linalg.norm(input[:,2])
input[:,3] = input[:,3] / np.linalg.norm(input[:,3])
input[:,4] = input[:,4] / np.linalg.norm(input[:,4])
preprocessing.scale(input, copy=False)
output = -1
buy = stock[i][1]
stoploss = buy - stock[i][5]
target = buy + rrr*stock[i][5]
for j in range(i+1, stock.shape[0]):
if stock[j][0] < stoploss or stock[j][2] < stoploss:
output = 0
break
elif stock[j][1] > target:
output = 1
break
if output != -1:
if test:
X_test.append(input)
y_test.append(output)
else:
X_train.append(input)
y_train.append(output)
按100批次而不是按epoch显示的结果
我听取了建议并做了一些更新。现在类别平衡为50%对50%,而不是之前的25%对75%。此外,现在验证数据是随机选择的,而不是特定的股票集。通过以更细的分辨率(100批次而不是1个epoch)绘制损失和准确率图,可以清楚地看到过拟合现象。模型在最开始确实开始学习,然后才开始分歧。我对它过拟合的速度感到惊讶,但现在我能看到问题所在,希望能调试它。
回答: