使用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层以避免过拟合,但没有成功。下图显示验证损失和训练损失在某一点开始分离。
我还能做些什么来优化这个网络?
更新:根据我收到的评论,我对代码进行了如下调整:
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的图表
回答:
第一个示例的验证准确率超过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])
准确率
和损失
图表: