MM 18有篇文章《Non-locally Enhanced Encoder-Decoder Network for Single Image De-raining》,這篇文章把兩大吃顯存利器——non-local 和 densely connection一起給用了(絕望臉)耕捞,如果要控制顯存使用的話宽堆,就對實現(xiàn)要求比較高了奇昙。里面提到了一個控制 non-local 運算的方法纤控,將feature map劃分成patch,在patch內(nèi)進行non-local操作活烙,而不是原來的全局non-local徐裸。
思路
這里實現(xiàn)一下這個patch版本的non-local。一般的non-local實現(xiàn)啸盏,請參考:Github 傳送門重贺。
思路很簡單,就是把patch的索引作為一個特殊的batch索引,原來的non-local運算會逐batch中的樣本進行气笙,現(xiàn)在就是逐batch中的樣本次企、逐每個樣本中的patch進行了。
上圖中潜圃,索引的第1個位置表示batch缸棵,第2、3個位置表示patch谭期,將1~3個位置的索引看成整體堵第,作為這個特殊的“batch”的索引。此時崇堵,patch版本的 non-local 就和一般的 non-local 沒有太大區(qū)別了型诚。
實現(xiàn)
那么,如何實現(xiàn)這樣的一個新索引呢鸳劳?
假如有輸入圖像 狰贯,首先需要將最后兩個表示位置的索引分解成四個索引,兩個表示塊的位置赏廓,兩個表示塊中元素的位置涵紊,例如要將行分解成m塊、列分解成n塊幔摸,就得到摸柄,使用 view
方法就能實現(xiàn)。如果對這個實現(xiàn)有疑惑既忆,可以參考附錄中的例子驱负。
然后進行轉(zhuǎn)置(或者說是交換索引的位置),得到患雇。這里使用前三個索引跃脊,表示具體某個patch(batch中某個feature map的某個patch)。最后苛吱,使用這個新的Tensor來進行non-local的操作即可酪术,方法類似,僅僅是在前面多了兩個索引翠储。
# implementation in PyTorch
# x=>(b, c, m, h/m, n, w/n)
# e.g. nb_patches = [2, 2]
b, c, h, w = x.size()
x = x.view(b, c,
nb_patches[0], h / nb_patches[0],
nb_patches[1], w / nb_patches[1])
# x=>(b, m, n, h/m, w/n, c)->(b, m, n, h/m*w/n, c)
x = x.permute(0, 2, 4, 3, 5, 1).contiguous()
x = x.view(b, nb_patches[0], nb_patches[1], -1, c)
附錄
如果不確定view
的使用绘雁,可以舉個簡單的例子,如上圖的的一個方塊 援所,顯然大小就是庐舟。上圖里中間一列,左邊表示元素住拭,右邊表示原來的元素索引继阻。如果使用 view
就是在新的 Tensor
中按順序排列舊的 Tensor
中的元素耻涛。按如下代碼重新排列元素废酷。圖中右邊一列瘟檩,就是使用了 view
后的新索引。
X = X.view(1, 1, 2, 4/2, 2, 4/2)
所以澈蟆,對于左上角的patch墨辛,其索引是,右上角則是趴俘,也就是使用view
得到新的 Tensor
的第3睹簇、5個位置的索引。
待填坑: Tensor
中的contiguous
方法