第44步 深度学习图像识别:ResNet50建模(Tensorflow)

基于WIN10的64位系统演示

一、写在前面

(1)ResNet50

ResNet50是一种深度学习模型,由微软研究院的研究人员在2015年提出。"ResNet"的全称是"Residual Network",意为"残差网络","50"则表示这个网络包含50层。

ResNet50的主要特点是引入了"残差块"(Residual Block)。在传统的神经网络中,每一层都是在前一层的基础上添加新的变换,而在ResNet中,每一层都是在前一层的基础上添加新的变换,同时还保留了前一层的原始输入,这就是所谓的"残差"。这种设计使得网络可以更好地学习输入和输出之间的差异,而不是直接学习输出,这有助于提高模型的性能。

 

(2)ResNet50的预训练版本

Keras有ResNet50的预训练模型,省事:

 

二、ResNet50迁移学习代码实战

我们继续胸片的数据集:肺结核病人和健康人的胸片的识别。其中,肺结核病人700张,健康人900张,分别存入单独的文件夹中。

(a)导入包

from tensorflow import keras
import tensorflow as tf
from tensorflow.python.keras.layers import Dense, Flatten, Conv2D, MaxPool2D, Dropout, Activation, Reshape, Softmax, GlobalAveragePooling2D
from tensorflow.python.keras.layers.convolutional import Convolution2D, MaxPooling2D
from tensorflow.python.keras import Sequential
from tensorflow.python.keras import Model
from tensorflow.python.keras.optimizers import adam_v2
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.python.keras.preprocessing.image import ImageDataGenerator, image_dataset_from_directory
from tensorflow.python.keras.layers.preprocessing.image_preprocessing import RandomFlip, RandomRotation, RandomContrast, RandomZoom, RandomTranslation
import os,PIL,pathlib
import warnings
#设置GPU
gpus = tf.config.list_physical_devices("GPU")

if gpus:
    gpu0 = gpus[0] #如果有多个GPU,仅使用第0个GPU
    tf.config.experimental.set_memory_growth(gpu0, True) #设置GPU显存用量按需使用
    tf.config.set_visible_devices([gpu0],"GPU")
    
warnings.filterwarnings("ignore")             #忽略警告信息
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False    # 用来正常显示负号

(b)导入数据集

#1.导入数据
data_dir = "./cat_dog"
data_dir = pathlib.Path(data_dir)
image_count = len(list(data_dir.glob('*/*')))
print("图片总数为:",image_count)

batch_size = 32
img_height = 100
img_width  = 100

train_ds = image_dataset_from_directory(
    data_dir,
    validation_split=0.2,
    subset="training",
    seed=12,
    image_size=(img_height, img_width),
    batch_size=batch_size)

val_ds = image_dataset_from_directory(
    data_dir,
    validation_split=0.2,
    subset="validation",
    seed=12,
    image_size=(img_height, img_width),
    batch_size=batch_size)

class_names = train_ds.class_names
print(class_names)
print(train_ds)


#2.检查数据
for image_batch, labels_batch in train_ds:
    print(image_batch.shape)
    print(labels_batch.shape)
    break

#3.配置数据
AUTOTUNE = tf.data.AUTOTUNE

def train_preprocessing(image,label):
    return (image/255.0,label)

train_ds = (
    train_ds.cache()
    .shuffle(800)
    .map(train_preprocessing)
    .prefetch(buffer_size=AUTOTUNE)
)

val_ds = (
    val_ds.cache()
.map(train_preprocessing)
    .prefetch(buffer_size=AUTOTUNE)
)

#4. 数据可视化
plt.figure(figsize=(10, 8))  
plt.suptitle("数据展示")

class_names = ["Dog","Cat"]

for images, labels in train_ds.take(1):
    for i in range(15):
        plt.subplot(4, 5, i + 1)
        plt.xticks([])
        plt.yticks([])
        plt.grid(False)
        plt.imshow(images[i])
        plt.xlabel(class_names[labels[i]-1])

plt.show()

(c)数据增强

data_augmentation = Sequential([
  RandomFlip("horizontal_and_vertical"),
  RandomRotation(0.2),
  RandomContrast(1.0),
  RandomZoom(0.5,0.2),
  RandomTranslation(0.3,0.5),
])

def prepare(ds):
    ds = ds.map(lambda x, y: (data_augmentation(x, training=True), y), num_parallel_calls=AUTOTUNE)
    return ds
train_ds = prepare(train_ds)

(d)导入ResNet50

#获取预训练模型对输入的预处理方法
from tensorflow.python.keras.applications import resnet
from tensorflow.python.keras import Input
IMG_SIZE = (img_height, img_width, 3)
base_model = resnet.ResNet50(include_top=False, #是否包含顶层的全连接层
                         weights='imagenet')

inputs = Input(shape=IMG_SIZE)
#模型
x = base_model(inputs, training=False) #参数不变化
#全局池化
x = GlobalAveragePooling2D()(x)
#BatchNormalization
x = BatchNormalization()(x)
#Dropout
x = Dropout(0.8)(x)
#Dense
x = Dense(128, kernel_regularizer=regularizers.l2(0.3))(x)  # 全连接层减少到128,添加 L2 正则化
#BatchNormalization
x = BatchNormalization()(x)
#激活函数
x = Activation('relu')(x)
#输出层
outputs = Dense(2, kernel_regularizer=regularizers.l2(0.3))(x)  # 添加 L2 正则化
#BatchNormalization
outputs = BatchNormalization()(outputs)
#激活函数
outputs = Activation('sigmoid')(outputs)
#整体封装
model = Model(inputs, outputs)
#打印模型结构
print(model.summary())

然后打印出模型的结构:

(e)编译模型

#定义优化器
from tensorflow.python.keras.optimizers import adam_v2, rmsprop_v2
#from tensorflow.python.keras.optimizer_v2.gradient_descent import SGD
optimizer = adam_v2.Adam()
#optimizer = SGD(learning_rate=0.001)
#optimizer = rmsprop_v2.RMSprop()
#编译模型
model.compile(optimizer=optimizer,
                loss='sparse_categorical_crossentropy',
                metrics=['accuracy'])

#训练模型
from tensorflow.python.keras.callbacks import ModelCheckpoint, Callback, EarlyStopping, ReduceLROnPlateau, LearningRateScheduler

NO_EPOCHS = 100
PATIENCE  = 10
VERBOSE   = 1

# 设置动态学习率
annealer = LearningRateScheduler(lambda x: 1e-5 * 0.99 ** (x+NO_EPOCHS))

# 设置早停
earlystopper = EarlyStopping(monitor='loss', patience=PATIENCE, verbose=VERBOSE)

# 
checkpointer = ModelCheckpoint('mtb_jet_best_model_ResNet50.h5',
                                monitor='val_accuracy',
                                verbose=VERBOSE,
                                save_best_only=True,
                                save_weights_only=True)

train_model  = model.fit(train_ds,
                  epochs=NO_EPOCHS,
                  verbose=1,
                  validation_data=val_ds,
                  callbacks=[earlystopper, checkpointer, annealer])

#保存模型
model.save('mtb_jet_best_model_ResNet50.h5')
print("The trained model has been saved.")

 模型训练速度也比较快。然而,准确率波动比较大:

(f)Accuracy和Loss可视化

import matplotlib.pyplot as plt

loss = train_model.history['loss']
acc = train_model.history['accuracy']
val_loss = train_model.history['val_loss']
val_acc = train_model.history['val_accuracy']
epoch = range(1, len(loss)+1)

fig, ax = plt.subplots(1, 2, figsize=(10,4))
ax[0].plot(epoch, loss, label='Train loss')
ax[0].plot(epoch, val_loss, label='Validation loss')
ax[0].set_xlabel('Epochs')
ax[0].set_ylabel('Loss')
ax[0].legend()
ax[1].plot(epoch, acc, label='Train acc')
ax[1].plot(epoch, val_acc, label='Validation acc')
ax[1].set_xlabel('Epochs')
ax[1].set_ylabel('Accuracy')
ax[1].legend()
plt.show()

通过这个图,观察模型训练情况:

蓝色为训练集,橙色为验证集。可以看到loss还是总体呈现下降趋势,验证集的loss虽有波动,但是可以接受。但是在准确度曲线,验证集的波动就很恐怖了,真的是冰红两重天。

(g)混淆矩阵可视化以及模型参数

没啥好说的,都跟之前的ML模型类似:

import numpy as np
import matplotlib.pyplot as plt
from tensorflow.python.keras.models import load_model
from matplotlib.pyplot import imshow
from sklearn.metrics import classification_report, confusion_matrix
import seaborn as sns
import pandas as pd
import math
# 定义一个绘制混淆矩阵图的函数
def plot_cm(labels, predictions):
    
    # 生成混淆矩阵
    conf_numpy = confusion_matrix(labels, predictions)
    # 将矩阵转化为 DataFrame
    conf_df = pd.DataFrame(conf_numpy, index=class_names ,columns=class_names)  
    
    plt.figure(figsize=(8,7))
    
    sns.heatmap(conf_df, annot=True, fmt="d", cmap="BuPu")
    
    plt.title('混淆矩阵',fontsize=15)
    plt.ylabel('真实值',fontsize=14)
    plt.xlabel('预测值',fontsize=14)

val_pre   = []
val_label = []

for images, labels in val_ds:#这里可以取部分验证数据(.take(1))生成混淆矩阵
    for image, label in zip(images, labels):
        # 需要给图片增加一个维度
        img_array = tf.expand_dims(image, 0) 
        # 使用模型预测图片中的人物
        prediction = model.predict(img_array)
        val_pre.append(np.argmax(prediction))
        val_label.append(label)

plot_cm(val_label, val_pre)

cm_val = confusion_matrix(val_label, val_pre)    
a_val = cm_val[0,0]
b_val = cm_val[0,1]
c_val = cm_val[1,0]
d_val = cm_val[1,1]
acc_val = (a_val+d_val)/(a_val+b_val+c_val+d_val) #准确率:就是被分对的样本数除以所有的样本数
error_rate_val = 1 - acc_val #错误率:与准确率相反,描述被分类器错分的比例
sen_val = d_val/(d_val+c_val) #灵敏度:表示的是所有正例中被分对的比例,衡量了分类器对正例的识别能力
sep_val = a_val/(a_val+b_val) #特异度:表示的是所有负例中被分对的比例,衡量了分类器对负例的识别能力
precision_val = d_val/(b_val+d_val) #精确度:表示被分为正例的示例中实际为正例的比例
F1_val = (2*precision_val*sen_val)/(precision_val+sen_val) #F1值:P和R指标有时候会出现的矛盾的情况,这样就需要综合考虑他们,最常见的方法就是F-Measure(又称为F-Score)
MCC_val = (d_val*a_val-b_val*c_val) / (math.sqrt((d_val+b_val)*(d_val+c_val)*(a_val+b_val)*(a_val+c_val))) #马修斯相关系数(Matthews correlation coefficient):当两个类别具有非常不同的大小时,可以使用MCC
print("验证集的灵敏度为:",sen_val, 
      "验证集的特异度为:",sep_val,
      "验证集的准确率为:",acc_val, 
      "验证集的错误率为:",error_rate_val,
      "验证集的精确度为:",precision_val, 
      "验证集的F1为:",F1_val,
      "验证集的MCC为:",MCC_val)
    
train_pre   = []
train_label = []
for images, labels in train_ds:#这里可以取部分验证数据(.take(1))生成混淆矩阵
    for image, label in zip(images, labels):
        # 需要给图片增加一个维度
        img_array = tf.expand_dims(image, 0)
        # 使用模型预测图片中的人物
        prediction = model.predict(img_array)

        train_pre.append(np.argmax(prediction))
        train_label.append(label)
        
plot_cm(train_label, train_pre)

cm_train = confusion_matrix(train_label, train_pre)  
a_train = cm_train[0,0]
b_train = cm_train[0,1]
c_train = cm_train[1,0]
d_train = cm_train[1,1]
acc_train = (a_train+d_train)/(a_train+b_train+c_train+d_train)
error_rate_train = 1 - acc_train
sen_train = d_train/(d_train+c_train)
sep_train = a_train/(a_train+b_train)
precision_train = d_train/(b_train+d_train)
F1_train = (2*precision_train*sen_train)/(precision_train+sen_train)
MCC_train = (d_train*a_train-b_train*c_train) / (math.sqrt((d_train+b_train)*(d_train+c_train)*(a_train+b_train)*(a_train+c_train))) 
print("训练集的灵敏度为:",sen_train, 
      "训练集的特异度为:",sep_train,
      "训练集的准确率为:",acc_train, 
      "训练集的错误率为:",error_rate_train,
      "训练集的精确度为:",precision_train, 
      "训练集的F1为:",F1_train,
      "训练集的MCC为:",MCC_train)

效果只能说勉勉强强吧:

 (h)AUC曲线绘制

from sklearn import metrics
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.python.keras.models import load_model
from matplotlib.pyplot import imshow
from sklearn.metrics import classification_report, confusion_matrix
import seaborn as sns
import pandas as pd
import math

def plot_roc(name, labels, predictions, **kwargs):
    fp, tp, _ = metrics.roc_curve(labels, predictions)

    plt.plot(fp, tp, label=name, linewidth=2, **kwargs)
    plt.plot([0, 1], [0, 1], color='orange', linestyle='--')
    plt.xlabel('False positives rate')
    plt.ylabel('True positives rate')
    ax = plt.gca()
    ax.set_aspect('equal')


val_pre_auc   = []
val_label_auc = []

for images, labels in val_ds:
    for image, label in zip(images, labels):      
        img_array = tf.expand_dims(image, 0) 
        prediction_auc = model.predict(img_array)
        val_pre_auc.append((prediction_auc)[:,1])
        val_label_auc.append(label)
auc_score_val = metrics.roc_auc_score(val_label_auc, val_pre_auc)


train_pre_auc   = []
train_label_auc = []

for images, labels in train_ds:
    for image, label in zip(images, labels):
        img_array_train = tf.expand_dims(image, 0) 
        prediction_auc = model.predict(img_array_train)
        train_pre_auc.append((prediction_auc)[:,1])#输出概率而不是标签!
        train_label_auc.append(label)
auc_score_train = metrics.roc_auc_score(train_label_auc, train_pre_auc)

plot_roc('validation AUC: {0:.4f}'.format(auc_score_val), val_label_auc , val_pre_auc , color="red", linestyle='--')
plot_roc('training AUC: {0:.4f}'.format(auc_score_train), train_label_auc, train_pre_auc, color="blue", linestyle='--')
plt.legend(loc='lower right')
#plt.savefig("roc.pdf", dpi=300,format="pdf")

print("训练集的AUC值为:",auc_score_train, "验证集的AUC值为:",auc_score_val)

ROC曲线如下:

三、调整过程

说实话,这个模型调整了很久。具体调整的方面如下:

  1. 动态学习率的初始学习数值:设置为1e-5,代码如下:

annealer = LearningRateScheduler(lambda x: 1e-5 * 0.99 ** (x+NO_EPOCHS))

(2)迭代次数增加到100次:NO_EPOCHS =100

思路就是给模型足够的时间慢慢学习,达到比较好的性能。

四、ResNet50、InceptionResnetV2、Mobilenet、Efficientnet、DenseNet201、Inception V3和VGG19的对比

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/32317.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

React 基本介绍

目录 1、React是什么 2、React 三大颠覆性的特点 2.1 组件 2.2 JSX 2.3 Virtual DOM 3、Flux 架构(redux) 3.1 Flux 3.2 redux 4、打包工具(webpack) 4.1 webpack与RequireJS、browserify 4.2 模块规范 4.3 非 JavaSc…

实验篇(7.2) 17. 站对站安全隧道 - FortiGate作为SSL客户端(SSL) ❀ 远程访问

【简介】虽然常用的站到站的连接用的是IPsec VPN,但是在某些特殊情况下,UDP500或4500端口被阻断,IPsec VPN无法连接,那么还有其它办法实现站到站的连接吗?SSL VPN也可以的。 实验要求与环境 OldMei集团深圳总部部署了域…

【云原生】二进制k8s集群(下)部署高可用master节点

本次部署说明 在上一篇文章中,就已经完成了二进制k8s集群部署的搭建,但是单机master并不适用于企业的实际运用(因为单机master中,仅仅只有一台master作为节点服务器的调度指挥,一旦宕机。就意味着整个集群的瘫痪&#…

【软考网络管理员】2023年软考网管初级常见知识考点(23)- 路由器的配置

涉及知识点 华为路由器的配置,华为路由器命令大全,软考大纲路由命令,静态路由和动态路由的配置命令,软考网络管理员常考知识点,软考网络管理员网络安全,网络管理员考点汇总。 原创于:CSDN博主-…

数字化转型的难点是什么?该如何突破?

01为什么要进行数字化转型? 数字化转型不仅是企业提高效率和竞争力的必经之路,也是市场发展趋势的体现。 提升业务效率:数字化转型可以采用自动化流程、数据分析和智能化技术,从而提高企业业务的自动化水平,优化流程…

贝叶斯算法人生

哈喽大家好,我是咸鱼 之前看到过耗子叔写的一篇文章《程序算法与人生选择》,这篇文章中耗子叔结合计算机中的经典算法(排序、动态规划等等),让大家在人生道路的选择上获得了一些启发 我最近看了一些关于贝叶斯思想的…

数字图像处理-图像复原与重建

文章目录 一、图像退化/复原过程的模型二、噪声模型2.1噪声的空间和频率特性2.2一些重要的噪声概率密度函数2.2.1高斯噪声2.2.2瑞利噪声2.2.3爱尔兰(伽马)噪声2.2.4指数噪声2.2.5均匀噪声2.2.6脉冲(椒盐)噪声 2.3周期噪声 三、只存…

为什么有了HTTP,还需要WebSocket协议?

目录 WebSocket是什么? WebSocket怎样建立连接? WebSocket的实际用途 WebSocket 与 HTTP 的选择 HTTP是基于TCP协议的,同一时间里,客户端和服务器只能有一方主动发数据,是半双工通信。 通常,打开某个网…

Redis从入门到精通【进阶篇】之高可用主从详解

文章目录 0.前言1.详解1.1 主从复制概述1.2 主从复制原理1.2.1.全量复制1.2.2.增量复制1.2.3.详细描述1.3 更深入理解1.4 常见面试题 2. 总结3. Redis从入门到精通系列文章 0.前言 Redis是一个高性能的键值存储系统,广泛应用于Web应用、缓存、消息队列等领域。在实…

论文解读:End-to-End Object Detection with Transformers

发表时间:2020 论文地址:https://arxiv.org/pdf/2005.12872.pdf 项目地址:https://github.com/facebookresearch/detr 提出了一种将对象检测视为集合预测问题的新方法。我们的方法简化了检测流程,有效地消除了许多手工设计的组件…

python自动化办公——读取PPT写入word表格

Python自动化办公——读取PPT内容写入word表格 文章目录 Python自动化办公——读取PPT内容写入word表格一、需求分析二、导入依赖三、代码四、结果及总结 一、需求分析 📖由于我们知识图谱课程需要将课堂小组汇报的PPT总结成word文档,而我觉得一页一页复…

python爬虫并做可视化分析--前程无忧

一.数据采集 1.采集逻辑 2.数据schema 招聘信息Schema { "岗位名称": "财务会计主管", "薪资":"1.3-2万", "地址": "*******", "经验要求": "5-7年", "公司名": "***…

JavaWeb小记——重定向和内部转发

目录 重定向 原理图 重定向语句 重定向特点 内部转发 原理图 请求转发特点 路径的书写 请求域对象request 特点 请求转发特点 重定向特点 重定向 原理图 重定向语句 response.setStatus(302); response.setHeader("location","http://www.baidu.c…

MS1826 HDMI 多功能视频处理器 4*4矩阵切换器

基本介绍 MS1826 是一款多功能视频处理器,包含 4 路独立 HDMI 音视频输入通道、4 路独立 HDMI 音视频输出通道以及四路独立可配置为输入或者输出的 SPDIF、I2S 音频信号。支持 4 个独立的字 库定制型 OSD;可处理隔行和逐行视频或者图形输入信号&#xff…

【计算机网络】网络安全,HTTP协议,同源策略,cors,jsonp

❤️ Author: 老九 ☕️ 个人博客:老九的CSDN博客 🙏 个人名言:不可控之事 乐观面对 😍 系列专栏: 文章目录 网络安全非对称加密中间人攻击XSSSQL注入CSRF HTTP协议同源策略corsjsonp 网络安全 非对称加密…

推荐好用的AI工具集

AI技术未来已来,我们要拥抱变化 ,笔记试用好用AI工具,也在代码中试用chatGPT 一、工具集 解决任何问题:ChatGPT 写文案:Jasper Al 、Copysmith 生成真人视频:Synthesia、 CogView2 AI AI 解决法律问题…

MySQL面试题--索引概念以及底层

目录 概述 索引的底层数据结构 二叉树 B树 B树 B树与B树对比: 面试回答 大纲 回答 概述 索引(index)是帮助MySQL高效获取数据的数据结构(有序)。 在数据之外,数据库系统还维护着满足特定查找算法的数据结构(B树&#xff0…

springboot 国家公务员招聘网站-计算机毕设 附源码80528

springboot 国家公务员招聘网站 目 录 摘要 1 绪论 1.1研究背景与意义 1.2开发现状 1.3系统开发技术的特色 1.4springboot框架介绍 1.5论文结构与章节安排 2 2国家公务员招聘网站系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1数据增加流程 2.3.2数据修改流程 2.…

【Solr】体验极速安装solr

目录 前言 安装下载- 方式一:官网下载- 方式二:仓库下载 启动方式 快速使用 关于查询 前言 solr是基于java开发的,所以solr需要用到jdk环境,并且solr需要在tomcat容器中才能运行,所以需要提前配置好jdk和tomcat环境。 安装下载 需要注意的…

springboot集成mybatisPlus

1、添加依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-jav…