当前位置: 首页 > news >正文

YOLO入门教程(番外):卷积神经网络—填充与步幅

卷积神经网络中的填充与步幅:让AI更好地理解图像的艺术

深入浅出地解析CNN中两个关键超参数,让你的模型既保持信息又提高效率

在卷积神经网络的世界里,每一次卷积运算都像是在用一个小窗口(卷积核)在图像上滑动观察局部特征。但在这个过程中,我们会遇到两个实际问题:随着网络层数加深,图像边缘信息会逐渐丢失;有时我们又希望主动降低图像分辨率来减少计算量。今天我们就来聊聊解决这两个问题的关键技术——填充(Padding)和步幅(Stride)。

卷积操作的基本原理:从滑动窗口说起

想象一下,你正在用一个放大镜观察一幅画的细节。这个放大镜就是我们的"卷积核",而移动放大镜的规则决定了我们能观察到什么。

正常情况下,如果我们有一张nh×nwn_h × n_wnh×nw大小的图像,使用kh×kwk_h × k_wkh×kw大小的卷积核,那么输出大小就是:

(nh−kh+1)×(nw−kw+1)(n_h - k_h + 1) × (n_w - k_w + 1)(nhkh+1)×(nwkw+1)

这意味着每做一次卷积,图像尺寸就会缩小。就像用放大镜看画时,如果放大镜很大,你一次能看到的内容很多,但需要移动的次数就少了。

填充(Padding):给图像加个相框

为什么需要填充?

假设你有一张240×240像素的照片,经过10层5×5的卷积后,会变成200×200像素。这就像每次裁剪照片边缘一样,原始图像边界的信息都丢失了!填充技术就是为了解决这个问题。

填充就像给照片加个相框:我们在图像周围添加一圈值为0的像素点(就像黑色相框),这样卷积核在边缘滑动时就有足够的"操作空间"了。

填充的计算公式

添加php_hph行和pwp_wpw列填充后,输出尺寸变为:

(nh−kh+ph+1)×(nw−kw+pw+1)(n_h - k_h + p_h + 1) × (n_w - k_w + p_w + 1)(nhkh+ph+1)×(nwkw+pw+1)

保持尺寸不变的技巧

通常我们设置ph=kh−1p_h = k_h - 1ph=kh1pw=kw−1p_w = k_w - 1pw=kw1,这样输入输出尺寸就完全相同了!这就像选择了刚好合适的相框尺寸。

为什么卷积核尺寸通常是奇数?
因为使用3、5、7这样的奇数尺寸,可以在各侧均匀填充,保持对称美观。想象一下,如果相框左右宽度不同,看起来会很不协调吧?

实际代码示例

import torch
from torch import nn# 定义一个方便的卷积测试函数
def test_convolution(conv_layer, input_tensor):"""测试卷积层并返回输出形状"""# 添加批次和通道维度:(批量大小, 通道数, 高度, 宽度)input_with_dims = input_tensor.reshape((1, 1) + input_tensor.shape)# 进行卷积计算output = conv_layer(input_with_dims)# 移除批次和通道维度,返回原始形状return output.reshape(output.shape[2:])# 创建8x8的随机输入图像
original_image = torch.rand(size=(8, 8))
print("原始图像尺寸:", original_image.shape)# 示例1:使用3x3卷积核,填充为1(保持尺寸不变)
conv_layer1 = nn.Conv2d(1, 1, kernel_size=3, padding=1)
output1 = test_convolution(conv_layer1, original_image)
print("使用填充后的输出尺寸:", output1.shape)  # 仍然是8x8

步幅(Stride):控制观察的步调

什么是步幅?

步幅决定了卷积核每次移动的距离。默认步幅为1,就像慢慢细看画的每个细节;增大步幅就像大步流星地浏览,虽然会错过一些细节,但能快速了解整体情况。

步幅的计算公式

当垂直步幅为shs_hsh、水平步幅为sws_wsw时,输出形状为:

⌊(nh−kh+ph+sh)/sh⌋×⌊(nw−kw+pw+sw)/sw⌋\lfloor(n_h - k_h + p_h + s_h)/s_h\rfloor × \lfloor(n_w - k_w + p_w + s_w)/s_w\rfloor⌊(nhkh+ph+sh)/sh×⌊(nwkw+pw+sw)/sw

这个公式看起来复杂,但实际上很简单:输出尺寸 ≈ 输入尺寸 / 步幅

步幅的实际效果

使用步幅为2时,输出尺寸大约减半;步幅为3时,约为原来的三分之一。这就像从"细嚼慢咽"变为"狼吞虎咽",虽然细节少了,但效率提高了!

# 示例2:使用步幅为2,尺寸减半
conv_layer2 = nn.Conv2d(1, 1, kernel_size=3, padding=1, stride=2)
output2 = test_convolution(conv_layer2, original_image)
print("使用步幅2的输出尺寸:", output2.shape)  # 变为4x4# 示例3:不同方向的步幅和填充
conv_layer3 = nn.Conv2d(1, 1, kernel_size=(3, 5), padding=(0, 1), stride=(3, 4))
output3 = test_convolution(conv_layer3, original_image)
print("复杂步幅的输出尺寸:", output3.shape)  # 根据公式计算的结果

填充与步幅的完美配合

在实际应用中,我们经常同时使用填充和步幅:

  1. 保持尺寸模式:填充=1,步幅=1(3×3卷积核)
  2. 降采样模式:填充=1,步幅=2(快速减少尺寸)
  3. 不对称模式:不同方向的步幅和填充(处理特殊需求)
# 同时使用填充和步幅的示例
def demonstrate_combinations(image_size):"""展示不同填充和步幅组合的效果"""image = torch.rand(size=(image_size, image_size))print(f"\n对于{image_size}x{image_size}输入图像:")# 模式1:保持尺寸conv1 = nn.Conv2d(1, 1, kernel_size=3, padding=1, stride=1)output1 = test_convolution(conv1, image)print(f"保持尺寸: {output1.shape}")# 模式2:降采样conv2 = nn.Conv2d(1, 1, kernel_size=3, padding=1, stride=2)output2 = test_convolution(conv2, image)print(f"降采样: {output2.shape}")# 模式3:特殊组合if image_size >= 8:conv3 = nn.Conv2d(1, 1, kernel_size=(3, 5), padding=(1, 2), stride=(2, 3))output3 = test_convolution(conv3, image)print(f"特殊组合: {output3.shape}")# 测试不同尺寸
demonstrate_combinations(8)
demonstrate_combinations(16)

实际应用场景

什么时候使用填充?

  1. 保持空间信息:在深层网络中防止信息丢失
  2. 预处理阶段:需要保持图像尺寸时
  3. 对称结构:当需要输入输出尺寸相同时

什么时候使用步幅?

  1. 快速降维:减少计算量和内存使用
  2. 特征抽象:从细节特征转向全局特征
  3. 替代池化层:现代网络中常用步幅卷积代替池化

总结:找到平衡的艺术

填充和步幅就像卷积神经网络中的"油门"和"刹车":

  • 填充保护信息,保持细节,但增加计算成本
  • 步幅提高效率,加速处理,但可能丢失信息

在实际设计中,我们需要根据任务需求找到平衡点:

任务类型推荐策略原因
图像分割小步幅,适当填充需要保持空间精度
图像分类大步幅,最小填充需要快速抽象特征
目标检测混合策略平衡精度和效率

动手实验建议

  1. 可视化效果:使用小矩阵手动计算,理解每一步的变化
  2. 尝试极端值:体验过大填充或步幅的影响
  3. 对比实验:在同一网络上测试不同策略的效果差异
# 简单的可视化实验
def manual_convolution_example():"""手动计算卷积示例"""# 创建简单输入input_matrix = torch.tensor([[1., 2., 3.],[4., 5., 6.],[7., 8., 9.]])# 创建简单卷积核kernel = torch.tensor([[0., 1.],[2., 3.]])print("输入矩阵:")print(input_matrix)print("\n卷积核:")print(kernel)# 计算不同填充和步幅的结果from torch.nn import functional as F# 无填充,步幅1output1 = F.conv2d(input_matrix.reshape(1,1,3,3), kernel.reshape(1,1,2,2), padding=0, stride=1)print(f"\n无填充,步幅1: {output1.shape} - 输出值: {output1.squeeze()}")# 填充1,步幅1output2 = F.conv2d(input_matrix.reshape(1,1,3,3), kernel.reshape(1,1,2,2), padding=1, stride=1)print(f"填充1,步幅1: {output2.shape} - 输出值: {output2.squeeze()}")manual_convolution_example()

通过理解和掌握填充与步幅这两个超参数,你就能够更好地设计卷积神经网络,在保持信息和提高效率之间找到最佳平衡点。记住,没有最好的配置,只有最适合特定任务的配置!

http://www.dtcms.com/a/442798.html

相关文章:

  • 中国建设银行校园招聘网站注册个公司要多少钱费用
  • 商务网站建设的主流程网站作为医院形象建设
  • 旅游网站推广方案华为外包做的网站
  • 国际民用航空组织ICAO
  • 1.6 傅里叶变换7-拉氏变换、Z变换
  • h5响应式网站设计方案软件开发步骤流程
  • 网站建设所用的工具大丰网店制作
  • 网站建设及网站推广网站开发与建设课程
  • python计算化学(autode系列—xTB)Atoms类详解
  • 网站没有在工信部备案中山seo外包
  • 不通过网站可以做360全景吗网页设计与制作基础教程
  • Simulink模型转换为UPPAAL模型(2016)
  • 部署Spring Boot项目+mysql并允许前端本地访问的步骤
  • 嵌入式linux内核驱动学习4——LED
  • 建设银行人力资源招聘网站建筑行业教育培训平台
  • 蚌埠网站制作网站开发好找工作吗
  • Spring Boot 整合 MyBatis
  • 【C++实战(70)】C++ 跨平台开发:CMake构建实战指南
  • algorithm <B> data manipulation in huffman algorithm 4/99
  • 三网合一网站建设福建省建设执业资格注册中心网站
  • Rokid JSAR 技术开发全指南+实战演练
  • 昆明做网站哪家便宜计算机网络课程设计
  • 《网页设计与网站建设》A卷答案成都o2o网站建设
  • 建筑工程网官网入口商丘seo教程
  • 求解子网掩码
  • 网站 转成 微信小程序西城上海网站建设
  • 【AI论文】SLA:通过精细可调的稀疏线性注意力机制突破扩散变换器中的稀疏性局限
  • 博客自定义网站服饰 视频 网站建设
  • SSM创新实践学分管理系统08a30(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • 太原建设网站制作WordPress手机号验证登录