神经网络---卷积神经网络CNN

一、从前馈神经网络到CNN

前馈神经网络(Feedforward Neural Networks)是最基础的神经网络模型,也被称为多层感知机(MLP)。

它由多个神经元组成,每个神经元与前一层的所有神经元相,形成一个“全连接”的结构。每个神经元会对其输入数据进行线性变换(通过权重矩阵),然后通过一个非线性函数(如ReLU或Sigmoid)进行激活。这就是前馈神经网络的基本操作。

然而前馈神经网络也会产生问题:如果加深网络层,全连接神经网络随着隐藏层和隐藏节点的增加,参数的增加量是十分巨大的。正是因为这些大量的参数,使得神经网络模型有着极强的学习能力,导致计算困难。

很大程度上,是CNN的基本组成部分与前馈神经网络有很紧密的关联,甚至可以说,CNN就是一种特殊的前馈神经网络。

这两者的主要区别在于,CNN在前馈神经网络的基础上加入了卷积层和池化层(下边会讲到),以便更好地处理图像等具有空间结构的数据。

CNN在前馈神经网络的基础上加入了卷积层和池化层

所谓深度学习,不就是层数比较多的神经网络嘛,那为什么不能使用一种几十层的前馈神经网络,而要设计一个所谓的卷积神经网络呢?接下来我们来学习卷积神经网络模型。

二、卷积神经网络(CNN)介绍

卷积神经网络(CNN)是一种高效的深度学习架构,用于图像和视频识别、分类等任务。CNN通过局部连接权重共享自动特征提取等特点减少模型复杂度并提高计算效率。它在商业领域有广泛应用,如图像识别、医学图像分析、人脸识别等。Python中的深度学习框架如TensorFlow、Keras等.

CNN的网络结构分为3部分:输入层,隐藏层与输出层CNN的输入层是直接输入二维图像信息,这一点与传统的神经网络输入层需要输入一维向量有所不同。

隐藏层由三种网络构成 —— 卷积层(包含激活函数),池化层,全连接层

      卷积层:主要作用是提取特征,使用滤波器(卷积核),通过设定步长、深度等参数,对输入进行不同层次的特征提取。滤波器中的参数可以通过反向传播算法进行学习。

      激活函数层:主要是将卷积层的输出做一个非线性映射。常见的激活函数包括sigmoid,tanh,Relu等

      池化层:对卷积层提取的特征进行降维,主要是用于参数量压缩。可以减轻过拟合情况。常见的有平均池化和最大池化,不包含需要学习的参数。

     全连接层:主要是指两层网络,所有神经元之间都有权重连接。常见用于网络的最后一层,用于计算类别得分。

     输出层:输出层位于全连接层之后,对从全连接层得到的特征进行分类输出。

1、卷积层

卷积本质来说就是通过卷积核滑动遍历一幅图像像素矩阵,其权重w与对应位置像素相乘再相加的操作这里就涉及到几个概念:卷积核、步长、填充。

举个例子说明:比如有一张猫的图像,这里猫眼睛、猫脚、猫尾巴之间的距离是很大的,看猫眼睛的时候并不会影响到猫尾巴,所以图像具有局部相关性,在特征提取的时候专门设计找猫眼睛的卷积核在这个图像中找猫眼睛,专门找猫脚的卷积核来找猫脚,专门找猫尾巴的卷积核来找猫尾巴。

 (1)卷积核(Kernel) 

卷积核也称作滤波器,是用来滑动的窗口,卷积核尺寸通常为3×3×c,3×3是卷积核的大小,c是卷积核的通道数。注意,这里的c和这层的输出的通道是一样的,比如224×224×3的图像,用3×3×c的卷积,那么这里的c就是3。卷积核的每个小方格上都有一个权重w,这些权重是可学习参数,训练就是要找到最优的参数.

接下来我们以灰度图像为例(通道c=1):

左边矩阵容易被理解为一张图片,中间的这个被理解为卷积核,右边的图片我们可以理解为另一张图片。

第一步计算:

第二步计算:

第一行计算完成:

接下来为了得到下一行的元素,现在把蓝色块下移:

最后我们得到一个卷积计算结果为:

下图展示了使用两个三通道滤波器从三通道(RGB)图像中生成两个卷积输出的详细过程。

以上就是三维卷积计算方法。这里面体现了局部连接权值共享:每层神经元只和上一层部分神经元相连(卷积计算规则),且filter的权值对于上一层所有神经元都是一样的。对于包含两个3*3*3的fitler的卷积层来说,其参数数量仅有(3*3*3+1)*2=56个,且参数数量与上一层神经元个数无关。与全连接神经网络相比,其参数数量大大减少了。

2、步长

步长(stride)是卷积操作中的一个重要参数,它决定了卷积核在输入数据上移动的间隔。步长的选择直接影响卷积操作后输出特征图的大小和信息保留程度,是神经网络卷积操作的关键参数。步长的大小可以是正整数,通常为1、2、3等。

3、填充(padding)

在标准卷积中,存在两问题(1)每次卷积都会缩小图像的尺寸,图像会失去原来的形状;(2)在滑动时位于中间的像素会被重复滑动到,而位于边缘的像素就只被滑动一次,这意味着卷积过程丢掉了图像边缘的许多信息,因此,要解决这些问题,可以使用padding零填充,这样,在滑动时的卷积核可以允许原始边缘像素位于其中心,边缘有值的像素也能被计算到。如下图是padding=1的零填充。

图像填充操作

图像填充后卷积操作图

图像经过卷积得到的特征图大小是由卷积核大小、步长、padding共同决定的,其计算公式为 

2、池化层 (Pooling )

随着模型网络不断加深,卷积核越来越多,要训练的参数还是很多,而且直接拿卷积核提取的特征直接训练也容易出现过拟合的现象。CNN使用的另一个有效的工具被称为“池化(Pooling)”出现并解决了上面这些问题,为了有效地减少计算量,池化就是将输入图像进行缩小,减少像素信息,只保留重要信息;为了有效地解决过拟合问题,池化可以减少数据,但特征的统计属性仍能够描述图像,而由于降低了数据维度,可以有效地避免过拟合。

池化的定义:对不同位置区域提取出有代表性的特征(进行聚合统计,例如最大值、平均值等),这种聚合的操作就叫做 池化,池化的过程通常也被称为 特征映射 的过程(特征降维)。听起来很高深,其实简单地说就是下采样。

池化主要有两种, 最大值池化(Max Pooling)和 平均值池化(Average pooling),最大池化是对局部窗口的值取最大,平均池化是对局部窗口的值取平均。

详细的池化过如下:

池化核的大小:3×3

池化步长:1

池化类型 : 最大值池化(Max Pooling)

池化层的主要作用就是对非线性激活函数后的结果进行降采样,以减少参数的数量,避免过拟合,并提高模型的处理速度。

3、Flatten层&全连接层(Full Connected Layer)

Flatten:将最后的二维特征图打平成一维。

全连接层:对提取的特征进行非线性组合以得到输出。

到这一步,其实我们的一个完整的“卷积部分”就算完成了,如果想要叠加层数,一般也是叠加“Conv-MaxPooing",通过不断的设计卷积核的尺寸,数量,提取更多的特征,最后识别不同类别的物体。做完Max Pooling后,我们就会把这些数据“拍平”,丢到Flatten层,然后把Flatten层的output放到full connected Layer里,采用softmax对其进行分类。

一个完整的CNN结构

4、CNN网络的实战

import torch
import torch.nn as nn
from torchvision import transforms
from torchvision import datasets #torchvision计算机视觉库
from torch.utils.data import DataLoader
import torch.nn.functional as f   #使用functional中的ReLu激活函数
import torch.optim as optim
import matplotlib.pyplot as plt

# 准备数据集
batch_size = 64
#神经网络希望输入的数值较小,最好在0-1之间,所以需要先将原始图像(0-255的灰度值)转化为图像张量(值为0-1)
#仅有灰度值->单通道   RGB -> 三通道 读入的图像张量一般为W*H*C (宽、高、通道数) 在pytorch中要转化为C*W*H
transform = transforms.Compose([
     #将数据转化为图像张量
    transforms.ToTensor(),
    # 进行归一化处理,切换到0-1分布 (均值, 标准差)
    transforms.Normalize(mean=[0.1307,],std=[0.3081,])
])
train_dataset = datasets.MNIST(root="../mnist_data/",train=True,transform=transform,download=True)
test_dataset = datasets.MNIST(root="../mnist_data/",train=False,transform=transform,download=True)
"""
for step,(b_x,b_y) in enumerate (train_dataset):
    if step>0:
        break
batch_x=b_x.squeeze(1).numpy();#将思维张量移除第一维度,并转化为numpy数组
batch_y=b_y.numpy()
class_label=train_dataset.classes;
print(class_label.classes)
"""


#将自定义的dataset根据batch size的大小、是否shuffle等选项封装成一个batch size大小的tensor,后续就只需要在包装成variable即可作为模型的输入进行训练。
train_dataloader = DataLoader(dataset=train_dataset,batch_size=batch_size,shuffle=True)
test_dataloader = DataLoader(dataset=test_dataset,batch_size=batch_size,shuffle=True)

# 网络模型
class Model(nn.Module):
    #构造函数,用于初始化对象的属性
    def __init__(self):
        super(Model, self).__init__()
        # 两个卷积层
        self.conv1 = nn.Conv2d(1,10,kernel_size=5) #1为in_channels 10为out_channels,卷积核大小是5X5的
        self.conv2 = nn.Conv2d(10,20,kernel_size=5)
        # 池化层
        self.pooling = nn.MaxPool2d(2)#2为最大池化窗口的大小
        # 全连接层 320 = 20 * 4 * 4
        self.fc = nn.Linear(320,10)

    def forward(self,x):
        # 先从x数据维度中得到batch_size
        batch_size = x.size(0)
        # 卷积层->池化层->激活函数
        x = f.relu(self.pooling(self.conv1(x)))
        x = f.relu(self.pooling(self.conv2(x)))
        x = x.view(batch_size, -1)  # 将数据展开,为输入全连接层做准备
        x = self.fc(x)
        return x
        # x = f.relu(self.pooling(self.conv1(x)))
        # x = f.relu(self.pooling(self.conv2(x)))
        # x = x.view(x.size(0), -1)
        # x = self.fc(x)
        # return x

model = Model()
#在这里加入两行代码,将数据送入GPU中计算!!!
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model.to(device) #将模型的所有内容放入cuda中
# 优化器和损失函数
criterion = nn.CrossEntropyLoss()
#神经网络已经逐渐变大,需要设置冲量momentum=0.5
optimizer = optim.SGD(model.parameters(),lr = 0.01,momentum=0.5)

# 训练
epoch_list = []
def train(epoch):
    running_loss = 0.0
    epoch_list.append(epoch+1)
    # for epoch in range(10):
    for i, data in enumerate(train_dataloader, 0):
        input, target = data
        input, target = input.to(device),target.to(device)
        y_pred = model(input)   #前向传播
        loss = criterion(y_pred, target)  #计算损失
        # print(i+1,epoch+1,loss.item())
        optimizer.zero_grad()
        loss.backward() #反向传播,计算梯度
        optimizer.step() #更新权重

        running_loss += loss.item()
        if i % 300 == 299:
            print("{} {} loss:{:.3f}".format(epoch + 1, i + 1, running_loss / 300))
            running_loss = 0.0
# 测试
accuracy_list = []
def test():
    total = 0
    correct = 0
    #表明当前计算不需要反向传播,使用之后,强制后边的内容不进行计算图的构建
    with torch.no_grad():
        for i,data in enumerate(test_dataloader,0):
            input,target = data
            input, target = input.to(device), target.to(device)
            y_pred = model(input)
            predicted = torch.argmax(y_pred.data,dim=1)  #找打最大概率的类别
            total += target.size(0)
            correct += (predicted==target).sum().item()
        accuracy = correct/total
        accuracy_list.append(accuracy)
        print("Accuracy on test set:{:.2f} %".format(100*correct/total))

if __name__ == '__main__':
    for epoch in range(10):
        train(epoch)
        test()
#画图
plt.plot(epoch_list,accuracy_list)
plt.xlabel('epoch')
plt.ylabel('accuracy')
plt.grid()
plt.show()

如果大家对神经网络知识感兴趣可以关注我的微信公众号,里面会分享一些知识干货。

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

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

相关文章

电子电气SCI期刊,中科院1区TOP,收稿范围广泛

一、期刊名称 IEEE Transactions on Smart Grid 二、期刊简介概况 期刊类型:SCI 学科领域:工程技术 影响因子:9.6 中科院分区:1区 三、期刊征稿范围 IEEE Transactions on Smart Grid是一本跨学科期刊,旨在传播智…

Gbase 国产数据库

参考:参考: 5分钟学会Linux环境GBase 8t安装和部署 - 光洋山 - twt企业IT交流平台 (talkwithtrend.com)https://www.talkwithtrend.com/Article/197237 视频 GBase 8s快速入门-功能简介与演示-大数据教程-腾讯课堂 (qq.com)https://ke.qq.com/course/…

Qt 插件机制使用及原理

目录 1.引言 2.插件原理 3.插件实现 3.1.定义一个接口集(只有纯虚函数的类) 3.2.实现接口 4.插件的加载 4.1.静态插件 4.1.1.静态插件实现方式 4.1.2.静态插件加载的过程 4.1.3.示例 4.2.动态插件 4.2.1.动态插件的加载过程 5.定位插件 6.插件开发的优势 7.总结…

蓝桥杯高频考点-与日期相关的题目

文章目录 前言1. 如何枚举合法日期1.1 预存每个月的天数1.2 封装一个判断日期是否合法的函数1.3 枚举日期并判断日期是否合法 2. 判断日期是否为回文日期2.1 将日期当作字符串进行处理2.2 将日期当作一个8位数进行处理 3. 给定初始日期,计算经过n天后对应的日期3.1 …

Java集合【超详细】2 -- Map、可变参数、Collections类

文章目录 一、Map集合1.1 Map集合概述和特点【理解】1.2 Map集合的基本功能【应用】1.3 Map集合的获取功能【应用】1.4 Map集合的两种遍历方式 二、HashMap集合2.1 HashMap集合概述和特点【理解】2.2 HashMap的组成、构造函数2.3 put、查找方法2.4 HashMap集合应用案例【应用】…

另一棵树的子树(oj题)

一、题目链接 https://leetcode.cn/problems/subtree-of-another-tree/submissions/536304222 二、题目思路 1.首先遍历大树,判断大树的根结点的值是否等于小树的根结点的值,如果不相等,就找大树的左孩子或者右孩子,以左孩子为根…

博士毕业论文/CTEX/LATEX

LATEX环境安装 CTEX 安装 (垃圾,不要装) 运行 clean.batcomp.bat 缺少字体 Couldn’t find Adobe Heiti S.cfg’ miktex-maketfm: No creation rule for font “Adobe Heiti Std”.解决方法:其实就是下载这四个字体之后&…

jsp实验19 File

三、源代码以及执行结果截图&#xff1a; readJSPFile.jsp <% page contentType"text/html" %> <% page pageEncoding "utf-8" %> <% page import"java.io.*"%> <style> #tom{ font-family:宋体;font-size:2…

Crosslink-NX器件应用连载(10): 图像输入并通过HDMI输出

作者&#xff1a;Hello,Panda 大家下午好&#xff0c;晚上好。这里分享一个Lattice Crosslink-NX器件通过MIPI或LVDS输入图像&#xff0c;并通过HDMI输出图像的案例&#xff08;其实这是个比较冷门的需求&#xff0c;Crosslink-NX器件还是主要做MIPI桥接用&#xff09;。 咱们…

《Kubernetes部署篇:基于麒麟V10+ARM64架构部署harbor v2.4.0镜像仓库》

总结&#xff1a;整理不易&#xff0c;如果对你有帮助&#xff0c;可否点赞关注一下&#xff1f; 更多详细内容请参考&#xff1a;企业级K8s集群运维实战 一、环境信息 K8S版本 操作系统 CPU架构 服务版本 1.26.15 Kylin Linux Advanced Server V10 ARM64 harbor v2.4.0 二、部…

文刻创作AI工具怎么注册卡密

在科技日新月异的今天&#xff0c;生成式人工智能&#xff08;AI&#xff09;的迅猛发展正在重塑各行各业的面貌。其中&#xff0c;文刻创作AI工具以其独特的魅力和强大的功能&#xff0c;成为了内容创作领域的一股清流&#xff0c;引领着内容生产的新潮流。 【文刻二创工具教…

人脸识别模型与人类视觉识别的对比——评估人脸识别模型存在偏见是否比人类的偏见大?

1. 概述 人脸识别系统是一个几十年来一直备受关注的研究领域。而且在过去的几年中。公司和政府一直在积极引入人脸识别系统&#xff0c;并且我们看到越来越多的机会可以看到人脸识别系统。例如&#xff0c;有的系统可以随便介绍&#xff0c;如搜索特定人的图像&#xff08;图像…

SAP Build引言

前言 SAP Build 似乎是一个整合了很多低代码或无代码产品的平台&#xff0c;最早的时候应该都是各自分开的几个产品&#xff0c;近年合并到一块上了SAP Build平台 现在看官网的介绍应该是有三四个产品被集成进来了&#xff0c;分别是SAP IRPA&#xff0c;SAP Workflow&#xf…

K8s Ingress 详解

文章目录 K8s Ingress 详解Ingress 资源清单Ingress 基于URL 实现路由Ingress 基于名称虚拟主机Ingress 实现HTTPS创建TLS 证书创建Secrets配置ingress Ingress RewriteIngress 灰度发布Ingress 配置认证 K8s Ingress 详解 Ingress 资源清单 apiVersion: networking.k8s.io/v…

编程学习 (C规划) 6 {24_4_18} 七 ( 简单扫雷游戏)

首先我们要清楚扫雷大概是如何实现的&#xff1a; 1.布置雷 2.扫雷&#xff08;排查雷&#xff09; &#xff08;1&#xff09;如果这个位置是雷就炸了&#xff0c;游戏结束 &#xff08;2&#xff09;如果不是雷&#xff0c;就告诉周围有几个雷 3.把所有不是雷的位置都找…

【Unity脚本】使用脚本操作游戏对象的组件

【知识链】Unity -> Unity脚本 -> 游戏对象 -> 组件 【知识链】Unity -> Unity界面 -> Inspector【摘要】本文介绍如何使用脚本添加、删除组件&#xff0c;以及如何访问组件 文章目录 引言第一章 游戏对象与组件1.1什么是组件&#xff1f;1.2 场景、游戏对象与组…

C++11中的新特性(2)

C11 1 可变参数模板2 emplace_back函数3 lambda表达式3.1 捕捉列表的作用3.2 lambda表达式底层原理 4 包装器5 bind函数的使用 1 可变参数模板 在C11之前&#xff0c;模板利用class关键字定义了几个参数&#xff0c;那么我们在编译推演中&#xff0c;我们就必须传入对应的参数…

Mac安装第三方软件的命令安装方式

场景&#xff1a; 打开终端命令行&#xff0c;sudo xattr -rd com.apple.quarantine&#xff0c;注意最后quarantine 后面加一个空格&#xff01;然后打开Finder&#xff08;访达&#xff09;&#xff0c;点击左侧的 应用程序&#xff0c;找到相关应用&#xff0c;拖进终端qua…

指纹浏览器大全

具体请前往&#xff1a;国内外指纹浏览器大全

vue3组件通信与props

title: vue3组件通信与props date: 2024/5/31 下午9:00:57 updated: 2024/5/31 下午9:00:57 categories: 前端开发 tags: Vue3组件Props详解生命周期数据通信模板语法Composition API单向数据流 Vue 3 组件基础 在 Vue 3 中&#xff0c;组件是构建用户界面的基本单位&#…