前言
刚入门深度学习的同学很容易搞混两件事:什么时候用 CNN,什么时候用 RNN。
- 图片、照片、摄像头画面、医学影像:空间结构数据 → CNN 卷积神经网络;
- 句子、语音、股价、气温时序、文字对话:前后有序依赖的数据 → RNN 循环神经网络。
本文整合 CNN 完整图像知识 + 卷积 / 池化原理、RNN 词嵌入 + 循环时序原理,全程大白话,避开晦涩公式堆砌,配套全新独立案例代码(不照搬原文示例),从零带你吃透两大基础网络,看完就能手写简单图像分类、文本处理模型。
第一部分:CNN 卷积神经网络 ------ 专门处理图像
一、图像底层基础知识(看懂 CNN 的前提)
1. 计算机怎么看懂图片?像素与通道
所有图片在电脑里都是数字矩阵,最小单位是像素 ,像素取值范围 0~255:
- 数值 0:纯黑色;数值 255:纯白色;中间数值是深浅过渡。
- 图像分 4 种常见类型:
- 二值图:仅 1 个通道,像素只有 0、1 两种取值,一般用于文字扫描、黑白线条图。
- 灰度图:单通道图像,像素取值范围 0~255,常应用在人脸识别、医学 X 光片等场景。
- 索引图:同样为 1 通道,像素区间 0~255,多用于压缩动图、色彩数量较少的图片。
- RGB 彩色图:包含红、绿、蓝 3 个通道,像素取值 0~255,手机拍摄的日常照片都属于这类图像。

图像存储格式约定:
- 普通读取:
[H, W, C]→ 高、宽、通道; - PyTorch 模型输入:必须转成
[Batch, C, H, W]批次、通道、高、宽。
2. 代码实操:用 matplotlib 生成 / 读取图片
python
import numpy as np
import matplotlib.pyplot as plt
# 1. 生成纯黑、纯白测试图
def create_color_img():
# 200*200 三通道黑色图
black = np.zeros((200, 200, 3), dtype=np.uint8)
plt.imshow(black)
plt.axis("off")
plt.title("纯黑图像")
plt.show()
# 纯白图
white = np.full((200, 200, 3), 255, dtype=np.uint8)
plt.imshow(white)
plt.axis("off")
plt.title("纯白图像")
plt.show()
# 2. 读取本地真实图片,查看尺寸
def read_local_img():
img = plt.imread("test.jpg")
print(f"图片形状[H,W,C]:{img.shape}")
plt.imshow(img)
plt.axis("off")
plt.title("原图展示")
plt.show()
if __name__ == "__main__":
create_color_img()
read_local_img()
二、CNN 整体概述:为什么不用全连接,非要卷积?
1. 全连接网络处理图片的致命缺陷
一张 640×640 彩色图,像素总量 640*640*3=1228800,全连接第一层就会产生百万级参数,存在两大问题:
- 参数爆炸,训练慢、极易过拟合;
- 丢失空间信息:全连接把图片拍平成一维,分不清上下左右,无法识别边缘、轮廓。
2. CNN 核心优势:局部连接 + 权重共享
- 局部感受野:卷积核只和图片一小块区域计算,不用全局连接;
- 权重共享:同一个卷积核在整张图滑动,一套权重复用,参数量大幅降低;
- 平移不变性:物体在图片左上角 / 右下角,卷积都能识别同类特征。
3. CNN 标准三层流水线(所有图像任务通用)
- 卷积层 Conv2d:提取图像特征(底层:边缘、纹理;多层堆叠后:五官、物体轮廓);
- 池化层 Pool:下采样降维,压缩图片尺寸,保留核心特征,减少计算;
- 全连接层 Linear:把二维特征图展平,输出分类 / 检测结果。
配套激活层 ReLU:卷积计算后加入非线性,让网络能学习复杂图像特征。
4. CNN 主流应用场景
图像分类、人脸识别、自动驾驶目标检测、医学病灶识别、图像语义分割、手写数字识别。 经典 CNN 架构:LeNet-5(手写数字开山之作)、AlexNet、VGG、GoogLeNet、ResNet(解决深层网络梯度消失)。
三、卷积层 Conv2d:图像特征提取核心
1. 卷积运算底层逻辑
核心操作:卷积核(滤波器)和图片局部区域做内积。
- 卷积核:固定尺寸权重矩阵(常见 3×3、5×5),一个卷积核提取一类特征;
- 特征图 Feature Map:原图经过卷积核滑动计算后输出的新矩阵,代表提取到的纹理 / 边缘。
2. 三大关键超参:Padding、Stride、Kernel_size
(1)Padding 填充
在图片四周补 0 像素,解决两个痛点:
- 不填充时卷积后图片持续缩小,深层网络容易丢失边缘像素;
- Same Padding:填充后输出特征图尺寸 = 输入图片尺寸,方便多层网络搭建。
(2)Stride 步长
卷积核每次滑动移动的像素数:
- stride=1:逐像素滑动,细节保留完整;
- stride=2:隔一个像素滑动,直接缩小特征图,替代部分池化降维。
(3)输出特征图尺寸计算公式

- W:输入图片宽高;F:卷积核大小;P:填充;S:步长;向下取整。
举例:5×5 图片,3×3 卷积核,padding=1,stride=1,N=(5−3+2×1)/1+1=5,输出仍为 5×5。
3. 多通道、多卷积核计算规则
- RGB 三通道图像卷积:卷积核通道数必须和图片通道一致(3 通道),每个通道单独卷积后数值相加,得到单张特征图;
- 多卷积核:设置 out_channels=N,代表 N 个不同卷积核,同时提取 N 类特征,输出 N 张特征图,通道数等于卷积核数量。
4. PyTorch 卷积 API 实战
python
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
# 解决中文乱码
plt.rcParams['font.sans-serif'] = ['SimHei'] # 或 'Microsoft YaHei'
plt.rcParams['axes.unicode_minus'] = False
def conv_image_test():
# 读取图片
img = plt.imread("test.jpg") # 形状 (H, W, C),通常是 uint8
h, w, c = img.shape
print(f"原图尺寸 H:{h}, W:{w}, C:{c}")
# 1. 构建卷积层
conv = nn.Conv2d(in_channels=3, out_channels=4, kernel_size=3, stride=2, padding=0)
# 2. 转换维度:HWC → CHW → [B, C, H, W]
img_tensor = torch.tensor(img).permute(2, 0, 1).unsqueeze(0).float()
print(f"模型输入张量形状:{img_tensor.shape}")
# 3. 前向传播得到特征图
feature = conv(img_tensor)
print(f"卷积输出特征图形状:{feature.shape}")
# 4. 取第一张特征图(通道0)
feat_map = feature[0, 0].detach().numpy() # 形状 (H_out, W_out)
# ---------- 可视化:原图 + 特征图 并排 ----------
fig, axes = plt.subplots(1, 2, figsize=(10, 5))
# 左:原图
axes[0].imshow(img) # 彩色显示
axes[0].set_title("原图")
axes[0].axis("off")
# 右:特征图(灰度)
axes[1].imshow(feat_map, cmap="gray")
axes[1].set_title("卷积提取特征图 (通道0)")
axes[1].axis("off")
plt.tight_layout() # 自动调整子图间距
plt.show()
if __name__ == "__main__":
conv_image_test()
效果图:

四、池化层 Pool:降维压缩,减少计算量
1. 池化两大核心作用
- 空间降维:缩小特征图宽高,大幅减少后续计算参数;
- 特征鲁棒性:轻微平移、噪声不会影响特征识别,降低过拟合。
2. 两种主流池化
- MaxPool2d 最大池化:窗口内取最大值,保留最明显纹理 / 边缘,工业最常用;
- AvgPool2d 平均池化:窗口内取平均值,柔和保留全局信息,多用于全局特征聚合。
3. 多通道池化特点
池化不会改变通道数量,每个通道独立池化,通道数前后保持一致。
4. PyTorch 池化代码示例
python
import torch
import torch.nn as nn
# 单通道池化测试
def pool_single():
# 3×3单通道矩阵
data = torch.tensor([[[0,1,2],[3,4,5],[6,7,8]]], dtype=torch.float)
# 最大池化 2×2窗口,步长1
max_pool = nn.MaxPool2d(kernel_size=2, stride=1)
print("最大池化结果:\n", max_pool(data))
# 平均池化
avg_pool = nn.AvgPool2d(kernel_size=2, stride=1)
print("平均池化结果:\n", avg_pool(data))
# 多通道池化测试
def pool_multi():
# 3通道3×3数据
data = torch.tensor([
[[0,1,2],[3,4,5],[6,7,8]],
[[10,20,30],[40,50,60],[70,80,90]],
[[11,22,33],[44,55,66],[77,88,99]]
], dtype=torch.float)
pool = nn.MaxPool2d(2, 1)
print("多通道池化结果:\n", pool(data))
if __name__ == "__main__":
pool_single()
pool_multi()
第二部分:RNN 循环神经网络 ------ 处理文本 / 时序数据
一、RNN 基础认知:专门处理有序序列数据
1. 什么是序列数据?
数据存在严格先后顺序,后文依赖前文:
- 文本:
我 喜欢 吃 火锅,词语颠倒语义完全改变; - 时序:气温、股价、传感器数据;
- 语音:连续音频波形。
CNN 只能处理空间静态图片,无法记忆前文信息,因此诞生 RNN,核心是隐藏状态(记忆单元),每一步运算携带上一步历史信息。
2. RNN 四大应用场景
- NLP 自然语言:情感分析、机器翻译、文本生成、聊天机器人;
- 时间序列预测:销量、气象、股市预测;
- 语音识别、AI 歌曲生成;
- 动作时序识别。
3. RNN 完整文本处理流水线
词嵌入层 Embedding → RNN 循环层 → 全连接输出层
- 词嵌入:文字转为低维数字向量;
- RNN 层:逐词读取向量,用隐藏状态保存上下文记忆;
- 全连接层:输出分类 / 生成词语概率。
二、词嵌入层 Embedding:文字数字化必经步骤
1. One-hot 编码的缺点
假设词表 5000 个词,每个词是 5000 维稀疏向量:
- 维度爆炸,计算开销巨大;
- 无法区分语义相近词语(奶茶、咖啡向量完全无关)。
2. 词嵌入三大优势
- 低维稠密向量:几千词汇统一映射为 32/64/128 维短向量;
- 语义编码:语义相近词语向量空间距离更近;
- 统一输入格式:将离散文字转为神经网络可计算的数值。
3. 完整工作流程
句子分词 → 构建词表(词→唯一索引)→ 句子转为索引序列 → Embedding 查表输出词向量 → 送入 RNN。
4. PyTorch nn.Embedding 案例代码(奶茶短句案例)
python
import torch
import torch.nn as nn
# 奶茶评论语料
words = ["我", "爱", "喝", "珍珠奶茶", "冰奶茶", "少糖"]
word2idx = {w:i for i,w in enumerate(words)}
vocab_size = len(word2idx)
embed_dim = 8 # 每个词映射8维向量
# 构建嵌入层
embedding = nn.Embedding(num_embeddings=vocab_size, embedding_dim=embed_dim)
# 句子转索引
sent_idx = torch.tensor([word2idx["我"], word2idx["爱"], word2idx["珍珠奶茶"]])
vec = embedding(sent_idx)
print("索引序列shape:", sent_idx.shape)
print("词向量shape [词数量,向量维度]:", vec.shape)
print(""珍珠奶茶"向量:", embedding(torch.tensor(3)))
三、RNN 循环层:自带记忆的时序处理器
1. 核心:隐藏状态 h(RNN 的短期记忆)
每个时间步输入两部分:
- 当前词语词向量
;
- 上一步记忆
。
运算后生成新记忆 ht,传递给下一个词语,全程共享同一个神经元循环运算。 隐藏状态三大作用:存储历史信息、理解上下文、串联所有时序步骤。
2. RNN 核心计算公式
-
更新隐藏记忆:

-
输出预测向量:

输出向量经过 Softmax 转为词语概率,用于文本生成 / 分类。
3. PyTorch nn.RNN API 介绍
python
nn.RNN(input_size, hidden_size, num_layers=1)
- input_size:输入向量维度 = 词嵌入维度;
- hidden_size:隐藏记忆向量长度;
- num_layers:堆叠 RNN 层数。
python
output, hn = rnn(x, h0)
- 输入
:
[seq_len, batch, input_size]句子长度、批次、词向量维度; - 初始隐藏
:
[num_layers, batch, hidden_size],不传默认全 0; :所有时间步隐藏状态
[seq_len, batch, hidden_size](文本生成使用);:最后一步全局记忆
[num_layers, batch, hidden_size](文本分类使用)。
4. RNN 单层测试代码
python
import torch
import torch.nn as nn
seq_len = 6 # 单句6个词
batch_size = 4 # 4条句子一批
embed_dim = 8 # 词向量维度
hidden_dim = 16# 记忆向量长度
rnn = nn.RNN(input_size=embed_dim, hidden_size=hidden_dim, num_layers=1)
# 模拟一批词向量数据
inputs = torch.randn(seq_len, batch_size, embed_dim)
# 初始化隐藏状态
h0 = torch.zeros(1, batch_size, hidden_dim)
output, hn = rnn(inputs, h0)
print("全部时间步输出shape:", output.shape) # [6,4,16]
print("最终全局记忆hn shape:", hn.shape) # [1,4,16]
参数匹配规则:

四、案例:RNN 文本情感分类模型(奶茶好评 / 差评)
python
import torch
import torch.nn as nn
# 超参数
VOCAB_NUM = 12
EMBED_DIM = 16
HIDDEN_DIM = 32
LAYERS = 1
CLASS_NUM = 2 # 二分类:好评0,差评1
class MilkTeaSentimentRNN(nn.Module):
def __init__(self):
super().__init__()
self.embedding = nn.Embedding(VOCAB_NUM, EMBED_DIM)
self.rnn = nn.RNN(EMBED_DIM, HIDDEN_DIM, LAYERS)
self.fc = nn.Linear(HIDDEN_DIM, CLASS_NUM)
def forward(self, x):
emb = self.embedding(x)
_, hn = self.rnn(emb)
hn = hn.squeeze(0) # 去除层数维度
out = self.fc(hn)
return out
if __name__ == "__main__":
model = MilkTeaSentimentRNN()
# 模拟3条评论,每条5个词
test_input = torch.randint(0, VOCAB_NUM, (5, 3))
pred = model(test_input)
print("模型输出 [批次,分类数]:", pred.shape)
第三部分:CNN 与 RNN 核心对比 + 相关问题
一、CNN vs RNN 适用场景清晰区分
表格
| 网络 | 处理数据 | 核心能力 | 核心结构 | 典型任务 |
|---|---|---|---|---|
| CNN 卷积网络 | 图像、空间二维数据 | 提取局部空间特征、平移不变 | 卷积层 + 池化层 | 图像分类、人脸识别、目标检测 |
| RNN 循环网络 | 文本、时序一维有序数据 | 记忆历史上下文、建模先后依赖 | 词嵌入 + 循环隐藏层 | 情感分析、股价预测、文本生成 |
二、相关问题
CNN 相关
- 卷积核为什么多用 3×3? 多个 3×3 堆叠可以替代大卷积核,参数量更少、非线性更强,VGG 网络标准设计。
- 池化会不会丢失信息? 只会丢弃无关细节,保留最强特征;现代网络也常用 stride=2 卷积替代池化。
- 图片输入为什么要转 B,C,H,W? PyTorch 卷积层通道维度放在第二维,符合 GPU 并行计算优化规范。
RNN 相关
- output 和 hn 什么时候用? 逐词生成任务(写诗、翻译)用 output;整条句子分类只用最后一步 hn。
- 基础 RNN 有什么缺陷? 长文本会出现梯度消失,远距离前文记忆丢失,工业改用 LSTM/GRU。
- 词嵌入维度怎么选? 短评论短句 32/64 维;长文章、大语料 128/256 维,维度越大语义承载越多,训练更慢。
全文总结
-
CNN 卷积神经网络 针对图像空间数据,依靠卷积核提取边缘 / 纹理特征,池化层降维压缩;核心三组件:卷积 Conv2d、池化 Pool、全连接 Linear;掌握尺寸计算公式与 PyTorch 卷积 / 池化 API 即可搭建简易图像分类模型。
-
RNN 循环神经网络 针对有序序列(文字、时序),依靠隐藏状态存储上下文记忆;文本处理固定流程:分词→词嵌入 nn.Embedding→nn.RNN 循环层→全连接输出;适合 NLP、时间序列预测任务。
-
两大网络是深度学习入门基石,CNN 负责视觉、RNN 负责文本与时序;理解基础原理后,后续学习 ResNet、LSTM、Transformer 等进阶模型会事半功倍。文中所有代码均为全新独立案例,不照搬原文示例,新手可直接复制运行调试,直观观察网络输出变化。