Mask_RCNN代碼研讀(matterport版本)系列文(二)- Feature Pyramid Network部份

news/2024/5/20 6:13:21 标签: CV, 深度学习, 目标检测, 实体分割, 语义分割

Mask_RCNN代碼研讀(matterport版本)系列文(二)- Feature Pyramid Network部份

  • 前言
  • 訓練及推論模式中的共同部份
    • Feature Pyramid Network
  • 小結
  • 參考連結

前言

在本系列的第一篇Mask_RCNN代碼研讀(matterport版本)系列文(一)- ResNet部份中,我們了解到ResNet在Mask RCNN的大架構裡扮演的是特徵抽取器(backbone)的角色,而這些feature maps將被Feature Pyramid Network(以下簡稱FPN)用來進一步構建在更層語義訊息皆很強的特徵。在本篇中將會接著對FPN進行探討。

對FPN還不了解的同學可以先看看Feature Pyramid Networks for Object Detection論文研讀與問題討論這篇文章。

訓練及推論模式中的共同部份

Feature Pyramid Network

以下是論文中闡述FPN的圖:
FPN
筆者參考代碼,畫了一個更能與代碼對應的圖:
FPN_full

FPN共由三個部份所組成,分別是:bottom-up pathway,top-bottom pathway及lateral connection。

其中bottom-up pathway就是backbone(即ResNet)中的前向傳播部份,會生成 C 1 C_1 C1 ~ C 5 C_5 C5。( C 1 C_1 C1未畫出)
top-bottom pathway是上圖中紅色朝下的箭頭。
lateral-connection則是上圖左側朝右的1x1 Conv。
以上這兩步會從 C 1 C_1 C1 ~ C 5 C_5 C5生成 P 2 ′ P_2' P2 ~ P 5 ′ P_5' P5

注意到紅色朝下的箭頭做的是將top-bottom pathway上的feature map做上採樣後與lateral connection出來的feature map做逐元素相加。但是為何是做逐元素相加呢?,這仍是筆者不太明白的地方。

FPN中top-down pathway及lateral connection的作用是什麼呢?論文中作者做了ablation experiment,從中可以看出top-down enrichment的重要性及lateral-connection的重要性。

得到 P 2 ′ P_2' P2 ~ P 5 ′ P_5' P5後,還會經過3x3 Convolution,生成 P 2 P_2 P2 ~ P 5 P_5 P5
P 6 P_6 P6則是由 P 5 P_5 P5下採樣而來,僅為region proposal network(RPN)所用。
至於為何得到P2’~P5’後,還要再做3x3 Convolution?,論文作者說是為了減少上採樣所帶來的aliasing effect。

FPN的輸入 C 2 C_2 C2 ~ C 5 C_5 C5間有很大的語義鴻溝,詳見使用deep ConvNet固有的feature hierarchy。
FPN會為這些feature maps做處理,得到在各層皆有很強語義訊息的 P 2 P_2 P2 ~ P 6 P_6 P6

如果直接使用 C 2 C_2 C2 ~ C 5 C_5 C5來做預測會怎麼樣呢?論文作者做了ablation experiment,結果詳見:
top-down enrichment的重要性及Fast R-CNN物體偵測效果的變化的(c)及(d)。

這些feature maps會接著送進RPN得到候選框,也會被稍後的classifier, regressor及mask branch所使用。
classifier, regressor及mask branch被稱作網路的頭部。而這些頭部是被 P 2 P_2 P2 ~ P 6 P_6 P6所共享的

這個repo裡的FPN並沒有獨立成一個函數,而是直接寫在MaskRCNN這個類別裡。
以下是它的代碼:

# Top-down Layers
# TODO: add assert to varify feature map sizes match what's in config
P5 = KL.Conv2D(config.TOP_DOWN_PYRAMID_SIZE, (1, 1), name='fpn_c5p5')(C5)
P4 = KL.Add(name="fpn_p4add")([
    KL.UpSampling2D(size=(2, 2), name="fpn_p5upsampled")(P5),
    KL.Conv2D(config.TOP_DOWN_PYRAMID_SIZE, (1, 1), name='fpn_c4p4')(C4)])
P3 = KL.Add(name="fpn_p3add")([
    KL.UpSampling2D(size=(2, 2), name="fpn_p4upsampled")(P4),
    KL.Conv2D(config.TOP_DOWN_PYRAMID_SIZE, (1, 1), name='fpn_c3p3')(C3)])
P2 = KL.Add(name="fpn_p2add")([
    KL.UpSampling2D(size=(2, 2), name="fpn_p3upsampled")(P3),
    KL.Conv2D(config.TOP_DOWN_PYRAMID_SIZE, (1, 1), name='fpn_c2p2')(C2)])
# Attach 3x3 conv to all P layers to get the final feature maps.
P2 = KL.Conv2D(config.TOP_DOWN_PYRAMID_SIZE, (3, 3), padding="SAME", name="fpn_p2")(P2)
P3 = KL.Conv2D(config.TOP_DOWN_PYRAMID_SIZE, (3, 3), padding="SAME", name="fpn_p3")(P3)
P4 = KL.Conv2D(config.TOP_DOWN_PYRAMID_SIZE, (3, 3), padding="SAME", name="fpn_p4")(P4)
P5 = KL.Conv2D(config.TOP_DOWN_PYRAMID_SIZE, (3, 3), padding="SAME", name="fpn_p5")(P5)
# P6 is used for the 5th anchor scale in RPN. Generated by
# subsampling from P5 with stride of 2.
P6 = KL.MaxPooling2D(pool_size=(1, 1), strides=2, name="fpn_p6")(P5)

# Note that P6 is used in RPN, but not in the classifier heads.
rpn_feature_maps = [P2, P3, P4, P5, P6]
mrcnn_feature_maps = [P2, P3, P4, P5]

C 2 C_2 C2 ~ C 5 C_5 C5是前篇介紹的ResNet輸出的feature maps。
而此處的FPN會接受 C 2 C_2 C2 ~ C 5 C_5 C5當作輸入,並輸出 P 2 P_2 P2 ~ P 6 P_6 P6

代碼的上半部可以對應到上圖的左側,即由 C 2 C_2 C2 ~ C 5 C_5 C5生成 P 2 ′ P_2' P2 ~ P 5 ′ P_5' P5(在此把這個中間結果稱作 P 2 ′ P_2' P2 ~ P 5 ′ P_5' P5)。
我們可以看到 P 5 ′ P_5' P5是由 C 5 C_5 C5做1x1 Conv2D而來。
P 4 ′ P_4' P4是由經過2x2 upsampling後的 P 5 ′ P_5' P5與做過1x1 Conv2D的 C 4 C_4 C4相加而來。
P 3 P_3 P3 P 2 P_2 P2也是經歷同樣的過程而得來的。
注意到 C 2 C_2 C2 ~ C 5 C_5 C5在經過Conv2D後的厚度都變為config.TOP_DOWN_PYRAMID_SIZE。這是在config.py檔案裡設置的參數,用於調控top-down pathway上的feature maps的厚度,預設值為256。

而代碼的下半部則對應到上圖的右側。
P 2 ′ P_2' P2 ~ P 5 ′ P_5' P5做3x3 Conv2D後得到 P 2 P_2 P2 ~ P 5 P_5 P5,而 P 6 P_6 P6是由 P 5 P_5 P5下採樣而來。

最後 P 2 P_2 P2 ~ P 6 P_6 P6會用作RPN的輸入feature maps。
P 2 P_2 P2 ~ P 5 P_5 P5則作為classifier, regressor, mask head的輸入feature maps。

小結

在本篇中我們看到了FPN會利用ResNet輸出的 C 2 C_2 C2 ~ C 5 C_5 C5,建構在各層語義訊息皆很強的 P 2 P_2 P2 ~ P 6 P_6 P6
而它們在下一步將會為region proposal network(RPN)及classifier, regressor, mask head所使用。
下一篇我們將會介紹RPN本身以及它在Mask RCNN這個大架構裡所發揮的作用。

參考連結

Mask_RCNN代碼研讀(matterport版本)系列文(一)- ResNet部份
Feature Pyramid Networks for Object Detection論文研讀與問題討論
為何是做逐元素相加呢?
top-down enrichment的重要性
lateral-connection的重要性
為何得到P2’~P5’後,還要再做3x3 Convolution?
使用deep ConvNet固有的feature hierarchy
Fast R-CNN物體偵測效果的變化
這些頭部是被 P 2 P_2 P2 ~ P 6 P_6 P6所共享的


http://www.niftyadmin.cn/n/778628.html

相关文章

oracle磁盘满了怎么办,运维攻坚之压缩表空间解决oracle数据库磁盘满问题

背景某项目数据库磁盘告警,磁盘使用率接近100%$ df -ThFilesystem Type Size Used Avail Use% Mounted on/dev/vda1 ext4 99G 60G 35G 64% /devtmpfs devtmpfs 32G 0 32G 0% /devtmpfs tmpfs 32G 69M 32G 1% /dev/shmtmpfs tmpfs 32G 7.8M 32G 1% /runtmpfs tmpfs 3…

CentOS下安裝Java

CentOS下安裝Java前言步驟下載jdk的rpm包使用yum來安裝設定環境變量查看java版本問題排查參考連結前言 本篇是筆者照著How to Install Apache Zeppelin on CentOS 7的教學安裝Java。 原文中的dead link己被替換成可以用的連結。 步驟 下載jdk的rpm包 可以直接使用以下指令下…

怎么禁用掉oracle,Oracle 怎么禁用外键

我们创建外键后,可能有时会遇到要禁用外键的情况,那么在Oracle中,我们如何对外键进行禁用呢?语法在Oracle中,我们要禁用外键可以使用以下语法:ALTER TABLE table_nameDISABLE CONSTRAINT constraint_name;示…

如何找出zeppelin的登入帳號密碼?

如何找出zeppelin的登入帳號密碼?前言步驟切換到zeppelin的安裝目錄從conf/shiro.ini中找出帳戶密碼參考連結前言 如果忘記了zeppelin的密碼該怎麼辦呢? 我們可以登入zeppelin的運行主機,然後從設定檔中找出可用的帳戶密碼。 本篇記錄了詳細…

oracle 10 crs日志路径,oracle 10g rac集群log日志存放路径

这里记录下10g rac crs下的log存放路径,以便从log中解决问题Log Directory Structure in Cluster Ready ServicesTo diagnose any problem, the first thing examined by Oracle Support are the installation log files. Anyone who knows anything about database administra…

CentOS下安裝Zeppelin

CentOS下安裝Zeppelin前言安裝步驟安裝Java安裝Zeppelin啟動zeppelin問題排除Zeppelin process died參考連結前言 一開始照著Zeppelin - Install的教學來安裝Zeppelin。 安裝完成後想啟動zeppelin-daemon卻一直不成功。 後來回去仔細看了官網的教學才發現原來Zeppelin必須有Ja…

oracle汉诺塔,VC++实现模拟汉诺塔效果

先上效果图再附上源代码:汉诺塔:#include "stdio.h"#include "math.h"int arrA[15], arrB[15], arrC[15]; // 分别为A、B、Cint length;int lenA, lenB, lenC;char plate[32];// Makevoid makeplate(int n){int i;if (n length …

如何除Zeppelin的錯?

如何除Zeppelin的錯?前言重啟interpreter查看log重啟Zeppelin參考連結前言 本篇記錄了一些簡單的Zeppelin除錯方法。 包括重啟interpreter,查看log,重啟Zeppelin等方法。 重啟interpreter 點擊zeppelin notebook右上角的箭頭,選…