Few-shot Learning
問題定義
Few-shot Learning 是 Meta Learning 在監督學習領域的應用。Meta Learning,又稱為learning to learn,該算法旨在讓模型學會“學習”,能夠處理類型相似的任務,而不是只會單一的分類任務。舉例來說,對於一個LOL玩家,他可以很快適應王者榮耀的操作,並在熟悉后打出不錯的戰績。人類利用已經學會的東西,可以更快的掌握一些新事物,而傳統的機器學習方法在這方面的能力還有所欠缺,因此提出了元學習這個概念。
Meta learning 中,在 meta training 階段將數據集分解為不同的 meta task,去學習類別變化的情況下模型的泛化能力,在 meta testing 階段,面對全新的類別,不需要變動已有的模型,就可以完成分類。
在 few-shot learning 中有一個術語叫做 \(N-way\ K -shot\) 問題。形式化來說,few-shot 的訓練集中包含了很多的類別,每個類別中有多個樣本。在訓練階段,會在訓練集中隨機抽取 N 個類別,每個類別 \(K\) 個樣本(總共 \(N*K\) 個數據),構建一個 meta-task,作為模型的支撐集(support set)輸入;再從這 \(N\) 個類中剩余的數據中抽取一批(batch)樣本作為模型的預測對象(batch set)。即要求模型從 \(N*K\) 個數據中學會如何區分這 \(N\) 個類別,這樣的任務被稱為 \(N-way\ K-shot\) 問題。
那這個小型分類任務的訓練集和測試集具體是怎么划分的呢?
以5-Way 5-Shot分類問題為例,在構建一個任務的數據集時的具體流程應該如下:
-
從元數據集(Meta-dataset)中隨機抽取5類(way)樣本,每一類樣本隨機抽取5+1個(shot)實例
元數據集
:就是指整體數據集中可以理解為傳統的大型數據集,其中數據類別>>N-Way,每一類的實例數量>>K-Shot
-
從這5類樣本的6個實例中,每類樣本隨機抽取5個實例一起作為Training Set(→
Support Set
),每一類剩下的一個實例一起組成Testing Set(→Query Set
)- 由於元學習是以任務(Task)作為自己的訓練數據的,即元學習的實際訓練集和測試集是由一個個的Task組成的,所以為了進行區分,每個任務內部的訓練集(Training Set)更名為支持集(Support Set)、測試集更名為查詢集(Query Set)
-
訓練:從Support Set中每一類隨機選取一個實例,一起夠成一組訓練數據,輸入到模型中,進行訓練
-
測試:從Query Set中隨機抽取一個實例,用模型判斷其屬於哪一類
這個判斷過程其實可以視為一種查詢過程,給定了支持集,只要讓模型能夠准確的查詢到其屬於支持集中的哪一類即可證明模型性能較好
-
重復幾輪,最終得出該任務模型的准確率,實際上即是
元學習參數確定的模型在該任務上的損失
-
損失梯度反向傳播到元學習參數,對其進行更新,也即元學習過程
way 1 (c1) | way 2 (c2) | way 3 (c3) | way 4 (c4) | way 5 (c5) | |
---|---|---|---|---|---|
\(c_{11}\) | \(c_{21}\) | \(c_{31}\) | \(c_{41}\) | \(c_{51}\) | Support |
\(c_{12}\) | \(c_{22}\) | \(c_{32}\) | \(c_{42}\) | \(c_{52}\) | Support |
\(c_{13}\) | \(c_{23}\) | \(c_{33}\) | \(c_{43}\) | \(c_{53}\) | Support |
\(c_{14}\) | \(c_{24}\) | \(c_{34}\) | \(c_{44}\) | \(c_{54}\) | Support |
\(c_{15}\) | \(c_{25}\) | \(c_{35}\) | \(c_{45}\) | \(c_{55}\) | Support |
\(c_{16}\) | \(c_{26}\) | \(c_{36}\) | \(c_{46}\) | \(c_{56}\) | Query |
Meta learning
在進一步了解小樣本學習前,先得了解元學習的相關內容。
元學習的核心想法是先學習一個先驗知識(prior),這個先驗知識對解決 few-shot learning 問題特別有幫助。Meta-learning 中有 task 的概念,比如上面圖片講的 5-way 1-shot 問題就是一個 task,我們需要先學習很多很多這樣的 task,然后再來解決這個新的 task 。重要的一點,這是一個新的 task。分類問題中,這個新的 task 中的類別是之前我們學習過的 task 中沒有見過的! 在 Meta-learning 中之前學習的 task 我們稱為 meta-training task,我們遇到的新的 task 稱為 meta-testing task。因為每一個 task 都有自己的訓練集和測試集,因此為了不引起混淆,我們把 task 內部的訓練集和測試集一般稱為 support set 和 query set
Meta-learning 方法的分類標准有很多,為解決過擬合問題,有下面常見的3種方法
- 學習微調 (Learning to Fine-Tune)
- 基於 RNN 的記憶 (RNN Memory Based)
- 度量學習 (Metric Learning)
論文解讀——Model-Agnostic Meta-Learning for Fast Adaptation of Deep Networks
元學習的目標是在各種學習任務上訓練一個可以僅僅使用少量訓練樣本就可以解決新任務的模型,在本文中,模型的參數訓練很明確,所以從新任務的少量樣本做幾步梯度下降就可以在新任務上得到好的泛化性。同時,由於模型可應用於一系列使用梯度下降訓練的模型,包括分類,回歸,強化學習等等,所以也叫作模型無關的模型。
本文的關鍵思想在於訓練模型的初始參數,使得模型的參數在某個新任務上僅適用少量樣本經過一步或者幾步梯度下降更新后就可以早新任務上有很好的表現。從特征學習的角度來看,這是一個建立適應多種任務的內部特征表達的過程,使得其可以更容易,更快速的fine-tune;從動態系統的角度來看,學習過程可以被看做是最大化loss function對於和新任務有關的參數的敏感度,當敏感度高時,參數的小的局部改變可以使loss得到巨大的提高。
文章的title,其中有三個關鍵字Model-Agnostic(與模型無關的)、Fast Adaptation(快速適應)、Deep Networks,這三個關鍵字是文章的核心。
- Model-Agnostic
- task換成其他可以進行SGD過程的模型
- Deep Networks
- 適用於所有的深度學習模型
模型
考慮一個模型,用\(f(x)=a\)表示,我們需要訓練這個網絡使得它可以適應不同的無限的任務
在元學習過程中,模型被訓練以適用於大量或無限任務。任務可以形式化地定義如下
其中\(\mathcal{L} ()\)是損失函數,這個損失是指在測試集上的損失,會在下面詳細敘述。\(q()\)是樣本的分布。由損失函數\(\mathcal{L}\),基於初始觀察值的分布\(q(x_1)\),一個transition分布\(q(x_{t+1}∣x_t,a_t)\),eposide length \(H\)組成。
對於模型要適應的任務分布\(p(\)\(\mathcal{T})\) ,在K-shot learning的設定下,模型從\(p(\)\(\mathcal{T})\)采樣任務\(\mathcal{T}_i\),再從\(q_i\)中采樣\(K\)個樣本,產生由\(\mathcal{T}\)產生的反饋\(\mathcal{L}_{\mathcal{T}_i}\) 。在\(K\)個樣本上訓練,然后在\(\mathcal{T}_i\)的新樣本上進行測試。然后,通過考慮新樣本的測試誤差改變相應的參數以提升模型效果,實際上,在元學習過程中,這個測試誤差被當做是訓練誤差。
算法
在學習過程中,一些特征比其他的更具有遷移性。比如,一個神經網絡可能學到廣泛適應於p(T)中所有任務內部特征,而不是對於某個單獨的任務。為了提取這種更具有一般性的特征,在新任務上使用基於梯度下降的fine-tune的方式去訓練模型。實際上,我們希望找到對於任務改變敏感的參數。
形式上,考慮參數為\(\theta\)的函數\(f_\theta\)表示的模型,當在新任務\(\mathcal{T}_i\)執行一步或者幾步梯度下降后,模型的參數變成了\(\theta_{i}'\),當執行一步梯度更新時,\(\theta_{i}'=\theta-\alpha\bigtriangledown _{\theta}\mathcal{L}_{\mathcal{T}_i}(f_\theta)\)
模型的參數通過從與\(\theta\)對應的\(p(\mathcal{T})\)中采樣的所有任務對應的\(f_{\theta_{i}'}\)進行優化,\(\underset{\theta}{min}\underset{\mathcal{L}_i\sim p(\mathcal{T})}{\sum}\mathcal{L}_{\mathcal{T}_i}(f_{\theta_{i}'})=\underset{\mathcal{L}_i\sim p(\mathcal{T})}{\sum}\mathcal{L}_{\mathcal{T}_i}(f_\theta-\alpha\bigtriangledown _{\theta}\mathcal{L}_{\mathcal{T}_i}(f_\theta))\)
需要注意的是元優化過程是針對模型參數\(\theta\)的,但是是通過更新后的參數\(\theta'\)計算的。在任務間的優化通過SGD,所以參數更新后,\(\theta \leftarrow \theta -\beta \bigtriangledown_{\theta}\underset{\mathcal{L}_i\sim p(\mathcal(T))}{\sum}\mathcal{L}_{\mathcal{T}_i}(f_{\theta_i'})\)
MAML的梯度計算包含二階導數,計算時,需要額外的反向傳播來計算海瑟矩陣。本文中,同時實驗了不進行這次反向傳播,使用一階導近似的情況,最終准確度是差不多的。說明了MAML的大部分提升來自於基於任務目標優化得到的梯度,而不是通過梯度的二次微分。
分類或回歸問題
所謂的task在圖片分類的這個實驗中就是一個普通的卷積神經網絡,當然作者實驗中也提供了不是卷積神經網絡的普通網絡的版本。這個網絡圖如下:
- 對於分類問題,使用交叉熵損失函數
- 對於回歸問題,使用MSE
其中\(p(\mathcal{T})\) 是Task的分布,其實在實現中並沒有去特別的設定,個人覺得就是對樣本采樣的那一塊就順帶形成了,只是不清楚是什么分布。\(\alpha,\beta\)分別是task中的進行梯度下降的學習率、和meta-learning過程的學習率,\(\theta\)是模型(神經網絡的參數)\(f\)的權重參數。
偽代碼解釋
- 初始化參數\(\theta\)
- wheil:
- 抽取task,就是形成可能由不同內別圖片組成的數據集,在作者提供的代碼中,設定一個抽取4個Task,作為meta-learning的一個batch。在5-way 5-shot的情境下,作者為一個task抽取了100張照片,也就是5x20,5個類別,每個類別20張圖片。task之間的5個類別有可能由重復的類別,也有可能不一樣,這個是隨機的
- for——對於每個task:
- 采樣數據,把數據分成兩部分,在5-way 5-shot設定中,一個類別只能使用5個樣本來學習,那么把這100張照片分成5x5的訓練集,以及5x15的驗證集
- 計算使用訓練集得到的Loss,在圖片分類的實驗中,使用的是交叉熵函數。
- 通過Loss來計算SGD,即利用梯度更新得到\(\theta '\)
- 使用驗證集在經過6,7步調整的權重下計算test error。6,7,8三個步驟在圖片分類的實驗中循環了5次
- end for
- 使用4個Task中的test error(5次循環中的最后一次)的平均值作為meta-learning的損失函數,來進行SGD過程
- end while
在一個task中,使用左邊的訓練集做5次SGD的過程,再使用右邊的測試集計算test error,在meta-learning過程中,把一個batch的4個task的test error平均一下作為loss再去進行優化。這個過程結束后,神經網絡的權重到達了下圖中的P點
那么,我們再使用這個模型或者測試這個模型的准確度怎么用呢?
例如把100類圖片分成了3個子集,train中有64個類,用於上述的meta-learning。
現在要將這個模型用在新的任務集具有16個類的test數據集上。仔細一想,訓練好的模型並沒有看見過test數據集中任何類。
現在就是要說論文標題中的Fast Adaptation的關鍵字了,在5-way 5-shot設定中,在測試的時候從test數據集中隨機抽取5個類,每個類抽取N(>5)張照片,其中5張照片,用來微調模型中的參數,比如說在一個新任務下,把模型的參數調整至\(\theta^*_3\)的位置,就是task做的事,即在新任務下只用5張照片來學習一下,用剩下的照片來預測並計算精度。
小樣本學習要解決什么問題?
舉一個例子,假如有如圖的兩類動物,左邊一類是犰狳,右邊一類是穿山甲,現在請你仔細區分一下它們。但是我並不告訴你到底什么是犰狳,什么是穿山甲。現在,我新給你一個圖像,請你判斷是犰狳還是穿山甲。
它顯然是穿山甲。這是人的能力,僅僅從一個很小的甚至為1的樣本量就可以進行同類或異類的區分。我們希望機器也能夠具有這樣僅僅根據很小的樣本量就可以區分同類和異類的能力。但是這樣小的樣本不可能用來訓練一個深度神經網絡,那該怎么辦呢?
我們首先回顧一下傳統的強監督分類問題。簡化來說,我們有一個訓練集,訓練集中包含很多類別,每個類別下有很多同類樣本。現在來了一個測試圖片,注意這個測試圖片本身是訓練集沒有見過的,但是!他的類別一定在訓練集中有。比如下圖所示:測試圖片是一個哈士奇,但是在訓練集中是有哈士奇這一類,所以網絡已經見過很多的哈士奇了。
對於小樣本問題,我們還是有訓練集,這個訓練集和之前傳統的強監督的差不多。但是現在這個測試圖像(FSL中叫做Query)訓練集既沒見過,他的類別訓練集中也沒有!比如下圖,訓練集中有哈士奇,大象,虎哥,鸚鵡和車五類,測試圖片卻是一個兔子。但是呢,我們有一些數量很少的卡片,叫做Support Set,它里面包含幾個類別(標注),每個類別下有很少量的圖片。已知Query一定來自Support Set中的一類。但是Support Set本身又無法支持網絡的訓練。
現在我們想要讓機器和人一樣只根據數量很少的樣本就能夠判斷Query是Support Set中的哪一類。這就是小樣本學習要解決的問題。
‘
小樣本學習的幾個概念
小樣本學習的數據集包含三個,一個是Training Set,一個是Support Set,另一個是Query。我剛學到這里時,對Training Set非常疑惑,既然Query的類別Training Set中都沒有,那么為什么我們還需要Training Set?其實我們需要在Training Set上訓練網絡能夠區分同類和異類的能力,這種能力的訓練是需要大量樣本的。后面就知道啦。
現在我們來看Support Set,Support Set中有k類樣本,每類中有n個樣本,我們將類別數叫做k-way,將每類中的樣本數叫做n-shot。如圖中這個就是4-way,2-shot。顯然,當way越多n越少的時候,就越困難。注意,當每類下就一個樣本時,叫做one-shot,這個是最困難的,也是目前比較火的。
怎么解決?
那我們怎么來解決這個問題呢?最主要的思路也很簡單,那就是看Query和Support Set中的哪一類更像唄!用學術語言來說,就是Learn a similarity function。那就得先讓網絡知道什么是像!但是Support Set中就那么幾個,網絡學不會啊。這個時候之前說的Training Set就派上用場了。原來我們不是用它來訓練一個分類器來分哪一個是虎哥,哪一個是大象,我們是要用它來讓網絡學習什么是像,什么是不像!
具體來看就是學習下面的這個sim函數,當兩張圖像是同一類時,sim=1,是不同類的時候sim=0。學會了像以后,就讓網絡來看Query和Support Set中的哪一個最像,那么Query就屬於Support Set中的哪一類。這個問題就解決啦。
讓網絡學習什么是像,什么是不像
讓網絡學會什么是像,什么是不像,這是最基本的想法也是最重要的一環。以下簡單介紹幾種經典的方法。
Learning Pairwise Similarity Scores
這個思想比較簡單,既然Training Set中有很多類,每類中也有很多樣本,那么就來構造正負樣本對來讓網絡學習哪些是像的,哪些是不像的。
如圖所示,訓練集中包含五類,我們使用類中的樣本構造正樣本,即他們是相似的;用類間的樣本構造負樣本,即他們是不相似的。我們給正樣本給予標簽1,負樣本給予標簽0。可以看到,這樣構造的話,我們的映射關系,就是輸入是一個圖像對,標簽是0或者1。我們如何設計網絡結構呢?
答案是使用孿生網絡Siamese Network,它的輸入是兩個圖像,並按照完全相同(共享)的權重將兩幅圖像映射到embedding中。然后我們將這兩個圖像在特征空間的embedding求一個距離,或者做差之后通過全連接層進一步映射,最后通過sigmoid函數和我們的標簽結合起來。這樣網絡就可以端到端的來學習什么是像啦。
然后呢,我們將Quary與Support Set中的每一個樣本均進行以上測試,最后sigmoid輸出的sim值越接近1,就說明Quary和這個樣本越像,最后找到那個最像的就可以啦!
Triplet Loss
之前我們構造樣本對每次都是一個正樣本對一個負樣本對這樣來構造,這樣其實並不能很明顯的進行對比。於是三個樣本的構造方法就出現了。首先我們在測試集中的某一類中選擇一個錨點樣本,比如那個虎哥。然后我們在虎哥所在的這一類中,再選一個虎弟作為正樣本;然后不在虎這一類里面選了,再到其他類里面選一個作為負樣本。這樣我們就選好了三個樣本。
然后我們依然使用孿生網絡來進行特征提取,只不過現在在一次訓練的過程中,我們計算兩個正樣本之間的特征距離和兩個負樣本之間的特征距離,接下來就是定義損失函數了。
對於正樣本們,我們當然希望它們在特征空間的距離盡可能地靠近,近成0了那最好;
對於負樣本對,我們盡可能地希望它們在特征空間的距離盡可能遠離,那么多遠就算遠了呢,我們需要給定一個條件。因此我們定義一個\(\alpha\),當兩個負樣本之間的距離比正樣本之間的距離遠到α的時候,我們就認為足夠了,loss=0,這樣正樣本之間的距離太遠了不行,負樣本之間的距離太近了也不行。所以這種思想是一種對比的思想,將相似的樣本在特征空間拉近,而將不相似的樣本在特征空間推遠。
之后我們來進行預測,我們分別計算Quary和每個樣本之間的距離,選距離最小的那個作為最終的決策類。
Pretraining and Fine-tuning
我們之前的思路是在訓練集上讓網絡學會什么是像,然后直接測試Quary和Support Set。其實Support Set在訓練集中也沒有,甚至連類別都沒有見過,網絡可能會有點害怕。那么能不能讓網絡也見見Support Set呢,答案是可以的!而且能漲好多點!
首先我們從余弦相似度說起,已知兩個單位向量,它們之間的余弦相似度就是它們的內積,當夾角越小的時候,兩個向量更像。因此余弦相似度可以表示兩個向量的相似程度,常常用在特征空間。當兩個向量不是單位向量時,需要先對其進行歸一化,然后再求內積。
我們再來說Softmax函數。Softmax函數可以將一組數轉化為每個數對應的概率值,概率和為1。當然,這樣轉化會使本來大的數更大,但是卻比直接max要溫和。那么所謂的softmax分類器,無非就是將一個d1的輸入向量左乘一個kd的權重矩陣,再加一個偏置,得到對應k類的概率值。這個權重是根據loss計算的。
好啦,下面我們開始具體說。我們還是在大型的訓練集上訓練我們的網絡。只不過不直接在Support Set上進行測試。我們將Support Set中的每一類樣本使用訓練好的網絡進行特征提取,如果每一類中有一些樣本,那么我們對他們的embedding進行平均。之后我們進行歸一化,這是為了后面更好的計算余弦相似度。這樣一來我們得到了Support Set中這些類的平均歸一化embedding。
接下來我們也對Query提取embedding,並使用之前Support Set提取的embedding初始化權重矩陣M。我們可以看出M中的每一行其實都代表Support Set中每一類的特征。接下來我們使用Support Set中的樣本根據softmax分類器進行fintuning。我們使用M來直接初始化softmax的權重矩陣W,這是因為Support Set中的樣本數量太少了,如果隨機初始化參數,則效果並不好。其實不難發現,我們直接求Q與M的內積再接softmax就可以得到Q屬於M中的哪一類的概率,由於沒有進行fintuning,它的結果還是差一些。
我們使用M作為初始化權重矩陣,之后使用交叉熵函數對Support Set中的所有樣本進行fintuning。
Trick
在fine-tuning的過程中,我們有三個非常好用的Trick。
第一個是我們剛才說過的,在fine-tuning的時候使用Support Set中每類樣本的特征組成的矩陣M進行初始化待訓練權重W,這是因為Support Set中的樣本數量太少了,如果隨機初始化參數,則效果可能不佳。
第二個是使用熵進行正則化。我們知道對於softmax,如果他輸出每一類的概率都差不多,那么說明分類器沒有學好,基本是在瞎猜的狀態,此時它的熵就會很大;但是如果有一類輸出的概率特別大,其他預測概率都很小,那么說明神經網絡此時很有把握,這時它的熵就會很小。我們希望fintuning中神經網絡能給出更有把握的結果,因此加入熵正則化,可以明顯提高性能。
第三個是使用余弦相似度與softmax分類器的組合。我們知道softmax分類器中是權重W與Q相乘來運算的,而我們這里將這個W替換為余弦相似度的計算,也可以提高性能。