Unfold与fold介绍
Unfold+fold
作者:elfin
參考資料來源:pytorch官網(wǎng)
目錄1、nn.Unfold2、nn.Fold
Top---Bottom
1、nn.Unfold
nn.Unfold是pytorch實(shí)現(xiàn)的一個(gè)layer,那么這個(gè)layer是干嘛的呢?
torch.nn.Unfold(kernel_size: Union[T, Tuple[T, ...]],
dilation: Union[T, Tuple[T, ...]] = 1,
padding: Union[T, Tuple[T, ...]] = 0,
stride: Union[T, Tuple[T, ...]] = 1)
這里有四個(gè)參數(shù),與我們熟知的卷積操作很相似,那么與卷積有什么區(qū)別?
實(shí)際上nn.Unfold就是卷積操作的第一步。
? 對(duì)于輸入特征圖shape=[N,C,H,W],我們的Conv2d是怎么工作的?
第一步,padding特征圖;
第二步,過濾器窗口對(duì)應(yīng)的特征圖區(qū)域,平鋪這些元素;
第三步,根據(jù)步長(zhǎng)滑動(dòng)窗口,并進(jìn)行第二步的計(jì)算;
此時(shí)我們得到的特征圖(shape=left[ N, C imes k imes k, frac{H}{stride} imes frac{W}{stride} ight])
上面的shape這里給的是一般情況的特例,實(shí)際我們表示為:
(shape=(N, C imes prod( ext{kernel_size}), L)),其中(L)的計(jì)算為:
[L = prod_d leftlfloorfrac{ ext{spatial_size}[d] + 2 imes ext{padding}[d] %
- ext{dilation}[d] imes ( ext{kernel_size}[d] - 1) - 1}{ ext{stride}[d]} + 1ightfloor
]
以上三步實(shí)際就是為乘法做準(zhǔn)備!
第四步,將卷積核與 Unfold 之后的對(duì)象相乘;
第五步:[nn.Fold]
nn.Unfold就是將輸入的特征圖“reshape”到卷積乘法所需要的形狀,只是很多元素在特征圖中是重疊出現(xiàn)的,所以叫unfold,即我們要先平鋪。
Top---Bottom
2、nn.Fold
pytorch接口:
torch.nn.Fold(output_size, kernel_size, dilation=1, padding=0, stride=1)
對(duì)于(shape=(N, C imes prod( ext{kernel_size}), L))的輸入,nn.Fold計(jì)算得到輸出(shape=(N, C, output\_size[0], output\_size[1]))。
那么pytorch是怎么處理這個(gè)過程的呢?輸入和輸出的shape明顯很難直觀對(duì)應(yīng)起來,我們查詢?cè)创a,可以追溯到torch._C._nn.col2im函數(shù),巧了,我們并不能在源碼中找到其代碼塊。下面是參考程序員修練之路的博客給出的代碼,我們對(duì)其進(jìn)行驗(yàn)證:
def col2im(input, output_size, block_size):
p, q = block_size
sx = output_size[0] - p + 1
sy = output_size[1] - q + 1
result = np.zeros(output_size)
weight = np.zeros(output_size) # weight記錄每個(gè)單元格的數(shù)字重復(fù)加了多少遍
col = 0
# 沿著行移動(dòng),所以先保持列(i)不動(dòng),沿著行(j)走
for i in range(sy):
for j in range(sx):
result[j:j + p, i:i + q] += input[:, col].reshape(block_size, order='F')
weight[j:j + p, i:i + q] += np.ones(block_size)
col += 1
return result / weight
這個(gè)Fold與上面的結(jié)果是差距較大的,待下次再研究吧 ……
nn.Fold的處理過程
明顯上面的結(jié)果在nn.Fold上是不成立的,下面我們以下圖展示其處理過程:
Fold的處理步驟如下:
第一步: 從輸入中選擇一個(gè)block某通道上的所有元素,將其reshape到指定的形狀,這里的形狀就是kernal_size。需要注意的是dim=1的維度與kernal_size的關(guān)系。
第二步: 在輸出矩陣上填充reshape后的值。
第三步: 在輸入矩陣上使用stride=1進(jìn)行滑窗,在輸出矩陣上,使用nn.Fold指定的stride進(jìn)行滑窗,重復(fù)第一步、第二步。
Top---Bottom
完!
清澈的愛,只為中國(guó)
總結(jié)
以上是生活随笔為你收集整理的Unfold与fold介绍的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 鸿蒙系统适配机型_华为鸿蒙 OS 适配机
- 下一篇: Kafka的原理和作用是什么