目录

卷积神经网络(CNN)详解

一、概述

二、CNN 与传统神经网络的区别

三、CNN 的核心组成部分

1. 卷积层(Convolutional Layer)

1.1 卷积操作的定义

1.2 特征图(Feature Map)

1.3 超参数

2. 非线性激活函数(Activation Function)

3. 池化层(Pooling Layer)

4. 扁平化层(Flatten Layer)

📐 举例说明

5. 全连接层(Fully Connected Layer)

🧮 数学原理

🧠 为什么 CNN 要加全连接层?

📐 举例说明

6. 输出层(Output Layer)

四、CNN 的典型结构

五、CNN 的参数计算

1. 卷积输出尺寸公式:

六、CNN 的训练过程

七、经典 CNN 架构

八、CNN示例

 八、CNN 的优势

九、典型应用场景

十、小结


卷积神经网络(CNN)详解

一、概述

        卷积神经网络(Convolutional Neural Network, CNN)是一种深度学习中的前馈神经网络,特别适合用于图像、语音、文本等具有局部结构特征的数据。CNN 是受生物学中视觉皮层结构启发而设计的,能够自动提取输入数据的空间和局部相关性,是目前计算机视觉中最重要和广泛使用的模型之一。


二、CNN 与传统神经网络的区别

传统的全连接神经网络(Fully Connected Neural Network, FCNN)存在以下问题:

  1. 参数过多:例如一张 224×224 像素的RGB图像,有 224×224×3 = 150,528 个输入节点(乘以3是因为RGB有三个通道)。

  2. 无法捕捉局部结构:FCNN 每个神经元与前一层的所有节点相连,忽略了像素间的空间关系。

  3. 容易过拟合:大规模参数量导致学习泛化能力差

        而 CNN 通过使用局部连接(local connectivity)和共享权重(weight sharing)等设计思想,有效地克服了上述问题。


三、CNN 的核心组成部分

1. 卷积层(Convolutional Layer)

目的:提取图像中的局部特征,如边缘、角点、纹理等。

1.1 卷积操作的定义

        在数学上,卷积操作(convolution)是一个积分变换,但在深度学习中,我们通常使用其离散形式:

S(i, j) = (I * K)(i, j) = \sum_m \sum_n I(i+m, j+n) \cdot K(m,n)

其中:

  • I 表示输入图像

  • K 表示卷积核(或称滤波器)

  • * 表示卷积操作

  • S(i, j) 为输出特征图(feature map)上的值

1.2 特征图(Feature Map)

        每一个卷积核在输入图像上滑动并与局部区域计算加权和,生成一个新的二维矩阵,称为特征图,反映了该卷积核对某一特定特征(如边缘)的响应程度。

1.3 超参数
  • 卷积核大小(Kernel Size):如 3×3, 5×5(注意:这里需要为奇数)

  • 步幅(Stride):卷积核每次滑动的距离,决定输出尺寸。

  • 填充(Padding):是否在输入图像边缘补零,以保持输出尺寸与输入一致。


2. 非线性激活函数(Activation Function)

目的:引入非线性因素,使网络具有更强的表达能力。

常用的激活函数:

  • ReLU(Rectified Linear Unit):f(x) = \max(0, x)

  • Leaky ReLU、ELU、Sigmoid、Tanh 等

ReLU 是最常用的,因为计算简单梯度传播稳定


3. 池化层(Pooling Layer)

目的压缩特征图的空间尺寸降低计算量过拟合风险,同时保留主要特征

常见的池化方式:

  • 最大池化(Max Pooling):取局部区域中的最大值

  • 平均池化(Average Pooling):取局部区域的平均值

超参数包括:

  • 池化窗口大小(如 2×2)

  • 步幅(通常等于窗口大小)


4. 扁平化层(Flatten Layer)

        扁平化层(Flatten Layer)的主要作用是将多维的张量(tensor)数据展开成一维向量,以便能够连接到后续的全连接层中。

  • 卷积层和池化层输出的是二维或三维的特征图,例如:(Channels, Height, Width)

  • 全连接层期望输入的是一维向量

因此,扁平化层起到了一个 “维度转换”的桥梁作用

📐 举例说明

假设某卷积神经网络中,最后一层卷积后得到的特征图维度是:

\text{Shape} = (C, H, W) = (64, 7, 7)

那么扁平化后变为一维向量:

\text{Flattened Vector Length} = 64 \times 7 \times 7 = 3136

此时,输出形状为:

\text{Shape} = (1, 3136)

这就是全连接层所需的输入格式。


5. 全连接层(Fully Connected Layer)

        全连接层(FC Layer),也称为密集层(Dense Layer),是传统神经网络中的核心组成部分。

在 CNN 中,它主要出现在模型的尾部,用于:

  • 综合前面层提取到的局部特征

  • 实现最终的决策(例如分类)

全连接层中的每个神经元都与上一层所有的输出单元相连接,使其具有全局信息整合能力


🧮 数学原理

设:

  • 输入向量为 \mathbf{x} = [x_1, x_2, \dots, x_n]

  • 权重矩阵为 \mathbf{W} \in {R}^{m \times n}

  • 偏置向量为 \mathbf{b} \in {R}^{m}

则输出向量 \mathbf{y} 为:

\mathbf{y} = \mathbf{W} \cdot \mathbf{x} + \mathbf{b}

每个输出神经元都可以表示为:

y_i = \sum_{j=1}^{n} w_{ij} x_j + b_i

随后通常会接一个激活函数(如 ReLU、Softmax)。


🧠 为什么 CNN 要加全连接层?
  1. CNN 前几层负责提取局部特征(边缘、形状、纹理、物体局部结构)

  2. 全连接层将这些特征整合为全局信息,用于最终分类或预测任务

可以把 CNN 卷积部分当作自动特征提取器,而全连接层则像是一个分类器


📐 举例说明

继续刚才的例子:

  • Flatten 后是一个大小为 3136 的向量

  • 接一个全连接层输出大小为 128

则这一层有:

参数量=3136×128+128=401,536

其中包含了:

  • 权重:3136×128 = 401,408

  • 偏置:128

接着可以继续连接一个分类层,例如输出为10类:

nn.Linear(128, 10)

6. 输出层(Output Layer)

对于分类任务:

  • 通常使用 Softmax 函数:

\text{Softmax}(z_i) = \frac{e^{z_i}}{\sum_{j=1}^{K} e^{z_j}}

输出为每个类别的概率分布。


四、CNN 的典型结构

一个典型的 CNN 网络结构如下所示:

输入图像 → 卷积层 → ReLU → 池化层 
→ 卷积层 → ReLU → 池化层 → Flatten → 全连接层 → Softmax 输出


五、CNN 的参数计算

1. 卷积输出尺寸公式:

设输入尺寸为 H_{in} \times W_{in}​,卷积核大小为K \times K,步幅为 S,填充为 P,输出尺寸为 H_{out} \times W_{out}

H_{out} = \left\lfloor \frac{H_{in} - K + 2P}{S} \right\rfloor + 1

W_{out} = \left\lfloor \frac{W_{in} - K + 2P}{S} \right\rfloor + 1


六、CNN 的训练过程

  1. 前向传播(Forward Propagation):计算网络输出。

  2. 损失函数计算:衡量预测与实际标签的差异(如交叉熵损失)。

  3. 反向传播(Backpropagation):使用链式法则计算梯度。

  4. 参数更新:使用优化器(如 SGD, Adam)更新权重和偏置。


七、经典 CNN 架构

以下是一些具有代表性的 CNN 模型:

模型名称 特点
LeNet-5 最早的CNN之一,用于手写数字识别
AlexNet 2012年ImageNet冠军,使用ReLU和Dropout
VGGNet 使用大量的3×3卷积核堆叠
GoogLeNet 引入Inception模块,结构更深但计算高效
ResNet 引入残差连接,解决深层网络的退化问题

八、CNN示例

        使用 Python + PyTorch 实现的经典 CNN 模型(LeNet-5)代码,这个网络是最早被广泛使用的卷积神经网络之一,用于手写数字识别(如 MNIST 数据集)

import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import datasets, transforms
from torch.utils.data import DataLoader


# ✅ 1. 定义 LeNet-5 网络结构
class LeNet5(nn.Module):
    def __init__(self):
        super(LeNet5, self).__init__()
        # 输入:1x28x28
        self.conv1 = nn.Conv2d(1, 6, kernel_size=5, padding=2)  # 输出:6x28x28
        self.pool1 = nn.AvgPool2d(2, stride=2)  # 输出:6x14x14
        self.conv2 = nn.Conv2d(6, 16, kernel_size=5)  # 输出:16x10x10
        self.pool2 = nn.AvgPool2d(2, stride=2)  # 输出:16x5x5

        self.fc1 = nn.Linear(16 * 5 * 5, 120)  # 展平后输入
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)  # 最终10类输出

    def forward(self, x):
        x = F.relu(self.conv1(x))  # C1
        x = self.pool1(x)  # S2
        x = F.relu(self.conv2(x))  # C3
        x = self.pool2(x)  # S4
        x = x.view(-1, 16 * 5 * 5)  # 展平
        x = F.relu(self.fc1(x))  # 全连接1
        x = F.relu(self.fc2(x))  # 全连接2
        x = self.fc3(x)  # 输出层(无激活,交给Loss)
        return x

# ✅ 2. 准备数据(MNIST)
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,))  # MNIST 均值和标准差
])

train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_dataset  = datasets.MNIST(root='./data', train=False, transform=transform)

train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader  = DataLoader(test_dataset, batch_size=1000)

# ✅ 3. 模型初始化与优化器
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = LeNet5().to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()

# ✅ 4. 训练函数
def train(model, loader, optimizer, criterion, epoch):
    model.train()
    total_loss = 0
    for batch_idx, (data, target) in enumerate(loader):
        data, target = data.to(device), target.to(device)
        optimizer.zero_grad()
        output = model(data)                 # 前向传播
        loss = criterion(output, target)     # 计算损失
        loss.backward()                      # 反向传播
        optimizer.step()                     # 更新参数
        total_loss += loss.item()
    print(f"Epoch {epoch}, Loss: {total_loss:.4f}")

# ✅ 5. 测试函数
def test(model, loader):
    model.eval()
    correct = 0
    total = 0
    with torch.no_grad():  # 关闭梯度计算
        for data, target in loader:
            data, target = data.to(device), target.to(device)
            output = model(data)
            pred = output.argmax(dim=1)
            correct += (pred == target).sum().item()
            total += target.size(0)
    acc = 100. * correct / total
    print(f"Test Accuracy: {acc:.2f}%")

# ✅ 6. 开始训练
for epoch in range(1, 6):  # 训练5轮
    train(model, train_loader, optimizer, criterion, epoch)
    test(model, test_loader)

Epoch 1, Loss: 267.0351
Test Accuracy: 97.25%
Epoch 2, Loss: 79.5980
Test Accuracy: 98.07%
Epoch 3, Loss: 56.7498
Test Accuracy: 98.29%
Epoch 4, Loss: 45.3591
Test Accuracy: 98.47%
Epoch 5, Loss: 36.6190
Test Accuracy: 98.83%


 八、CNN 的优势

  • 自动提取特征,减少人工特征工程

  • 局部感知、参数共享,显著降低模型复杂度

  • 强大的图像识别、检测、分割能力


九、典型应用场景

  • 图像分类(Image Classification)

  • 目标检测(Object Detection)

  • 图像分割(Image Segmentation)

  • 面部识别(Face Recognition)

  • 医学图像分析(Medical Imaging)

  • 视频分析(Video Surveillance)


十、小结

        卷积神经网络通过模仿人类视觉系统的结构,有效提取图像的局部特征,逐层构建抽象表示,是目前图像识别、语音识别等任务中不可或缺的模型。掌握其原理和结构,对于深入学习深度学习具有重要意义。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐