這個是一個常用的模塊,就是我們可以對輸入的特征嵌入位置編碼。
位置編碼(Positional Encoding)是一種將空間位置信息嵌入到特征中的方法,通常用于幫助模型更好地理解特征的空間關系。
這里介紹的這個是相對位置編碼,代碼如下:
def _make_coord(batch, height, width):xv, yv = torch.meshgrid([torch.arange(0, height), torch.arange(0, width)])xv_min = (xv.float() * 2 - width) / widthyv_min = (yv.float() * 2 - height) / heightxv_max = ((xv + 1).float() * 2 - width) / widthyv_max = ((yv + 1).float() * 2 - height) / heightxv_ctr = (xv_min + xv_max) / 2yv_ctr = (yv_min + yv_max) / 2hmap = torch.ones(height, width) * (1. / height)wmap = torch.ones(height, width) * (1. / width)coord = torch.cat([xv_min.unsqueeze(0), yv_min.unsqueeze(0),xv_max.unsqueeze(0), yv_max.unsqueeze(0),xv_ctr.unsqueeze(0), yv_ctr.unsqueeze(0),hmap.unsqueeze(0), wmap.unsqueeze(0)], dim=0)coord = coord.unsqueeze(0).repeat(batch, 1, 1, 1)return coord
這個模塊怎么用?
比如說你現在特征大小是2x64x4x4,batchsize是2,通道數64,寬和高是4
給定參數寬和高就可以生成位置編碼,生成的位置編碼是8維的,然后直接復制到跟batchsize保持一致就行
就得到了bx8xHxW的位置編碼,然后直接和特征進行拼接,拼接完了直接卷積融合就行,就可以實現位置編碼的嵌入
解釋一下這個模塊:
根據代碼來講解
我們假設特征
batch_size = 2 # 批量大小
height = 4 # 特征圖高度
width = 4 # 特征圖寬度
首先
xv, yv = torch.meshgrid([torch.arange(0, height), torch.arange(0, width)])
# 生成兩個網格矩陣 xv 和 yv,分別表示每個像素的橫坐標和縱坐標。
可能有點抽象,具體來說
xv如下(每一個位置的數代表該位置像素的橫坐標)
[0,0,0,0],
[1,1,1,1],
[2,2,2,2],
[3,3,3,3]
yv如下(每一個位置的數代表該位置像素的縱坐標)
[0,1,2,3],
[0,1,2,3],
[0,1,2,3],
[0,1,2,3]
隨后就是
xv_min = (xv.float() * 2 - width) / widthyv_min = (yv.float() * 2 - height) / height
這個計算就是進行相對位置編碼,前面兩行的計算公式:(xv.float() * 2 - width) / width
這就是將坐標映射到[-1,1)
上去,注意,左閉右開,不會映射到1,因為從0開始的。
xv_max = ((xv + 1).float() * 2 - width) / widthyv_max = ((yv + 1).float() * 2 - height) / height
那么這個max也是一樣,這個是映射到(-1,1]
上去
最終得到的矩陣如下:
xv_min
如下
[-1 ,-1 ,-1 ,-1 ],
[-0.5,-0.5,-0.5,-0.5],
[0 ,0 ,0 ,0 ],
[0.5 ,0.5 ,0.5 ,0.5 ]
yv_min
如下
[-1 ,-0.5 ,0 ,0.5 ],
[-1 ,-0.5 ,0 ,0.5 ],
[-1 ,-0.5 ,0 ,0.5 ],
[-1 ,-0.5 ,0 ,0.5 ]
xv_max
如下
[-0.5,-0.5,-0.5,-0.5],
[0 ,0 ,0 ,0 ],
[0.5 ,0.5 ,0.5 ,0.5 ],
[1 ,1 ,1 ,1 ]
yv_max
如下
[-0.5 ,0 ,0.5 ,1 ],
[-0.5 ,0 ,0.5 ,1 ],
[-0.5 ,0 ,0.5 ,1 ],
[-0.5 ,0 ,0.5 ,1 ]
這個東西的意義是什么?就是你把xv_min
和yv_min
組合起來,左上角為[-1,-1],其余坐標都是相對左上角的坐標。
你把xv_max
和yv_max
組合起來,右下角為[1,1],其余坐標都是相對右下角的坐標。
xv_min
和 yv_min
表示每個像素相對于左上角的坐標,xv_max
和 yv_max
表示每個像素相對于右下角的坐標。
緊接著,是計算每個像素的中心坐標,即像素的幾何中心位置。
xv_ctr = (xv_min+xv_max)/2
yv_ctr = (yv_min+yv_max)/2
這個計算出來得到的是相對中心值,就是你相對左上角的值加上相對右下角的值,除以2,就是個平均值,就是中間的值
xv_ctr
如下
[-0.75,-0.75,-0.75,-0.75],
[-0.25,-0.25,-0.25,-0.25],
[0.25 ,0.25 ,0.25 ,0.25 ],
[0.75 ,0.75 ,0.75 ,0.75 ]
yv_ctr
如下
[-0.75,-0.25,0.25,0.75],
[-0.75,-0.25,0.25,0.75],
[-0.75,-0.25,0.25,0.75],
[-0.75,-0.25,0.25,0.75]
然后下面兩行,這個計算的就是寬度步長和高度步長,換句話說:分別表示每個像素的高度和寬度的歸一化值。
hmap = torch.ones(height, width) * (1. / height)
wmap = torch.ones(height, width) * (1. / width)
計算出來hmap
和wmap
都如下所示,一樣的,因為設置的寬高是一樣的,1/4都是0.25
[0.25,0.25,0.25,0.25],
[0.25,0.25,0.25,0.25],
[0.25,0.25,0.25,0.25],
[0.25,0.25,0.25,0.25]
將上述計算的 8 個通道(xv_min
, yv_min
, xv_max
, yv_max
, xv_ctr
, yv_ctr
, hmap
, wmap
)拼接在一起,形成一個 8×H×W 的張量。
使用 unsqueeze(0)
將其擴展為 1×8×H×W,然后通過 repeat(batch, 1, 1, 1)
將其復制到每個樣本上,最終得到一個 B×8×H×W 的張量。
這個 8 維位置編碼包含了以下信息:
- 每個像素左上角的歸一化坐標(
xv_min
,yv_min
)。 - 每個像素右下角的歸一化坐標(
xv_max
,yv_max
)。 - 每個像素中心的歸一化坐標(
xv_ctr
,yv_ctr
)。 - 每個像素的相對高度和寬度(
hmap
,wmap
)。
這些信息為模型提供了豐富的空間位置信息,有助于模型更好地理解特征圖中像素之間的空間關系。