首页 > 解决方案 > 使用 keras 进行迁移学习

问题描述

我正在尝试对从公开数据集中拍摄的医学图像进行分类。我使用迁移学习来完成这项任务。最初,当我在与 VGG、Resnet、Densenet 和 Inception 相同的数据集上使用以下代码时,未进行微调(TensorFlow 版本 1.15.2)的准确率在 85% 以上。现在,在将 TensorFlow 升级到 2 后。 x,当我在同一个数据集上尝试相同的代码时,准确率永远不会超过 32%。谁能帮我纠正这个问题?它与 TensorFlow 版本或其他有关吗?我尝试过改变学习率、微调模型等。这是 Keras 中批量归一化错误的问题吗?

import os
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"] = "2"
import sys

import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras.applications.resnet50 import ResNet50, preprocess_input
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.applications.densenet import DenseNet121
from tensorflow.keras.applications.vgg16 import VGG16
from tensorflow.keras.applications.inception_v3 import InceptionV3
import cv2
import glob
from tensorflow.keras.layers import Input, Dense, Flatten, Conv2D, MaxPooling2D, Dropout
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
import tensorflow.keras as keras
from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping
import numpy as np
from sklearn.metrics import accuracy_score
from sklearn.metrics import confusion_matrix
from keras import backend as k
from mlxtend.evaluate import confusion_matrix
from mlxtend.plotting import plot_confusion_matrix
import math
import pandas as pd
from openpyxl import load_workbook


save_dir = '../new_tran/'

def extract_outputs(cnf_matrix, mdl_name):
  cnf_matrix_T=np.transpose(cnf_matrix)
  recall = np.diag(cnf_matrix) / np.sum(cnf_matrix, axis = 1)
  precision = np.diag(cnf_matrix) / np.sum(cnf_matrix, axis = 0)
  n_class=3
  TP=np.zeros(n_class)
  FN=np.zeros(n_class)
  FP=np.zeros(n_class)
  TN=np.zeros(n_class)
  for i in range(n_class):
    TP[i]=cnf_matrix[i,i]
    FN[i]=np.sum(cnf_matrix[i])-cnf_matrix[i,i]
    FP[i]=np.sum(cnf_matrix_T[i])-cnf_matrix[i,i]
    TN[i]=np.sum(cnf_matrix)-TP[i]-FP[i]-FN[i]
  P=TP+FN
  N=FP+TN
  classwise_sensitivity=np.true_divide(TP,P)
  classwise_specificity=np.true_divide(TN,N)
  classwise_accuracy=np.true_divide((TP+TN), (P+N))
  OS=np.mean(classwise_sensitivity)
  OSp=np.mean(classwise_specificity)
  OA=np.sum(np.true_divide(TP,(P+N)))
  Px=np.sum(P)
  TPx=np.sum(TP)
  FPx=np.sum(FP)
  TNx=np.sum(TN)
  FNx=np.sum(FN)
  Nx=np.sum(N)
  pox=OA
  pex=((Px*(TPx+FPx))+(Nx*(FNx+TNx)))/(math.pow((TPx+TNx+FPx+FNx),2))
  kappa_overall=[np.true_divide(( pox-pex ), ( 1-pex )),np.true_divide(( pex-pox ), ( 1-pox ))]
  kappa=np.max(kappa_overall)
  Rcl=np.mean(recall)
  Prcn=np.mean(precision)
  #######--------------------- Print all scores
  print('classwise_sen',classwise_sensitivity*100)
  print('classwise_spec',classwise_specificity*100)
  print('classwise_acc',classwise_accuracy*100)
  print('overall_sen',OS*100)
  print('overall_spec',OSp*100)
  print('overall_acc',OA*100)
  print('overall recall', Rcl)
  print('overall precision',Prcn)
  f1score=(2 * Prcn * Rcl) / (Prcn + Rcl)
  print('overall F1-score',f1score )
  print('Kappa',kappa)
 

def preProcess(X):
    X = X.astype('float32')
    # scale from [0,255] to [-1,1]
    X = (X - 127.5) / 127.5
    return X

train_datagen = ImageDataGenerator(preprocessing_function=preProcess)
test_datagen = ImageDataGenerator(preprocessing_function=preProcess)

IMG_SIZE = 256
batch_size = 16
train_data_dir = '../data/train/'
test_dir = '../data/test/'
val_dir = '../data/val/'
train_generator = train_datagen.flow_from_directory(
    train_data_dir,
    target_size=(IMG_SIZE , IMG_SIZE),
    batch_size=16,
    class_mode='sparse')
valid_generator = train_datagen.flow_from_directory(
    val_dir,
    target_size=(IMG_SIZE , IMG_SIZE),
    batch_size=16,
    class_mode='sparse')
test_generator = train_datagen.flow_from_directory(
    test_dir,
    target_size=(IMG_SIZE , IMG_SIZE),
    batch_size=16,
    class_mode='sparse')


test_im=np.concatenate([test_generator.next()[0] for i in range(test_generator.__len__())])
test_lb=np.concatenate([test_generator.next()[1] for i in range(test_generator.__len__())])

t_x, t_y = next(train_generator)

checkpoint1 = ModelCheckpoint(save_dir+"best_res.hdf5", monitor='val_accuracy', verbose=1, save_best_only=True, mode='max')
checkpoint2  = EarlyStopping(monitor='val_loss', patience=10, verbose=0, mode='min')
callbacks_list1 = [checkpoint1, checkpoint2]



def new_model():
    img_in = Input(t_x.shape[1:])             
    model = DenseNet121(include_top= False , 
                layers=tf.keras.layers, 
                weights='imagenet',      
                input_tensor= img_in, 
                input_shape= t_x.shape[1:],
                pooling ='avg') 
    x = model.output  
    predictions = Dense(3, activation="softmax", name="predictions")(x)    
    model = Model(inputs=img_in, outputs=predictions)
    return model

model1 = new_model()
opt = Adam(lr=3E-4)
model1.compile(optimizer = opt, loss = 'sparse_categorical_crossentropy',metrics = ['accuracy'])

history1 = model1.fit(train_generator, 
                                  validation_data = valid_generator, 
                                  epochs = 200,
                                  callbacks=callbacks_list1)
model1.load_weights(save_dir+'best_res.hdf5')
model1.compile(optimizer = opt, loss = 'sparse_categorical_crossentropy',metrics = ['accuracy'])

y_pred1 = model1.predict(test_im)
pred_class1=np.argmax(y_pred1,axis=1)
print('accuracy = ',accuracy_score(pred_class1,test_lb))
cm = confusion_matrix(y_target=test_lb,y_predicted=pred_class1, binary=False)
print(cm)
fig, ax = plot_confusion_matrix(conf_mat=cm)
plt.gcf().savefig(save_dir+"resnet.png", dpi=144) 
plt.close()
extract_outputs(cm, 'Resnet')

以下是 tensorflow 2.x 输出的一些截图 使用 Tensorflow 2 执行代码时的准确度值

训练 epochs 的进展表明,在训练过程中损失减少并且准确度增加。

标签: pythontensorflowkeras

解决方案


基本上flow_from_directory默认情况下会随机播放数据并且您没有更改它。

只需添加shuffle=False到您的test_generator应该就足够了。

喜欢

test_generator = train_datagen.flow_from_directory(
    test_dir,
    target_size=(IMG_SIZE, IMG_SIZE),
    batch_size=16,
    class_mode='sparse',
    shuffle=False)

或者,如果您真的想将其洗牌,test_im并且test_lb必须以相同的顺序排列。例如

test_im = []
test_lb = []
for im, lb in test_generator:
    test_im.append(im)
    test_lb.append(lb)
test_im = np.array(test_im)
test_lb = np.array(test_lb)    

推荐阅读