卷积神经网络必备基础

卷积神经网络(Convolutional Neural Network,  CNN)

传统的全连接神经网络并不适用于图像处理,这是因为:每个像素点都是一个输入特征,随着层数的增加,参数以指数级增长,而图片的像素点往往非常多,导致参数的规模非常巨大。

例如:

  • 32x32的图片:仅仅输入层,就有32x32x3(三原色) = 3072个特征
  • 200x200的图片:仅仅输入层,就有200x200x3(三原色) = 120000个特征

仅仅特征就有这么多,其后的隐藏层,对应的权重参数的数量是:(特征数)x (隐藏层结点数),可以想象这个参数的规模。

卷积(Convolution)

本文只解释卷积的具体操作,不讨论卷积的数学定义。如下所示,对于左上角的原始矩阵数据,我们使用一个卷积核(Convolution Kernel,也成为过滤器filter)的3x3小方阵,依次和原始矩阵数据中的每一个3x3的子方阵数据做“相乘+求和”的操作。

以图中为例

  • 绿色的两个区域的卷积计算过程见图片右上角,得到计算结果“-8”,即完成了一次卷积运算。
  • 下一次卷积运算,是将第一个3x3子方阵向右平移一个单位,得到第二个3x3子方阵\begin{bmatrix} 0 &0 &0 \\ 1 & 1 &1 \\ 1 & 2&2 \end{bmatrix},将其和卷积核相乘再求和,得到结果依然是-8。
  • 向右平移到最后一个3x3子方阵之后,回到矩阵最左边,再向下平移一个单位,得到3x3子方阵\begin{bmatrix} 0 &1 &1 \\ 0 &1 &2 \\ 0 &1 &2 \end{bmatrix},将其和卷积核相乘再求和,得到结果依然是-8。
  • 按照这个顺序平移下去,直到最后一个3x3子方阵的卷积运算完成,得到结果为一个5x5矩阵\begin{bmatrix} -8 &-8 &-4 &-4 &0 \\ -8 &-4 &-4 &0 &4 \\ -4 &-4 &0 &4 &4 \\ -4 &0 &4 &4 &8 \\ -4 &-4 &0 &4 &8 \end{bmatrix}

填充零(Zero Padding)

通过前面的例子可以看出,在对一张原始图片像素数据执行卷积计算后,得到的输出数据尺寸往往会略小于原始数据的尺寸(例子中7x7的矩阵经过计算后得到一个较小的5x5矩阵)。如果希望输出相同尺寸的数据,则可以在原始矩阵外围填充零,然后再进行卷积计算。注意:一般这个操作会对图片的上下左右对称填充,如下所示

假设:N为原始图片大小,F为卷积核(过滤器)大小,S为移动步长,P为填充零的(P是上下左右对称填充),则卷积操作后,得到的图片大小为:\frac{N-F+2P}{S} + 1

汇聚(Pooling,也有翻译为池化)

在神经网络介绍中,我们已经介绍了常用的汇聚层算法有:取最大值,取平均值,取线性组合等。一般最常用的就是前两种,分别称为最大汇聚(Max Pooling)平均汇聚(Average Pooling)。

最大汇聚

确定一个过滤器的大小,对原数据中同样大小区域的数据取最大值,作为结果。如下所示,对于原始的4x4数据,确定过滤器大小为2x2,则对4x4数据上的每一个2x2区域选一个最大值。这样的区域一共有4个(注意:每一个划分出来的2x2区域是不重叠的)。依次取出最大值7、4、9、8,得到了右边的汇聚结果。

平均汇聚

和最大汇聚的区别是:对每一区域取平均值作为结果

汇聚的作用是什么?

  • 以非线性的方式降低采样,减少参数和计算量
  • 降低了过拟合(Overfitting)的机率
  • 降低原始数据的大小,意味着损失了一些信息,因此一般会增加过滤器的个数

各种汇聚中,最大汇聚是最流行的,因为

  • 它可以提升一个图片在某个区域的显著特征
  • 在降低采样的时候,它能保留图片中最具有特征的部分

在卷积神经网络必备基础中,我们使用了传统的FNN模型解决了MNIST问题。下图是这个问题的CNN处理模型,下一节将用程序来实现这个模型。

使用Keras实现CNN

1. 导入Python的包

注意:在层的导入中,我们导入了卷积层Conv2D,最大汇聚层MaxPooling2D,平铺层Flatten(将矩阵数据平铺为向量),全连接层Dense

from keras.datasets import mnist
from keras.utils import to_categorical
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D, Flatten, Dense

import matplotlib.pyplot as plt

# Allow view plots in the notebook, '%' is a magic usage for python for special
%matplotlib inline

2. 加载数据

和神经网络必备基础中一样

(X_train_raw, y_train_raw), (X_test_raw, y_test_raw) = mnist.load_data()
print(X_train_raw.shape, X_test_raw.shape)
print(y_train_raw.shape, y_test_raw.shape)

3. 预处理训练数据

注意:对图像数据进行卷积操作,需要将数据reshape为3维,即(长,宽,颜色),因为是黑白图片,所以“颜色”这个维度取1,如果是彩色,则“颜色”这个维度取3

# suppose we don't know the data shape of the raw loaded MNIST data
# , we must make sure the data shape is what we wanted
X_train = X_train_raw.reshape(60000,28,28,1)
X_test = X_test_raw.reshape(10000,28,28,1)

# centered the data value, which is divided by 255 (each pixel value is 0~255)
X_train = X_train.astype('float32') / 255.0
X_test = X_test.astype('float32') / 255.0
print(X_train.shape, X_test.shape)

4. 预处理测试数据

和神经网络必备基础中一样,我们将标签扩张为一个由若干0和1组成的向量。

# convert each class value to a vector with value of 0 or 1
# i.e. if class vector, then it will be a matrix with value of 0 or 1
# e.g. for 0~9, 10 classes in total, if value is 5, then it will be
#      coverted to [0,0,0,0,0,1,0,0,0,0]
y_train = to_categorical(y_train_raw, NUM_CLASSES)
y_test = to_categorical(y_test_raw, NUM_CLASSES)
print(y_train.shape, y_test.shape)
print(y_train[0])

5. 创建和编译模型

cnn = Sequential()
cnn.add(Conv2D(32, kernel_size=(5,5), input_shape=(28,28,1), padding='same',activation='relu'))
cnn.add(MaxPooling2D())
cnn.add(Conv2D(64, kernel_size=(5,5), padding='same',activation='relu'))
cnn.add(MaxPooling2D())
cnn.add(Flatten())
cnn.add(Dense(1024, activation='relu'))
cnn.add(Dense(10, activation='softmax'))

cnn.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
print(cnn.summary())

summary()输出如下:

Model: "sequential_3"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv2d_5 (Conv2D)           (None, 28, 28, 32)        832       
                                                                 
 max_pooling2d_5 (MaxPoolin  (None, 14, 14, 32)        0         
 g2D)                                                            
                                                                 
 conv2d_6 (Conv2D)           (None, 14, 14, 64)        51264     
                                                                 
 max_pooling2d_6 (MaxPoolin  (None, 7, 7, 64)          0         
 g2D)                                                            
                                                                 
 flatten_2 (Flatten)         (None, 3136)              0         
                                                                 
 dense_4 (Dense)             (None, 1024)              3212288   
                                                                 
 dense_5 (Dense)             (None, 10)                10250     
                                                                 
=================================================================
Total params: 3274634 (12.49 MB)
Trainable params: 3274634 (12.49 MB)
Non-trainable params: 0 (0.00 Byte)
_________________________________________________________________
None

关于参数个数的说明:

  • 对于汇聚层,因为是对原数据取最大值,所以不需要参数
  • 对于卷积层,参数即卷积核中的参数,外加每一个新图片数据对应的一个偏好参数,例如
    • 对于conv2d_5层:每个卷积核有5x5=25个参数,由1个输入图片产生32个输出图片,于是由1x32个卷积核,外加32个偏好,总共有5x5x1x32+32 = 832个参数
    • 对于conv2d_6层:同理,总共有5x5x32x64+64 = 51264个参数
  • 对于平铺层,只是将数据展开,所以也不需要参数
  • 对于全连接层dense_4:3136(7x7x64) x 1024+1024=3212288
  • 对于全连接层dense_5:1024x10_10=10250

6. 训练和评价模型

这个模型训练时间比较长,是因为我们在卷积层使用了较多的特征提取:第一次卷积操作从一张图中提取了32种不同的特征,第二次卷积操作从32张图种提取了更多的特征。注意到,如果图片像素增加了,只要卷积核和特征图片的种类不变,上述模型的参数是不会增加的。

history_cnn = cnn.fit(X_train, y_train, epochs=2, verbose=1, validation_data=(X_test, y_test))

输出如下:

Epoch 1/2
1875/1875 [==============================] - 227s 121ms/step - loss: 0.0980 - accuracy: 0.9693 - val_loss: 0.0304 - val_accuracy: 0.9895
Epoch 2/2
1875/1875 [==============================] - 221s 118ms/step - loss: 0.0362 - accuracy: 0.9888 - val_loss: 0.0244 - val_accuracy: 0.9918

可以看到,每个epoch训练时间接近4分钟。

使用evaluate()评价模型

score = cnn.evaluate(X_test, y_test)
print(score)

得到输出如下:

313/313 [==============================] - 9s 28ms/step - loss: 0.0244 - accuracy: 0.9918
[0.024433128535747528, 0.9918000102043152]

和神经网络必备基础种的FNN相比,这里我们得到了更高的准确度:99.18%

CNN的增强

丢弃(Dropout)

  • 以p为概率、随机去掉一些训练层中的神经元(结点)
  • 目的:防止过拟合,只能用于训练数据

图像增强(image augmentation)

从训练集中取出图片数据,然后对其进行某些操作,从而:

  • 得到更多的图片用于模型训练
  • 通过操作后得到的新图片,使得模型更加健壮

关于这部分的细节,可以参考这篇博文:(数据)图像预处理——image augmentation图像增广之cutout、Mixup、CutMix方法及其实现_cutmix代码实现-CSDN博客

用Keras可以实现图像增强,程序如下

import numpy as np
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
from keras.applications.inception_v3 import preprocess_input

train_datagen = ImageDataGenerator(
    preprocessing_function=preprocess_input,
    width_shift_range=0.2,
    height_shift_range=0.2,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True)

train_generator = train_datagen.flow_from_directory('Colab Notebooks/images/sample_train/',
                                  target_size=(150, 150),
                                  save_to_dir='Colab Notebooks/images/sample_confirm/')

可以看到,Keras提供了ImageDataGenerator()这个类实现了这一功能:在'Colab Notebooks/images/sample_train/'这个路径下预先存放了几张原始图片,然后在'Colab Notebooks/images/sample_confirm/'路径下根据原始团片产生了很多新的图片。

这段程序不详解了,有兴趣可以自己查阅手册研究。

ImageNet介绍

什么是ImageNet

  • 一个很容易访问的大规模图片数据库
  • 起始于2009年
  • 基于WordNet架构
  • 每一个概念有多个同义词集合(synset, or synonym set)描述,例如对于Continental glacier(大陆冰川)有以下同义词集:Geological formation | ice mass | glacier | continental glacier
  • 当前,每一个同义词集大约有1000张图片

 ImageNet网址:https://image-net.org/

ImageNet挑战赛(ImageNet Challenge)

  • 每年一次的竞赛:区分几千张照片,并将其划分到1000个类别中
  • 全称ImageNet Large Scale Visual Recognition Challenge (ILSVRC)

下图反映了从10年到15年参加ILSVRC的优秀模型的深度(层数)变化,可以看到深度是在逐渐降低的。

VGG模型

VGG模型是一种深度卷积神经网络(CNN),由牛津大学的Visual Geometry Group(Oxford VGG)提出,该模型在2014年的ILSVRC(ImageNet大规模视觉识别挑战赛)中获得了第二名。VGG模型在多个迁移学习任务中的表现优于其他模型,并且从图像中提取CNN特征时,VGG模型是首选算法。

VGG16模型的示意图如下:

Keras同样也支持了VGG模型,程序如下:

import numpy as np
from keras.applications import vgg16
from keras.preprocessing import image

model = vgg16.VGG16(weights='imagenet')
# VGG16 model requires a image size of 224x224
img = image.load_img('Colab Notebooks/images/sample_train/cats/cat_02.jpeg',
                     target_size=(224,224))
img

#convet to numpy array
arr = image.img_to_array(img)
arr.shape

# expand dimension, as 1 dimension is batch, or else predict() will report error
#  "convolution input must be 4-dimensional:"
arr = np.expand_dims(arr, axis=0)
arr.shape

# preprocessing
arr = vgg16.preprocess_input(arr)
arr

# predict
pred = model.predict(arr)
# shows probilites in 1000 categories, as vgg model has 1000 categories
pred

# predications for top5
vgg16.decode_predictions(pred, top=5)

上述程序对我们存放的一张猫的图片:'Colab Notebooks/images/sample_train/cats/cat_02.jpeg',使用vgg16直接进行预测。程序输出如下:

[[('n02123045', 'tabby', 0.6933489),
  ('n02123159', 'tiger_cat', 0.13225932),
  ('n02124075', 'Egyptian_cat', 0.098001406),
  ('n02123394', 'Persian_cat', 0.009920092),
  ('n02883205', 'bow_tie', 0.0063082646)]]

可以看到,模型预测出来的结果中,具有最大概率的是'tabby'(斑猫)。

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

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

相关文章

【STM32】HAL库 CubeMX 教程 --- 高级定时器 TIM1 定时

实验目标: 通过CUbeMXHAL,配置TIM1,1s中断一次,闪烁LED。 一、常用型号的TIM时钟频率 1. STM32F103系列: 所有 TIM 的时钟频率都是72MHz;F103C8不带基本定时器,F103RC及以上才带基本定时器。…

2024.3.10 win11系统设置环境变量的方法

2024.3.10 win11系统设置环境变量的方法 win11和其他版本略有区别,以安装maven为例进行操作。 一、鼠标右键点击下拉菜单中选择“个性化” 二、点击个性化中选项后在左侧菜单选择“系统” 三、在右侧系统项目中选择“系统信息” 四、在系统信息中选择“高级系统…

Android将自己写的maven库上传至jitpack(2024靠谱版)

浏览了一堆陈年旧贴,终于实验成功了 第一步 将自建空项目同步至github并保证能正常运行第二步新增一个library类型的modul第三步 在新建的library里面写一些测试用的代码第四步在library的gradle文件增加插件和发布脚本第五步新建一个配置文件第六步 把所有更改push…

面试题:分布式锁用了 Redis 的什么数据结构

在使用 Redis 实现分布式锁时,通常使用 Redis 的字符串(String)。Redis 的字符串是最基本的数据类型,一个键对应一个值,它能够存储任何形式的字符串,包括二进制数据。字符串类型的值最多可以是 512MB。 Re…

基于java+springboot+vue实现的火车票订票系统(文末源码+Lw)294

摘要 火车票订票系统可以对火车票订票系统信息进行集中管理,可以真正避免传统管理的缺陷。火车票订票系统是一款运用软件开发技术设计实现的应用系统,在信息处理上可以达到快速的目的,不管是针对数据添加,数据维护和统计&#xf…

SaulLM-7B: A pioneering Large Language Model for Law

SaulLM-7B: A pioneering Large Language Model for Law 相关链接:arxiv 关键字:Large Language Model、Legal Domain、SaulLM-7B、Instructional Fine-tuning、Legal Corpora 摘要 本文中,我们介绍了SaulLM-7B,这是为法律领域量…

Keepalived+LVS构建高可用集群

目录 一、Keepalive基础介绍 1. Keepalive与VRRP 2. VRRP相关技术 3. 工作原理 4. 模块 5. 架构 6. 安装 7. Keepalived 相关文件 7.1 配置组成 7.2 全局配置 7.3 VRRP实例配置(lvs调度器) 7.4 虚拟服务器与真实服务器配置 二、Keepalived…

用*把棱形画出来

输入一个整数n表示棱形的对角半长度&#xff0c;请你用*把这个棱形画出来。 输入&#xff1a;1输出&#xff1a;*输入&#xff1a;3输出&#xff1a;**** *********输入输出格式 输入描述: 输入一个整数n&#xff08;n < 10&#xff09;。 输出描述: 按题目要求输出字符棱…

Jobs Portal求职招聘系统源码v3.5版本

源码介绍: Jobs Portal 求职招聘系统 是为求职者和公司发布职位而开发的交互式求职招聘源码。它使求职者能够发布简历、搜索工作、查看个人工作列表。它将提供各种公司在网站上放置他们的职位空缺资料&#xff0c;并且还可以选择搜索候选人简历。除此之外&#xff0c;还有一个…

Jupyter Notebook使用教程——从Anaconda环境构建到Markdown、LaTex语法介绍

0. 前言 按照国际惯例&#xff0c;首先声明&#xff1a;本文只是我自己学习的理解&#xff0c;虽然参考了他人的宝贵见解及成果&#xff0c;但是内容可能存在不准确的地方。如果发现文中错误&#xff0c;希望批评指正&#xff0c;共同进步。 你是否在视频教程或说明文档或Githu…

TC7.0简单编程十六进制跟十进制转化函数

写脚本的时候&#xff0c;没用内存的功能什么的&#xff0c;基本跟十六进制用得都比较少。最近因为易语言的一个代码要转化过来&#xff0c;看到易语言里面有现成的函数 16到10 跟10 到16&#xff0c;就想着TC是否也有这样的函数。找来找去没找到。其实TC也有这样的函数来的。藏…

misc49

下载附件是个txt文件&#xff0c;打开发现是个压缩包的头 后缀改成zip后打开 base解码无果&#xff0c;我们尝试字母解码 然后音符解码得到 ❀✿✼❇❃❆❇✿❁❇✻✿❀✾✿✻❀❊❆❃❀❊✻❅❀❄✼❂❊❊✾❇❁✽✽✼❁❂❀❀❀❉❃❂❀❉❃❂❊❊✾✼✻✻❀❆✻✻❀❀✻✻✿…

C#MQTT编程10--MQTT项目应用--工业数据上云

1、文章回顾 这个系列文章已经完成了9个内容&#xff0c;由浅入深地分析了MQTT协议的报文结构&#xff0c;并且通过一个有效的案例让伙伴们完全理解理论并应用到实际项目中&#xff0c;这节继续上马一个项目应用&#xff0c;作为本系列的结束&#xff0c;奉献给伙伴们&#x…

Visual Studio单步调试中监视窗口变灰的问题

在vs调试中&#xff0c;写了这样一条语句 while((nfread(buf, sizeof(float), N, pf))>0) 然而&#xff0c;在调试中&#xff0c;只要一执行while这条语句&#xff0c;监视窗口中的变量全部变为灰色&#xff0c;不能查看&#xff0c;是程序本身并没有报错&#xff0c;能够继…

简单了解一个数据包在网络的一生

在主题之前&#xff0c;我想先谈谈目前计算机的网络模型&#xff0c;主要谈谈 TCP/IP 模型&#xff1a; 应用层&#xff1a;产生最原始的数据&#xff0c;常见协议如 http、ftp、websocket、DNS、QUIC 传输层&#xff1a;传递应用层的数据给网络层&#xff0c;必要时进行切割&…

[Angular 基础] - 表单:响应式表单

[Angular 基础] - 表单&#xff1a;响应式表单 之前的笔记&#xff1a; [Angular 基础] - routing 路由(下) [Angular 基础] - Observable [Angular 基础] - 表单&#xff1a;模板驱动表单 开始 其实这里的表单和之前 Template-Driven Forms 没差很多&#xff0c;不过 Tem…

从16-bit 到 1.58-bit :大模型内存效率和准确性之间的最佳权衡

通过量化可以减少大型语言模型的大小&#xff0c;但是量化是不准确的&#xff0c;因为它在过程中丢失了信息。通常较大的llm可以在精度损失很小的情况下量化到较低的精度&#xff0c;而较小的llm则很难精确量化。 什么时候使用一个小的LLM比量化一个大的LLM更好? 在本文中&a…

C 嵌套循环

C 语言允许在一个循环内使用另一个循环&#xff0c;下面演示几个实例来说明这个概念。 语法 C 语言中 嵌套 for 循环 语句的语法&#xff1a; for (initialization; condition; increment/decrement) {statement(s);for (initialization; condition; increment/decrement){s…

Java项目修改源码jar文件(无需反编译)

文章目录 应用场景实现方案实现原理注意事项 应用场景 在项目中用了第三方的jar包&#xff0c;但是jar包内某个类不符合项目业务需求&#xff0c;需要修改第三方jar包源码文件内容。 实现方案 首先我们尝试直接修改jar包源码文件内容时&#xff0c;页面上会提示文件是只读的&a…

【Java】生成条形码工具类

报销单需要根据单号生成条形码 先看效果图 直接上代码&#xff0c;复制即可使用 /*** Description:生成条形码*/ public class BarCodeUtils {/*** 默认图片宽度*/private static final int DEFAULT_PICTURE_WIDTH 300;/*** 默认图片高度*/private static final int DEFAULT_…
最新文章