Destruction and Construction Learning for Fine-grained Image Recognition
Intro
本文提出一種細粒度圖像分類的方法,即將原圖像拼圖一樣shuffle成不同的block,丟進一個分類器,當然,直接這樣訓練會引入shuffle帶來的無關噪聲,所以又加上了adversarial learning和construction learning,類比自編碼器,其實這樣的操作是使得網絡學習到的feature map更加貼近正常圖片的feature map,防止網絡輸出的feature map引入過多的噪聲,從而關注真正對細粒度分類有用的部分。整個過程相當於用三個放大鏡,層層篩選,篩選得到不管怎么shuffle都對細粒度分類有用的特征。
整個網絡的結構如下圖所示,清晰明了:
Region Confusion Mechanism
這一部分是“拼圖”打亂的過程。
文章中對該部分的描述比較模糊,我看了一下沒怎么看懂,就直接取找了一下源碼,看了一下源碼瞬間就秒懂了。
首先將原圖划分為NxN個patch,然后遍歷每個patch,遍歷每個patch時,將行patch的該位置減k到該位置所有的patch shuffle,然后將列patch做同樣的操作,直到遍歷完所有像素。細節見代碼,畢竟talk is cheap:
def swap(img, crop):
def crop_image(image, cropnum):
width, high = image.size
crop_x = [int((width / cropnum[0]) * i) for i in range(cropnum[0] + 1)]
crop_y = [int((high / cropnum[1]) * i) for i in range(cropnum[1] + 1)]
im_list = []
for j in range(len(crop_y) - 1):
for i in range(len(crop_x) - 1):
im_list.append(image.crop((crop_x[i], crop_y[j], min(crop_x[i + 1], width), min(crop_y[j + 1], high))))
return im_list
widthcut, highcut = img.size
img = img.crop((10, 10, widthcut-10, highcut-10))
images = crop_image(img, crop)
pro = 5
if pro >= 5:
tmpx = []
tmpy = []
count_x = 0
count_y = 0
k = 1
RAN = 2
for i in range(crop[1] * crop[0]):
tmpx.append(images[i])
count_x += 1
if len(tmpx) >= k:
tmp = tmpx[count_x - RAN:count_x]
random.shuffle(tmp)
tmpx[count_x - RAN:count_x] = tmp
if count_x == crop[0]:
tmpy.append(tmpx)
count_x = 0
count_y += 1
tmpx = []
if len(tmpy) >= k:
tmp2 = tmpy[count_y - RAN:count_y]
random.shuffle(tmp2)
tmpy[count_y - RAN:count_y] = tmp2
random_im = []
for line in tmpy:
random_im.extend(line)
# random.shuffle(images)
width, high = img.size
iw = int(width / crop[0])
ih = int(high / crop[1])
toImage = Image.new('RGB', (iw * crop[0], ih * crop[1]))
x = 0
y = 0
for i in random_im:
i = i.resize((iw, ih), Image.ANTIALIAS)
toImage.paste(i, (x * iw, y * ih))
x += 1
if x == crop[0]:
x = 0
y += 1
else:
toImage = img
toImage = toImage.resize((widthcut, highcut))
return toImage
Adversarial Learning
如上所說,對抗訓練的目的是為了給網絡加一層約束,即讓網絡學習到的特征能夠過濾掉shuffle帶來的noise,從而學習到對細粒度分類更加有幫助的特征。
因此只需要一個二分類判別器來判斷圖像是否真實即可,其loss可寫為:
其中\(I\)表述輸入圖像,D為二分類神經網絡,\(\textbf{d}_I\)表示gt的one-hot表示,\(\phi\)表示RCM操作。
上式相當於是兩個二分類交叉熵的和,因為公式是對正例和負例同時做的(因為可以直接得到兩個),所以求和很好理解。
Construction Learning
與上面對抗訓練一樣,重建支路帶來的梯度回傳同樣可以指導網絡學習更加有用的feature,這在很多paper都用到了,討論班的時候也聽學長們講過。
該部分的設計是使得網絡學習將結構后的feature map映射到原來沒有RCM的位置,也就是patch的下標。因此,重構網絡的輸出必須是\(2 \cdot N \cdot N\)的,文章的做法是先接一個1×1 conv將結構網絡輸出的feature map 轉化為channel為2的feature map,然后relu+pooling,使得網絡的輸出剛好為\(2\cdot N \cdot N\)的。
其Loss定義為:
其中,\(\sigma(i,j)\)表示(i,j)經過RCM變換后的位置M表述重構網絡,\(M_{(i,j)}\)表示取重構網絡輸出結果的第(i,j)個向量,因為該處的feature對應的應該是未經過RCM的原圖的(i,j)位置,所以兩者的target都是(i,j).
最終聯合訓練的loss為: