作者|Chien Vu
編譯|Flin
來源|towardsdatascience

背景與挑戰??
在現代深度學習演算法中,對未標記資料的手工標注是其主要局限性之一,為了訓練一個好的模型,我們通常需要準備大量的標記資料,在少數類和資料的情況下,我們可以使用帶有標簽的公共資料集的預訓練模型,并使用你的資料微調最后幾層即可,
但是,當你的資料很大時(比如商店中的產品或人的臉,..),很容易遇到問題,并且僅通過幾個可訓練的層就很難學習模型,此外,未標記資料(例如,檔案文本,Internet上的影像)的數量是不可數的,為任務標記所有標簽幾乎是不可能的,但是不使用它們絕對是一種浪費,
在這種情況下,使用新的資料集從頭開始訓練深度模型是一種選擇,但是使用預先訓練的深度模型時標記資料需要花費大量的時間和精力,這似乎不再有幫助,這就是自監督學習誕生的原因,這背后的想法很簡單,主要有兩個任務:
-
代理任務:深度模型將從沒有注釋的未標記資料中學習可歸納的表示,然后能夠利用隱式資訊自行生成監督信號,
-
下游任務:將針對監督學習任務(如分類和影像檢索)對表示進行微調,標記資料的數量更少(標記資料的數量取決于模型的性能,具體取決于你的需求)
學習這些表示有很多不同的訓練方法:
-
相對位置[1]:模型需要理解物件的空間背景關系,以判斷部件之間的相對位置;
-
拼圖游戲[2]:模型需要將9個打亂的補丁放回原始位置;
-
著色[3]:模型已訓練為對灰度輸入影像進行著色;確切的任務是將該影像映射到量化的顏色值輸出上的分布;
-
計數特征[4]:模型利用輸入影像的特征計數關系,通過縮放和平鋪來學習特征編碼器;
-
SimCLR[5]:該模型通過潛在空間中的對比損失來最大化同一樣本不同增強視圖之間的一致性,從而學習視覺輸入的表示形式,
不過,我想介紹一種有趣的方法,它能夠識別像人類一樣的東西,人類學習的關鍵是通過比較相關物體和不同物體來獲取新知識,因此,如果我們能夠通過關系推理方法在自監督機器學習中應用相似的機制,這是一個非常重要的解決方案[6],
關系推理范式基于一個關鍵的設計原則:使用關系網路作為未標記資料集的可學習函式,量化同一物件視圖之間的關系(內部推理)和不同場景中不同物件之間的關系(互動推理),通過在標準資料集(CIFAR-10、CIFAR-100、CIFAR-100-20、STL-10、tiny-ImageNet、SlimageNet)、學習進度和主干(兩者)上的性能來評估通過關系推理在自監督機器學習中利用類似機制的可能性,
結果表明,關系推理方法在所有條件下都比最好的競爭對手平均高出14%的準確率,而最新的方法比此文(https://arxiv.org/abs/2006.05849) 的方法高出3%,
技術亮點??

簡單地說,關系推理只是一種方法論,它試圖幫助學習者理解不同物件(思想)之間的關系,而不是單獨地學習物件,這有助于學習者根據自己的差異輕松地辨別和記憶物體,
關系推理系統有兩個主要組成部分:主干結構和關系頭,在代理任務階段使用關系頭來支持底層神經網路主干學習未標記資料集中的有用表示,然后將其丟棄,在代理任務訓練后,將主干結構用于后續任務,如分類或影像檢索,
-
以前的作業:關注場景內的關系,意思是同一物件中的所有元素都屬于同一場景(例如,籃子中的球);在標簽資料集上進行訓練,主要目標是關系,
-
新的方法:關注同一物件不同視圖之間的關系(內部推理)和不同場景中不同物件之間的關系(互動推理);對未標記的資料使用關系推理,關系頭是學習底層主干中有用表示的代理任務,
讓我們來討論一下關系推理系統某些部分的要點:
- 小批量增強
如前所述,本系統引入了內部推理和互動推理?為什么我們需要他們?當沒有給出標簽時,不可能創建一對相似和不同的物件,為了解決這個問題,采用了自舉技術,形成了內部推理和互動推理,其中:
-
內部推理由對同一物件{A1; A2}(正對)(例如,同一籃球的不同視角)
-
互動推理包括耦合兩個隨機物件{A1; B1}(負對)(例如帶隨機球的籃球)
此外,還考慮使用隨機增強函式(如幾何變換、顏色失真)使場景間的推理更加復雜,這些增強功能的好處迫使學習者(骨干)注意更廣泛的特征(例如顏色、尺寸、紋理等)之間的相關性,
例如,在{foot ball,basket ball}對中,顏色本身就可以很好地預測類,然而,隨著顏色和形狀大小的隨機變化,學習者現在很難區分這兩種顏色之間的差異,學習者必須考慮另一個特征,因此,它可以提供更好的表示,
- 度量學習
度量學習的目的是使用距離度量來接近相似輸入(正輸入)的表示,同時移開不同輸入(負)的表示,然而,在關系推理中,度量學習有著根本的不同:



- 損失函式
學習目標是一個基于表示對的二元分類問題,因此,我們可以使用二進制交叉熵損失來最大化伯努利對數似然,其中關系分數y表示通過sigmoid激活函式誘導的表示成員的概率估計,

最后,本文[6]還提供了在標準資料集(CIFAR-10、CIFAR-100、CIFAR-100-20、STL-10、tiny-ImageNet、SlimageNet)、不同主干(淺層和深層)、相同的學習進度(epochs)上的關系推理結果,結果如下,欲了解更多資訊,請查閱他的論文,
實驗評估??
在本文中,我想在公共影像資料集STL-10上重現關系推理系統,該資料集由10個類(飛機、鳥、汽車、貓、鹿、狗、馬、猴、船、卡車)組成,顏色為96x96像素,
首先,我們需要匯入一些重要的庫
import torch
import torchvision
import torchvision.transforms as transforms
from PIL import Image
import math
import time
from torch.utils.data import DataLoader
from time import sleep
from tqdm import tqdm
import numpy as np
from fastprogress.fastprogress import master_bar, progress_bar
from torchvision import models
import matplotlib.pyplot as plt
from torchvision.utils import make_grid
%config InlineBackend.figure_format = 'svg'
STL-10資料集包含1300個標記影像(500個用于訓練,800個用于測驗),然而,它也包括100000個未標記的影像,這些影像來自相似但更廣泛的分布,例如,除了標簽集中的動物外,它還包含其他型別的動物(熊、兔子等)和車輛(火車、公共汽車等)

然后根據作者的建議創建關系推理類
class RelationalReasoning(torch.nn.Module):
"""自監督關系推理,
方法的基本實作,它使用
“cat”聚合函式(最有效),
可與任何主干一起使用,
"""
def __init__(self, backbone, feature_size=64):
super(RelationalReasoning, self).__init__()
self.backbone = backbone.to(device)
self.relation_head = torch.nn.Sequential(
torch.nn.Linear(feature_size*2, 256),
torch.nn.BatchNorm1d(256),
torch.nn.LeakyReLU(),
torch.nn.Linear(256, 1)).to(device)
def aggregate(self, features, K):
relation_pairs_list = list()
targets_list = list()
size = int(features.shape[0] / K)
shifts_counter=1
for index_1 in range(0, size*K, size):
for index_2 in range(index_1+size, size*K, size):
# 默認情況下使用“cat”聚合函式
pos_pair = torch.cat([features[index_1:index_1+size],
features[index_2:index_2+size]], 1)
# 通過滾動小批無碰撞的洗牌(負)
neg_pair = torch.cat([
features[index_1:index_1+size],
torch.roll(features[index_2:index_2+size],
shifts=shifts_counter, dims=0)], 1)
relation_pairs_list.append(pos_pair)
relation_pairs_list.append(neg_pair)
targets_list.append(torch.ones(size, dtype=torch.float32))
targets_list.append(torch.zeros(size, dtype=torch.float32))
shifts_counter+=1
if(shifts_counter>=size):
shifts_counter=1 # avoid identity pairs
relation_pairs = torch.cat(relation_pairs_list, 0)
targets = torch.cat(targets_list, 0)
return relation_pairs.to(device), targets.to(device)
def train(self, tot_epochs, train_loader):
optimizer = torch.optim.Adam([
{'params': self.backbone.parameters()},
{'params': self.relation_head.parameters()}])
BCE = torch.nn.BCEWithLogitsLoss()
self.backbone.train()
self.relation_head.train()
mb = master_bar(range(1, tot_epochs+1))
for epoch in mb:
# 實際目標被丟棄(無監督)
train_loss = 0
accuracy_list = list()
for data_augmented, _ in progress_bar(train_loader, parent=mb):
K = len(data_augmented) # tot augmentations
x = torch.cat(data_augmented, 0).to(device)
optimizer.zero_grad()
# 前向傳播(主干)
features = self.backbone(x)
# 聚合函式
relation_pairs, targets = self.aggregate(features, K)
# 前向傳播 (關系頭)
score = self.relation_head(relation_pairs).squeeze()
# 交叉熵損失與向后傳播
loss = BCE(score, targets)
loss.backward()
optimizer.step()
train_loss += loss.item()*K
predicted = torch.round(torch.sigmoid(score))
correct = predicted.eq(targets.view_as(predicted)).sum()
accuracy = (correct / float(len(targets))).cpu().numpy()
accuracy_list.append(accuracy)
epoch_loss = train_loss / len(train_loader.sampler)
epoch_accuracy = sum(accuracy_list)/len(accuracy_list)*100
mb.write(f"Epoch [{epoch}/{tot_epochs}] - Accuracy: {epoch_accuracy:.2f}% - Loss: {epoch_loss:.4f}")
為了比較關系推理方法在淺層模型和深層模型上的性能,我們將創建一個淺層模型(Conv4),并使用深層模型的結構(Resnet34),
backbone = Conv4() # 淺層模型
backbone = models.resnet34(pretrained = False) # 深層模型
根據作者的建議,設定了一些超引數和增強策略,我們將在未標記的STL-10資料集上用關系頭訓練主干,
# 模擬的超引數
K = 16 # tot augmentations, 論文中 K=32
batch_size = 64 # 論文中使用64
tot_epochs = 10 # 論文中使用200
feature_size = 64 # Conv4 主干的單元數
feature_size = 1000 # Resnet34 主干的單元數backbone
# 擴充策略
normalize = transforms.Normalize(mean=[0.4406, 0.4273, 0.3858],
std=[0.2687, 0.2613, 0.2685])
color_jitter = transforms.ColorJitter(brightness=0.8, contrast=0.8,
saturation=0.8, hue=0.2)
rnd_color_jitter = transforms.RandomApply([color_jitter], p=0.8)
rnd_gray = transforms.RandomGrayscale(p=0.2)
rnd_rcrop = transforms.RandomResizedCrop(size=96, scale=(0.08, 1.0),
interpolation=2)
rnd_hflip = transforms.RandomHorizontalFlip(p=0.5)
train_transform = transforms.Compose([rnd_rcrop, rnd_hflip,
rnd_color_jitter, rnd_gray,
transforms.ToTensor(), normalize])
# 加載到資料加載器
torch.manual_seed(1)
torch.cuda.manual_seed(1)
train_set = MultiSTL10(K=K, root='data', split='unlabeled', transform=train_transform, download=True)
train_loader = DataLoader(train_set,batch_size=batch_size, shuffle=True,num_workers=2, pin_memory=True)

到目前為止,我們已經創造了訓練我們模型所需的一切,現在我們將在10個時期和16個增強影像(K)中訓練主干和關系頭模型,使用1個GPU Tesla P100-PCIE-16GB在淺層模型(Conv4)上花費4個小時,在深層模型(Resnet34)上花費6個小時(你可以自由地更改時期數以及另一個超引數以獲得更好的結果)
device = torch.device("cuda:0") if torch.cuda.is_available() else torch.device("cpu")
backbone.to(device)
model = RelationalReasoning(backbone, feature_size)
model.train(tot_epochs=tot_epochs, train_loader=train_loader)
torch.save(model.backbone.state_dict(), 'model.tar')
在訓練了我們的主干模型之后,我們丟棄了關系頭,只將主干用于下游任務,我們需要使用STL-10(500個影像)中的標記資料來微調我們的主干,并在測驗集中測驗最終的模型(800個影像),訓練和測驗資料集將加載到Dataloader中,而無需進行擴充,
# set random seed
torch.manual_seed(1)
torch.cuda.manual_seed(1)
# no augmentations used for linear evaluation
transform_lineval = transforms.Compose([transforms.ToTensor(), normalize])
# Download STL10 labeled train and test dataset
train_set_lineval = torchvision.datasets.STL10('data', split='train', transform=transform_lineval)
test_set_lineval = torchvision.datasets.STL10('data', split='test', transform=transform_lineval)
# Load dataset in data loader
train_loader_lineval = DataLoader(train_set_lineval, batch_size=128, shuffle=True)
test_loader_lineval = DataLoader(test_set_lineval, batch_size=128, shuffle=False)
我們將加載預訓練的主干模型,并使用一個簡單的線性模型將輸出特性與資料集中的許多類連接起來,
# linear model
linear_layer = torch.nn.Linear(64, 10) # if backbone is Conv4
linear_layer = torch.nn.Linear(1000, 10) # if backbone is Resnet34
# defining a raw backbone model
backbone_lineval = Conv4() # Conv4
backbone_lineval = models.resnet34(pretrained = False) # Resnet34
# load model
checkpoint = torch.load('model.tar') # name of pretrain weight
backbone_lineval.load_state_dict(checkpoint)
此時,只訓練線性模型,凍結主干模型,首先,我們將看到微調Conv4的結果
device = torch.device("cuda:0") if torch.cuda.is_available() else torch.device("cpu")
optimizer = torch.optim.Adam(linear_layer.parameters())
CE = torch.nn.CrossEntropyLoss()
linear_layer.to(device)
linear_layer.train()
backbone_lineval.to(device)
backbone_lineval.eval()
print('Linear evaluation')
for epoch in range(20):
accuracy_list = list()
for i, (data, target) in enumerate(train_loader_lineval):
optimizer.zero_grad()
data = https://www.cnblogs.com/panchuangai/p/data.to(device)
target= target.to(device)
output = backbone_lineval(data).to(device).detach()
output = linear_layer(output)
loss = CE(output, target)
loss.backward()
optimizer.step()
# estimate the accuracy
prediction = output.argmax(-1)
correct = prediction.eq(target.view_as(prediction)).sum()
accuracy = (100.0 * correct / len(target))
accuracy_list.append(accuracy.item())
print('Epoch [{}] loss: {:.5f}; accuracy: {:.2f}%' \
.format(epoch+1, loss.item(), sum(accuracy_list)/len(accuracy_list)))
Linear evaluation
Epoch [1] loss: 2.24857; accuracy: 14.77%
Epoch [2] loss: 2.23015; accuracy: 24.49%
Epoch [3] loss: 2.18529; accuracy: 32.46%
Epoch [4] loss: 2.24595; accuracy: 36.45%
Epoch [5] loss: 2.09482; accuracy: 42.46%
Epoch [6] loss: 2.11192; accuracy: 43.40%
Epoch [7] loss: 2.05064; accuracy: 47.29%
Epoch [8] loss: 2.03494; accuracy: 47.38%
Epoch [9] loss: 1.91709; accuracy: 47.46%
Epoch [10] loss: 1.99181; accuracy: 48.03%
Epoch [11] loss: 1.91527; accuracy: 48.28%
Epoch [12] loss: 1.93190; accuracy: 49.55%
Epoch [13] loss: 2.00492; accuracy: 49.71%
Epoch [14] loss: 1.85328; accuracy: 49.94%
Epoch [15] loss: 1.88910; accuracy: 49.86%
Epoch [16] loss: 1.88084; accuracy: 50.76%
Epoch [17] loss: 1.63443; accuracy: 50.74%
Epoch [18] loss: 1.76303; accuracy: 50.62%
Epoch [19] loss: 1.70486; accuracy: 51.46%
Epoch [20] loss: 1.61629; accuracy: 51.84%
然后檢查測驗集
accuracy_list = list()
for i, (data, target) in enumerate(test_loader_lineval):
data = https://www.cnblogs.com/panchuangai/p/data.to(device)
target= target.to(device)
output = backbone_lineval(data).detach()
output = linear_layer(output)
# estimate the accuracy
prediction = output.argmax(-1)
correct = prediction.eq(target.view_as(prediction)).sum()
accuracy = (100.0 * correct / len(target))
accuracy_list.append(accuracy.item())
print('Test accuracy: {:.2f}%'.format(sum(accuracy_list)/len(accuracy_list)))
Test accuracy: 49.98%
Conv4在測驗集上獲得了49.98%的準確率,這意味著主干模型可以在未標記的資料集中學習有用的特征,只需在很少的時間段內進行微調就可以達到很好的效果,現在讓我們檢查深度模型的性能,
device = torch.device("cuda:0") if torch.cuda.is_available() else torch.device("cpu")
optimizer = torch.optim.Adam(linear_layer.parameters())
CE = torch.nn.CrossEntropyLoss()
linear_layer.to(device)
linear_layer.train()
backbone_lineval.to(device)
backbone_lineval.eval()
print('Linear evaluation')
for epoch in range(20):
accuracy_list = list()
for i, (data, target) in enumerate(train_loader_lineval):
optimizer.zero_grad()
data = https://www.cnblogs.com/panchuangai/p/data.to(device)
target= target.to(device)
output = backbone_lineval(data).to(device).detach()
output = linear_layer(output)
loss = CE(output, target)
loss.backward()
optimizer.step()
# estimate the accuracy
prediction = output.argmax(-1)
correct = prediction.eq(target.view_as(prediction)).sum()
accuracy = (100.0 * correct / len(target))
accuracy_list.append(accuracy.item())
print('Epoch [{}] loss: {:.5f}; accuracy: {:.2f}%' \
.format(epoch+1, loss.item(), sum(accuracy_list)/len(accuracy_list)))
Linear evaluation
Epoch [1] loss: 2.68060; accuracy: 47.79%
Epoch [2] loss: 1.56714; accuracy: 58.34%
Epoch [3] loss: 1.18530; accuracy: 56.50%
Epoch [4] loss: 0.94784; accuracy: 57.91%
Epoch [5] loss: 1.48861; accuracy: 57.56%
Epoch [6] loss: 0.91673; accuracy: 57.87%
Epoch [7] loss: 0.90533; accuracy: 58.96%
Epoch [8] loss: 2.10333; accuracy: 57.40%
Epoch [9] loss: 1.58732; accuracy: 55.57%
Epoch [10] loss: 0.88780; accuracy: 57.79%
Epoch [11] loss: 0.93859; accuracy: 58.44%
Epoch [12] loss: 1.15898; accuracy: 57.32%
Epoch [13] loss: 1.25100; accuracy: 57.79%
Epoch [14] loss: 0.85337; accuracy: 59.06%
Epoch [15] loss: 1.62060; accuracy: 58.91%
Epoch [16] loss: 1.30841; accuracy: 58.95%
Epoch [17] loss: 0.27441; accuracy: 58.11%
Epoch [18] loss: 1.58133; accuracy: 58.73%
Epoch [19] loss: 0.76258; accuracy: 58.81%
Epoch [20] loss: 0.62280; accuracy: 58.50%
然后評估測驗資料集
accuracy_list = list()
for i, (data, target) in enumerate(test_loader_lineval):
data = https://www.cnblogs.com/panchuangai/p/data.to(device)
target= target.to(device)
output = backbone_lineval(data).detach()
output = linear_layer(output)
# estimate the accuracy
prediction = output.argmax(-1)
correct = prediction.eq(target.view_as(prediction)).sum()
accuracy = (100.0 * correct / len(target))
accuracy_list.append(accuracy.item())
print('Test accuracy: {:.2f}%'.format(sum(accuracy_list)/len(accuracy_list)))
Test accuracy: 55.38%
這是更好的,我們可以在測驗集上獲得55.38%的精度,本文的主要目的是重現和評估關系推理方法論,以指導模型識別無標簽物件,因此,這些結果是非常有前途的,如果你覺得不滿意,你可以通過改變超引數來自由地做實驗,比如增加數量,時期,或者改變模型結構,
最后的想法??
自監督關系推理在定量和定性兩方面都是有效的,并且具有從淺到深的不同大小的主干,通過比較學習到的表示可以很容易地從一個領域轉移到另一個領域,它們具有細粒度和緊湊性,這可能是由于精度和擴充次數之間的相關性,在關系推理中,根據作者的實驗,擴充的數量對物件簇的質量有著主要的影響[4],自監督學習在許多方面都有很強的潛力成為機器學習的未來,
參考文獻
[1] Carl Doersch et. al, Unsupervised Visual Representation Learning by Context Prediction, 2015.
[2] Mehdi Noroozi et. al, Unsupervised Learning of Visual Representations by Solving Jigsaw Puzzles, 2017.
[3] Zhang et. al, Colorful Image Colorization, 2016.
[4] Mehdi Noroozi et. al, Representation Learning by Learning to Count, 2017.
[5] Ting Chen et. al, A Simple Framework for Contrastive Learning of Visual Representations, 2020.
[6] Massimiliano Patacchiola et. al, Self-Supervised Relational Reasoning for
Representation Learning, 2020.
[7] Adam Santoro et. al, Relational recurrent neural networks, 2018.
原文鏈接:https://towardsdatascience.com/train-without-labeling-data-using-self-supervised-learning-by-relational-reasoning-b0298ad818f9
歡迎關注磐創AI博客站:
http://panchuang.net/
sklearn機器學習中文官方檔案:
http://sklearn123.com/
歡迎關注磐創博客資源匯總站:
http://docs.panchuang.net/
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/178583.html
標籤:其他
上一篇:HTML筆記(詳細)
