【深度学习|学习笔记】深度学习神经网络中的权值共享 (Weight Sharing)详解。
【深度学习|学习笔记】深度学习神经网络中的权值共享 (Weight Sharing)详解。
·
【深度学习|学习笔记】深度学习神经网络中的权值共享 (Weight Sharing)详解。
【深度学习|学习笔记】深度学习神经网络中的权值共享 (Weight Sharing)详解。
文章目录
欢迎铁子们点赞、关注、收藏!
祝大家逢考必过!逢投必中!上岸上岸上岸!upupup
大多数高校硕博生毕业要求需要参加学术会议,发表EI或者SCI检索的学术论文会议论文。详细信息可扫描博文下方二维码 “
学术会议小灵通”或参考学术信息专栏:https://blog.csdn.net/2401_89898861/article/details/148877490
1. 什么是权值共享?
在一般的 全连接层 (Fully Connected Layer) 中,每个输入神经元与每个输出神经元都有独立的权重,因此参数量非常大。
而在 卷积神经网络 (CNN) 中,我们采用 卷积核 (filter/kernel) 在输入特征图上滑动,每个位置使用 相同的一组权重 来进行特征提取,这就是权值共享。
直观理解:
- 如果用全连接层处理一张
256×256×3的图片,参数量可能达到上亿级; - 使用卷积核(例如
3×3×3大小,64 个卷积核),参数量仅仅是3*3*3*64=1728,极大减少计算量。
优势:
- 减少参数量 → 避免过拟合,提高训练效率。
- 提高泛化性 → 一个卷积核学到的特征(如边缘/纹理)可以在图像的不同区域复用。
- 适合空间结构数据 → 保留图像的局部结构特征。
2. 代码示例:对比「无权值共享 vs 有权值共享」
(1) 无权值共享:每个位置独立参数(模拟卷积但不共享权值)
import torch
import torch.nn as nn
# 一个 "不共享权值的卷积":本质上是全连接的展开
class UnsharedConv(nn.Module):
def __init__(self, in_channels, out_channels, kernel_size, input_size):
super().__init__()
H, W = input_size
self.weight = nn.Parameter(torch.randn(out_channels, in_channels, H, W)) # 每个位置独立权值
self.bias = nn.Parameter(torch.zeros(out_channels))
def forward(self, x): # x: [N, C, H, W]
# 模拟逐像素乘法(效率低,仅作演示)
return (x * self.weight).sum(dim=(1,2,3), keepdim=True) + self.bias.view(1, -1, 1, 1)
x = torch.randn(1, 3, 32, 32) # 输入 32x32x3 图像
model = UnsharedConv(3, 10, 3, (32, 32))
print("参数量(不共享):", sum(p.numel() for p in model.parameters()))
- (2) 有权值共享(普通卷积层)
conv = nn.Conv2d(in_channels=3, out_channels=10, kernel_size=3, padding=1)
print("参数量(共享权值):", sum(p.numel() for p in conv.parameters()))
输出对比:
- 不共享权值:参数量 ≈ 3×32×32×10 = 30720
- 共享权值:参数量 = 3×3×3×10 + 10 = 280
→ 参数量差距 100 倍以上,但卷积能捕捉相同甚至更好的特征。
3. 权值共享的实际效果
- 我们可以训练一个小模型,比较 CNN (权值共享) 与 全连接网络 (无共享) 在图像分类任务上的差异。
CNN 示例(共享权值)
class SmallCNN(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, 16, 3, padding=1)
self.conv2 = nn.Conv2d(16, 32, 3, padding=1)
self.fc = nn.Linear(32*7*7, 10) # 假设输入 28x28
def forward(self, x):
x = torch.relu(self.conv1(x))
x = torch.relu(self.conv2(x))
x = torch.flatten(x, 1)
return self.fc(x)
print("CNN 参数量:", sum(p.numel() for p in SmallCNN().parameters()))
MLP 示例(无共享)
class MLP(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(28*28, 128)
self.fc2 = nn.Linear(128, 64)
self.fc3 = nn.Linear(64, 10)
def forward(self, x):
x = torch.flatten(x, 1)
x = torch.relu(self.fc1(x))
x = torch.relu(self.fc2(x))
return self.fc3(x)
print("MLP 参数量:", sum(p.numel() for p in MLP().parameters()))
- → 你会发现,CNN 参数量远小于 MLP,但在图像任务上往往效果更好,这就是 权值共享带来的好处。
4. 总结
- 权值共享 = 相同的一组卷积核在输入的不同区域重复使用 → 显著减少参数量,增强泛化能力。
- 在图像/序列任务中尤其重要(CNN、RNN 等都有权值共享思想)。
- 对比实验:CNN vs 全连接 → CNN 参数量更小,收敛更快。
更多推荐
所有评论(0)