使用keras转移学习

时间:2020-09-05 13:05:54

标签: python tensorflow 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输出的一些屏幕截图 The accuracy value when the code was executed using Tensorflow 2

The training epochs progress shows that the loss decreases and accuracy increases while training.

1 个答案:

答案 0 :(得分:2)

默认情况下,基本上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_imtest_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)