从全连接到卷积:为什么 CV 需要卷积层?

📂 所属阶段:第二阶段 — 深度学习视觉基础(CNN 篇)
🔗 相关章节:卷积核、步长与池化 · 经典 CNN 架构剖析


1. 全连接层的问题

"""
全连接层(Fully Connected):
  每个输入连接到每个输出

问题:
  100×100 图像 = 10000 像素
  → 全连接到 1000 个神经元 = 1000 万参数
  → 计算量巨大,容易过拟合
"""

import torch
import torch.nn as nn

# 全连接网络
fc_net = nn.Sequential(
    nn.Flatten(),
    nn.Linear(10000, 1000),  # 1000 万参数!
    nn.ReLU(),
    nn.Linear(1000, 10),
)

# 输入:100×100 图像
x = torch.randn(1, 1, 100, 100)
output = fc_net(x)

2. 卷积层的优势

"""
卷积层(Convolutional Layer):
  用小卷积核(如 3×3)扫描整个图像
  
优势:
  1. 参数共享:同一个卷积核用于整个图像
  2. 局部连接:只关注局部特征
  3. 平移不变性:卷积核对平移敏感度低
"""

import torch
import torch.nn as nn

# 卷积网络
cnn = nn.Sequential(
    nn.Conv2d(1, 32, kernel_size=3, padding=1),  # 只有 32×3×3 = 288 参数
    nn.ReLU(),
    nn.MaxPool2d(2),
    nn.Conv2d(32, 64, kernel_size=3, padding=1),
    nn.ReLU(),
    nn.MaxPool2d(2),
    nn.Flatten(),
    nn.Linear(64 * 25 * 25, 10),
)

# 输入:100×100 图像
x = torch.randn(1, 1, 100, 100)
output = cnn(x)
print(f"参数量:{sum(p.numel() for p in cnn.parameters())}")  # 远小于全连接

3. 卷积的数学原理

"""
卷积操作:

输入:I(图像)
卷积核:K(小矩阵)
输出:O = I * K

计算方式:
  O[i,j] = Σ Σ I[i+m, j+n] × K[m, n]
"""

import numpy as np
from scipy import signal

# 简单的卷积例子
image = np.array([[1, 2, 3],
                  [4, 5, 6],
                  [7, 8, 9]], dtype=float)

kernel = np.array([[1, 0, -1],
                   [2, 0, -2],
                   [1, 0, -1]], dtype=float)

# 卷积
output = signal.convolve2d(image, kernel, mode='same')
print(output)

4. 小结

全连接 vs 卷积:

全连接:
  - 参数多(10000 → 1000 = 1000 万)
  - 计算慢
  - 容易过拟合

卷积:
  - 参数少(3×3 卷积核 = 9 参数)
  - 计算快
  - 参数共享,泛化性好
  - 对平移、旋转有一定鲁棒性

结论:CV 必须用卷积!

💡 记住:卷积的核心是"参数共享"和"局部连接",这两个特性使得 CNN 能高效处理图像。


🔗 扩展阅读