如何避免在简单的前馈网络中过拟合

使用pima indians diabetes数据集,我尝试使用Keras构建一个准确的模型。我编写了以下代码:

# Visualize training historyfrom keras import callbacksfrom keras.layers import Dropouttb = callbacks.TensorBoard(log_dir='/.logs', histogram_freq=10, batch_size=32,                           write_graph=True, write_grads=True, write_images=False,                           embeddings_freq=0, embeddings_layer_names=None, embeddings_metadata=None)# Visualize training historyfrom keras.models import Sequentialfrom keras.layers import Denseimport matplotlib.pyplot as pltimport numpy# fix random seed for reproducibilityseed = 7numpy.random.seed(seed)# load pima indians datasetdataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")# split into input (X) and output (Y) variablesX = dataset[:, 0:8]Y = dataset[:, 8]# create modelmodel = Sequential()model.add(Dense(12, input_dim=8, kernel_initializer='uniform', activation='relu', name='first_input'))model.add(Dense(500, activation='tanh', name='first_hidden'))model.add(Dropout(0.5, name='dropout_1'))model.add(Dense(8, activation='relu', name='second_hidden'))model.add(Dense(1, activation='sigmoid', name='output_layer'))# Compile modelmodel.compile(loss='binary_crossentropy',              optimizer='rmsprop',              metrics=['accuracy'])# Fit the modelhistory = model.fit(X, Y, validation_split=0.33, epochs=1000, batch_size=10, verbose=0, callbacks=[tb])# list all data in historyprint(history.history.keys())# summarize history for accuracyplt.plot(history.history['acc'])plt.plot(history.history['val_acc'])plt.title('model accuracy')plt.ylabel('accuracy')plt.xlabel('epoch')plt.legend(['train', 'test'], loc='upper left')plt.show()# summarize history for lossplt.plot(history.history['loss'])plt.plot(history.history['val_loss'])plt.title('model loss')plt.ylabel('loss')plt.xlabel('epoch')plt.legend(['train', 'test'], loc='upper left')plt.show()

经过几次尝试后,我添加了dropout层以避免过拟合,但没有成功。下图显示验证损失和训练损失在某一点开始分离。

enter image description here

我还能做些什么来优化这个网络?

更新:根据我收到的评论,我对代码进行了如下调整:

model = Sequential()model.add(Dense(12, input_dim=8, kernel_initializer='uniform', kernel_regularizer=regularizers.l2(0.01),                activity_regularizer=regularizers.l1(0.01), activation='relu',                name='first_input'))  # 添加了正则化model.add(Dense(8, activation='relu', name='first_hidden'))  # 减少到8个神经元model.add(Dropout(0.5, name='dropout_1'))model.add(Dense(5, activation='relu', name='second_hidden'))model.add(Dense(1, activation='sigmoid', name='output_layer'))

以下是500个epoch的图表

enter image description hereenter image description here


回答:

enter image description here

第一个示例的验证准确率超过75%,而第二个示例的准确率低于65%,如果你比较100个epoch以下的损失,第一个示例的损失低于0.5,而第二个示例的损失超过0.6。但是第二个案例怎么会更好呢?

在我看来,第二个案例是欠拟合的例子:模型没有足够的能力进行学习。而第一个案例存在过拟合的问题,因为在过拟合开始时没有停止训练(早期停止)。如果在第100个epoch停止训练,相比之下会是一个更好的模型。

目标应该是获得在未见数据上的小预测误差,为此你应该增加网络的容量,直到过拟合开始发生为止。

那么在这种特定情况下如何避免过拟合呢?采用早期停止

代码更改:包含早期停止输入缩放

 # 输入缩放 scaler = StandardScaler() X = scaler.fit_transform(X) # 早期停止   early_stop = EarlyStopping(monitor='val_loss', min_delta=0, patience=3, verbose=1, mode='auto') # 创建模型 - 几乎相同的代码 model = Sequential() model.add(Dense(12, input_dim=8, activation='relu', name='first_input')) model.add(Dense(500, activation='relu', name='first_hidden')) model.add(Dropout(0.5, name='dropout_1')) model.add(Dense(8, activation='relu', name='second_hidden')) model.add(Dense(1, activation='sigmoid', name='output_layer'))) history = model.fit(X, Y, validation_split=0.33, epochs=1000, batch_size=10, verbose=0, callbacks=[tb, early_stop])

准确率损失图表:

enter image description here

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注