深度学习:卷积神经网络CNN

news2024/9/25 2:19:12

目录

一、什么是卷积?

二、卷积神经网络的组成

1. 卷积层

2. 池化层

3. 激活函数

4. 全连接层

三、卷积神经网络的构造

四、代码实现

1.数据预处理

2.创建卷积神经网络

3.创建训练集和测试集函数

4.创建损失函数和优化器并进行训练


一、什么是卷积?

        对图像(不同的数据窗口数据)和卷积核(一组固定的权重:因为每个神经元的多个权重固定,所以又可以看做一个恒定的滤波器filter)做内积(逐个元素相乘再求和)的操作就是所谓的『卷积』操作,也是卷积神经网络的名字来源。

 

二、卷积神经网络的组成

1. 卷积层

  • 功能:通过卷积操作提取特征。卷积核(滤波器)在输入图像上滑动,计算局部区域的加权和,生成特征图
  • 参数:卷积核的大小(如3x3、5x5)、步幅(每次滑动的像素数)和填充(为避免信息损失,通常在图像边缘添加零)。

 

2. 池化层

  • 功能:降低特征图的空间维度,减少计算量和参数数量,防止过拟合
  • 类型
    • 最大池化:在每个窗口中取最大值。
    • 平均池化:在每个窗口中取平均值。
  • 参数:池化窗口的大小和步幅。

 

3. 激活函数

  • 功能:引入非线性,帮助模型捕捉复杂的模式。
  • 常用类型
    • ReLU(修正线性单元):输出为输入的正部分,负部分输出为0。
    • Sigmoid:将输出限制在0到1之间,适用于二分类问题。
    • Softmax:将输出转化为概率分布,适用于多分类问题。

 

4. 全连接层

  • 功能:将卷积层和池化层提取的特征进行整合,用于最终的分类或回归。
  • 结构:每个神经元与前一层的所有神经元相连接。

 

三、卷积神经网络的构造

  • 输入层--卷积层--池化层--全连接层--输出层

 

四、代码实现

1.数据预处理

  • 从本地读取图片数据并打包
  • 将其裁剪成256*256大小并转换成tensor类型数据
  • 将对应图片标签也转换成tensor类型数据
import torch
import numpy as np
from torch.utils.data import DataLoader, Dataset  # 数据包管理工具,打包数据,
from torchvision import transforms
from PIL import Image

class food_dataset(Dataset):
    def __init__(self, file_path, transform=None):  # 类的初始化,解析数据文件txt
        self.file_path = file_path
        self.imgs = []
        self.labels = []
        self.transform = transform
        with open(self.file_path) as f:  # 是把train.txt文件中图片的路径保存在 self.imgs,train.txt文件中标签保存在self.label里
            samples = [x.strip().split(' ') for x in f.readlines()]  # 去掉首尾空格 再按空格分成两个元素
            for img_path, label in samples:
                self.imgs.append(img_path)  # 图像的路径
                self.labels.append(label)  # 标签,还不是tensor

# 初始化:把图片目录加载到self
    def __len__(self):  # 类实例化对象后,可以使用len函数测量对象的个数
        return len(self.imgs)

    def __getitem__(self, idx):  # 关键,可通过索引的形式获取每一个图片数据及标签
        image = Image.open(self.imgs[idx])  # 读取到图片数据,还不是tensor
        if self.transform:
            # 将pil图像数据转换为tensor
            image = self.transform(image)  # 图像处理为256x256,转换为tenor

        label = self.labels[idx]  # label还不是tensor
        label = torch.from_numpy(np.array(label, dtype=np.int64))  # label也转换为tensor
        return image, label

data_transforms = {
    'train':
        transforms.Compose([
            transforms.Resize([256, 256]),
            transforms.ToTensor()
        ]),
    'test':
        transforms.Compose([
            transforms.Resize([256, 256]),
            transforms.ToTensor()
        ])
}

train_data = food_dataset(file_path=r'.\train.txt', transform=data_transforms['train'])   # 64张图片为一个包  训练集60000张图片 打包成了938个包
test_data = food_dataset(file_path=r'.\test.txt', transform=data_transforms['test'])

train_dataloader = DataLoader(train_data, batch_size=64, shuffle=True)
test_dataloader = DataLoader(test_data, batch_size=64, shuffle=True)

for x, y in test_dataloader:
    print(f"shape of x [N ,C,H,W]:{x.shape}")
    print(f"shape of y :{y.shape} {y.dtype}")
    break

 

2.创建卷积神经网络

from torch import nn  # 导入神经网络模块

class CNN(nn.Module):  # Convolutional Neural Network
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Sequential(  # 将多个层组合成一起。
            nn.Conv2d(  # 2d一般用于图像,3d用于视频数据(多一个时间维度),1d一般用于结构化的序列数据
                in_channels=3,  # 图像通道个数,1表示灰度图(确定了卷积核 组中的个数),
                out_channels=16,  # 要得到几多少个特征图,卷积核的个数
                kernel_size=5,  # 卷积核大小,5*5
                stride=1,  # 步长
                padding=2  # 一般希望卷积核处理后的结果大小与处理前的数据大小相同,效果会比较好。那pading改如何设计呢?建议stride为1
            ),
            nn.ReLU(),  # relu层,不会改变特征图的大小
            nn.MaxPool2d(kernel_size=2),  # 进行池化操作(2x2 区域)  最大值池化
        )
        self.conv2 = nn.Sequential(  # 但整个 nn.Sequential 可以视为一个卷积模块
            nn.Conv2d(16, 32, 5, 1, 2),
            nn.ReLU(),
            nn.Conv2d(32, 32, 5, 1, 2),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )
        self.conv3 = nn.Sequential(
            nn.Conv2d(32, 128, 5, 1, 2),
            nn.ReLU()
        )
        self.out = nn.Linear(128 * 64 * 64, 20)  # 全连接层得到的结果

    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = self.conv3(x)
        x = x.view(x.size(0), -1)
        output = self.out(x)
        return output

device = 'cuda' if torch.cuda.is_available() else 'mps' if torch.backends.mps.is_avaibale() else 'cpu'

model = CNN().to(device)  # 把刚刚创建的模型传入到GPU
print(model)

输出:

  • 可以看到该卷积神经网络有三个卷积模块
  • 最后通过全连接层输出预测结果
CNN(
  (conv1): Sequential(
    (0): Conv2d(3, 16, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
    (1): ReLU()
    (2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (conv2): Sequential(
    (0): Conv2d(16, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
    (1): ReLU()
    (2): Conv2d(32, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
    (3): ReLU()
    (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (conv3): Sequential(
    (0): Conv2d(32, 128, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
    (1): ReLU()
  )
  (out): Linear(in_features=524288, out_features=20, bias=True)
)

 

3.创建训练集和测试集函数

def train(dataloader, model, loss_fn, optimizer):
    model.train()  # 告诉模型,我要开始训练,模型中w进行随机化操作,已经更新w.在训练过程中,w会被修改的
    # pytorch提供2种方式来切换训练和测试的模式,分别是:model.train()和 model.eval().
    # 一般用法是: 在训练开始之前写上model.trian(),在测试时写上model.eval().
    batch_size_num = 1
    for x, y in dataloader:  #
        x, y = x.to(device), y.to(device)  # 把训练数据集和标签传入CPU或GPU
        pred = model.forward(x)  # 向前传播
        loss = loss_fn(pred, y)  # 通过交叉熵损失函数计算损失值loss

        optimizer.zero_grad()  # 梯度值清零
        loss.backward()  # 反向传播计算得到每个参数的梯度值w
        optimizer.step()  # 根据梯度更新网络w参数

        loss_value = loss.item()  # 从tensor数据中提取数据出来,tensor获取损失值
        if batch_size_num % 2 == 0:
            print(f"loss:{loss_value:>7f} [number:{batch_size_num}]")
        batch_size_num += 1


def test(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    model.eval()  # 测试,w就不能再更新。
    test_loss, correct = 0, 0
    with torch.no_grad():  # 一个上下文管理器,关闭梯度计算。当你确认不会调用Tensor.backward()的时候。这可以减少计算所占用的消耗
        for x, y in dataloader:
            x, y = x.to(device), y.to(device)
            pred = model.forward(x)
            test_loss += loss_fn(pred, y).item()  # test loss是会自动累加每一个批次的损失值
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()
            a = (pred.argmax(1) == y)  # dim=1表示每一行中的最大值对应的索引号,dim=0表示每一列中的最大值对应的索引号
            b = (pred.argmax(1) == y).type(torch.float)
    test_loss /= num_batches  # 能来衡量模型测试的好坏。
    correct /= size  # 平均的正确率
    print(f"Test result: \n Accuracy: {(100 * correct)}%, Avg loss: {test_loss}")

 

4.创建损失函数和优化器并进行训练

  • 创建处理多分类的损失函数
  • 使用Adam优化器
loss_fn = nn.CrossEntropyLoss()  # 处理多分类
optimizer = torch.optim.Adam(model.parameters(), lr=0.0002)

epochs = 20  # 到底选择多少呢?
for t in range(epochs):
    print(f"Epoch {t + 1}\n--------------")
    train(train_dataloader, model, loss_fn, optimizer)
print("Done!")
test(test_dataloader, model, loss_fn)

输出:

Epoch 20
--------------
loss:0.002920 [number:2]
loss:0.003376 [number:4]
Done!
Test result: 
 Accuracy: 41.02564102564102%, Avg loss: 5.77920389175415

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

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

相关文章

Kivy,一个上天入地的 Python 库

大家好!我是炒青椒不放辣,关注我,收看每期的编程干货。 一个简单的库,也许能够开启我们的智慧之门, 一个普通的方法,也许能在危急时刻挽救我们于水深火热, 一个新颖的思维方式,也许能…

USB 电缆中的信号线 DP、DM 的缩写由来

经常在一些芯片的规格书中看到 USB 的信号对是以 DP 和 DM 命名: 我在想,这些规格书是不是写错了,把 N 写成 M 了?DM 中的 M 到底是什么的缩写? 于是我找了一些资料,终于在《Universal Serial Bus Cables …

string 的介绍及使用

一.string类介绍 C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理&a…

BUUCTF [SCTF2019]电单车详解两种方法(python实现绝对原创)

使用audacity打开,发现是一段PT2242 信号 PT2242信号 有长有短,短的为0,长的为1化出来 这应该是截获电动车钥匙发射出的锁车信号 0 01110100101010100110 0010 0前四位为同步码0 。。。中间这20位为01110100101010100110为地址码0010为功…

ssm病人跟踪治疗信息管理系统

专业团队,咨询就送开题报告,欢迎大家咨询留言 摘 要 病人跟踪治疗信息管理系统采用B/S模式,促进了病人跟踪治疗信息管理系统的安全、快捷、高效的发展。传统的管理模式还处于手工处理阶段,管理效率极低,随着病人的不断…

《SG-Former: Self-guided Transformer with Evolving Token Reallocation》ICCV2023

摘要 SG-Former(Self-guided Transformer)是一种新型的视觉Transformer模型,旨在解决传统Transformer在处理大型特征图时面临的计算成本高的问题。该模型通过一种自适应细粒度的全局自注意力机制,实现了有效的计算成本降低。它利…

VmWare安装虚拟机教程(centos7)

VMWare下载: 下载 VMware Workstation Pro - VMware Customer Connect 安装包:(16的版本)免费!(一个赞就行) 一直点下一步即可,注意修改一下安装位置就好 二、安装虚拟机 安装虚…

鸭脖变“刺客”,啃不起了

撰文|ANGELICA 编辑|ANGELICA 审核|烨 Lydia 声明|图片来源网络。日晞研究所原创文章,如需转载请留言申请开白。 你有多久没吃卤味了? 2020年之后,人们对于几大卤味巨头的关注度正在下降。 …

视频字幕生成:分享6款专业易操作的工具,让创作更简单!

​视频字幕如何添加?日常剪辑Vlog视频时,就需要给视频添加上字幕了。字幕是一个比较重要的元素,它不仅可以帮助听力受损或语言障碍的人士理解内容,还可以让你的视频更加易于理解和吸引观众。 那么如何实现视频字幕生成&#xff0c…

【LLaMa2入门】从零开始训练LLaMa2

目录 1 背景2 搭建环境2.1 硬件配置2.2 搭建虚拟环境2.2.1 创建虚拟环境2.2.2 安装所需的库 3 准备工作3.1 下载GitHub代码3.2 下载模型3.3 数据处理3.3.1 下载数据3.3.2 数据集tokenize预处理 4 训练4.1 修改配置4.2 开始训练4.3 多机多卡训练 5 模型推理5.1 编译5.1.1 安装gc…

ResNet18模型扑克牌图片预测

加入会员社群,免费获取本项目数据集和代码:点击进入>> 1. 项目简介 该项目旨在通过深度学习技术,使用ResNet18模型对扑克牌图像进行预测与分类。扑克牌图片分类任务属于图像识别中的一个应用场景,要求模型能够准确识别扑克…

【python篇】python pickle模块一篇就能明白,快速理解

持久性就是指保持对象,甚至在多次执行同一程序之间也保持对象。通过本文,您会对 Python对象的各种持久性机制(从关系数据库到 Python 的 pickle以及其它机制)有一个总体认识。另外,还会让您更深一步地了解Python 的对象…

音视频入门基础:FLV专题(5)——FFmpeg源码中,判断某文件是否为FLV文件的实现

一、引言 通过FFmpeg命令: ./ffmpeg -i XXX.flv 可以判断出某个文件是否为FLV文件: 所以FFmpeg是怎样判断出某个文件是否为FLV文件呢?它内部其实是通过flv_probe函数来判断的。从《FFmpeg源码:av_probe_input_format3函数和AVI…

Serilog文档翻译系列(五) - 编写日志事件

日志事件通过 Log 静态类或 ILogger 接口上的方法写入接收器。下面的示例将使用 Log 以便语法简洁,但下面显示的方法同样可用于接口。 Log.Warning("Disk quota {Quota} MB exceeded by {User}", quota, user); 通过此日志方法创建的警告事件将具有两个相…

mes系统在中小企业智能制造作用

MES系统(制造执行系统)在中小企业智能制造中扮演着至关重要的角色,其作用主要体现在以下几个方面: 1. 提升生产效率与质量 实时监控与数据采集:MES系统能够实时采集生产现场的各项数据,如设备状态、生产进…

nmap 命令:网络扫描

一、命令简介 ​nmap​(Network Mapper)是一个开放源代码的网络探测和安全审核的工具。它最初由Fyodor Vaskovich开发,用于快速地扫描大型网络,尽管它同样适用于单个主机。 ​nmap​的功能包括: 发现主机上的开放端…

电信、移动、联调等运营商都有那些国产化自研软件

国产化自研软件方面有着积极的探索和实践,包括操作系统、数据库和中间件等,电信运营商在国产化软件方面取得了显著进展: 操作系统: 中国电信推出了基于华为欧拉openEuler开源系统的天翼云操作系统CTyunOS,已上线部署5万…

【2024W38】肖恩技术周刊(第 16 期):白嫖AI的最佳时段

周刊内容: 对一周内阅读的资讯或技术内容精品(个人向)进行总结,分类大致包含“业界资讯”、“技术博客”、“开源项目”和“工具分享”等。为减少阅读负担提高记忆留存率,每类下内容数一般不超过3条。 更新时间: 星期天 历史收录:…

asp.net core日志与异常处理小结

asp.net core的webApplicationBuilder中自带了一个日志组件,无需手动注册服务就能直接在控制器中构造注入,本文主要介绍了net core日志与异常处理小结,需要的朋友可以参考下 ILogger简单使用 asp.net core的webApplicationBuilder中自带了一个日志组件…

Elasticsearch可视化工具ElasticHD

目录 介绍 ElasticHD应用程序页面 安装 基本用法 独立可执行文件 ES版本支持 SQL特性支持: 超越SQL功能支持: SQL的用法 Docker快速入门: 下载地址 介绍 ElasticHD是ElasticSearch可视化管理工具。它不需要任何软件。它在您的Web浏览器中工作,允许您随时随地管理…