我需要构建一个CNN模型来诊断第四阶段的糖尿病视网膜病变(二分类 – 0表示非第四阶段(nonPdr),1表示第四阶段(pdr))。我使用了VGG16模型和高斯模糊来提高分类效果。我有1400张测试图像(每类700张),这是我的train.py文件:
#import tensorflow as tfimport cv2import osimport numpy as npfrom keras.layers.core import Flatten, Dense, Dropout, Reshapefrom keras.models import Modelfrom keras.layers import Input, ZeroPadding2D, Dropoutfrom keras import optimizersfrom keras.optimizers import SGDfrom keras.preprocessing.image import ImageDataGeneratorfrom keras.callbacks import EarlyStoppingfrom keras.applications.vgg16 import VGG16TRAIN_DIR = 'train/'TEST_DIR = 'test/'v = 'v/'BATCH_SIZE = 32NUM_EPOCHS = 5def ReadImages(Path): LabelList = list() ImageCV = list() classes = ["nonPdr", "pdr"] # Get all subdirectories FolderList = [f for f in os.listdir(Path) if not f.startswith('.')] # Loop over each directory for File in FolderList: for index, Image in enumerate(os.listdir(os.path.join(Path, File))): # Convert the path into a file ImageCV.append(cv2.resize(cv2.imread(os.path.join(Path, File) + os.path.sep + Image), (224,224))) LabelList.append(classes.index(os.path.splitext(File)[0])) ImageCV[index] = cv2.addWeighted (ImageCV[index],4,cv2.GaussianBlur(ImageCV[index] , (0,0) , 10) ,-4 ,128) return ImageCV, LabelListdata, labels = ReadImages(TRAIN_DIR)valid, vlabels = ReadImages(TEST_DIR)vgg16_model = VGG16(weights="imagenet", include_top=True)# (2) remove the top layerbase_model = Model(input=vgg16_model.input, output=vgg16_model.get_layer("block5_pool").output)# (3) attach a new top layerbase_out = base_model.outputbase_out = Reshape((25088,))(base_out)top_fc1 = Dense(64, activation="relu")(base_out)top_fc1 = Dropout(0.50)(base_out)# output layer: (None, 5)top_preds = Dense(1, activation="sigmoid")(top_fc1)# (4) freeze weights until the last but one convolution layer (block4_pool)for layer in base_model.layers[0:14]: layer.trainable = False# (5) create new hybrid modelmodel = Model(input=base_model.input, output=top_preds)# (6) compile and train the modelsgd = SGD(lr=0.000001, momentum=0.9)model.compile(optimizer=sgd, loss="binary_crossentropy", metrics=["accuracy"])data = np.asarray(data)valid = np.asarray(valid)data = data.astype('float32')valid = valid.astype('float32')data /= 255valid /= 255labels = np.array(labels)datagen = ImageDataGenerator( featurewise_center=True, featurewise_std_normalization=True, rotation_range=20, width_shift_range=0.2, height_shift_range=0.2, horizontal_flip=True)# compute quantities required for featurewise normalization# (std, mean, and principal components if ZCA whitening is applied)datagen.fit(data)mean = datagen.mean std = datagen.stdprint(mean, "mean")print(std, "std")es = EarlyStopping(monitor='val_loss', verbose=1)# fits the model on batches with real-time data augmentation:model.fit_generator(datagen.flow(data, np.array(labels), batch_size=32), steps_per_epoch=len(data) / 32, epochs=50, validation_data=(valid, np.array(vlabels)), nb_val_samples=72, callbacks=[es])model.save('model.h5')
运行后得到以下结果:
Epoch 1/5044/43 [==============================] - 475s 11s/step - loss: 0.9671 - acc: 0.4789 - val_loss: 0.6808 - val_acc: 0.6389Epoch 2/5044/43 [==============================] - 467s 11s/step - loss: 0.8427 - acc: 0.5007 - val_loss: 0.6364 - val_acc: 0.6389Epoch 3/5044/43 [==============================] - 468s 11s/step - loss: 0.7703 - acc: 0.5204 - val_loss: 0.6136 - val_acc: 0.6806Epoch 4/5044/43 [==============================] - 466s 11s/step - loss: 0.7324 - acc: 0.5512 - val_loss: 0.5941 - val_acc: 0.7500Epoch 5/5044/43 [==============================] - 466s 11s/step - loss: 0.7074 - acc: 0.5679 - val_loss: 0.5758 - val_acc: 0.7639Epoch 6/5044/43 [==============================] - 461s 10s/step - loss: 0.6640 - acc: 0.6146 - val_loss: 0.5584 - val_acc: 0.8194Epoch 7/5044/43 [==============================] - 455s 10s/step - loss: 0.6562 - acc: 0.6077 - val_loss: 0.5418 - val_acc: 0.8333Epoch 8/5044/43 [==============================] - 458s 10s/step - loss: 0.6076 - acc: 0.6700 - val_loss: 0.5263 - val_acc: 0.8889Epoch 9/5044/43 [==============================] - 456s 10s/step - loss: 0.5743 - acc: 0.7005 - val_loss: 0.5119 - val_acc: 0.9167Epoch 10/5044/43 [==============================] - 457s 10s/step - loss: 0.5649 - acc: 0.7041 - val_loss: 0.4981 - val_acc: 0.9306Epoch 11/5044/43 [==============================] - 452s 10s/step - loss: 0.5654 - acc: 0.7088 - val_loss: 0.4855 - val_acc: 0.9444Epoch 12/5044/43 [==============================] - 458s 10s/step - loss: 0.5046 - acc: 0.7616 - val_loss: 0.4740 - val_acc: 0.9444Epoch 13/5044/43 [==============================] - 465s 11s/step - loss: 0.5002 - acc: 0.7808 - val_loss: 0.4633 - val_acc: 0.9444Epoch 14/5044/43 [==============================] - 459s 10s/step - loss: 0.4694 - acc: 0.7924 - val_loss: 0.4514 - val_acc: 0.9583Epoch 15/5044/43 [==============================] - 463s 11s/step - loss: 0.4482 - acc: 0.8184 - val_loss: 0.4432 - val_acc: 0.9444Epoch 16/5044/43 [==============================] - 456s 10s/step - loss: 0.4326 - acc: 0.8343 - val_loss: 0.4330 - val_acc: 0.9583Epoch 17/5044/43 [==============================] - 454s 10s/step - loss: 0.4291 - acc: 0.8303 - val_loss: 0.4233 - val_acc: 0.9583Epoch 18/5044/43 [==============================] - 457s 10s/step - loss: 0.4060 - acc: 0.8376 - val_loss: 0.4145 - val_acc: 0.9583Epoch 19/5044/43 [==============================] - 457s 10s/step - loss: 0.3933 - acc: 0.8686 - val_loss: 0.4069 - val_acc: 0.9583Epoch 20/5044/43 [==============================] - 455s 10s/step - loss: 0.3786 - acc: 0.8684 - val_loss: 0.3985 - val_acc: 0.9583
这是我的predict.py文件:
from keras.models import load_modelimport cv2import osimport numpy as npfrom keras.preprocessing import imageTEST_DIR = 'v/'pdr = 0nonPdr = 0model = load_model('model.h5')def normalize(x, mean, std): x[..., 0] -= mean[0] x[..., 1] -= mean[1] x[..., 2] -= mean[2] x[..., 0] /= std[0] x[..., 1] /= std[1] x[..., 2] /= std[2] return xfor filename in os.listdir(r'v/'): if filename.endswith(".jpg") or filename.endswith(".ppm") or filename.endswith(".jpeg") or filename.endswith(".png"): ImageCV = cv2.resize(cv2.imread(os.path.join(TEST_DIR) + filename), (224,224)) ImageCV = cv2.addWeighted (ImageCV,4,cv2.GaussianBlur(ImageCV , (0,0) , 10) ,-4 ,128) ImageCV = np.asarray(ImageCV) ImageCV = ImageCV.astype('float32') ImageCV /= 255 x = ImageCV x = np.expand_dims(x, axis=0) x = normalize(x, [0.23883381, 0.23883381, 0.23883381], [0.24483591, 0.24579705, 0.2510857]) prob = model.predict(x) if prob <= 0.75: #.75 = 80% | .70=79% >>>> .70 = 82% | .75 = 79% print("nonPDR >>>", filename) nonPdr += 1 else: print("PDR >>>", filename) pdr += 1 print(prob)print("Number of retinas with PDR: ",pdr)print("Number of retinas without PDR: ",nonPdr)
问题是:在训练返回约97%的准确率后,我的所有预测都是错误的…例如,这三张图像应该是PDR(类别1):
nonPDR >>> 16_left.jpeg[[0.07062916]]nonPDR >>> 16_right.jpeg[[0.09434311]]nonPDR >>> 217_left.jpeg[[0.14126943]]
如果我用训练集中的相同图像进行测试,模型也无法正确预测…
我已经尝试过不使用高斯模糊进行训练,但准确率非常低。
我做错了什么?请帮帮我,我非常感激!
回答:
可以尝试以下几点:我建议在你对训练过程有一定信心之前,不要使用数据增强,即使初始性能不佳。作为双重检查,你可以直接在model.fit之后使用训练数据进行预测,只需验证得到的准确率与训练中的相同。你可能在处理测试数据时存在一些小的差异,导致网络表现不佳,所以首先确保训练部分是正确的,然后你可以专注于测试部分。希望这些建议对你有帮助。