Python 基于keras的迁移学习

Python 基于keras的迁移学习,python,tensorflow,keras,Python,Tensorflow,Keras,我试图对从公开数据集中获取的医学图像进行分类。我使用迁移学习来完成这项任务。最初,当我在带有VGG、Resnet、Densenet和Inception的同一数据集上使用以下代码时,在没有微调的情况下(TensorFlow版本1.15.2),准确率高于85%。现在,在将TensorFlow升级到2.x之后,当我在同一数据集上尝试相同的代码时,准确率永远不会超过32%。有人能帮我纠正这个问题吗?这与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')

下面是TensorFlow2.x输出的一些屏幕截图


基本上,默认情况下,目录中的
流\u
会洗牌数据,而您不会更改它

只需将
shuffle=False
添加到
test\u生成器中就足够了

或者,如果你真的想让它洗牌,那么
test\u im
test\u 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)    

基本上,默认情况下,
flow\u from\u目录
会洗牌数据,而您不会更改它

只需将
shuffle=False
添加到
test\u生成器中就足够了

或者,如果你真的想让它洗牌,那么
test\u im
test\u 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)    

你使用了多少训练数据?@Aniket Bote我有2500张图片。我也尝试过增加数据。结果是你的数据集太小了。尝试冻结上层。“这个型号太过合适了。”AniketBote谢谢你。我将尝试冻结顶层并返回结果。@AniketBote我尝试冻结顶层。我只是在模型后面有一个密集的连接层。所以结果还是一样的。精确度低。(31.71)这次。请寻求您的帮助您使用了多少培训数据?@Aniket Bote我有2500张图片。我也尝试过增加数据。结果是你的数据集太小了。尝试冻结上层。“这个型号太过合适了。”AniketBote谢谢你。我将尝试冻结顶层并返回结果。@AniketBote我尝试冻结顶层。我只是在模型后面有一个密集的连接层。所以结果还是一样的。精确度低。(31.71)这次。请寻求您的帮助非常感谢!!!!这解决了我的问题。我真的为这个错误浪费了好几天。那么,这是否意味着来自目录的流只会洗牌数据,而不会洗牌标签?只需更改shuffle=False,准确率就可以提高到97%。谢谢你一直都很准确。当心,当你使用模型时,不要忘记预处理,否则你将再次获得30%的准确率。非常感谢!!!!这解决了我的问题。我真的为这个错误浪费了好几天。那么,这是否意味着来自目录的流只会洗牌数据,而不会洗牌标签?只需更改shuffle=False,准确率就可以提高到97%。谢谢你一直都很准确。当心,当你使用模型时,不要忘记预处理,否则你将再次获得30%的准确率。