我知道在CNN模型中添加dropout层可以提高准确性,因为它能减少过拟合的影响。然而,我构建了一个具有16、32和64个滤波器、大小为3和最大池化2的CNN模型,我注意到没有dropout层的模型在所有情况下表现得比有dropout层的模型更好。
from keras.models import Sequentialfrom keras.layers import Conv2D,Activation,MaxPooling2D,Dense,Flatten,Dropoutimport numpy as npfrom keras.preprocessing.image import ImageDataGeneratorfrom IPython.display import displayimport matplotlib.pyplot as pltfrom PIL import Imagefrom sklearn.metrics import classification_report, confusion_matriximport kerasfrom keras.layers import BatchNormalizationfrom keras.optimizers import Adamimport pickleclassifier = Sequential()classifier.add(Conv2D(16,(3,3),input_shape=(200,200,3)))classifier.add(Activation('relu'))classifier.add(MaxPooling2D(pool_size =(2,2)))classifier.add(Flatten())classifier.add(Dense(128))classifier.add(Activation('relu'))classifier.add(Dropout(0.5))classifier.add(Dense(7))classifier.add(Activation('softmax'))classifier.summary()classifier.compile(optimizer =keras.optimizers.Adam(lr=0.001), loss ='categorical_crossentropy', metrics =['accuracy'])train_datagen = ImageDataGenerator(rescale =1./255, shear_range =0.2, zoom_range = 0.2, horizontal_flip =True)test_datagen = ImageDataGenerator(rescale = 1./255)batchsize=10training_set = train_datagen.flow_from_directory('/home/osboxes/Downloads/Downloads/Journal_Paper/Malware_Families/Spectrogram/Train/', target_size=(200,200), batch_size= batchsize, class_mode='categorical')test_set = test_datagen.flow_from_directory('/home/osboxes/Downloads/Downloads/Journal_Paper/Malware_Families/Spectrogram/Validate/', target_size = (200,200), batch_size = batchsize, shuffle=False, class_mode ='categorical')history=classifier.fit_generator(training_set, steps_per_epoch = 2340 // batchsize, epochs = 100, validation_data =test_set, validation_steps = 781 // batchsize)classifier.save('16_With_Dropout_rl_001.h5')with open('16_With_Dropout_rl_001.h5', 'wb') as file_pi: pickle.dump(history.history, file_pi)Y_pred = classifier.predict_generator(test_set, steps= 781 // batchsize+1)y_pred = np.argmax(Y_pred, axis=1)print('Confusion Matrix')print(confusion_matrix(test_set.classes, y_pred))print('Classification Report')target_names = test_set.classesclass_labels = list(test_set.class_indices.keys()) target_names = ['coinhive','emotet','fareit','gafgyt','mirai','ramnit','razy'] report = classification_report(test_set.classes, y_pred, target_names=class_labels)print(report) # summarize history for accuracyplt.plot(history.history['accuracy'])plt.plot(history.history['val_accuracy'])plt.title('model accuracy 16 with dropout rl .001')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 16 with dropout rl .001')plt.ylabel('loss')plt.xlabel('epoch')plt.legend(['train', 'test'], loc='upper left')plt.show()
回答:
我知道在CNN模型中添加dropout层可以提高准确性,因为它能减少过拟合的影响。
你可以这样说,但这并不总是成立。dropout层是一种泛化技术,它降低了模型的灵活性,可以防止过拟合,假设你的模型足够灵活以处理任务(实际上,假设你的模型比所需的更灵活)。如果你的模型一开始就无法处理任务,意味着它太弱,那么添加任何形式的正则化可能会使其性能变得更差。
话虽如此,CNN通常在包含不止一个卷积层时表现更好。想法是更深的卷积层学习更复杂的特征,而靠近输入的层只学习基本形状(当然,这取决于网络结构本身和任务的复杂性)。由于你通常希望包含更多的卷积层,这样的模型复杂性(和灵活性)会增加,这可能导致过拟合,因此需要正则化技术。(具有正则化的三个卷积层通常会优于没有正则化的一个卷积层)。
你的设计只包含一个卷积层。我建议你堆叠多个卷积/池化层,并在必要时添加一些dropout层来对抗过拟合(在这样一个简单的模型上,很难看到正则化的任何积极效果)。