简体   繁体   English

Keras CNN 精度高但预测不佳。 如何改进它

[英]Keras CNN high accuracy but bad predictions. How to improve it

I have to identify a retinal disease with CNN.我必须通过 CNN 确定视网膜疾病。 I have 1400 images, 700 each class.我有 1400 张图片,每张 class 有 700 张。 My classes are (0 - no PDR) and (1 - PDR).我的课程是(0 - 无 PDR)和(1 - PDR)。 I'm trying to make a model to identify if an input retina have the disease in level 4 or not.我正在尝试制作 model 来识别输入视网膜是否患有 4 级疾病。

I'm making a follow manipulation with my images and rezise all to 256x256:我正在对我的图像进行跟踪操作并将所有图像调整为 256x256:

ImageCV[index] = cv2.addWeighted(ImageCV[index],4, cv2.GaussianBlur(ImageCV[index],(0,0), 256/30), -4, 128)

And it made the follow with my imgs: https://imgur.com/X1p9G1c它使我的imgs如下: https://imgur.com/X1p9G1c

Then, when I train my model I got a very high accuracy (like 99....) but when I try to predict some test images, it fails.. for example, I've putted 10 PDR examples in test folder and tries to predict them (all must be 1).. this is the result:然后,当我训练我的 model 时,我得到了非常高的准确度(比如 99 ......)但是当我尝试预测一些测试图像时,它失败了......例如,我在测试文件夹中放置了 10 个 PDR 示例并尝试预测它们(都必须为 1).. 这是结果:

[[0.]]
[[0.]]
[[1.]]
[[0.]]
[[0.]]
[[0.]]
[[1.]]
[[0.]]
[[0.]]
[[0.]]

This is my model:这是我的 model:

visible = Input(shape=(256,256,3))
conv1 = Conv2D(16, kernel_size=(3,3), activation='relu', strides=(1, 1))(visible)
conv2 = Conv2D(16, kernel_size=(3,3), activation='relu', strides=(1, 1))(conv1)
bat1 = BatchNormalization()(conv2)
conv3 = ZeroPadding2D(padding=(1, 1))(bat1)
pool1 = MaxPooling2D(pool_size=(2, 2))(conv3)

conv4 = Conv2D(32, kernel_size=(3,3), activation='relu', padding='valid', kernel_regularizer=regularizers.l2(0.01))(pool1)
conv5 = Conv2D(32, kernel_size=(3,3), activation='relu', padding='valid', kernel_regularizer=regularizers.l2(0.01))(conv4)
bat2 = BatchNormalization()(conv5)
pool2 = MaxPooling2D(pool_size=(1, 1))(bat2)

conv6 = Conv2D(64, kernel_size=(3,3), activation='relu',strides=(1, 1), padding='valid')(pool2)
conv7 = Conv2D(64, kernel_size=(3,3), activation='relu',strides=(1, 1), padding='valid')(conv6)
bat3 = BatchNormalization()(conv7)
conv7 = ZeroPadding2D(padding=(1, 1))(bat3)
pool3 = MaxPooling2D(pool_size=(1, 1))(conv7)

conv8 = Conv2D(128, kernel_size=(3,3), activation='relu', padding='valid', kernel_regularizer=regularizers.l2(0.01))(pool3)
conv9 = Conv2D(128, kernel_size=(2,2), activation='relu', strides=(1, 1), padding='valid')(conv8)
bat4 = BatchNormalization()(conv9)
pool4 = MaxPooling2D(pool_size=(1, 1))(bat4)

flat = Flatten()(pool4)

output = Dense(1, activation='sigmoid')(flat)
model = Model(inputs=visible, outputs=output)

opt = optimizers.adam(lr=0.001, decay=0.0)

model.compile(optimizer= opt, loss='binary_crossentropy', metrics=['accuracy'])


data, labels = ReadImages(TRAIN_DIR)

test, lt = ReadImages(TEST_DIR)

data = np.array(data)
labels = np.array(labels)
test = np.array(test)
lt = np.array(lt)

np.random.permutation(len(data))
np.random.permutation(len(labels))
np.random.permutation(len(test))
np.random.permutation(len(lt))

model.fit(data, labels, epochs=7, validation_data = (test,lt))

model.save('model.h5')

And this is predict.py这是 predict.py

model = load_model('model.h5')

for filename in os.listdir(r'v/'):
    if filename.endswith(".jpg") or filename.endswith(".ppm") or filename.endswith(".jpeg"):
        ImageCV = cv2.resize(cv2.imread(os.path.join(TEST_DIR) + filename), (256,256))
        ImageCV = cv2.addWeighted(ImageCV,4, cv2.GaussianBlur(ImageCV,(0,0), 256/30), -4, 128)
        cv2.imshow('image', ImageCV)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
        ImageCV = ImageCV.reshape(-1,256,256,3)
        print(model.predict(ImageCV))

What do I could to do to improve my predictions at all?我能做些什么来改善我的预测? I strongly appreciate your help我非常感谢你的帮助

UPDATE Well, I tried to do all of were said in answers but still'nt working... this is my code now:更新好吧,我试图做所有的答案,但仍然没有工作......这是我现在的代码:

visible = Input(shape=(256,256,3))
conv1 = Conv2D(16, kernel_size=(3,3), activation='relu', strides=(1, 1))(visible)
conv2 = Conv2D(32, kernel_size=(3,3), activation='relu', strides=(1, 1))(conv1)
bat1 = BatchNormalization()(conv2)
conv3 = ZeroPadding2D(padding=(1, 1))(bat1)
pool1 = MaxPooling2D(pool_size=(2, 2))(conv3)
drop1 = Dropout(0.30)(pool1)

conv4 = Conv2D(32, kernel_size=(3,3), activation='relu', padding='valid', kernel_regularizer=regularizers.l2(0.01))(drop1)
conv5 = Conv2D(64, kernel_size=(3,3), activation='relu', padding='valid', kernel_regularizer=regularizers.l2(0.01))(conv4)
bat2 = BatchNormalization()(conv5)
pool2 = MaxPooling2D(pool_size=(1, 1))(bat2)
drop1 = Dropout(0.30)(pool2)

conv6 = Conv2D(128, kernel_size=(3,3), activation='relu', padding='valid', kernel_regularizer=regularizers.l2(0.01))(pool2)
conv7 = Conv2D(128, kernel_size=(2,2), activation='relu', strides=(1, 1), padding='valid')(conv6)
bat3 = BatchNormalization()(conv7)
pool3 = MaxPooling2D(pool_size=(1, 1))(bat3)
drop1 = Dropout(0.30)(pool3)

flat = Flatten()(pool3)
drop4 = Dropout(0.50)(flat)

output = Dense(1, activation='sigmoid')(drop4)
model = Model(inputs=visible, outputs=output)

opt = optimizers.adam(lr=0.001, decay=0.0)

model.compile(optimizer= opt, loss='binary_crossentropy', metrics=['accuracy'])

data, labels = ReadImages(TRAIN_DIR)
test, lt = ReadImages(TEST_DIR)

data = np.array(data)
labels = np.array(labels)

perm = np.random.permutation(len(data))
data = data[perm]
labels = labels[perm]
#model.fit(data, labels, epochs=8, validation_data = (np.array(test), np.array(lt)))

aug = ImageDataGenerator(rotation_range=20, width_shift_range=0.2, height_shift_range=0.2, shear_range=0.15,
    horizontal_flip=True)

# train the network
model.fit_generator(aug.flow(data, labels, batch_size=32),
    validation_data=(np.array(test), np.array(lt)), steps_per_epoch=len(data) // 32,
    epochs=7)

And this is the return:这是回报:

Epoch 1/7
43/43 [==============================] - 1004s 23s/step - loss: 1.8090 - acc: 0.9724 - val_loss: 1.7871 - val_acc: 0.9861
Epoch 2/7
43/43 [==============================] - 1003s 23s/step - loss: 1.8449 - acc: 0.9801 - val_loss: 1.4828 - val_acc: 1.0000
Epoch 3/7
43/43 [==============================] - 1092s 25s/step - loss: 1.5704 - acc: 0.9920 - val_loss: 1.3985 - val_acc: 1.0000
Epoch 4/7
43/43 [==============================] - 1062s 25s/step - loss: 1.5219 - acc: 0.9898 - val_loss: 1.3167 - val_acc: 1.0000
Epoch 5/7
43/43 [==============================] - 990s 23s/step - loss: 2.5744 - acc: 0.9222 - val_loss: 2.9347 - val_acc: 0.9028
Epoch 6/7
43/43 [==============================] - 983s 23s/step - loss: 1.6053 - acc: 0.9840 - val_loss: 1.3299 - val_acc: 1.0000
Epoch 7/7
43/43 [==============================] - 974s 23s/step - loss: 1.6180 - acc: 0.9801 - val_loss: 1.5181 - val_acc: 0.9861

I'd have added dropouts, reduce the model layers, put data augmentation, and doesn't work at all (all the predictions returns 0)...我会添加辍学,减少 model 层,进行数据增强,并且根本不起作用(所有预测都返回 0)...

Please anyone can help in it.请任何人都可以提供帮助。

It seems you having issues with overfitting.看来你有过度拟合的问题。 I have kind of a personal dilemma in here whether this is off-topic or not because the approach one can give it's somewhat opinion-based, but here I go: First off, if you need to regularize an overfitting network, you want to use dropout starting at 0.25 and checking if that improves the model.我在这里有一种个人困境,无论这是否偏离主题,因为可以给出的方法有点基于意见,但在这里我 go:首先,如果你需要规范一个过度拟合的网络,你想使用从0.25开始的dropout并检查是否改善了 model。 Data augmentation is a must when dealing with overfitting, together with batch normalization (which you are applying).在处理过度拟合时,必须使用Data augmentation以及batch normalization (您正在应用)。 If this still not solves your overfitting problems, then you should try working on your network architecture to tweak it in order to make it generalize better.如果这仍然不能解决您的过度拟合问题,那么您应该尝试对您的网络架构进行调整以使其更好地泛化。 Did you check a simple of the inputs being used for train and test?您是否检查了用于训练和测试的简单输入?

TLDR: Try dropout and data augmentation, if it doesn't work and your data is correct, you might have to work on improving the architecture to make a better generalizing model. TLDR:尝试 dropout 和数据增强,如果它不起作用并且您的数据是正确的,您可能必须努力改进架构以更好地概括 model。

EDIT: The consensus on approaching this kind of models is to have it overfit at first, with a decent accuracy and then work towards generalizing it without losing accuracy if possible.编辑:接近这种模型的共识是首先让它过拟合,具有不错的准确性,然后在可能的情况下努力推广它而不会失去准确性。

Your model is very big for your training set size, leading to overfitting.您的 model 对于您的训练集大小来说非常大,导致过度拟合。 Use less layers使用更少的图层

You're overfitting ie have a high variance problem.您过度拟合,即存在高方差问题。 Try adding some soft dropout (0.2-0.3) at the end of your convolution blocks.尝试在卷积块的末尾添加一些软丢失 (0.2-0.3)。 You can also add a couple of Dense layers with decreasing unit numbers before the output layer and put more dropout layers in between those (0.5+).您还可以在 output 层之前添加几个具有递减单元数的 Dense 层,并在它们之间放置更多的 dropout 层(0.5+)。

You should also implement more data augmentation such as rotations, flips, random noise, random brightness, etc. Check out Keras' documentation for the ImageDataGenerator class.您还应该实现更多的数据增强,例如旋转、翻转、随机噪声、随机亮度等。查看 Keras 的 ImageDataGenerator class 文档。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM