作者:Amit Chaudhary
編譯:ronghuaiyang
導讀
視覺上的自監督學習方法,結合聚類,將無監督轉變為有監督。
許多自監督方法使用[pretext tasks](https://amitness.com/2020/02/illustrated-selfsupervision -learning/)來生成代理標簽,并將無監督學習問題轉化為有監督學習的問題。一些例子包括旋轉預測,圖像著色,拼圖等。然而,這樣的pretext任務是依賴于領域的,需要專業知識來設計它們。
DeepCluster是Facebook AI研究的Caron等人提出的一種自監督方法,帶來了一種不同的方法。這種方法不需要特定于領域的知識,可以用于學習缺乏注釋數據的場景的深層表示。
DeepCluster
DeepCluster結合了兩部分:無監督聚類和深度神經網絡。提出了一種端到端聯合學習深度神經網絡參數及其表示的聚類分配的方法。這些特征被迭代地生成和聚合,最后得到一個訓練過的模型和標簽作為輸出結果。
Deep Cluster Pipeline
現在讓我們了解一下深度聚類的pipleline是如何工作的。
End to End Pipeline of DeepCluster Paper
簡介:
如上圖所示,將拍攝未標記的圖像并對其應用圖像增強。然后,使用AlexNet或vgg16等ConvNet架構作為特征提取器。首先,對ConvNet進行隨機權值初始化,并在最終的分類頭之前從層中取特征向量。然后使用PCA對特征向量進行降維,同時進行白化和L2歸一化。最后,將處理后的特征傳遞到K-means,對每幅圖像進行聚類分配。
這些聚類分配被用作偽標簽,并訓練ConvNet來預測這些聚類。用交叉熵損失來衡量模型的性能。模型訓練了100個epoch,每個epoch進行一次聚類的操作。最后,我們可以將學到的表示用于下游任務。
手把手的例子
讓我們通過一個從輸入數據到輸出標簽的整個pipeline的一步步例子來看看DeepCluster是如何實際應用的:
1. 訓練數據
我們從ImageNet數據集中提取未標記的圖像,該數據集包括130萬張圖像,均勻分布在1000個類中。這些圖像的minibatch為256。
Example of ImageNet datasets for DeepCluster
N幅圖像的訓練集在數學上可以表示為:
2. 圖像增強
將各種變換應用于圖像,以便學習到的不受增強的影響的特征。分別在訓練模型學習表示和將圖像表示發送到聚類算法時進行了兩種不同的增強:
Case 1: 聚類時使用的變換
當要把模型表示送去進行聚類時,不使用隨機增強。圖像簡單地調整為256×256,并使用中心剪裁得到224×224的圖像。然后應用歸一化。
Augmentations done during clustering in DeepCluster
在PyTorch中,可以這樣實現:
from PIL import Image
import torchvision.transforms as transforms
im = Image.open('dog.png')
t = transforms.Compose([transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])])
aug_im = t(im)
Case 2: 訓練模型時候的變換
當模型在圖像和標簽上進行訓練時,我們使用隨機增強。圖像裁剪為隨機大小和高寬比,然后調整為224*224。然后,圖像水平翻轉的概率為50%。最后,利用ImageNet均值和方差對圖像進行歸一化。
Sequence of Image Augmentations Used before passing to model
在PyTorch中,可以這樣實現:
from PIL import Image
import torchvision.transforms as transforms
im = Image.open('dog.png')
t = transforms.Compose([transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])])
aug_im = t(im)
Sobel變換
一旦我們得到了歸一化的圖像,我們就把它轉換成灰度。然后,我們使用Sobel濾波器增加圖像的局部對比度。
Sobel Transformation in DeepCluster
下面是改編自作者實現的簡化代碼片段,我們可以將它應用到上面得到的增強圖像aug_im上。
import torch
import torch.nn as nn
# Fill kernel of Conv2d layer with grayscale kernel
grayscale = nn.Conv2d(3, 1, kernel_size=1, stride=1, padding=0)
grayscale.weight.data.fill_(1.0 / 3.0)
grayscale.bias.data.zero_()
# Fill kernel of Conv2d layer with sobel kernels
sobel = nn.Conv2d(1, 2, kernel_size=3, stride=1, padding=1)
sobel.weight.data[0, 0].copy_(
torch.FloatTensor([[1, 0, -1],
[2, 0, -2],
[1, 0, -1]])
)
sobel.weight.data[1, 0].copy_(
torch.FloatTensor([[1, 2, 1],
[0, 0, 0],
[-1, -2, -1]])
)
sobel.bias.data.zero_()
# Combine the two
combined = nn.Sequential(grayscale, sobel)
# Apply
batch_image = aug_im.unsqueeze(dim=0)
sobel_im = combined(batch_image)
3. 確定聚類的數量(類別數)
要進行聚類,我們需要決定聚類的數量。這將是模型將要訓練的類的數量。
Impact of number of clusters on DeepCluster model
默認情況下,ImageNet有1000個類,但是本文使用了10,000個聚類,因為這樣可以對未標記的圖像進行更細粒度的分組。例如,如果你以前有一組貓和狗,你增加聚類,然后可以創建貓和狗品種的分組。
4. 模型結構
本文主要采用AlexNet架構,由5個卷積層和3個全連接層組成。刪除LRN層,使用Batch Normalization。也添加了Dropout。使用的卷積尺寸為2012年比賽所用的:96, 256, 384, 384, 256。
AlexNet Architecture Used in DeepCluster
另外,本文還嘗試用帶batch normalization的vgg16替換AlexNet,以查看對性能的影響。
5. 生成初始的標簽
為了生成用于訓練的模型的初始標簽,我們使用隨機權重初始化AlexNet,并去除最后一個完全連接的層FC3。我們在圖像上對模型進行前向傳遞,并在圖像上取來自模型的第二個全連接層FC2的特征向量。該特征向量的維數為4096。
How Feature Vectors are taken from AlexNet for Clustering
對整個數據集的batch中的所有圖像重復此過程。因此,如果我們有N幅圖像,我們將得到一個圖像特征矩陣[N, 4096]。
The Image-Feature Matrix Generated in DeepCluster
6. 聚類
在聚類之前,對圖像特征矩陣進行降維處理。
Preprocessing for clustering in DeepCluster
在降維方面,采用主成分分析(PCA)方法,將特征從4096維降至256維,然后進行白化。本文使用faiss庫來進行大規模操作。Faiss提供了一種有效的PCA實現方法,可以應用于圖像特征矩陣x:
import faiss
# Apply PCA with whitening
mat = faiss.PCAMatrix(d_in=4096, d_out=256, eigen_power=-0.5)
mat.train(x)
x_pca = mat.apply_py(x)
然后,對PCA后得到的值進行L2歸一化處理。
import numpy as np
norm = np.linalg.norm(x_pca, axis=1)
x_l2 = x_pca / norm[:, np.newaxis]
這樣,我們最終得到了N幅圖像的矩陣(N, 256)?,F在對預處理后的特征進行K-means聚類,得到圖像及其對應的聚類。這些聚類將充當偽標簽,模型將在其上進行訓練。
Complete Pipeline from Image to Clustering in DeepCluster
本文使用Johnson的K-means實現,faiss庫里有。因為聚類必須在所有圖像上運行,所以它需要花費總訓練時間的三分之一。
聚類完成后,將創建新的圖像batch,這樣來自每個聚類的圖像都有相同的被包含的機會。對這些圖像進行隨機增強。
7. 表示學習
一旦我們有了圖像和聚類,我們就像訓練常規的監督學習一樣訓練我們的ConvNet模型。我們使用256的batch size,并使用交叉熵損失來比較模型預測和ground truth聚類標簽。模型可以學習到有用的表示。
Representation Learning Part of the DeepCluster Pipeline
8. 在模型訓練和聚類之間切換
這個模型訓練了500個epochs。聚類步驟在每個epoch開始時運行一次,為整個數據集生成偽標簽。然后,對所有batch繼續使用交叉熵損失對卷積神經網絡進行常規訓練。本文采用動量為0.9、學習率為0.05、權值衰減為10^-5^的SGD優化器。使用用Pascal P100 GPU進行訓練。
DeepCluster的代碼實現
官方實現:https://github.com/facebookresearch/deepcluster,還有AlexNet和Resnet-50的預訓練權重:https://github.com/facebookresearch/deepcluster#pre-trained-models。
英文原文:https://amitness.com/2020/04/deepcluster/