美文网首页
基于深度学习的图片分类(完整流程)

基于深度学习的图片分类(完整流程)

作者: Nick是老外 | 来源:发表于2020-05-28 20:31 被阅读0次

基于深度学习的图片分类

环境依赖:

Requirments:

python 3.7
jupyter-notebook : 6.0.3
cudatoolkit 10.0.130
cudnn 7.6.5
tensorflow-gpu 2.0.0
scikit-learn 0.22.1
numpy
cv2
matplotlib

需要导入的包

  import os
  import cv2
  import numpy as np
  import pandas as pd
  import tensorflow as tf
  from tensorflow import keras
  from tensorflow.keras import layers,models
  from tensorflow.keras.models import Sequential
  from tensorflow.keras.optimizers import Adam
  from tensorflow.keras.callbacks import Callback
  from tensorflow.keras.utils import to_categorical
  from tensorflow.keras.applications import VGG19
  from tensorflow.keras.models import load_model
  import matplotlib.pyplot as plt
  from sklearn.preprocessing import label_binarize
  tf.compat.v1.disable_eager_execution()
  os.environ['CUDA_VISIBLE_DEVICES'] = '0' #使用GPU

1.参数设置(路径,图像尺寸,数据集分割比例)

 preprocessedFolder = '.\\ClassificationData\\' #预处理文件夹
 outModelFileName=".\\outModelFileName\\" 
 ImageWidth = 512
 ImageHeight = 320
 ImageNumChannels = 3
 TrainingPercent = 70  #训练集比例
 ValidationPercent = 15 #验证集比例

2.从preprocessedFolder读取图片并返回numpy格式(便于在神经网络中训练)

def read_dl_classifier_data_set(preprocessedFolder):
  num = 0  # 图片的总数量
  cnt_class = 0  #图片所属的类别
  label_list = []  # 存放每个图像的label,图像的类别
  img_list = []   #存放图片数据
  for directory in os.listdir(preprocessedFolder):
      tmp_dir = preprocessedFolder + directory
      cnt_class += 1
      for image in os.listdir(tmp_dir):
          num += 1
          tmp_img_filepath = tmp_dir + '\\' + image
          im = cv2.imread(tmp_img_filepath)  # numpy.ndarray
          im = cv2.resize(im, (ImageWidth, ImageHeight))  # 重新设置图片的大小
          img_list.append(im)
          label_list.append(cnt_class)  # 在标签中添加类别
          print("Picture " + str(num) + "Load "+tmp_img_filepath+"successfully")
print("共有" + str(num) + "张图片")
print("all"+str(num)+"picturs belong to "+str(cnt_class)+"classes")
return np.array(img_list),np.array(label_list)

all_data,all_label=read_dl_classifier_data_set(preprocessedFolder)
加载图片数据.png

3.数据预处理

1).图像数据压缩
2).标签数据进行独立热编码one-hot
def preprocess_dl_Image(all_data,all_label):
      all_data = all_data.astype("float32")/255  #把图像灰度值压缩到0--1.0便于神经网络训练
      all_label = to_categorical(all_label)  #对标签数据进行独立热编码
      return all_data,all_label

all_data,all_label = preprocess_dl_Image(all_data,all_label) #处理后的数据

4.对数据及进行划分(训练集:验证集:测试集 = 0.7:0.15:0.15)

def split_dl_classifier_data_set(all_data,all_label,TrainingPercent,ValidationPercent):
      s = np.arange(all_data.shape[0])
      np.random.shuffle(s)  #随机打乱顺序
      all_data = all_data[s] #打乱后的图像数据
      all_label = all_label[s] #打乱后的标签数据
      all_len = all_data.shape[0]
      train_len = int(all_len*TrainingPercent/100)  #训练集长度
      valadation_len = int(all_len*ValidationPercent/100)#验证集长度
      temp_len=train_len+valadation_len
      train_data,train_label = all_data[0:train_len,:,:,:],all_label[0:train_len,:] #训练集
      valadation_data,valadation_label = all_data[train_len:temp_len, : , : , : ],all_label[train_len:temp_len, : ] #验证集
      test_data,test_label = all_data[temp_len:, : , : , : ],all_label[temp_len:, : ] #测试集
      return train_data,train_label,valadation_data,valadation_label,test_data,test_label

train_data,train_label,valadation_data,valadation_label,test_data,test_label=split_dl_classifier_data_set(all_data,all_label,TrainingPercent,ValidationPercent)

5.训练分类模型

1).使用迁移学习(基于VGG19)
2).epochs = 30
3).batch_size = 16
4).使用 keras.callbacks.EarlyStopping 提前结束训练
def train_classifier(train_data,train_label,valadation_data,valadation_label,lr=1e-4):
      conv_base = VGG19(weights='imagenet',
              include_top=False,
              input_shape=(ImageHeight, ImageWidth, 3) )  
      model = models.Sequential()
      model.add(conv_base)
      model.add(layers.Flatten())
      model.add(layers.Dense(30, activation='relu')) 
      model.add(layers.Dense(6, activation='softmax')) #Dense: 全连接层。activation: 激励函数,‘linear’一般用在回归任务的输出层,而‘softmax’一般用在分类任务的输出层
      conv_base.trainable=False
      model.compile(
      loss='categorical_crossentropy',#loss: 拟合损失方法,这里用到了多分类损失函数交叉熵  
      optimizer=Adam(lr=lr),#optimizer: 优化器,梯度下降的优化方法 #rmsprop
      metrics=['accuracy'])
      model.summary() #每个层中的输出形状和参数。
      early_stoping =tf.keras.callbacks.EarlyStopping(monitor="val_loss",min_delta=0,patience=5,verbose=0,baseline=None,restore_best_weights=True)
      history = model.fit(
      train_data, train_label,
      batch_size=16, #更新梯度的批数据的大小 iteration = epochs / batch_size,
      epochs=30,  # 迭代次数
      validation_data=(valadation_data, valadation_label),  # 验证集
      callbacks=[early_stoping])
      return model,history
model,history = train_classifier(train_data,train_label,valadation_data,valadation_label,)
训练过程.png

6.模型训练效果(绘制训练集和验证集acc,loss曲线)

def plot_history(history):
      history_df = pd.DataFrame(history.history)
      history_df[['loss', 'val_loss']].plot()
      plt.title('Train and valadation loss')
      history_df = pd.DataFrame(history.history)
      history_df[['accuracy', 'val_accuracy']].plot()
      plt.title('Train and valadation accuracy')

plot_history(history)
loss.png
accuracy.png

7.模型性能评估

1).使用测试集进行评估
2).输出分类报告和混淆矩阵
3).绘制ROC和AUC曲线
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score
import seaborn as sns
Y_pred_tta=model.predict_classes(test_data) #模型对测试集数据进行预测
Y_test = [np.argmax(one_hot)for one_hot in test_label]# 由one-hot转换为普通np数组
Y_pred_tta=model.predict_classes(test_data) #模型对测试集进行预测
Y_test = [np.argmax(one_hot)for one_hot in test_label]# 由one-hot转换为普通np数组
print('验证集分类报告:\n',classification_report(Y_test,Y_pred_tta))
confusion_mc = confusion_matrix(Y_test,Y_pred_tta)#混淆矩阵
df_cm = pd.DataFrame(confusion_mc)
plt.figure(figsize = (10,7))
sns.heatmap(df_cm, annot=True, cmap="BuPu",linewidths=1.0,fmt="d")
plt.title('PipeLine accuracy:{0:.3f}'.format(accuracy_score(Y_test,Y_pred_tta)),fontsize=20)
plt.ylabel('True label',fontsize=20)
plt.xlabel('Predicted label',fontsize=20)
分类报告.png
混淆矩阵.png
from sklearn.metrics import precision_recall_curve
from sklearn.metrics import average_precision_score
from sklearn.metrics import roc_curve
from sklearn import metrics
import matplotlib as mpl

# 计算属于各个类别的概率,返回值的shape = [n_samples, n_classes]
y_score = model.predict_proba(test_data)
# 1、调用函数计算验证集的AUC 
print ('调用函数auc:', metrics.roc_auc_score(test_label, y_score, average='micro'))
# 2、手动计算验证集的AUC
#首先将矩阵test_label和y_score展开,然后计算假正例率FPR和真正例率TPR
fpr, tpr, thresholds = metrics.roc_curve(test_label.ravel(),y_score.ravel())
auc = metrics.auc(fpr, tpr)
print('手动计算auc:', auc)
mpl.rcParams['font.sans-serif'] = u'SimHei'
mpl.rcParams['axes.unicode_minus'] = False
#FPR就是横坐标,TPR就是纵坐标
plt.figure(figsize = (10,7))
plt.plot(fpr, tpr, c = 'r', lw = 2, alpha = 0.7, label = u'AUC=%.3f' % auc)
plt.plot((0, 1), (0, 1), c = '#808080', lw = 1, ls = '--', alpha = 0.7)
plt.xlim((-0.01, 1.02))
plt.ylim((-0.01, 1.02))
plt.xticks(np.arange(0, 1.1, 0.1))
plt.yticks(np.arange(0, 1.1, 0.1))
plt.xlabel('False Positive Rate', fontsize=16)
plt.ylabel('True Positive Rate', fontsize=16)
plt.grid(b=True, ls=':')
plt.legend(loc='lower right', fancybox=True, framealpha=0.8, fontsize=12)
plt.title('37个验证集分类后的ROC和AUC', fontsize=18)
plt.show()
ROC&AUC曲线.png

8.将模型保存为h5文件

def WriteDlClassifier(model,outModelFileName):
      model.save(outModelFileName+'image_classifer_model.h5')  # creates a HDF5 file 'my_model.h5'
      print("save image_classifer_model successfully!")

WriteDlClassifier(model,outModelFileName)

9.加载模型

load_path = outModelFileName
def load_Model(load_path):#加载模型
      model = load_model(load_path+'image_classifer_model.h5')
      print("加载模型成功")
      return model

 restored_model=load_Model(load_path)

代码说明:本网络用的笔记本电脑上的GeForce GTX 1650 GPU来跑,如果没有GPU or GPU较小可以下载tensorflow cpu版本,并去掉 os.environ['CUDA_VISIBLE_DEVICES'] = ' 0' 这行代码

tensorflow学习:tensorflow2.0官方学习文档 TensorFlow Core v2.0.0

数据下载:百度网盘-提取码:aajy
数据说明:解压后共5个子文件夹(如下图),每个文件夹是一类;共5类,每个类别中有50张图片,共计250张

解压后共5个子文件夹.png

参考文章1: 医学图像 | 使用深度学习实现乳腺癌分类(附python演练)
参考文章2: 代码实践 | 卷积神经网络之图像分类

说明:本文为原创文章,转载或引用请注明网址;小编刚入门,有不正确之处欢迎批评指正2210432548@qq.com

相关文章

网友评论

      本文标题:基于深度学习的图片分类(完整流程)

      本文链接:https://www.haomeiwen.com/subject/xxzaahtx.html