4.4 神经网络与 CNN
打开深度学习的大门
在前面的章节中,我们看到传统的计算机视觉方法在现实世界中常常会失败。它们的成功通常依赖于场景符合特定模式或一组假设,例如稳定的光照、干净的背景、固定的视角或可预测的物体形状。一旦这些条件发生变化,性能可能会迅速下降。然而,深度学习采取了一种非常不同的方法。它不再主要依赖人工设计的规则,而是直接从大量数据中学习有用的视觉模式。这使它能够处理外观、背景、尺度、光照和姿态上更大的变化。因此,深度学习使计算机视觉在真实世界应用中变得更加鲁棒和实用。
从规则到学习到的表示
在经典视觉中,我们显式地编写规则:
- 模糊图像
- 找到边缘
- 提取轮廓
而在神经网络中,我们让模型从样例中学习有用的模式。
这是关键的概念转变:系统学习表示,而不是仅仅依赖人工设计的特征。
什么是神经网络

神经网络是由若干层组成的函数,这些层逐步对输入数据进行变换。
每一层都会学习参数。在训练期间,会调整这些参数,使网络的输出对该任务更加有用。
神经网络在代码中是什么样子?
import torch
import torch.nn as nn
import torch.nn.functional as F
# 1. Define the Network Structure
class SimpleMLP(nn.Module):
def __init__(self, input_size=784, hidden_size=128, num_classes=10):
super(SimpleMLP, self).__init__()
# --- Fully Connected Layers (Dense Layers) ---
# First layer: Maps input features to the first hidden layer
self.fc1 = nn.Linear(input_size, hidden_size)
# Second layer: Maps first hidden layer to the second hidden layer
self.fc2 = nn.Linear(hidden_size, 64)
# Output layer: Maps second hidden layer to the number of classes
self.fc3 = nn.Linear(64, num_classes)
# Optional: Dropout layer to prevent overfitting (drops 20% of neurons)
self.dropout = nn.Dropout(p=0.2)
# 2. Define the Data Flow (Forward Pass)
def forward(self, x):
# Flatten the input tensor
# Converts (batch_size, channels, height, width) to (batch_size, -1)
# Example: 28x28 image becomes a 784-dimensional vector
x = x.view(x.size(0), -1)
# First hidden layer: Linear transformation -> ReLU Activation -> Dropout
x = F.relu(self.fc1(x))
x = self.dropout(x)
# Second hidden layer: Linear transformation -> ReLU Activation
x = F.relu(self.fc2(x))
# Output layer: Linear transformation (no activation here, usually handled by loss function)
x = self.fc3(x)
return x
# 3. Instantiate the Model
model = SimpleMLP()
print(model)试一试
cd 4.4-Neural-Networks-and-CNNs/code
python powerful_neural_network.py🚀 训练你自己的神经网络,看看它的表现如何!

为什么 CNN 适合处理图像
CNN(卷积神经网络)之所以适合图像,是因为图像并不是随机的数字。在一张图像中,相邻的像素通常属于同一个边缘、形状或纹理,因此局部模式非常重要。CNN 利用这一点,通过使用在图像上扫描的小滤波器来寻找有用的特征,例如边缘、角点和简单的形状。随着网络变得更深,它将这些小特征组合成更大的特征,比如物体的部件,最终是整个物体本身。这就是为什么 CNN 在高效准确地理解图像方面尤其出色。
%20-%20Output%20Shape%20:%20(1,%207,%207)%20-%20K%20:%20(3,%203)%20-%20P%20:%20(0,%200)%20-%20S%20:%20(1,%201)%20-%20D%20:%20(1,%201)%20-%20G%20:%201.gif?raw=true)
CNN 通常具有分层结构,将图像转化为更高层次的视觉理解。它从一张输入图像开始,然后通过若干卷积层学习诸如边缘、纹理和形状等局部模式。这些层之后通常跟随像 ReLU 这样的激活函数和池化层,在保留重要信息的同时缩小空间尺寸。在若干这样的模块之后,特征图会被展平或被池化为紧凑的表示,并传入一个或多个全连接层以产生最终预测,例如类别标签。简而言之,常见的 CNN 结构看起来像:
输入 → 卷积 + 激活 → 池化 → 重复的特征提取模块 → 全连接层 → 输出

卷积的优点:
- 局部模式提取
卷积帮助模型在图像中找到小而有用的模式,例如边缘、角点、纹理或简单形状。这些小模式是理解更大物体的基本构建块。

- 参数共享
同一个滤波器会作用于图像的不同位置。这意味着模型不需要为每个位置学习一组新的权重,从而更高效,并减少了参数数量。
- 平移鲁棒性
如果物体移动到图像中的另一个位置,卷积滤波器仍然能够检测到它。换句话说,模型即使在位置变化时仍能识别相同的模式。
特征图
当卷积层处理图像时,会产生特征图。这些特征图响应诸如以下模式:
- 边缘
- 角点
- 纹理
- 在更深的层中响应更大的语义结构

池化与下采样
池化在保留重要信息的同时减小空间尺寸。
这有助于:
- 减少计算量
- 提高鲁棒性
- 构建更紧凑的表示
试一试
cd 4.4-Neural-Networks-and-CNNs/code
python cnn_process_visualization.py🚀 运行脚本,体验卷积网络对图像的处理过程。
训练与推理
Training:模型通过更新权重来学习Inference:训练好的模型在不更新权重的情况下进行预测
这一区别至关重要,因为后续的部署章节主要聚焦于推理。
CNN 在代码中是什么样子?
mport torch
import torch.nn as nn
class TinyCNN(nn.Module):
def __init__(self):
super().__init__()
self.features = nn.Sequential(
nn.Conv2d(3, 16, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(2),
nn.Conv2d(16, 32, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(2)
)
self.classifier = nn.Sequential(
nn.Flatten(),
nn.Linear(32 * 56 * 56, 64),
nn.ReLU(),
nn.Linear(64, 10)
)
def forward(self, x):
x = self.features(x)
x = self.classifier(x)
return x
model = TinyCNN()
dummy = torch.randn(1, 3, 224, 224)
output = model(dummy)
print(output.shape)常见误解
- "CNN 字面上就像人眼一样观察。"
- CNN 处理的是数值模式。这种类比有助理解,但并非字面意义上的相同。
- "层数越多性能越好。"
- 更深的模型可能更强大,但也更难训练和部署。
- "如果我看懂了代码,就自动理解了训练。"
- 训练还依赖于数据、损失函数、优化和评估。
练习 / 反思
- 用你自己的话解释为什么卷积比纯全连接层更适合处理图像。
- 运行 tiny CNN 示例并打印输出形状。
- 改变第一个卷积层的输出通道数,并观察模型结构如何变化。
- 反思 CNN 与诸如模糊或边缘检测之类的经典滤波器有何不同。
总结
神经网络从数据中学习表示,而 CNN 因为利用了局部结构,在图像方面尤其有效。理解卷积、特征图、池化以及训练与推理的区别,能为学习者迎接现代视觉任务做好准备。
建议下一步
继续学习 4.5 深度学习计算机视觉任务。