用于二进制分类的 ResNet - 只有 2 个交叉验证准确度值

Posted

技术标签:

【中文标题】用于二进制分类的 ResNet - 只有 2 个交叉验证准确度值【英文标题】:ResNet for Binary classification- Just 2 values of cross-validation accuracy 【发布时间】:2019-07-14 18:37:19 【问题描述】:

我是 python 和 Keras 的新手。我正在尝试使用 ResNet 的迁移学习进行二进制分类。我的数据集非常小,但我正在使用图像增强。对于所有图像,我的交叉验证准确度只是 0.3442 和 0.6558 这两个值中的一个。谁能告诉我为什么会这样?此外,当我预测(0 或 1)时,它会将所有图像标记为一类(0)。这是我的代码:

from keras.preprocessing.image import ImageDataGenerator, load_img
from keras.models import Sequential,Model,load_model
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense, GlobalMaxPooling2D
from keras import backend as K
from keras.callbacks import TensorBoard
from keras.applications.resnet50 import ResNet50
from keras.optimizers import SGD, Adam
from keras.utils import plot_model
import matplotlib.pyplot as plt
import os, os.path
import glob
import cv2
import time
from keras.utils import np_utils
from keras.callbacks import ReduceLROnPlateau, CSVLogger, EarlyStopping
import numpy as np
import pydot
import graphviz

batch_size = 32
nb_classes = 2
data_augmentation = True

img_rows, img_cols = 224,224
img_channels = 3

#Creating array of training samples
train_path = "D:/data/train\*.*"
training_data=[]
for file in glob.glob(train_path):
    print(file)
    train_array= cv2.imread(file)
    train_array=cv2.resize(train_array,(img_rows,img_cols),3)
    training_data.append(train_array)

x_train=np.array(training_data)

#Creating array of validation samples
valid_path = "D:/data/valid\*.*"
valid_data=[]
for file in glob.glob(valid_path):
    print(file)
    valid_array= cv2.imread(file)
    valid_array=cv2.resize(valid_array,(img_rows,img_cols),3)
    valid_data.append(train_array)

x_valid=np.array(valid_data)

x_train = np.array(x_train, dtype="float")/255.0
x_valid = np.array(x_valid, dtype="float")/255.0

#Creating array for Labels
y_train=np.ones((num_trainsamples,),dtype = int)
y_train[0:224]=0 #Class1=0
y_train[225:363]=1 #Class2=1
print(y_train)

y_valid=np.ones((num_validsamples,),dtype = int)
y_valid[0:101]=0 
y_valid[102:155]=1 
print(y_valid)

y_train = np_utils.to_categorical(y_train,nb_classes,dtype='int32')
y_valid = np_utils.to_categorical(y_valid,nb_classes,dtype='int32')

base_model=ResNet50(weights='imagenet',include_top=False)

x = base_model.output
x = GlobalMaxPooling2D()(x)
x=Dense(1024,activation='relu')(x) 
x=Dense(1024,activation='relu')(x) 
x=Dense(512,activation='relu')(x) 
x=Dense(2, activation= 'sigmoid')(x)
model = Model(inputs = base_model.input, outputs = x)

for i,layer in enumerate(model.layers):
  print(i,layer.name)

for layer in model.layers[:75]:
    layer.trainable=False
for layer in model.layers[75:]:
    layer.trainable=True

adam = Adam(lr=0.0001)
model.compile(optimizer= adam, loss='binary_crossentropy', metrics=['accuracy'])

train_datagen = ImageDataGenerator(
    brightness_range=(0.2,2.5),
    rotation_range=180,
    zoom_range=0.5,
    width_shift_range=0.2,
    height_shift_range=0.2,
    horizontal_flip=True,
    vertical_flip=True)

train_datagen.fit(x_train)

history= model.fit_generator(train_datagen.flow(x_train, y_train, batch_size = 10,shuffle=True),steps_per_epoch=len(x_train),epochs = 500,shuffle=True,
    validation_data=(x_valid,y_valid),validation_steps=num_validsamples // batch_size,callbacks=[tensorboard])

eval = model.evaluate(x_valid, y_valid)
print ("Loss = " + str(eval[0]))
print ("Test Accuracy = " + str(eval[1]))

predictions= model.predict(x_valid)
print(predictions)

训练结果如下:

Epoch 1/500
362/362 [==============================] - 34s 93ms/step - loss: 0.6060 - acc: 0.7257 - val_loss: 0.7747 - val_acc: 0.3442
Epoch 2/500
362/362 [==============================] - 30s 82ms/step - loss: 0.4353 - acc: 0.7722 - val_loss: 0.7658 - val_acc: 0.5000
Epoch 3/500
362/362 [==============================] - 30s 82ms/step - loss: 0.4391 - acc: 0.7863 - val_loss: 0.7949 - val_acc: 0.3442
Epoch 4/500
362/362 [==============================] - 30s 82ms/step - loss: 0.4007 - acc: 0.7992 - val_loss: 0.6540 - val_acc: 0.6558
Epoch 5/500
362/362 [==============================] - 30s 82ms/step - loss: 0.3638 - acc: 0.8226 - val_loss: 0.6460 - val_acc: 0.6558
Epoch 6/500
362/362 [==============================] - 30s 82ms/step - loss: 0.3509 - acc: 0.8294 - val_loss: 0.7875 - val_acc: 0.3442
Epoch 7/500
362/362 [==============================] - 30s 82ms/step - loss: 0.3406 - acc: 0.8359 - val_loss: 0.7667 - val_acc: 0.3442
Epoch 8/500
362/362 [==============================] - 29s 80ms/step - loss: 0.3410 - acc: 0.8365 - val_loss: 0.6900 - val_acc: 0.6558
Epoch 9/500
362/362 [==============================] - 29s 80ms/step - loss: 0.3297 - acc: 0.8366 - val_loss: 0.7292 - val_acc: 0.3442
Epoch 10/500
362/362 [==============================] - 29s 80ms/step - loss: 0.3262 - acc: 0.8412 - val_loss: 0.6829 - val_acc: 0.6558
Epoch 11/500
362/362 [==============================] - 29s 80ms/step - loss: 0.3168 - acc: 0.8457 - val_loss: 0.7032 - val_acc: 0.3442
Epoch 12/500
362/362 [==============================] - 29s 80ms/step - loss: 0.3195 - acc: 0.8452 - val_loss: 0.6985 - val_acc: 0.5000
Epoch 13/500
362/362 [==============================] - 29s 80ms/step - loss: 0.3030 - acc: 0.8432 - val_loss: 0.6740 - val_acc: 0.6558
Epoch 14/500
362/362 [==============================] - 29s 80ms/step - loss: 0.3191 - acc: 0.8405 - val_loss: 0.6896 - val_acc: 0.6558
Epoch 15/500
362/362 [==============================] - 29s 80ms/step - loss: 0.3084 - acc: 0.8437 - val_loss: 0.7114 - val_acc: 0.3442

【问题讨论】:

你是怎么得到num_trainsamples的? 【参考方案1】:

当您使用任何 CNN 模型实现二进制分类时,您最好在最后一个密集层中使用单个单元。

x=密集(2,激活='sigmoid')(x) ---> x=Dense(1, activation= 'sigmoid')(x)

它将为您提供比现在更好的性能。

【讨论】:

以上是关于用于二进制分类的 ResNet - 只有 2 个交叉验证准确度值的主要内容,如果未能解决你的问题,请参考以下文章

Keras CIFAR-10图像分类 ResNet 篇

猿创征文|深度学习基于ResNet18网络完成图像分类

使用 tf slim 重新训练预训练的 ResNet-50 模型以进行分类

图像分类手撕ResNet——复现ResNet(Keras,Tensorflow 2.x)

ResNet:用于图像识别的深度残差网络

ResNet 基于迁移学习对CIFAR10 数据集的分类