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

做爰全过程免费的视频网站爱网站建设与技术团队

做爰全过程免费的视频网站爱,网站建设与技术团队,免费微信小程序制作软件,加速网页的加速器第一部分:FPN实例教学1. 问题:鱼与熊掌不可兼得现在我们有一个普通的卷积神经网络(像ResNet),我们用它来处理一张图片。这张图片里有一辆很大的卡车,还有一个很小的行⼈。网络在处理图片时,会产…

第一部分:FPN实例教学

1. 问题:鱼与熊掌不可兼得

现在我们有一个普通的卷积神经网络(像ResNet),我们用它来处理一张图片。这张图片里有一辆很大的卡车,还有一个很小的行⼈。

网络在处理图片时,会产生不同层次的“特征图”:

浅层特征图 (e.g., C3):尺寸很大 (比如 32x32),保留了很多细节信息,比如物体的边缘、颜色、纹理。它的优点是定位精准,知道行人在哪个像素点附近。但缺点是它不知道这个纹理组合起来是个“行人”。

深层特征图 (e.g., C5):尺寸很小 (比如 8x8),经过了多次压缩,细节信息丢失严重。但优点是,它具有高度浓缩的语义信息,能认出“这是一辆卡车”和“这是一个行人”。但缺点是定位粗糙,它只知道行人大致在左上角那块区域,具体在哪说不清。

负责定位的浅层特征,不认识物体。负责识别的深层特征,定不准物体。

这导致检测小物体(如那个行人)时非常困难。我们需要一种方法,让浅层特征图,也能获得深层特征图的智慧。FPN就是解决这个问题的

2. FPN的解决方案:自顶向下的信息传递

FPN通过一个“自顶向下”的路径,让深层特征把智慧传递给浅层特征。

实例:

输入图片 256x256

Backbone网络产生了三层特征图:

C3: 尺寸 32x32,通道数 512

C4: 尺寸 16x16,通道数 1024

C5: 尺寸 8x8,通道数 2048

融合步骤 :

步骤一:先整理C5

C5虽然智慧(语义信息强),但它的信息太多(通道数2048)。我们先用一个1x1卷积给它“降维”,把通道数从 2048 减少到 256

这个降维后的特征图,我们称之为 P5。现在 P5 的尺寸是 8x8x256。它是我们金字塔的顶层,专门用来检测大物体(比如那辆卡车)。

步骤二:C5向C4传递信息

上采样 (Upsample): C5的 P5 要和 C4 联系融合到一起,得先把自己的尺寸变得和C4一样大。我们通过上采样操作,将 P5 从 8x8 放大到 16x16

C4整理: C4自己也要用一个1x1卷积,把通道数从 1024 降到 256,方便待会儿和 P5 融合

融合 (Fusion): 现在,上采样后的 P5 和降维后的 C4 尺寸完全一样了(都是16x16x256)。我们把它们按元素相加 (Element-wise Addition)。

这“相加”的一步,就是特征融合的核心,它意味着C4的特征图,每一个点都融入了来自C5的更高级的语义信息。融合后的结果,我们称之为 P4。

现在 P4 (16x16x256) 既有C4的较好定位能力,又有C5的强大识别能力。它很适合用来检测中等大小的物体。

步骤三:C4向C3传递信息

这个过程完全一样:

将刚刚生成的新P4上采样,从 16x16 放大到 32x32

对原始的 C3 进行1x1卷积,通道数从 512 降到 256

把两者相加,得到 P3 (32x32x256)。

最终成果: 我们得到了一个新的特征金字塔:P3, P4, P5

P5 (8x8): 主要来自C5,负责检测大物体。

P4 (16x16): 融合了C5和C4,负责检测中等物体。

P3 (32x32): 融合了P4和C3(间接也融合了C5),它既有C3本身超强的细节定位能力,又被赋予了来自高层的识别能力。因此,它现在能够轻松地识别并定位出那个很小的行人!

这就是FPN特征融合的魅力所在。

第二部分:FPN代码教学

下面我们用 PyTorch 来实现上面描述的整个过程。我会写一个非常简化的例子,让读者看到数据的维度是如何变化的。

1. 模拟一个骨干网络 (Backbone)  真实的骨干网络会是ResNet等,这里我们用几个简单的卷积层来模拟,它的作用是输入一张图片,输出我们在实例中提到的 C3, C4, C5 特征图

import torch
import torch.nn as nn
import torch.nn.functional as F
class ToyBackbone(nn.Module):def __init__(self):super().__init__()# 模拟从图片到C3的过程self.conv_to_c3 = nn.Sequential(nn.Conv2d(3, 128, kernel_size=3, stride=2, padding=1),nn.ReLU(),nn.Conv2d(128, 256, kernel_size=3, stride=2, padding=1),nn.ReLU(),nn.Conv2d(256, 512, kernel_size=3, stride=2, padding=1),nn.ReLU())# 模拟从C3到C4self.conv_to_c4 = nn.Sequential(nn.Conv2d(512, 1024, kernel_size=3, stride=2, padding=1),nn.ReLU())# 模拟从C4到C5self.conv_to_c5 = nn.Sequential(nn.Conv2d(1024, 2048, kernel_size=3, stride=2, padding=1),nn.ReLU())def forward(self, x):c3 = self.conv_to_c3(x)c4 = self.conv_to_c4(c3)c5 = self.conv_to_c5(c4)return c3, c4, c5

2. 实现FPN

class FPN(nn.Module):def __init__(self, c3_channels, c4_channels, c5_channels, out_channels=256):super().__init__()self.out_channels = out_channels# 建立横向连接 (Lateral Connection)# 这是给C3, C4, C5整理的1x1卷积self.lat_c5 = nn.Conv2d(c5_channels, self.out_channels, kernel_size=1)self.lat_c4 = nn.Conv2d(c4_channels, self.out_channels, kernel_size=1)self.lat_c3 = nn.Conv2d(c3_channels, self.out_channels, kernel_size=1)# 建立平滑层# 融合后的特征图可以用一个3x3卷积来消除上采样带来的混叠效应self.smooth = nn.Conv2d(self.out_channels, self.out_channels, kernel_size=3, padding=1)def forward(self, c3, c4, c5):# 自顶向下 (Top-Down) 的路径# 1. 处理最高层 C5,得到 P5p5 = self.lat_c5(c5)# 2. P5上采样,与处理后的C4融合,得到 P4p5_upsampled = F.interpolate(p5, scale_factor=2, mode='nearest')p4 = self.lat_c4(c4) + p5_upsampled # <- 核心的特征融合# 3. P4上采样,与处理后的C3融合,得到 P3p4_upsampled = F.interpolate(p4, scale_factor=2, mode='nearest')p3 = self.lat_c3(c3) + p4_upsampled # <- 核心的特征融合# 对最终的金字塔层进行平滑处理,得到最终输出p3 = self.smooth(p3)p4 = self.smooth(p4)# p5也经过一次平滑,保持一致性p5 = self.smooth(p5)return p3, p4, p5

实例运行:

if __name__ == '__main__':# 假设输入一张 1x3x256x256 的图片 (Batch, Channel, Height, Width)dummy_input = torch.randn(1, 3, 256, 256)# 1. 通过骨干网络,得到C3, C4, C5backbone = ToyBackbone()c3, c4, c5 = backbone(dummy_input)print("--- Backbone输出 ---")print(f"C3 shape: {c3.shape}") # 预期: [1, 512, 32, 32]print(f"C4 shape: {c4.shape}") # 预期: [1, 1024, 16, 16]print(f"C5 shape: {c5.shape}") # 预期: [1, 2048, 8, 8]print("-" * 20)# 2. 将C3, C4, C5送入FPN,得到新的特征金字塔 P3, P4, P5fpn_model = FPN(c3_channels=512, c4_channels=1024, c5_channels=2048, out_channels=256)p3, p4, p5 = fpn_model(c3, c4, c5)print("--- FPN输出 ---")print(f"P3 shape: {p3.shape}") # 预期: [1, 256, 32, 32]print(f"P4 shape: {p4.shape}") # 预期: [1, 256, 16, 16]print(f"P5 shape: {p5.shape}") # 预期: [1, 256, 8, 8]print("-" * 20)print("可以看到,所有输出特征图的通道数都统一为了256,且尺寸与输入对应层相同。")print("这些P3, P4, P5就是被送去预测的、融合了多尺度信息的全新特征图。")

第三部分:为什么还需要“自底向上?

我们先回顾一下FPN(自顶向下)做了什么:它让具有高层语义信息的特征图,去“帮助”具有高分辨率的低层特征图,解决了“低层特征不认识物体”的问题

但是,这里面隐藏着一个信息传递的“小瑕疵”:

信息路径过长:我们想让最底层的特征C3(32x32,定位最准)的精确位置信息,去帮助最高层的预测P5(8x8)。在FPN架构中,这个信息需要先经过整个Backbone一路向上到C5,再经过FPN的路径一路向下传回到P3,路径非常长,途中的信息可能会丢失。

FPN的“自顶向下”C5把信息传达给C3。但是,C3发现了一个非常紧急、非常具体的本地情报,比如一个精确的像素级边缘,他需要一个快速上报通道”直接反馈给C5

“自底向上”的路径,就是这个为“定位信息”建立的快速上报通道。

第四部分:PANet - 实例教学

这个新增的路径,其思想主要来源于 PANet (Path Aggregation Network)。它在FPN生成的特征金字塔(P3, P4, P5)的基础上,立即开始工作。

FPN已经为我们生成了融合后的特征金字塔:

P3: 尺寸 32x32x256

P4: 尺寸 16x16x256

P5: 尺寸 8x8x256

新增的“自底向上”步骤

步骤一:P3向P4“上报”信息

下采样 (Downsample): 我们从最底层的P3开始,因为它包含了最丰富的定位信息。我们通过一个步长为2的3x3卷积,将P3的尺寸从32x32缩小到16x16

融合 (Fusion): 将下采样后的P3,与FPN已经生成的P4进行拼接 (Concatenate)

注意: 这里的融合方式通常是拼接,而不是相加。拼接可以看作是把两个信息渠道“并排”放在一起,保留了各自更完整的信息,然后再通过一个1x1卷积进行降维和真正的融合。

融合后的结果,我们称之为N4。现在 N4 (16x16x256) 不仅拥有来自高层的语义信息(继承自P4),还拥有了从底层P3直接传递过来的精确定位信息。它比原来的P4更强大。

步骤二:新N4向P5“上报”信息

过程完全一样:

  1. 将刚刚生成的新N4通过一个步长为2的卷积,从16x16缩小到8x8

  2. 将下采样后的N4,与FPN生成的P5进行拼接和融合。

  3. 最终得到的结果,我们称之为N5 (8x8x256)。

最终成果: 经过“自顶向下(FPN)” + “自底向上(PANet)”这一个来回,我们得到了一套全新的、用于最终预测的特征金字塔:N3, N4, N5

N3: 就是原始的P3。

N4: 是P4融合了来自N3的定位信息。

N5: 是P5融合了来自N4的(间接也包含了N3的)定位信息。

核心优势: 这条新增的路径,极大地缩短了精确定位信息(来自底层)到高层语义特征的传递路径。现在,无论是负责检测大、中、小物体的哪个预测头,都能同时享受到最好的语义信息和定位信息。

完整的颈部 (Neck) 流程如下: Backbone -> FPN (自顶向下) -> PANet (自底向上) -> 最终的特征金字塔 (N3, N4, N5)

第三部分:PAnet代码讲解

我们在上一节的代码基础上,扩展FPN类,让它完整地包含PANet的路径。

骨干网络 ToyBackbone 和上一节完全一样,这里省略以保持简洁:

import torch
import torch.nn as nn
import torch.nn.functional as Fclass ToyBackbone(nn.Module):def __init__(self):super().__init__()self.conv_to_c3 = nn.Sequential(nn.Conv2d(3, 512, kernel_size=8, stride=8))self.conv_to_c4 = nn.Sequential(nn.Conv2d(512, 1024, kernel_size=2, stride=2))self.conv_to_c5 = nn.Sequential(nn.Conv2d(1024, 2048, kernel_size=2, stride=2))def forward(self, x):c3 = self.conv_to_c3(x); c4 = self.conv_to_c4(c3); c5 = self.conv_to_c5(c4)return c3, c4, c5

实现一个包含 FPN + PANet 的完整颈部:

通过torch.cat将两个特征图在通道维度上堆叠起来,然后立即使用一个1x1卷积,一方面将翻倍的通道数降回原来的维度,另一方面更重要的是,通过可学习的权重,对来自不同源头的信息进行智能的、加权的融合,从而产生一个全新的、信息更丰富的特征图。

class FPN_PANet_Neck(nn.Module):def __init__(self, c3_channels, c4_channels, c5_channels, out_channels=256):super().__init__()self.out_channels = out_channels# --- FPN (自顶向下) 部分的层 ---self.lat_c5 = nn.Conv2d(c5_channels, self.out_channels, kernel_size=1)self.lat_c4 = nn.Conv2d(c4_channels, self.out_channels, kernel_size=1)self.lat_c3 = nn.Conv2d(c3_channels, self.out_channels, kernel_size=1)self.fpn_smooth = nn.Conv2d(self.out_channels, self.out_channels, kernel_size=3, padding=1)# --- PANet (自底向上) 部分的层 ---# 用于下采样的卷积self.pan_downsample1 = nn.Conv2d(self.out_channels, self.out_channels, kernel_size=3, stride=2, padding=1)self.pan_downsample2 = nn.Conv2d(self.out_channels, self.out_channels, kernel_size=3, stride=2, padding=1)# 拼接后用于融合的卷积self.pan_fuse1 = nn.Conv2d(self.out_channels * 2, self.out_channels, kernel_size=1)self.pan_fuse2 = nn.Conv2d(self.out_channels * 2, self.out_channels, kernel_size=1)

前向传播:

def forward(self, c3, c4, c5):# --- 1. FPN: 自顶向下路径 ---p5 = self.lat_c5(c5)p5_upsampled = F.interpolate(p5, scale_factor=2, mode='nearest')p4 = self.lat_c4(c4) + p5_upsampledp4_upsampled = F.interpolate(p4, scale_factor=2, mode='nearest')p3 = self.lat_c3(c3) + p4_upsampled# FPN 路径的输出(经过平滑)p3 = self.fpn_smooth(p3)p4 = self.fpn_smooth(p4)p5 = self.fpn_smooth(p5)# --- 2. PANet: 自底向上路径 ---# P3 就是最终的 N3n3 = p3 # 从 N3 到 N4n3_downsampled = self.pan_downsample1(n3)# 拼接 P4 和下采样后的 N3n4_concatenated = torch.cat([n3_downsampled, p4], dim=1) # dim=1 是通道维度n4 = self.pan_fuse1(n4_concatenated)# 从 N4 到 N5n4_downsampled = self.pan_downsample2(n4)# 拼接 P5 和下采样后的 N4n5_concatenated = torch.cat([n4_downsampled, p5], dim=1)n5 = self.pan_fuse2(n5_concatenated)# 返回最终用于预测的特征图return n3, n4, n5

实例运行:

if __name__ == '__main__':dummy_input = torch.randn(1, 3, 256, 256)backbone = ToyBackbone()c3, c4, c5 = backbone(dummy_input)print("--- Backbone输出 ---")print(f"C3 shape: {c3.shape}")print(f"C4 shape: {c4.shape}")print(f"C5 shape: {c5.shape}")print("-" * 30)# 实例化完整的颈部neck = FPN_PANet_Neck(c3_channels=512, c4_channels=1024, c5_channels=2048, out_channels=256)n3, n4, n5 = neck(c3, c4, c5)print("--- FPN + PANet Neck 输出 ---")print("这些是最终送入预测头的特征图:")print(f"N3 (for small objects) shape: {n3.shape}")print(f"N4 (for medium objects) shape: {n4.shape}")print(f"N5 (for large objects) shape: {n5.shape}")print("-" * 30)print("虽然维度和单独使用FPN时一样,但N4和N5现在包含了从底层'快速上报'的更精准的定位信息。")

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

相关文章:

  • 专业做数据的网站wordpress 添加字段
  • 河北三河建设局网站wordpress主题破解2019
  • 金融营销的网站设计案例电子商务主要学什么适合女生吗
  • 现在最好的企业网站管理系统北京营销网站建设设计
  • 网站建设开发服务费下什么科目大学网站建设与功能开发
  • 信誉好的邯郸网站建设深圳知名设计公司有哪些
  • dede如何生成网站源码wordpress修改用户名
  • 寻找电商网站建设北京建设协会网站
  • 怎么做徐州市环保局网站备案表自己搭建网站需要多少钱
  • 县区组织部12380网站建设微信公众号php网站开发
  • 我们的网站网站建设关于公司怎么写
  • 北京网站开发价格手机网站翻页效果
  • 学校二级网站建设dede网站地图栏目如何上传文件
  • 做网站游戏怎么挣钱北京市城乡建设协会官方网站
  • 小装修网站开发费用视频网站开发用什么服务器
  • 安防公司网站模板影院网站怎么做
  • 网站管理系统软件重庆是哪个省份的
  • O2O网站开发工程师新手怎样学校做网站
  • 手机网站策划书方案国外设计网站pinterest设计网址
  • 阳江营销网站开发企业网络推广方案
  • 常平镇网站建设常宁网站
  • 珠海酒店网站建设餐饮公司网站建设
  • 广州商城型网站百度搜索 网站介绍
  • 网站生成工具网站规划的要素不包括
  • h5建设网站公司移动网站的建设
  • 在线html制作网页泉州seo网络优化公司
  • 饮品店网站模板做mod游戏下载网站
  • 白领兼职做网站系统定制开发
  • 行业门户网站设计免费发软文的网站
  • 网站排版怎么做的微机做网站的软件