我是深度学习(和机器学习)的新手,我创建了一个Python脚本,使用TensorFlow/Keras来识别这个数据集中的花朵,并将它们分类到不同的组别中。这是我的代码:(我在Kaggle上进行的)
import numpy as npimport pandas as pdfrom sklearn.model_selection import train_test_splitfrom sklearn.model_selection import GridSearchCVfrom sklearn.preprocessing import LabelEncoderfrom keras.preprocessing.image import ImageDataGeneratorfrom keras.models import Sequentialfrom keras.optimizers import Adam, SGDfrom keras.utils import to_categoricalfrom keras.layers import Conv2D, Dropout, Dense, Flattenimport matplotlib.pyplot as pltimport cv2import osNUM_CLASSES = 5IMG_SIZE = 150DAISY = '../input/flowers-recognition/flowers/daisy'DANDELION = '../input/flowers-recognition/flowers/dandelion'ROSE = '../input/flowers-recognition/flowers/rose'SUNFLOWER = '../input/flowers-recognition/flowers/sunflower'TULIP = '../input/flowers-recognition/flowers/tulip'x = []y = []def train_data_gen(DIR, ID): for img in os.listdir(DIR): try: path = DIR + '/' + img img = plt.imread(path) img = cv2.resize(img,(IMG_SIZE,IMG_SIZE)) x.append(img) y.append(ID) except: Nonetrain_data_gen(DAISY, 0)train_data_gen(DANDELION, 1)train_data_gen(ROSE, 2)train_data_gen(SUNFLOWER, 3)train_data_gen(TULIP, 4)x = np.array(x)y = to_categorical(y,num_classes = 5)x_train,x_test,y_train,y_test = train_test_split(x, y, test_size = 0.15)x_train,x_val,y_train,y_val = train_test_split(x_train, y_train, test_size = 0.15)datagen = ImageDataGenerator( featurewise_center=False, samplewise_center=False, samplewise_std_normalization=False, rotation_range=60, zoom_range = 0.1, width_shift_range=0.1, height_shift_range=0.1, shear_range=0.1, fill_mode = "reflect")datagen.fit(x_train)model = Sequential()model.add(Conv2D(64, kernel_size=(3, 3), strides=2, activation='relu', input_shape=(IMG_SIZE, IMG_SIZE, 3)))model.add(Dropout(0.5))model.add(Conv2D(128, kernel_size=(3, 3), strides=2, activation='relu'))model.add(Dropout(0.5))model.add(Conv2D(128, kernel_size=(3, 3), strides=2, activation='relu'))model.add(Dropout(0.5))model.add(Conv2D(128, kernel_size=(3, 3), strides=2, activation='relu'))model.add(Dropout(0.5))model.add(Flatten())model.add(Dense(1024, activation='relu'))model.add(Dense(5, activation='softmax'))model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])model.fit_generator(datagen.flow(x_train,y_train,batch_size=16), epochs=10, steps_per_epoch=x_train.shape[0]//16, validation_data=(x_val, y_val), verbose=1)
我知道这里的epochs设置为10,但后来我把它改成了100。这花了很长时间,所以我在第63个epoch时停止了。即使如此,准确率也一直在60%左右,实在是太低了。我可以做些什么来提高准确率呢?是因为我的CNN太小了吗?还是我的数据有问题?我对这个领域很新,所以我无法更具体地问“为什么我的模型表现不好?”提前感谢大家的建设性反馈。
回答:
你的模型使用了太多的Dropout层。model.add(Dropout(0.5))
实际上会丢弃50%的输入层的neurons,而且你有4个这样的层。你很可能在欠拟合。
在每个Conv2D
层之后添加一个keras.layers.MaxPooling2D
层。
首先尝试移除所有Dropout层。这样做可能会有过拟合的风险——但如果你没有过拟合,那么Dropout层就没必要。如果确实过拟合了,可以尝试只使用一个Dropout层,设置20%的dropout率,然后逐渐增加到50%,之后可以再添加一个20%的dropout层并继续调整。