天啦嚕。。我發現更新的pytorch已經有instance normalization了。。
不用自己折騰了。。
-2017.5.25
利用 nn.Module 裡的 子類 _BatchNorm (在torch.nn.modules.batchnorm中定義),可以實現各種需求的normalize。
在docs裡,可以看到,有3種normalization layer,但其實他們都是繼承了_BatchNorm這個類的,所以我們看看BatchNorm2d,就可以對其他的方法舉一反三啦~
先來看看文檔
不清楚沒關係,接下來用例子講解:
建立一個BatchNorm2d的執行個體的方法如下
import torch.nn as nnnorm = nn.BatchNorm2d(fea_num, affine=False).cuda()
其中,fea_num 是拉出來的維度,就是說按照 fea_num 的維度,其他維度拉成一長條來normalize,fea_num對應input的第1個(維度從0開始計)維度, 所以兩者的值應相等。.cuda()是把這個module放到gpu上。 在普通的batch normalize的情況下
input是(batchsize,channel,height,width)=(4,3,5,5)來看,fea_num對應channel。所以channel=0時,求一次mean,var,做一次normalize;channel=1時,求一次。。channel=2時,求一次。。
在訓練中,還有兩個可以學習的參數gamma & beta,所以在gamma & beta設定為可變參數的情況下,應該這樣建立和使用batchnorm layer:
#input is cuda float Variable of batchsize x channel x height x width#train statenorm = nn.BatchNorm2d(channel).cuda()#預設affine=Trueinput = norm(input)
注意: 在train之前正確的初始化可變參數 在test/eval 模式下,應該用.eval() 固定住可變參數。 一個input的測試例子:
import numpy as npfrom torch.autograd import VariableBS = 2C = 3H = 2W = 2input = np.arange(BS*C*H*W)input.resize(BS, C, H, W)input = Variable(torch.from_numpy(input).clone().float()).cuda().contiguous()
如果不需要可變參數 gamma & beta,那直接:
#input is cuda float Variable of batchsize x channel x height x widthnorm = nn.BatchNorm2d(channel, affine=False).cuda()input = norm(input)
其他情況的normalize,如instance normalize
input還是(batchsize,channel,height,width)=(4,3,5,5)假設我們想把batchsize這一個維度拉出來,對每一個instance(batchsize=0~3)看做(3,5,5)的3D tensor 求一次normalize,那怎麼做呢。其實很簡單,把input的第0維和第1維調換一下就好了。
#input is cuda float Variable of batchsize x channel x height x widthinstanceNorm = nn.BatchNorm2d(BS, affine=False).cuda()input = input .transpose(0,1).contiguous()input = instanceNorm(input)input = input .transpose(0,1).contiguous()
注意: affine參數看需求設定,注意事項同普通batch normalize情況 如果沒使用.contiguous(),很有可能報錯
RuntimeError: Assertion `THCTensor_(isContiguous)(state, t)' failed. at **/pytorch/torch/lib/THCUNN/generic/BatchNormalization.cu:20
總而言之,記得BatchNorm layer 的 fea_num的取值=input拉出來的那個維度大小,且該維度應該是input的第1維,如果不是,用resize、transpose、unsqueeze啥的搞到是就好了