ResNet-50算法

news2024/12/28 5:48:02
  • 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
  • 🍖 原作者:K同学啊

一、理论知识储备

1.CNN算法发展

  1. AlexNet是2012年ImageNet竞赛中,由Alex Krizhevsky和Ilya Sutskever提出,在2012年ImageNet竞赛中,AlexNet以top5错误率为15.3%取得了分类任务的第一名。
  2. VGGNet是2014年ImageNet竞赛中,由Karen Simonyan和Andrew Zisserman提出,在2014年ImageNet竞赛中,VGGNet以top5错误率为7.3%取得了分类任务的第二名。
  3. GoogLeNet是2014年ImageNet竞赛中,由Christian Szegedy提出,在2014年ImageNet竞赛中,GoogLeNet以top5错误率为6.6%取得了分类任务的第一名。
  4. ResNet是2015年ImageNet竞赛中,由Kaiming He、Xiangyu Zhang、Saining Xie、Trevor Darrell提出,在2015年ImageNet竞赛中,ResNet以top5错误率为3.57%取得了分类任务的第一名。
  5. DenseNet是2016年ImageNet竞赛中,由Gao Huang、Zhuang Liu、Kaiming He、Xiangyu Zhang提出,在2016年ImageNet竞赛中,DenseNet以top5错误率为3.03%取得了分类任务的第一名。
  6. SE-ResNet是2017年ImageNet竞赛中,由Xiaolong Wang、Kaiming He、Jian Sun提出,在2017年ImageNet竞赛中,SE-ResNet以top5错误率为2.97%取得了分类任务的第一名。
  7. ResNeXt是2017年ImageNet竞赛中,由Saining Xie、Zhifeng Cai、Trevor Darrell提出,在2017年ImageNet竞赛中,ResNeXt以top5错误率为2.80%取得了分类任务的第一名。

2.残差网络的由来

深度残差网络RestNet(deep residual network)是2015年ImageNet竞赛中由何凯明等提出,因为它简单与实用并存,随后很多研究都是建立在ResNet-50或者ResNet-101的基础上完成。
ResNet主要解决深度卷积网络在深度加深时候的“退化”问题。在一般的卷积神经网络中,增大网络深度后带来的第一个问题就是梯度消失、爆炸,这个问题Szegedy提出BN层后被顺利解决。BN层能对各层的输出做归一化,这样梯度在反向层层传递后仍能保持大小稳定,不会出现过小或过大的情况。但是作者发现加了BN后再加大深度仍然不容易收敛,其提到了第二个问题–准确率下降问题:层级大到一定程度时准确率就会饱和,然后迅速下降,这种下降即不是梯度消失引起的也不是过拟合造成的,而是由于网络过于复杂,以至于光靠不加约束的放养式的训练很难达到理想的错误率。
准确率下降问题不是网络结构本身的问题,而是现有的训练方式不够理想造成的。当前广泛使用的优化器,无论是SGD,还是RMSProp,或是Adam,都无法在网络深度变大后达到理论上最优的收敛结果。
作者在文中证明了只要有合适的网络结构,更深的网络肯定会比较浅的网络效果要好。证明过程也很简单:假设在一种网络A的后面添加几层形成新的网络B,如果增加的层级只是对A的输出做了个恒等映射(identity mapping),即A的输出经过新增的层级变成B的输出后没有发生变化,这样网络A和网络B的错误率就是相等的,也就证明了加深后的网络不会比加深前的网络效果差。

在这里插入图片描述

何恺明提出了一种残差结构来实现上述恒等映射(图1):整个模块除了正常的卷积层输出外,还有个分支把输入直接连到输出上,该分支输出和卷积的输出做算术相加得到最终的输出,用公式表达就是 H ( x ) = F ( x ) + x H(x)= F(x)+ x H(x)=F(x)+x $ x $是输入, $ F(x) 是卷积分支的输出, 是卷积分支的输出, 是卷积分支的输出, H(x) $是整个结构的输出。可以证明如果 $ F(x) $分支中所有参数都是0 $ H(x) $就是个恒等映射。残差结构人为制造了恒等映射,就能让整个结构朝着恒等映射的方向去收敛,确保最终的错误率不会因为深度的变大而越来越差。如果一个网络通过简单的手工设置参数值就能达到想要的结果,那这种结构就很容易通过训练来收敛到该结果,这是一条设计复杂的网络时通用的规则。

在这里插入图片描述

图2左边的单元为 ResNet 两层的残差单元,两层的残差单元包含两个相同输出的通道数的 3x3 卷积,只是用于较浅的 ResNet 网络,对较深的网络主要使用三层的残差单元。三层的残差单元又称为bottleneck 结构,先用一个1x1卷积进行降维,然后 3x3 卷积,最后用 1x1 升维恢复原有的维度。另外,如果有输入输出维度不同的情况,可以对输入做一个线性映射变换维度,再连接后面的层。层的残差单元对于相同数量的层又减少了参数量,因此可以拓展更深的模型。通过残差单元的组合有经典的 ResNet-50ResNet-101等网络结构。

二、前期工作

1.设置GPU

import tensorflow as tf
gpus = tf.config.list_physical_devices('GPU')

if gpus:
    tf.config.explicitly_set_memory_growth(gpus[0], True)
    tf.config.set_visible_devices(gpus[0], 'GPU')
    print("GPUs available")

2.导入数据

import matplotlib.pyplot as plt
# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

import os,PIL,pathlib
import numpy as np

from tensorflow import keras
from tensorflow.keras import layers,models
data_dir = pathlib.Path('F:/host/Data/bird_photos')

3.查看数据

image_count = len(list(data_dir.glob('*/*')))

print("图片总数为:",image_count)

在这里插入图片描述

三、数据预处理

文件夹数量
Bananaquit166张
Black Skimmer111张
Black Throated Bushtiti122张
Cockatoo166张

1.加载数据

使用image_dataset_from_directory方法将磁盘中的数据加载到tf.data.Dataset对象中。

batch_size = 8
img_height = 224
img_width = 224
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
    data_dir,
    validation_split=0.2,
    subset="training",
    seed=123,
    image_size=(img_height, img_width),
    batch_size=batch_size,
)
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
    data_dir,
    validation_split=0.2,
    subset="validation",
    seed=123,
    image_size=(img_height, img_width),
    batch_size=batch_size,
)
# 我们可以通过`class_names`属性查看类别名称
class_names = train_ds.class_names
print(class_names)

在这里插入图片描述

2.可视化数据

plt.figure(figsize=(10, 5)) # 图形的宽为10高为5
plt.suptitle('Bird Photos')

for images, labels in train_ds.take(1):
  for i in range(8):
    ax = plt.subplot(2, 4, i+1)
    plt.imshow(images[i].numpy().astype("uint8"))
    plt.title(class_names[labels[i]])
    plt.axis("off")

在这里插入图片描述

plt.imshow(images[1].numpy().astype("uint8"))

在这里插入图片描述

3.再次检查数据

for image_batch, labels_batch in train_ds:
  print(image_batch.shape)
  print(labels_batch.shape)
  break

在这里插入图片描述

  • image_batch: 包含8张图像的张量,形状为(8, 224, 224, 3)。
  • labels_batch: 包含8个标签的张量,形状为(8,)。

4.配置数据集

  • shuffle: 随机打乱数据集。
  • prefetch: 预取数据集,以加速数据集的迭代。
  • cache: 缓存数据集,以加速数据集的迭代。
AUTOTUNE = tf.data.AUTOTUNE

train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

四、残差网络(ResNet)介绍

1.残差网络解决了什么

残差网络是为了解决深度神经网络(DNN)训练过程中梯度消失和梯度爆炸的问题而提出的。它通过引入残差连接,将输入直接加到输出上,从而允许网络学习更复杂的函数。

2.ResNet-50介绍

ResNet-50有两个基本的块,分别名为Conv BlockIdentity Block

五、构建ResNet-50网络模型

from keras import layers

from keras.layers import Input, Activation, BatchNormalization, Flatten
from keras.layers import Conv2D, AveragePooling2D, Dense, MaxPooling2D, ZeroPadding2D
from keras.models import Model

def identity_block(input_tensor, kernel_size, filters, stage, block):
    filters1, filters2, filters3 = filters
    
    name_base = str(stage) + block + '_identity_block_'
    
    x = Conv2D(filters1, (1, 1), name=name_base + 'conv1')(input_tensor)
    x = BatchNormalization(name=name_base + 'bn1')(x)
    x = Activation('relu',name=name_base + 'relu1')(x)
    
    x = Conv2D(filters2, kernel_size, padding='same', name=name_base + 'conv2')(x)
    x = BatchNormalization(name=name_base + 'bn2')(x)
    x = Activation('relu',name=name_base + 'relu2')(x)
    
    x = Conv2D(filters3, (1, 1), name=name_base + 'conv3')(x)
    x = BatchNormalization(name=name_base + 'bn3')(x)
    
    x = layers.add([x, input_tensor], name=name_base + 'add')
    x = Activation('relu',name=name_base + 'relu4')(x)
    return x

# 在残差网络中,广泛地使用了BN层;但是没有使用MaxPoo1ing以便减小特征图尺寸,
# 作为替代,在每个模块的第一层,都使用了strides=(2,2)的方式进行特征图尺寸缩减,
# 与使用MaxPooling相比,毫无疑问是减少了卷积的次数,输入图像分辨率较大时比较适合
# 在残差网络的最后一级,先利用layer.add()实现H(x)=x+F(x)
def conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2, 2)):
    filters1, filters2, filters3 = filters
    
    res_name_base = str(stage) + block + '_conv_block_res_'
    name_base =  str(stage) + block + '_conv_block_'
    
    x = Conv2D(filters1, (1, 1), strides=strides, name=name_base + 'conv1')(input_tensor)
    x = BatchNormalization(name=name_base + 'bn1')(x)
    x = Activation('relu',name=name_base + 'relu1')(x)
    
    x = Conv2D(filters2, kernel_size, padding='same', name=name_base + 'conv2')(x)
    x = BatchNormalization(name=name_base + 'bn2')(x)
    x = Activation('relu',name=name_base + 'relu2')(x)
    
    x = Conv2D(filters3, (1, 1), name=name_base + 'conv3')(x)
    x = BatchNormalization(name=name_base + 'bn3')(x)
    
    shortcut = Conv2D(filters3, (1, 1), strides=strides, name=res_name_base + 'conv')(input_tensor)
    shortcut = BatchNormalization(name=res_name_base + 'bn')(shortcut)
    
    x = layers.add([x, shortcut],name=name_base + 'add')
    x = Activation('relu',name=name_base + 'relu4')(x)
    return x

def ResNet50(input_shape=(224, 224, 3), num_classes=1000):
    
    img_input = Input(shape=input_shape)
    x = ZeroPadding2D((3, 3))(img_input)
    
    x = Conv2D(64, (7, 7), strides=(2, 2), name='conv1')(x)
    x = BatchNormalization(name='bn_conv1')(x)
    x = Activation('relu')(x)
    x = MaxPooling2D((3, 3), strides=(2, 2))(x)
    
    x =     conv_block(x, 3, [64, 64, 256], stage=2, block='a', strides=(1, 1))
    x = identity_block(x, 3, [64, 64, 256], stage=2, block='b')
    x = identity_block(x, 3, [64, 64, 256], stage=2, block='c')
    
    x =     conv_block(x, 3, [128, 128, 512], stage=3, block='a')
    x = identity_block(x, 3, [128, 128, 512], stage=3, block='b')
    x = identity_block(x, 3, [128, 128, 512], stage=3, block='c')
    x = identity_block(x, 3, [128, 128, 512], stage=3, block='d')
    
    x =     conv_block(x, 3, [256, 256, 1024], stage=4, block='a')
    x = identity_block(x, 3, [256, 256, 1024], stage=4, block='b')
    x = identity_block(x, 3, [256, 256, 1024], stage=4, block='c')
    x = identity_block(x, 3, [256, 256, 1024], stage=4, block='d')
    x = identity_block(x, 3, [256, 256, 1024], stage=4, block='e')
    x = identity_block(x, 3, [256, 256, 1024], stage=4, block='f')
    
    x =     conv_block(x, 3, [512, 512, 2048], stage=5, block='a')
    x = identity_block(x, 3, [512, 512, 2048], stage=5, block='b')
    x = identity_block(x, 3, [512, 512, 2048], stage=5, block='c')
    
    x = AveragePooling2D((7, 7), name='avg_pool')(x)
    
    x =  Flatten()(x)
    x = Dense(num_classes, activation='softmax', name='fc1000')(x)
    
    model = Model(img_input, x, name='ResNet50')
    
    # 加载预训练模型
    model.load_weights('./weights/resnet50_weights_tf_dim_ordering_tf_kernels.h5')
    
    return model

model = ResNet50()
model.summary()

在这里插入图片描述

六、编译

在准备对模型进行训练之前,还需要再对其进行一些设置。以下内容是在模型的编译步骤中添加的:

  • 损失函数(loss):用于衡量模型在训练期间预测值和实际值之间的差距。
  • 优化器(optimizer):决定模型如何根据其看到的数据和自身的损失函数进行更新。
  • 指标(metrics):用于监控训练和测试步骤。
# 设置优化器
opt = tf.keras.optimizers.Adam(learning_rate=1e-7)

model.compile(optimizer="adam",
              loss='sparse_categorical_crossentropy',
             metrics=['accuracy'])

七、训练模型

epochs = 10

history = model.fit(train_ds,
                    validation_data=val_ds,
                    epochs=epochs)

在这里插入图片描述

八、评估模型

acc = history.history['accuracy']
val_acc = history.history['val_accuracy']

loss = history.history['loss']
val_loss = history.history['val_loss']

epochs_range = range(epochs)

plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)

plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()

在这里插入图片描述

九、预测

# 采用加载的模型来看预测结果

plt.figure(figsize=(10, 5))
plt.suptitle('Predictions')

for images, labels in val_ds.take(1):
  
  for i in range(8):
      ax = plt.subplot(2, 4, i + 1)
      
      # 显示图片
      plt.imshow(images[i].numpy().astype("uint8"))
      
      # 需要给图片增加一个维度
      img_array = tf.expand_dims(images[i], 0)
      
      # 使用模型预测图片
      predictions = model.predict(img_array)
      plt.title(class_names[np.argmax(predictions)])
      
      plt.axis("off")

在这里插入图片描述

十、个人小结

在这篇文章中,我深入探讨了卷积神经网络(CNN)的发展历程,特别是残差网络(ResNet)的诞生和原理。CNN在图像识别领域取得了显著的进展,但随着网络深度的增加,梯度消失和爆炸的问题逐渐显现,影响了深层网络的性能。ResNet通过引入残差学习框架,有效地解决了这一问题,使得网络能够学习到恒等映射,从而在保持性能的同时增加深度。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

防火墙双双机热备

设备直路部署,上下行连接交换机 如 图所示,DeviceA和DeviceB的业务接口都工作在三层,上下行分别连接二层交换机。上行交换机连接运营商的接入点,运营商为企业分配的IP地址为1.1.1.3和1.1.1.4。现在希望DeviceA和DeviceB以负载分担…

鸿蒙 雷达图 绘制 人生四运图

let radius = Math.min(this.context.width, this.context.height) / 2 - 20;let centerX = this.context.width / 2;let centerY = this.context.height / 2;// 绘制圆环this.context.strokeStyle = #E4E4E4;const numRings = 5;const ringInterval = 1;for (let i = 0; i <…

Zookeeper:基于Zookeeper的分布式锁

一、Zookeeper分布式锁原理 二、Zookeeper JavaAPI操作 1、Curator介绍 Curator是Apache Zookeeper的Java客户端。常见的Zookeeper Java API&#xff1a; 原生Java API。ZkClient。Curator。 Curator项目目标是简化Zookeeper客户端的使用。Curator最初是Netfix研发的&#xf…

C++学习笔记---串口通信

串口基础知识 DB9针的RS-232串口&#xff0c;分别是公头、母头&#xff0c;这两种串口可以连接在一起。DB9针的串口信号脚编号及信号脚的具体含义如下 串口通信可以使用3根线完成&#xff0c;对应信号脚分别是&#xff1a;2接收、3发送、5地线。对此&#xff0c;有个简单的记法…

你知道大数据信用分低需要如何改善吗?

在当今社会&#xff0c;大数据信用分已经成为个人信用评估的重要指标之一。然而&#xff0c;有时候我们会发现自己的大数据信用分较低&#xff0c;这可能会对我们的信用状况产生负面影响。那么&#xff0c;如何改善自己的大数据信用分呢?本文将从信用分低的原因进行分析&#…

python pyautogui.position实时输出坐标

import pyautogui import timewhile True:# 获取鼠标当前坐标x, y pyautogui.position()# 打印坐标print(f"当前坐标&#xff1a;({x}, {y})")# 暂停1秒time.sleep(1) 输出实时鼠标位置坐标

6.26.4.1 基于交叉视角变换的未配准医学图像多视角分析

1. 介绍 许多医学成像任务使用来自多个视图或模式的数据&#xff0c;但很难有效地将这些数据结合起来。虽然多模态图像通常可以在神经网络中作为多个输入通道进行配准和处理&#xff0c;但来自不同视图的图像可能难以正确配准(例如&#xff0c;[2])。因此&#xff0c;大多数多视…

【集成学习】基于python的stacking回归预测

1 回归模型 当涉及到线性回归、岭回归、套索回归、决策树回归、随机森林回归、梯度提升回归和支持向量机回归模型的原理时&#xff0c;我们可以按照以下方式清晰地解释它们&#xff1a; 1.1 线性回归 线性回归是利用数理统计中的回归分析来确定两种或两种以上变量间相互依赖的…

说一说ABAP CDS View的发展历史与特性

1. 背景 随着SAP Fiori应用程序的兴起&#xff0c;SAP领域的小伙伴接触和使用ABAP CDS View的机会也是越来越多。今天&#xff0c;让我们花些时间&#xff0c;一起在了解下这项技术的设计初衷和发展历史。 2. 设计初衷 说起ABAP CDS View&#xff0c;就不得不提及SAP HANA。…

从零开始了解GPT-4o模型:它是如何工作的?

人工智能&#xff08;AI&#xff09;技术正以惊人的速度发展&#xff0c;其中最引人注目的是OpenAI发布的GPT-4o模型。作为GPT系列的新成员&#xff0c;GPT-4o在多模态输入处理和响应速度上取得了重大进展。本文将深入探讨GPT-4o的工作原理&#xff0c;帮助您全面了解这一尖端A…

2、数据库模型图、er图

关系 user和administarators是多对一的关系 user和order是一对多的关系 shipped和order是多对一的关系 order和books是多对多的关系 leavewords和order是一对一的关系 stock和books是一对多的关系 Chens 数据库表示法——ER图 Crows Foot数据库表示法——数据库模型图 Navicat表…

【实战教程】如何使用JMeter来轻松测试WebSocket接口?

1、websocket接口原理 打开网页&#xff1a;从http协议&#xff0c;升级到websocket协议&#xff0c;请求建立websocket连接服务器返回建立成功成功客户端向服务端发送匹配请求服务端选择一个客服上线服务器返回客服id客户端向服务器发送消息服务器推送消息给指定的客服服务器…

经典神经网络(13)GPT-1、GPT-2原理及nanoGPT源码分析(GPT-2)

经典神经网络(13)GPT-1、GPT-2原理及nanoGPT源码分析(GPT-2) 2022 年 11 月&#xff0c;ChatGPT 成功面世&#xff0c;成为历史上用户增长最快的消费者应用。与 Google、FaceBook等公司不同&#xff0c;OpenAI 从初代模型 GPT-1 开始&#xff0c;始终贯彻只有解码器&#xff0…

Vue-cli搭建项目----基础版

什么是Vue-cli 全称:Vue command line interface 是一个用于快速搭建Vue.js项目的标准工具,他简化了Vue.js应用的创建和管理过程,通过命令工具帮助开发者快速生成,配置和管理Vue项目. 主要功能 同一的目录结构本地调试热部署单元测试集成打包上线 具体操作 第一步创建项目:…

STL-迭代器

1.迭代器 1.1正向迭代器 正向迭代器是用一个类封装的&#xff0c;迭代器类。例如&#xff1a;在vector&#xff0c;string中的迭代器就相当于一个指针&#xff0c;在list类中用一个类来封装一个节点&#xff0c;实质上也还是一个指针&#xff0c;迭代器就相当于指向一个节点的…

Ueditor中集成135编辑器

一、背景 在资讯项目平台运营过程中&#xff0c;资讯需要排版&#xff0c;一般都是在135编辑器排好以后&#xff0c;复制到平台中UEditor编辑器中&#xff0c;所以&#xff0c;他们建议集成一下135哈 二、了解135编辑器 开始调研了解135编辑器&#xff0c;发现人家就支持集成…

系统架构师考点--系统配置与性能评价

大家好。今天我们来总结一下系统配置与性能评价的考点内容&#xff0c;这一部分一般是出在上午场的选择题中&#xff0c;占1-2分左右。 一、性能指标 计算机 对计算机评价的主要性能指标有&#xff1a;时钟频率(主频)&#xff1b;运算速度&#xff1b;运算精度内存的存储容量…

通达信机构买卖抓牛指标公式源码

通达信机构买卖抓牛指标公式源码&#xff1a; X_1:V/CLOSE/2; X_2:SUM(IF(X_1>100 AND CLOSE>REF(CLOSE,1),X_1,0),0); X_3:SUM(IF(X_1>100 AND CLOSE<REF(CLOSE,1),X_1,0),0); X_4:SUM(IF(X_1<100 AND CLOSE>REF(CLOSE,1),X_1,0),0); X_5:SUM(IF(X_1&l…

涉案财物管理系统|DW-S405系统实现涉案财物科学化管理

随着社会的不断发展&#xff0c;犯罪形式日益复杂&#xff0c;涉案财物的种类和数量也不断增加。传统的涉案财物管理方式已经无法满足现代执法办案的需求。因此&#xff0c;建立一套科学、高效、规范的警用涉案财物管理系统成为公安机关亟待解决的问题。 涉案财物管理系统DW-S…

sheng的学习笔记-AI-K均值算法

ai目录&#xff1a;sheng的学习笔记-AI目录-CSDN博客 需要学习前置知识&#xff1a;聚类&#xff0c;可参考 sheng的学习笔记-聚类(Clustering)-CSDN博客 目录 什么是k均值算法 流程 伪代码 数据集 伪代码 代码解释 划分示意图 优化目标 随机初始化 选择聚类数…