【CV细粒度识别论文总结】The Devil is in the Channels: Mutual-Channel Loss for Fine-Grained Image Classification
Paper:The Devil is in the Channels: Mutual-Channel Loss for Fine-Grained Image Classification(TIP 2021)
1 Motivation and Advantage
簡單來說,就是想做細粒度的圖像分類(特征細膩,類間差異小,類內差異大等原因)。別人都是通過關鍵區域標注、注意力機制等方法解決,這篇文章作者另辟蹊徑,從損失函數入手,很有創意。
但是作者不想給模型增加額外的網絡參數,所以提出只用一個新的損失函數就能夠很好地解決細粒度問題,并且提出的損失函數具有很好的移植性,理論上能用于現有的各種網絡架構。
2 Total Effect
-
上面部分:傳統的細粒度分類模型,關注的是整個特征圖,同時關注到了一幅圖中的三個關鍵區域
-
下面部分:MC-Loss方法,每個類別有多個通道,每個通道都對應一個判別區域
后面在方法介紹中細說
3 Methodology of MC-Loss
細粒度識別框架的整體流程(經典的細粒度分類模型,不針對具體某一種模型):
損失函數結合了Cross Entropy(CE)和 MC-Loss兩者,將卷積神經網絡最后一層的輸出特征作為本文損失函數的輸入。
總體的損失函數表示為CE和MC的加權和:
Loss(F)=LCE(F)+μ×LMC(F)Loss(F)=L_{CE}(F)+\mu\times L_{MC}(F)Loss(F)=LCE?(F)+μ×LMC?(F)
- CE:促使網絡提取有利于全局目標類別的判別特征
- MC:關注不同局部判別塊的特征
其中FFF是卷積層提取的特征,其中F∈RN×H×WF\in R^{N\times H\times W}F∈RN×H×W中NNN表示channel數,HWH WHW表示特征圖的高和寬。
在MC-Loss中,N=c×ξN=c\times \xiN=c×ξ,ccc表示類別總數,ξ\xiξ表示每類的channel數(需要注意:ξ\xiξ是一個超參,一般大于2,在paper中作者假定ξ\xiξ是個定值)
對于某個類別iii,特征表示為Fi∈Rξ×W×H,i=0,1,2,...,c?1F_i\in R^{\xi\times W\times H}, i=0, 1, 2, ..., c-1Fi?∈Rξ×W×H,i=0,1,2,...,c?1
獲取到各類別特征后,特征集表示為F={F0,F1,...,Fc?1}F=\{F_0, F_1, ..., F_{c-1}\}F={F0?,F1?,...,Fc?1?},把特征集輸入流程分別計算CE和MC兩個損失。
MC-Loss由兩部分組成:判別模塊和多樣性,在paper中表示為Ldis(F)L_{dis}(F)Ldis?(F)和Ldiv(F)L_{div}(F)Ldiv?(F),所以LMC(F)L_{MC}(F)LMC?(F)表示為:
LMC(F)=Ldis(F)?λLdiv(F)L_{MC}(F)=L_{dis}(F)-\lambda L_{div}(F)LMC?(F)=Ldis?(F)?λLdiv?(F)
-
判別性模塊(discriminality component)
作者設定ξ\xiξ個channel的特征表示一個類別,這個模塊要求這些特征關注某個特定的類別并且每個channel的特征要有足夠的判別性。
Ldis(F)L_{dis}(F)Ldis?(F)表示如下:
-
CWA:使用mask進行channel-attention,mask是個01掩模,隨機選擇一半的通道?ξ?\lfloor \xi \rfloor?ξ?為0,Mi=diag(Maski)M_i=diag(\text{Mask}_i)Mi?=diag(Maski?)為一個對角矩陣,其中0對應的位置(channel)被消除,其實就等同于是channel級別的dropout機制
維度:c×ξ×WH→c×ξ2×WHc\times \xi \times WH \to c\times \frac{\xi}{2} \times WHc×ξ×WH→c×2ξ?×WH
-
CCMP:跨channel的max pooling,在WH空間位置上選取最大值(avg pooling不適用細粒度分類?)
c×ξ2×WH→c×1×WHc\times \frac{\xi}{2} \times WH\to c\times 1 \times WHc×2ξ?×WH→c×1×WH
-
GAP:在空間維度進行avg pooling
c×1×WH→c×1c\times 1 \times WH \to c\times 1c×1×WH→c×1
-
Softmax
借鑒別人博客中的一些解釋:THE MUTUAL-CHANNEL LOSS (MC-LOSS,附代碼分析)
-
多樣性模塊(diversity component)
這個模塊的目的是同一類別的ξ\xiξ個channel應該關注圖像的不同區域,而不是同一類的所有channel都關注最有判別性的區域。多樣性組件不能單獨用于分類,它充當判別器的正則化項,隱式發現圖像中不同的原始區域的損失。
Ldiv(F)L_{div}(F)Ldiv?(F)相當于計算各個channel特征間的距離,相比于歐氏距離和KL散度計算量更小。
Ldiv(F)L_{div}(F)Ldiv?(F)表示如下:
- Softmax:先對特征的每一位置Softmax,變為預測類別
- CCMP:選取一個類別的ξ\xiξ個channel中各空間位置的最大值
- Sum:在空間位置求和,得到各類別的預測概率在所有channel上的和
- Average:對各類別求均值,值越大表示模型對于所有類別,不同的channel都關注到了圖像的不同區域 (故越大越好)
所以,這也是為什么LMC(F)=Ldis(F)?λLdiv(F)L_{MC}(F)=L_{dis}(F)-\lambda L_{div}(F)LMC?(F)=Ldis?(F)?λLdiv?(F)這里是做減法
值得說明的是:Ldiv(F)∈[1,ξ]L_{div}(F)\in [1,\xi]Ldiv?(F)∈[1,ξ],取最大值時表示不同channel的特征注意到了圖像的不同區域,取最小值時表示不同的channel的特征只注意到圖像的同一區域
4 Conclusion
MC-Loss通過Ldis(F)L_{dis}(F)Ldis?(F)使一個類別的ξ\xiξ個channel盡可能學習該類別最有判別性的特征(如上圖中同類別的多個通道都變成了同顏色),Ldiv(F)L_{div}(F)Ldiv?(F)使各channel關注圖像的不同空間位置(如上圖中一組ξ\xiξ個channel的特征的不同位置有了加深區域)
5 Core Code
def Mask(nb_batch, channels):foo = [1] * 2 + [0] * 1 # [1, 1, 0]bar = []for i in range(200):random.shuffle(foo)bar += foo# after the loop: bar->600bar = [bar for i in range(nb_batch)]bar = np.array(bar).astype("float32")bar = bar.reshape(nb_batch, 200 * channels, 1, 1)bar = torch.from_numpy(bar)bar = bar.cuda()bar = Variable(bar)return bar# calculate L_MC def supervisor(x, targets, height, cnum):mask = Mask(x.size(0), cnum)# calculate L_divbranch = xbranch = branch.reshape(branch.size(0), branch.size(1), branch.size(2) * branch.size(3))# Softmaxbranch = F.softmax(branch, 2)branch = branch.reshape(branch.size(0), branch.size(1), x.size(2), x.size(2))# CCMPbranch = my_MaxPool2d(kernel_size=(1, cnum), stride=(1, cnum))(branch)branch = branch.reshape(branch.size(0), branch.size(1), branch.size(2) * branch.size(3))# SUMloss_2 = 1.0 - 1.0 * torch.mean(torch.sum(branch, 2)) / cnum # set margin = 3.0# calculate L_dis# CWAbranch_1 = x * mask # channel-wise dropout# CCMPbranch_1 = my_MaxPool2d(kernel_size=(1, cnum), stride=(1, cnum))(branch_1) # GAPbranch_1 = nn.AvgPool2d(kernel_size=(height, height))(branch_1) branch_1 = branch_1.view(branch_1.size(0), -1)# Softmaxloss_1 = criterion(branch_1, targets)return [loss_1, loss_2] # MC_loss includes 2 parts: dis and divclass model_bn(nn.Module):def __init__(self, feature_size=512, classes_num=200):super(model_bn, self).__init__()self.features_1 = nn.Sequential(*list(VGG('VGG16').features.children())[:34])self.features_2 = nn.Sequential(*list(VGG('VGG16').features.children())[34:])self.max = nn.MaxPool2d(kernel_size=2, stride=2)self.num_ftrs = 600 * 7 * 7self.classifier = nn.Sequential(nn.BatchNorm1d(self.num_ftrs),# nn.Dropout(0.5),nn.Linear(self.num_ftrs, feature_size),nn.BatchNorm1d(feature_size),nn.ELU(inplace=True),# nn.Dropout(0.5),nn.Linear(feature_size, classes_num),)def forward(self, x, targets):x = self.features_1(x)x = self.features_2(x)if self.training:MC_loss = supervisor(x, targets, height=14, cnum=3)x = self.max(x)x = x.view(x.size(0), -1)x = self.classifier(x)loss = criterion(x, targets) # cross_entropy lossif self.training:return x, loss, MC_loss # return ce_loss and MC_losselse:return x, loss# in train function out, ce_loss, MC_loss = net(inputs, targets) loss = ce_loss + args["alpha_1"] * MC_loss[0] + args["beta_1"] * MC_loss[1] loss.backward()上面即是MC-Loss的核心代碼,其余部分其實就是搭建CNN的代碼(可替換成自己的神經網絡)。
總結
以上是生活随笔為你收集整理的【CV细粒度识别论文总结】The Devil is in the Channels: Mutual-Channel Loss for Fine-Grained Image Classification的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 高中英语语法(005)-五大句型(下)
- 下一篇: 量化交易之股票数据的获取——同花顺软件