卷积神经网络CNN

ps:最快速度了解一下下,当扩充了

对比维度 全连接神经网络(普通神经网络) 卷积神经网络(CNN)
网络结构 输入层→全连接层→全连接层→输出层仅包含全连接层 输入层→卷积层→池化层→卷积层→池化层→全连接层→输出层新增卷积层、池化层
连接方式 全局连接:每个神经元与上一层所有神经元相连 局部连接 + 滑动窗口:仅连接相邻的局部数据,卷积核滑动遍历
参数数量 参数量极大,容易参数爆炸、过拟合、训练慢 参数共享,参数量极少,训练快、不易过拟合
特征提取 无法自动提取特征,必须人工定义规则(如:心率 > 100 为异常) 自动分层提取特征:小波动→组合模式→整体波形
对顺序 / 位置的敏感度 完全不敏感,打乱数据结果不变 高度敏感,尊重时序 / 空间结构,具备平移不变性
适合的数据类型 表格数据、低维无顺序数据 图像、语音、心率时序、波形等有结构 / 顺序的数据
心率检测适用场景 简单统计判断(平均心率超标) 专业波形识别(早搏、陡升、心律失常等形态异常)

图像知识

  1. 知道图像的基本概念
  1. 掌握使用matplotlib加载图片方法

Plt.imread()

Plt.imshow()

  • 640(高):图片的纵向像素数量
  • 640(宽):图片的横向像素数量
  • 3(通道):RGB 三通道彩色图像

CNN

层级 核心作用 通俗理解 能干什么 核心特点 形象比喻
卷积层 自动提取图像 / 时序数据特征 拿一个小窗口,在整张图上慢慢滑动扫描 找边缘、找纹理、找形状、找波形尖峰 / 波动 局部连接、参数共享、自动学特征,不用人工写规则 专门看细节、找轮廓的眼睛
池化层 压缩数据、降维、保留关键特征 把卷积层扫完的大图,缩成小图,只留重点,去掉冗余 缩小图片尺寸、减少参数量、防止过拟合、保留主要特征 只保留区域最大值 / 平均值,不学习参数、简化数据 给图片缩大小、提纯关键信息,删多余细节

全连接层用来输出想要的结果。

卷积层

学习要点 核心概念 主要作用
1. 卷积层计算过程 卷积核(小矩阵) 在输入图像上按步长滑动,逐个局部区域做加权求和,叠加偏置,得到新数据。 从原始图像中自动提取边缘、纹理、轮廓、细节等浅层、深层特征。

Pytorch API

  • nn.Conv2d :PyTorch 中专门用于构建二维卷积层的工具
  • 负责自动提取图像特征(边缘、纹理、形状、轮廓)
  • 通过调整 5 个参数,自由控制特征种类、特征图大小、扫描范围
  • 是搭建卷积神经网络(CNN)最核心的基础模块
阶段 数据 形状 / 类型 作用
原始输入 data/img.jpg 图像文件 读取后是 numpy 数组,形状 (640, 640, 3) 原始彩色图像,高 640、宽 640、RGB 三通道
第一步处理后 img = torch.tensor(img).permute(2, 0, 1) torch.Tensor,形状 (3, 640, 640) 把通道维度从最后移到最前面,适配 PyTorch 的通道优先格式
第二步处理后 img = img.unsqueeze(0) torch.Tensor,形状 (1, 3, 640, 640) 增加一个batch维度,变成批量大小为 1 的张量
卷积层最终输入 img.to(torch.float32) torch.float32 张量,形状 (1, 3, 640, 640) 送入 nn.Conv2d 的最终数据,符合 PyTorch 输入格式:(批量数, 通道数, 高度, 宽度)
维度顺序 数值 含义 通俗解释
第 1 维:N(Batch Size) 1 批量大小 表示一次输入模型的样本数量,这里就是「1 张图片」
第 2 维:C(Channels) 3 通道数 表示数据的特征通道,这里是「RGB 三通道彩色图」(红、绿、蓝各一个通道)
第 3 维:H(Height) 640 图像高度 图片纵向有 640 个像素
第 4 维:W(Width) 640 图像宽度 图片横向有 640 个像素

torch.Size([1, 3, 319, 319])

项目 内容
代码作用 打印 卷积后输出的特征图形状
输出格式 一定会输出 4 个数字
4 个数字依次代表 [几张图,输出通道数,高度,宽度]
通俗理解 告诉你:卷积处理完后,得到了多大的特征图
核心意义 查看数据尺寸是否正确,避免网络报错

池化层

  1. 掌握池化层计算过程

池化层 (Pooling) 降低维度, 从而减少计算量、减少内存消耗,并提高模型的鲁棒性

  1. 掌握PyTorch池化层API

池化层通常位于卷积层之后,它通过对卷积层输出的特征图进行下采样,保留最重要的特征信息,同时丢弃一些不重

要的细节

PyTorch 池化 API

最大池化

nn.MaxPool2d(kernel_size=2, stride=2, padding=1)

平均池化

nn.AvgPool2d(kernel_size=2, stride=1, padding=0)

图像分类案例 自写

  1. 了解CIFAR10数据集 2. 掌握分类网络搭建 3. 掌握模型构建流程
  1. 了解 CIFAR10 数据集

  2. 搭建卷积神经网络

  3. 编写训练函数

  4. 编写预测函数

导入一下工具包

数据集介绍

一句话:它是计算机视觉里,专门用来训练和测试图像分类模型的「公开标准图片数据集」,相当于给 AI 做 "看图认东西" 练习题的题库。

项目 具体内容 通俗理解
本质 大量标注好的图片集合 给 AI 做 "看图认类别" 的练习题库
规模 6 万张图片(5 万训练 + 1 万测试) 训练用 5 万张题,考试用 1 万张题
类别 10 个固定类别 飞机、汽车、鸟、猫、鹿、狗、青蛙、马、船、卡车
图像大小 32×32×3(像素) 很小的彩色图,比手机头像还小,方便快速训练
作用 训练、测试图像分类模型 新手入门 CNN 最常用的 "练手数据集"

PyTorch 中的 torchvision.datasets 计算机视觉模块封装了 CIFAR10 数据集, 使用方法如下

python 复制代码
# 导入需要的库
import torchvision
from torchvision.datasets import CIFAR10
from torchvision.transforms import ToTensor
import matplotlib.pyplot as plt

# 定义函数:创建并返回CIFAR10训练集和测试集
def create_dataset():
    """
    功能:加载CIFAR10数据集
    返回:训练集train、测试集valid
    """
    # 1. 加载训练集数据
    # root='data':数据集下载后存放在当前目录的data文件夹下
    # train=True:表示加载训练集
    # transform=ToTensor():
    #   - 把PIL.Image格式的图片,转换成PyTorch能处理的Tensor张量
    #   - 同时自动把像素值从0~255归一化到[0.0, 1.0],方便模型计算
    train = CIFAR10(
        root='data', 
        train=True, 
        transform=ToTensor(),
        download=True  # 自动下载数据集(第一次运行需要)
    )

    # 2. 加载测试集数据
    # train=False:表示加载测试集
    valid = CIFAR10(
        root='data', 
        train=False, 
        transform=ToTensor(),
        download=True
    )

    # 把训练集和测试集返回给调用这个函数的地方
    return train, valid


# 主程序入口:当你直接运行这个文件时,下面的代码会执行
if __name__ == '__main__':
    # 调用上面定义的create_dataset函数,拿到训练集和测试集
    train_dataset, valid_dataset = create_dataset()

    # 打印数据集的类别映射:比如'airplane'对应数字0,'car'对应数字1
    print("数据集类别:", train_dataset.class_to_idx)

    # 打印训练集数据的形状:(50000, 32, 32, 3)
    # 含义:50000张图片,每张图片是32×32像素,3个RGB通道
    print("训练集数据集:", train_dataset.data.shape)

    # 打印测试集数据的形状:(10000, 32, 32, 3)
    print("测试集数据集:", valid_dataset.data.shape)

    # 用matplotlib展示一张训练集里的图片
    plt.figure(figsize=(2, 2))  # 创建一个2×2大小的画布
    plt.imshow(train_dataset.data[1])  # 展示训练集里第2张图片(索引从0开始)
    plt.title(train_dataset.targets[1])  # 把这张图片的标签(数字类别)设为标题
    plt.show()  # 显示图片窗口
  • 自动下载 CIFAR10 数据集到./data文件夹
  • 控制台打印出:
    • 10 个类别的名称和对应数字
    • 训练集、测试集的图片数量和尺寸
  • 弹出一个窗口,显示训练集里的第 2 张图片,标题是它的类别数字
流程
python 复制代码
自己的图片(JPG/PNG 照片)
    ↓
【图片预处理】
  统一尺寸 → 缩放到固定大小(如 32×32 / 224×224)
  统一通道 → 转为 RGB 三通道彩色图
  像素归一化 → 把 0~255 缩成 0~1 或 -1~1,方便模型计算
    ↓
【转为数字矩阵】
  像素 → 张量 Tensor
  维度调整为模型标准格式:(批量数, 通道数, 高度, 宽度)
    ↓
【输入层】
  接收标准化后的数字张量
  不做计算,只负责传递数据
    ↓
===============================
【前向传播开始】
概念:数据从输入层开始,依次经过卷积、激活、池化、全连接
      按固定网络层级单向流动,逐层计算特征,最终输出预测结果
===============================
    ↓
【第一层卷积层】
  卷积核滑动扫描图片
  提取浅层特征:边缘、线条、基础纹理
  输出多张特征图
    ↓
【激活函数 ReLU】
  加入非线性能力
  让网络能学习复杂特征(必须加!)
    ↓
【第一层池化层】
  缩小特征图尺寸(宽高减半)
  保留关键信息,降低计算量
    ↓
【第二层卷积层】
  继续扫描特征图
  提取中层特征:局部形状、部件轮廓
    ↓
【激活函数 ReLU】
  再次增强非线性学习能力
    ↓
【第二层池化层】
  再次压缩尺寸
  进一步提炼关键特征
    ↓
(可重复 N 轮:卷积 → ReLU → 池化)
  提取高层抽象特征:整体轮廓、物体结构、语义信息
    ↓
【展平层 Flatten】
  把多维特征图拉直成一维长向量
  适配全连接层输入格式
    ↓
【全连接层】
  对所有特征进行加权融合
  建立特征与类别之间的联系
    ↓
【激活函数 ReLU】
  增强分类判断的表达能力
    ↓
【输出层】
  输出每个类别的原始预测分数
===============================
【前向传播结束】
概念:完成一次从原图到预测分值的完整推理,只做正向计算,不更新参数
===============================
    ↓
【Softmax 函数】
  把分数转为概率(总和=1)
  概率最高 = 模型判断的类别
    ↓
【损失函数】
  计算预测结果与真实标签的误差
  衡量前向传播预测的对错程度
    ↓
【反向传播】
概念:根据损失误差,从后往前逐层求导,传回每一层
    ↓
【优化器】
  根据反向传播传回的误差,自动更新卷积核、全连接层参数
  让模型下一次前向传播预测更准确
  • 前向传播 输入数据按网络结构从上到下依次经过各层,逐层计算特征,最后输出预测结果;只做正向计算,不修改网络参数。

  • 反向传播 根据损失函数的误差,从后往前倒着传回误差,配合优化器更新权重参数,用来训练模型、降低误差。

搭建图像分类网络

我们要搭建的网络结构如下:

  1. 输入形状: 32x32

  2. 第一个卷积层输入 3 个 Channel, 输出 6 个 Channel, Kernel Size 为: 3x3

  3. 第一个池化层输入 30x30, 输出 15x15, Kernel Size 为: 2x2, Stride 为: 2

  4. 第二个卷积层输入 6 个 Channel, 输出 16 个 Channel, Kernel Size 为 3x3

  5. 第二个池化层输入 13x13, 输出 6x6, Kernel Size 为: 2x2, Stride 为: 2

  6. 第一个全连接层输入 576 维, 输出 120 维

  7. 第二个全连接层输入 120 维, 输出 84 维

  8. 最后的输出层输入 84 维, 输出 10 维

我们在每个卷积计算之后应用 relu 激活函数来给网络增加非线性因素

构建网络代码实现如下

python 复制代码
# 导入 PyTorch 神经网络工具箱
import torch
import torch.nn as nn

# ====================== 1. 模型构建 ======================
# 定义一个类,专门用来搭建图像分类模型(固定写法)
# nn.Module 是所有神经网络的父类,必须继承
class ImageClassification(nn.Module):

    # ====================== 2. 定义网络结构 ======================
    # __init__:初始化函数,用来定义所有层(卷积、池化、全连接)
    def __init__(self):
        # 固定写法:调用父类初始化
        super(ImageClassification, self).__init__()

        # -------------------- 第一组卷积 + 池化 --------------------
        # 卷积层1:输入3通道,输出6通道,卷积核3×3,步长1
        # 作用:提取图片的边缘、线条、纹理
        self.conv1 = nn.Conv2d(3, 6, stride=1, kernel_size=3)
        
        # 最大池化层1:窗口2×2,步长2
        # 作用:把特征图宽高缩小一半,保留关键信息
        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)

        # -------------------- 第二组卷积 + 池化 --------------------
        # 卷积层2:输入6通道,输出16通道,卷积核3×3,步长1
        # 作用:提取更复杂的特征(形状、局部结构)
        self.conv2 = nn.Conv2d(6, 16, stride=1, kernel_size=3)
        
        # 最大池化层2
        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)

        # -------------------- 全连接层 --------------------
        # 全连接层1:输入576维,输出120维
        self.linear1 = nn.Linear(576, 120)
        
        # 全连接层2:输入120维,输出84维
        self.linear2 = nn.Linear(120, 84)
        
        # 输出层:输入84维,输出10类(对应CIFAR10的10个分类)
        self.out = nn.Linear(84, 10)

    # ====================== 3. 定义前向传播(数据怎么走) ======================
    # forward:数据流向,决定图片怎么一步步变成结果
    def forward(self, x):
        # x 就是输入的图片张量

        # 第一步:卷积1 → 激活ReLU → 池化1
        x = torch.relu(self.conv1(x))
        x = self.pool1(x)

        # 第二步:卷积2 → 激活ReLU → 池化2
        x = torch.relu(self.conv2(x))
        x = self.pool2(x)

        # 第三步:展平(把二维特征图拉成一维向量)
        # 作用:为了能输入到全连接层
        x = x.reshape(x.size(0), -1)

        # 第四步:全连接层 + ReLU激活
        x = torch.relu(self.linear1(x))
        x = torch.relu(self.linear2(x))

        # 第五步:输出最终结果(10个类别的分数)
        return self.out(x)
  • conv1/conv2 = 提取特征
  • pool1/pool2 = 缩小图片
  • relu = 让网络变聪明,学复杂特征
  • linear = 做分类判断
  • forward = 规定数据怎么走

输入 → conv1 → ReLU → pool1 → conv2 → ReLU → pool2 → 展平 → linear → 输出

python 复制代码
→ conv1 卷积层(提取浅层纹理边缘特征)
→ ReLU 激活函数(引入非线性、学复杂特征)
→ pool1 池化层(下采样缩尺寸、保留关键特征)
→ conv2 卷积层(提取中层形状结构特征)
→ ReLU 激活函数(增强非线性表达)
→ pool2 池化层(二次下采样、精简降维)
→ 展平层(多维特征转一维向量)
→ 全连接层(特征融合、关联类别)
→ 输出层(输出分类预测分值)
  • 前向传播 输入数据按网络结构从上到下依次经过各层,逐层计算特征,最后输出预测结果;只做正向计算,不修改网络参数。

  • 反向传播 根据损失函数的误差,从后往前倒着传回误差,配合优化器更新权重参数,用来训练模型、降低误差。

  • 第一行 = 创建模型
  • 第二行 = 查看模型长什么样、每层输出多大、有多少参数
层名 输出形状 含义(大白话)
Conv2d-1 [1, 6, 30, 30] 输入 1 张 3 通道 32×32 的图,卷积后变成 1 张 6 通道、30×30 的特征图,提取了边缘 / 纹理特征
MaxPool2d-2 [1, 6, 15, 15] 池化后,特征图宽高减半,变成 1 张 6 通道、15×15 的特征图,无参数
Conv2d-3 [1, 16, 13, 13] 第二次卷积后,变成 1 张 16 通道、13×13 的特征图,提取更复杂的形状特征
MaxPool2d-4 [1, 16, 6, 6] 第二次池化后,宽高再次减半,变成 1 张 16 通道、6×6 的特征图,无参数
Linear-5 [1, 120] 展平后进入全连接层,输出 120 维特征向量
Linear-6 [1, 84] 第二层全连接,输出 84 维特征向量
Linear-7 [1, 10] 输出层,输出 10 个类别的预测分数(对应 CIFAR10 的 10 个类别)
编写训练函数

在训练时,使用多分类交叉熵损失函数,Adam 优化器. 具体实现代码如下

python 复制代码
# ====================== 训练函数 ======================
# 功能:把模型喂给数据,让它学习、变聪明
# model:你的CNN网络
# train_dataset:训练用的图片数据集
def train(model, train_dataset):

    # 1. 定义损失函数(CrossEntropyLoss 交叉熵)
    # 作用:计算模型预测错了多少,误差有多大
    criterion = nn.CrossEntropyLoss()

    # 2. 定义优化器(Adam)
    # 作用:根据误差,自动调整模型参数,让模型越练越准
    # lr=1e-3:学习率,控制每次调整的步子大小
    optimizer = optim.Adam(model.parameters(), lr=1e-3)

    # 3. 训练总轮数:把全部数据看 100 遍
    epoch = 100

    # 开始循环训练
    for epoch_idx in range(epoch):

        # 构建数据加载器
        # 作用:把数据集打包,一批一批喂给模型
        dataloader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True)

        sam_num = 0          # 记录已经训练了多少张图片
        total_loss = 0.0     # 记录这一轮总的误差值
        start = time.time()  # 记录开始时间,算跑多久

        # ====================== 核心训练循环 ======================
        # 把数据集里的图片,一张一张喂给模型
        for x, y in dataloader:
            # x = 图片数据(张量)
            # y = 图片真实标签(猫/狗/车...)

            # 【前向传播】
            # 把图片输入模型,得到预测结果
            output = model(x)

            # 【计算损失】
            # 对比预测结果和真实答案,算误差
            loss = criterion(output, y)

            # 【反向传播三部曲】
            optimizer.zero_grad()   # 清空上一次的梯度(必须清!)
            loss.backward()         # 反向传播,计算梯度(误差往回传)
            optimizer.step()        # 更新模型参数(改错)

            # 统计这一轮的总损失
            total_loss += loss.item() * len(y)
            sam_num += len(y)

        # 打印这一轮的训练结果
        print('epoch:%2s loss:%.5f time:%.2fs' %(epoch_idx + 1, total_loss / sam_num, time.time() - start))

    # 训练全部结束后,保存训练好的模型参数到文件
    torch.save(model.state_dict(), 'model/image_classification.pth')
  • 准备工具 :准备好损失函数 (算对错)、优化器(改错)
  • 循环 100 轮:把所有图片给模型看 100 遍
  • 逐批训练
    • 图片输入模型 → 前向传播 → 出预测结果
    • 损失(错多少)
    • 反向传播(把误差传回每一层)
    • 优化器更新参数(模型改错)
  • 打印进度:每轮显示当前误差、耗时
  • 保存模型:训练完,把训练好的模型存成文件

输入图片 ↓(前向传播) 卷积→激活→池化→卷积→激活→池化→展平→全连接→输出 ↓ 损失函数(算误差) ↓(反向传播) 优化器(更新参数)

输出名词 意思(人话) 代表什么
epoch: 1 第 1 轮训练 模型把所有图片完整看了一遍
loss:1.59926 误差值 数字越小 = 模型越准
acc:0.41 准确率 模型答对了 41% 的题目
time:28.97s 耗时 这一轮花了 29 秒
编写预测函数
总结

掌握模型构建流程

加载数据集

模型构建

模型训练

模型测试

从程序的运行结果来看,网络模型在测试集上的准确率

并不高。我们可以从以下几个方面来进行优化:

  1. 增加卷积核输出通道数

  2. 增加全连接层的参数量

  3. 调整学习率

  4. 调整优化方法

  5. 修改激活函数

  6. 等等...

相关推荐
Soari1 小时前
字节跳动重磅开源:UI-TARS-desktop 深度拆解,构建跨平台的“全自动”多模态 AI Agent
人工智能·ui
QYR-分析1 小时前
压力电气转换器行业市场现状与发展前景分析
大数据·人工智能
deephub2 小时前
2026 RAG 选型指南:Vector、Graph、Vectorless 该怎么挑
人工智能·python·大语言模型·rag
ECT-OS-JiuHuaShan2 小时前
彻底定理化:从量子纠缠到量子代谢
数据库·人工智能·学习·算法·生活·量子计算
八月瓜科技2 小时前
用AI来省电?iOS26.5正式版全球推送:信号弱网双提升,AI省电模式上新
数据库·人工智能·科技·深度学习·机器人
人机与认知实验室2 小时前
人机协同的命门:权限与信任
大数据·人工智能
视觉&物联智能2 小时前
【杂谈】-当人工智能能力增速凌驾于安全管控模型之上
人工智能·安全·ai·chatgpt·agi·deepseek
AiTop1002 小时前
Claude Code 推出 Agent View:命令行编程正式进入“多线程并发“时代
开发语言·人工智能·ai·aigc