作者丨小小理工男@知乎
編輯丨極市平台
導讀
本文作者從圖像空間、特征空間、Loss profile 空間以及利用backpropagated gradient資訊做異常檢測四個方面,結合2019年和2020的頂會論文,對工業圖像上的異常檢測的最新進展進行了總結。
寫在前面
這裡對我最近的研究領域——工業圖像上的異常檢測中最新的一些進展做一個總結。主要總結的是在2019和2020的一些頂會上,關于Semi-supervised或者Unsupervised anomaly detection的一些比較有意思的文章,并給出我自己的一些看法。
由于水準有限,是以大家辯證地看就好,如有不當之處或可補充之處,歡迎指正~
1. 簡要地介紹一下什麼是異常檢測(anomaly detection)
如果将每個樣本看作空間中的一個點的話,異常(anomaly)簡單地來說就是離群點,或者說是“非主流”的點,即離大多數樣本點都比較遠。這裡隐藏的意思是,異常通常是少數。
下圖很形象地展示了什麼是異常。其中,黑色的點為正常的樣本點,紅色的點為異常點樣本點。(更多的介紹可以參考Kiwi:異常檢測概述(一):An Overview of Anomaly Detection Part I https://zhuanlan.zhihu.com/p/50384515)
異常檢測的任務,就是找到正常樣本與異常樣本之間的界線,盡可能地将正常樣本與異常樣本分開。這裡的界線,可以是在各種空間中的,例如圖像空間、特征空間,甚至後文會介紹到的一篇論文中的loss profile空間(現在可能看到這個比較懵逼,後面的文章會介紹這篇文章,還是挺有意思的)。
目前實際的異常檢測遇到的一個很大的困難,是在實際的場景中(例如工業流水線等),異常樣本往往很難獲得,甚至很多時候沒有異常樣本。這就迫使我們采用semi-supervised或者unsupervised的方法。接下來介紹的文章也都是semi-supervised或者unsupervised的方法。
下面我将以做異常檢測的空間為劃分标準,将最近的一些新方法做一個分類。預計将分3-4篇文章介紹完。
2. 圖像空間上的異常檢測方法
圖像空間上的異常檢測一般采用的是下圖的Auto-encoder結構。
圖像空間上的異常檢測方法的主流結構
主要的思想是,如果我們隻在正常樣本的訓練集上訓練我們的Auto-encoder,則我們重構出來的圖像會比較趨近于正常樣本。利用這一個假設/性質,在推理階段,即使輸入的圖像是異常樣本,我們重構出來的圖像也會像正常樣本。是以我們隻需對比原圖和重構後的圖,就可以判斷輸入的圖像是否為異常,甚至可以定位到異常區域。
2.1 MemAE:利用Memory抑制模型的泛化能力
MemAE結構圖
Story:
上文所說的Auto-encoder架構其實隐藏了一個問題:機器學習模型一般都是具有泛化能力的。也就是說,即使我們在隻有正常樣本的訓練集上訓練,在推理階段,如果輸入異常樣本,由于泛化能力的存在,我們的模型也有一定的機率輸出類似于異常的樣本。這時候我們對比原圖和重構後的圖像,會發現非常相似... 這時候我們的異常檢測方法就失效了QwQ。
是以ICCV 2019的一篇文章提出了MemAE來顯式地抑制Auto-encoder的泛化能力。他們的思路是,既然Auto-encoder泛化能力有時候會過強,那麼如果讓輸入decoder的embedding都由正常樣本的embedding組合而成,能夠預計decoder輸出的重構圖像也主要由正常樣本的特征組成。這樣,通過抑制泛化能力來逼迫重構後的圖像貼近于正常樣本。
具體做法是,将所有正常樣本經過encoder得到的embedding儲存在Memory中。當輸入一個圖像時,首先用encoder提取出其embedding,并逐一計算圖像的embedding和memory中的各個embedding的相似度(例如cosine similarity),再用相似度作為權重,将memory中的embedding權重平均得到新的embedding。
得到的這個新的embedding将同時具有兩個特點:
- 比較接近原本圖像的embedding;
- 由正常樣本的特征構成。
再将這個新的embedding輸入decoder中,就可以得到既接近于原圖、又貼近于正常樣本的圖像了。
Tricks:
- 首先是在權重Memory中embedding時weight的計算:
其中 為輸入圖像的embedding, 為memory中第 個embedding, 為對應的權重。
2. 限制參與融合的memory的個數:
文章中提到了一個有趣的現象,當memory中參與融合的embeding過多時,重構後的圖像在異常檢測中的效果會下降。這樣比較好了解:畢竟正常的要素過多,也會組成異常。
為了抑制這個現象,文章中限制了參與融合的embedding個數。一種比較naive的方式如下:
但是上式是不可導的,是以用下式替代:
優缺點總結:
優點:這篇文章提出了一個非常好的想法來抑制auto-encoder的泛化能力——加入隻由正常樣本特征構成的memory。據我所知,這應該是第一篇将memory引入異常檢測的文章,能夠算是一篇挖坑之作。後續也有文章跟進這一方面的研究。
缺點:一般來說由于缺少類似于U-net中的skip connection的存在,auto-encoder重構出來的圖像一般都比較糊。此篇也不例外。這就給異常區域的定位帶來了一定的困難。是以可以看到此篇文章的實驗都是在比較簡單的資料集上(例如MNIST, cifar10等)做的實驗,而且隻能将圖檔分類為正常或異常,而不能定位到異常的位置。我覺得後續如何在隻用正常樣本的特征情況下,重構出清晰的圖,進而定位到異常區域位置也是一個可以挖的點。
2.2 Memory的進一步改進
這是CVPR 2020的一篇文章,可以看作是在上一篇文章之上的更新版。我個人認為這篇文章對上一篇文章的改進之處主要有以下幾點:
- 增加了memory update的機制,隻需存儲固定個數的memory;
- 引入了feature compactness loss 和 feature separateness loss,減少需要儲存的memory的數量;
- 采用了将原圖的embedding和memory中的embedding結合輸入decoder的方式,一定程度上解決了重構後的圖像比較糊的缺點,進而可以定位到異常區域的位置,進而可以運用到一些更加複雜、貼近現實情況的資料集上。
這裡主要介紹一下feature compactness loss和feature separateness loss。
feature copactness loss的作用是使得memory中的embedding和資料集中圖像的embedding盡可能的接近。其計算公式如下圖。具體地,對于圖像的每一個embedding ,找到memory中與其距離最近的embedding ,使得它們的距離越小越好。
feature compactness loss公式. K為一個圖像的embedding (query) 的個數,T為視訊的幀數
feature separateness loss的作用則是使得memory中的embedding相距越大越好。想象一下,如果僅有feature compactness loss,則memory中的embedding會有一種趨于一緻的趨勢,那麼memory就沒有什麼存在的意義了。
feature separateness loss的計算公式如下。對于圖像的每一個embedding ,找到memory中與其距離最近的embedding 和距離第二近的embedding ,使得 和 的距離越小越好, 和 的距離越大越好。
2.3 利用bad quality reconstructed image做異常檢測
這是CVPR 2020的一篇論文中的工作,是一種無監督異常檢測的方法,模型名稱為OGNet。
OGNet架構
Story:
這篇文章總體不是嚴格的Auto-encoder架構,而是采用另一種在異常檢測領域也比較常用的架構——GAN。一般的用GAN做異常檢測有兩種思路:
- 用generator重構圖像,discriminator隻是用來幫助generator更好地重構圖像。在判斷異常時,類似于auto-encoder檢測異常的思路,用generator重構後的圖像和原圖做對比,不同處認為是異常;
- 總體思路與1中類似,隻是在檢測異常時,綜合generator和discriminator的結果作為判斷異常的依據。
這篇文章的亮點就是将discriminator的任務做了轉化:區分圖像為原圖還是generator生成的圖 -> 區分是高品質重構圖像還是低品質重構圖像。按照文章中的說法,這樣可以使得在判斷異常時,discriminator更能找到generator重構異常圖像時的細微的擾動,進而更加取得更好的異常檢測效果。
Tricks:
這篇文章的細節有幾個需要注意的點:
- 如何生成高品質和低品質的重構圖像?
作者的想法很簡單:将訓練分為兩個階段。
第一個階段按照通常的方法訓練GAN,即generator負責重構圖像,discriminator負責判斷圖像為原圖還是重構的圖像;
第二階段選用兩個generator:一個是第一階段中訓練好的generator(即圖中的 ),另一個是第一階段中訓練的次數較少的generator(即圖中的 )。認為 生成的圖像為高品質重構圖像, 生成的圖像為低品質重構圖像。
此外,文章中還提出了另一種bad quality examples——僞異常重構圖像(pseudo-anomaly recontructed image),即人為地僞造異常的圖像。僞異常重構圖像生成的方式如下圖所示,即從訓練集中随機選取兩張圖像,用 重構後将結果做pixel-level的平均,得到新的僞異常圖像 (其實這個三角形應該在X上面,但是我查不到怎麼打出來QwQ,大家意會一下即可),再将 用 再重構一遍就得到了僞異常重構圖像 .
僞異常重構圖像(pseudo-anomaly recontructed image)生成示意圖
2. 兩階段discriminator的任務
第一階段中discriminator的任務和傳統的方法相同,即判斷圖像為原圖還是重構後的圖像。如下圖(6)式所示。
第二階段中discriminator的任務發生了變化,原圖 和高品質重構圖像 為positive的類别,低品質重構圖像 和僞異常重構圖像 為negative的類别。如下圖(7)式所示。
我個人的看法:
我個人覺得這篇文章本質上做了兩件事:
- 資料增強。用不充分訓練的generator和人為僞造出來的異常圖像作為負樣本,來訓練discriminator;
- 異常檢測任務轉移。将檢測異常的任務從generator或者generator與discriminator共同承擔,轉移到由discriminator承擔
這兩點還是比較具有借鑒意義的。
2.4 利用image segmentation資訊做異常檢測
這是發表在ECCV 2020的一篇文章。也是做無監督的異常檢測。
文章的核心方法是從image segmentation的結果出發,利用cGAN重構圖像,再将重構後的圖像與原圖做比較,不同之處認為是異常。整個異常檢測的流程為:
原圖 -> image segmentation結果 -> 基于segmentation結果重構後的圖像 -> 對比,檢測異常
說白了就是用image segmentation模型和cGAN替代之前auto-encoder架構中auto-encoder的角色,不算是一個特别有意思的story。
文章除了上述用到了cGAN來重構圖像的亮點之外,還将failure detection和anomaly detection融合到了同一個架構中,如下圖所示。不過據我讀文章時的認識,failure detection和anomaly detection隻是流程架構一緻,但是不能同時處理,更不能相輔相成。如果我了解的沒錯的話,也沒有太多的意思。
3. 特征空間上的異常檢測方法
特征空間的方法主要是将圖像的資料通過某種方法映射到特征空間上,再通過特征空間中的距離判斷是否為特征。
相比于圖像空間上的異常檢測,我個人更看好在特征空間上的異常檢測。因為特征空間表達的是比圖像空間更高層次、更抽象的資訊;而且特征空間更加靈活,因為特征空間可以有非常多種定義,而圖像空間隻有一個。
在這裡主要會介紹兩個最新的特征空間上的方法。
3.1 利用teacher和students的差異做異常檢測
這是CVPR 2020上的一篇文章,主要用teacher-students架構做無監督的異常檢測。值得一提的是,這篇文章的作者也是MVTec AD這個異常檢測資料集的提出者。是以這篇文章比較有借鑒意義。雖然他們沒有公開代碼,但是我自己曾複現過他們的結果,名額上還是基本一緻的。
Story:
這篇文章基于兩個假設:
- 在僅包含正常樣本的資料集上,讓pretrained的teacher模型去教沒有pretrain的student模型,使得teacher模型和student模型輸出的embedding盡可能一緻。那麼在inference時,由于teacher隻教過student如何embed正常樣本,是以正常樣本上teacher模型和student模型輸出的embedding會比較相似,但異常樣本上兩者輸出的embedding差異會比較大;
- 如果在1中的訓練過程中,采用多個随即初始化的students模型和一個pretrained teacher模型,那麼在正常樣本上students之間的embedding比較一緻,而在異常樣本上,由于students是随機初始化的,且teacher并沒有在異常樣本上教過他們,是以在students之間embedding差異也會比較大。
利用這兩個假設,在inference時,如果在某個樣本上,teacher和students的embedding差異比較大,且students的embeddings之間差異也比較大,那麼就說明該樣本為異常樣本。
此外,為了定位異常的位置,而不是僅僅判斷某張圖檔是否為異常,teacher和students的輸入是圖檔的patch,而不是整張圖像。這樣,當在某個patch上teacher和students表現差異很大,或者students之間表現差異很大時,就可以認為這個patch為異常,進而定位到了異常的區域。
Tricks:
- 多尺度。由于模型的輸入都是patch,是以patch的大小直接決定了異常檢測的resolution。由于圖像中的異常大小不盡相同,當異常區域比較大時,用比較大的patch可能會比較好;反之,比較小的patch效果會比較好。是以文章中采用了三種邊長的正方形patch: 17, 33和64(機關為pixel)。将這三種patch size的結果做算數平均就得到了multi-scale的結果;
- 如何pretrain模型。現在有很多unsupervised pretrain的方法,例如MoCo。但是文章沒有采用這種unsupervised方法,而是用pretrained resnet-18,通過蒸餾得到了teacher模型。我個人比較困惑的一點是為什麼不直接用pretrained resnet-18,可能是為了更快吧...(迷)
優缺點:
優點:teacher students這個架構用在異常檢測還是比較有新意的。這種方法既利用了在異常資料上pretrain過的模型和沒有pretrain過的模型的差異,也利用了沒有pretrain過的模型之間的差異;此外multi-scale也可以勉強算一個新意...
缺點:multi-scale過于粗糙,隻采用三種patch size的結果疊加;另外複現出來之後看結果會發現一個比較緻命的缺點,但是由于我目前做的工作與之相關,是以暫時保密 :-)
3.2 以patch為機關做SVDD
這是一篇挂在arxiv上的文章,主要将SVDD方法從以圖像為機關擴充到了以patch為機關。SVDD是一個比較“古老”的one-class classification方法,因為異常檢測也可以看作是一個one-class classification(正常樣本為一類,之外的都是異常樣本),是以SVDD通常也用作異常檢測。
SVDD的主要思想是,用某種方法将樣本投射到某個特征空間中,計算出所有樣本投影的中心點,再規定一個半徑 。距離中心點在 以内的認為是正常樣本,否則認為是異常樣本。Deep SVDD則是将這個投影的過程用深度神經網絡處理,是以在SVDD前加了Deep。
Story:
SVDD和Depp SVDD都有一個缺點,那就是他們處理的都是整個圖像,也就是說,在投影的過程中将每個圖像對應特征空間中的一個點。這樣的缺點是,我們隻能判别這個圖像是否為異常,但是不能定位異常的區域。
是以patch SVDD做的事情就是将處理的對象從整個圖像變為patch,每個patch對應特征空間上的一個點。
此外,由于不同的patch的特征可能會非常不同,即使是正常樣本的patch,在特征空間中的距離也可能非常遠,是以隻用一個中心點是不可行的。patch SVDD将SVDD中的一個中心點,改為了用聚類的方式形成多個中心點,
Method:
patch SVDD用到的backbone就是一個encoder,輸入為patch,輸出為patch的embedding.
文章的精髓就在于在訓練時如何設計監督,使得patch的embedding能夠自動地聚類為在多個中心周圍(中心的個數是我們無法事先設定的,需要在訓練中模型自己生成)。
Training階段,作者設計了兩個Loss,用來達到相鄰patch的embedding相似,但patch embedding之間具有一定的區分度的效果。第一個是SVDD loss,計算公式如下:
其中 是encoder, 和 是相鄰的某兩個patch,上面 的作用就是讓相鄰的patch的embedding盡可能接近。
但是如果隻用 ,那麼模型就會有讓所有的patch都輸出同一個embedding的趨勢,這肯定不是我們想要的。是以作者加入了另一個loss,SSL(self-supervised learning) loss,來使得不同patch的embedding具有一定區分度:
其中, 是encoder, 是一個分類器, 是分類的label。大家讀到這裡可能一頭霧水,我結合下面這張圖來解釋 是怎麼讓不同patch的embedding具有區分度的。
上圖中,中間的patch(記為 )周圍8個方向分别有8個patch,我們将這8個patch按照相對于中心patch的方位依次标記為 。然後從這8個patch中随機選一個patch(記為 ),将 和 的embedding(分别是 和 )輸入分類器 中,讓 來分類 相對于 的方位(即标簽 ),最後用Cross Entropy Loss來計算分類器結果和标簽之間的損失。
如果所有patch embedding都極為相似,那麼 将無法分辨出相鄰patch之間的相對方位,就會非常大。這樣就通過加入 避免了patch embedding完全一緻的情況。
Inference階段,作者通過下面的式子計算patch的anomaly score:
其中 為待檢測異常的patch,而 則是訓練集中正常的patch。通過尋找在embedding空間上與 最近的那個正常patch,計算它們倆embedding之間的距離,作為 的anomaly score。即與正常patch的最近距離越大,異常越嚴重。
優缺點:
這篇文章的優點在story部分已經介紹得很詳細,不再贅述。這裡主要講講我個人認為的不足之處:
不足之處:
- 資訊提取不充分(這裡和我現在做的工作有關,是以不詳細說了hhh)
- 訓練時使相鄰的patch特征聚合在一起,這個設想不一定合理
- 對于物品會旋轉的類别,判斷patch相對方位可能不合理
4. Loss profile 空間上做異常檢測
結構圖
這是ECCV 2020 CMU的一篇文章,是一個semi-supervised的異常檢測工作。他們提出了一個比較新穎的思路——在loss profile空間上做異常檢測。所謂的loss profile,就是在訓練過程中loss的記錄曲線(橫軸為iteration / epoch,縱軸為loss)。
Story:
這篇文章觀察到了一個現象:當auto-encoder在正常樣本為主的訓練集上訓練時,訓練圖像中正常區域的reconstruction loss随訓練的iteration / epoch增加而穩步下降,而異常區域的reconstruction loss則不斷波動。
是以作者提出利用loss随訓練次數的變化趨勢——loss profile來做異常檢測。換句話說,将異常檢測的空間從通常的圖像空間/特征空間轉化到了loss profile空間。因為在訓練時訓練集隻要以正常樣本為主即可,是以這個方法是semi-supervised的。
模型結構:
雖然上面的想法聽起來很新穎且非常易懂,但是實際上文章的實作是比較複雜的,涉及到的細節非常多。是以這裡隻介紹模型的大緻架構,感興趣的朋友可以閱讀原論文。
如上結構圖所示,模型主要由三個部分組成:
- Neural Batch Sampler
如《異常檢測最新研究總結(三)》中所說,當需要定位圖像中的異常區域時,一般模型的處理機關為圖像的patch而不是整張圖像。這篇文章為了定位到圖像中的異常區域,也是以patch為機關處理。
Neural Batch Sampler是一個RL (reinforcement learing) 模型,其作用就是選出那些使得loss profile差距最大的正常和異常的patches。
2. Auto-encoder
這部分就是通常的auto-encoder,輸入為圖像的patch,輸出為重構後的patch
3. Predictor
predictor用以預測圖像中的pixel-wise的異常區域。其輸入為經過FIFO Buffer累積的訓練時的loss profile,輸出為對圖像中每個pixel是否為異常的pixel-wise的label。由于是semi-supervised的,是以可以用已知的正常和異常圖像的ground truth做監督,得到 ,還可以順帶給neural batch sampler一個reward
優缺點:
優點:這篇文章最大的優點就是它的insight。利用loss profile做異常檢測這個思路是非常新穎的,感覺是一個可以深挖的坑;此外,這個模型還可以定位到異常的位置,且從論文的實驗部分可以看出,該模型在工業資料集MVTec AD上表現也還不錯。是以是相對成熟的。
缺點:讀這篇文章的時候就會發現,其實這篇文章涉及到的模型非常多,訓練的tricks也很多。此外個人感覺這個模型雖然複雜,實際效果可能并不和其複雜度成正比,感覺有簡化的空間。
但是總體來說還是一篇非常不錯、非常有借鑒意義的文章。(CMU的四大之一的名頭果然名不虛傳)
5. 利用backpropagated gradient資訊做異常檢測
這一篇也是ECCV 2020上的一篇文章,做的是unsupervised的異常檢測。他們也提出了一個比較新穎的角度:用backpropagated gradient做異常檢測。個人感覺雖然沒有上一篇那麼新穎,但是這個insight還是非常不錯的。
Story:
他們也是基于一個重要的觀察:當一個auto-encoder在隻包含正常樣本的訓練集上訓練好之後,如果再在一個正常樣本上訓練,則模型通常隻需要比較小的update;但是如果再在一個異常樣本上訓練,由于這個樣本不同于之前所有的訓練樣本,則模型需要比較大的update。update的不同展現在backpropagated gradient上。是以利用gradient的差異(文中用的是cosine similarity),就可以将正常樣本和異常樣本區分開來。
Method:
模型的結構比較簡單,其實就是一個auto-encoder。所不同的是他們用的loss。是以下面将重點介紹loss:
總的loss 計算公式如下:
其中, 為reconstruction loss, 為latent loss,都是auto-encoder中常用的loss,這裡就不多加贅述。 是文章的重點,正常樣本和異常樣本的gradient的差異就展現這個 上。
的計算公式如下:
乍一看很吓人,其實不複雜。 是目前訓練次數, 就是前 次訓練的gradient平均, 就是目前訓練的gradient。通過計算兩者的cosine similarity,如果cosine similarity較小,說明目前訓練帶給模型的變化較大, 也較大;反之說明目前訓練對模型改變不大, 也相應較小。
優缺點:
優點:據我所知應該是第一篇将gradient用于異常檢測的文章,雖然gradient在其他領域可能不算是新穎的idea,在異常檢測領域還是比較新穎的;此外,如果閱讀原論文的話,可以發現文章從Geometric和Theory兩個角度對gradient的方法做了解讀,讓人不明覺厲 :-)
缺點:文章中隻用gradient估計了圖檔的anomaly score,但沒有定位anomaly的位置;此外,文章中experiment的datasets比較簡單,在更加複雜的異常檢測資料集上的表現有待檢驗。
綜合來說,這篇文章也算是一篇挖坑之作,雖然個人覺得相對于上一篇loss profile異常檢測來說,idea不是那麼新穎,且方法也沒有那麼成熟(資料集較簡單且不能定位異常區域)。
寫在後面
到此為止,我最近看到的異常檢測方面的最新論文就介紹完畢了(完結撒花~)。感謝大家的閱讀、點贊、關注和評論中的鼓勵。其實每天看到自己寫的文章被閱讀、點贊,或者新增了關注還是很開心的。