談談機器學習模型的可解釋性

ZhiboZhao發表於2021-07-29

深度學習一直被認為是一個黑盒子,但是試圖對模型的理解仍然是非常必要的。先從一個例子來說明解釋神經網路的重要性:古代一個小鎮上的一匹馬能夠做數學題,比如給它一個題目 2+3 ,它踏馬蹄 5 下後就會停下,這匹馬被當地稱作神馬漢斯。後來人們發現,漢斯其實並不會做數學題,它通過觀察主人的反應來判斷什麼時候停下。因此當一個訓練好的網路模型根據輸入來輸出他的答案時,有時候雖然也能得到正確的結果,但是我們更多時候還需要知道網路輸出這個結果的原因,這樣能夠幫助我們來判斷模型得到的這個結果是否可靠。進一步地,我們可以憑藉解釋的結果來進一步優化我們的模型,而不僅僅是從結果層面來進行約束

在之前的一篇研究中,網路能夠準確地將一幅大熊貓地圖片識別為大熊貓,但是當這張圖片混有一定的噪聲時,網路識別的結果是長臂猿。由此可見,網路有時候只能根據資料集和損失函式來優化它的擬合過程,但是網路具體做出決定依靠的是影像的哪些特徵則很難進行判斷。就像考試的目的是為了讓學生更好地掌握書本知識,然後取得高分,往往我們會通過題海戰術來更方便快捷地總結出題規律,能達到更好的效果,這顯然與素質教育的本質背道而馳。

筆者曾在2021年CVPR上發表過一篇關於影像去噪的文章,裡面提到了“提高神經網路的可解釋性”,最近在面試中經常被問到相關的問題,但是我回答的總是不能令面試官滿意,直到真正瞭解到針對神經網路可解釋性的文章,我才明白其中的區別:

  1. 我們文章的可解釋性是針對在網路設計時網路結構,模組等都是經驗性地選取,因此我們根據傳統的演算法進行理論推導,然後使用神經網路的擬合能力對理論進行建模,完成整個網路的設計過程;
  2. 而本篇文章提到的可解釋性是對網路輸出結果的原因進行討論,試圖解釋網路輸出結果的原因,來幫助我們判斷模型得到的結果是否可靠。

Local Explanation主要解釋做出決定的原因,比如一張圖片模型輸出是貓,那麼local explanation的目的就是解釋為什麼它覺得這張圖片是貓?很容易想到關於Attention機制的一些研究,通過 Attention 機制能夠給特徵賦予不同的空間和通道權重,從而使網路更加重視重要資訊。通常在解釋Attention的效果時,會採用 Salience Map 來表示。如下圖所示:

在 Salience Map 中,較亮的部分代表對網路影響最重要的區域。比如在分類任務中,判斷是否是猴子網路主要感興趣的區域確實是猴子,而不是其他的內容。因此,Salience Map 就相當於網路做出決定所給出的理由。那麼 Salience Map 是怎麼得出來的呢?

想象一下:如果我對圖片的某個區域做干擾,那麼如果干擾後影響了網路的判斷結果,證明該干擾區域在網路做出判斷時是重要的,反之則不重要。數學描述為:對於輸入 \(X = [x_{1},x_{2},...x_{n}]\),其中 \(x_{i}\) 代表了每個輸入,對於圖片而言就是每個畫素點。如果判斷 \(x_{i}\) 對輸出 \(y\) 的影響,那麼可以給 \(x_{i}\) 增加一個擾動 \(\Delta x_{i}\),相應地輸出結果的變化量為 \(\Delta y\),於是 \(x_{i}\) 的重要程度就可以描述為:

\[\dfrac{\Delta y}{\Delta x_{i}} = \dfrac{\partial y}{ \partial x_{i}} \]

計算 Salience Map 的PyTorch程式碼如下:

def compute_saliency_maps(X, y, model):
    """
    X表示圖片, y表示分類結果, model表示使用的與訓練好的分類模型
    輸出為salience map: A Tensor of shape (N, H, W)
    """
    # 確保model是test模式
    model.eval()
    # 確保X是需要gradient
    X.requires_grad_()
    saliency = None
    logits = model.forward(X)
    logits.backward(torch.FloatTensor([1.]))  # 計算梯度
    saliency = abs(X.grad.data)  # 返回X的梯度絕對值大小
    saliency, _ = torch.max(saliency, dim=1)
    return saliency.squeeze()

輸出結果如下:

但是 Salience Map 會存在一些問題,比如判斷一個動物是否是大象,長鼻子是其中一個非常明顯的特徵,但是當鼻子長到一定程度時,再增加鼻子的長度絲毫不會改變網路的判斷結果,此時鼻子的長度對網路判斷的貢獻就很小。

除了 Salience Map 外,類啟用的熱力圖也可以顯示原始圖片的不同區域對某個CNN輸出結果的 “貢獻” 程度,如下圖所示:

類啟用的熱力圖在文獻 "Grad-CAM: visual explanations from deep networks via gradient-based localization" 首次被提出,方法可以總結為:給定一張輸入影像,對於一個卷積層的輸出特徵圖,用類別相對於通道的梯度對這個特徵圖中的每個通道進行加權。直觀上來看,理解這個技巧的一種方法是,你是用 “每個通道對類別的重要程度” 對 “輸入影像對不同通道的啟用強度” 的空間圖進行加權,從而得到了 “輸入影像對類別的啟用強度” 的空間圖。參考程式碼連結:https://github.com/jacobgil/pytorch-grad-cam

其實對於神經網路而言,它所看到的只是一堆資料而已,通過損失函式可以使模型將這一堆資料對映為我們想要的值,其實人是無法真正理解機器想的是什麼的,這些只是想找一些合理的方法來將機器想的內容合理化為人們所期望的那個樣子而已。所以對一些新入門的朋友而言,不必過分糾結於神經網路到底是怎麼實現特定的功能的,就像一位大佬說過:The question of whether machines could think was “about as relevant as the question of whether Submarines Can Swim. 個人理解就是:思考和游泳都是人類具有的屬性,目的能夠幫助我們解決事情或者能夠在水裡生存,但是反過來不一定成立,解決事情或者在水裡生存不一定非要是我們人類具有的屬性,機器也能擁有這些,但是他們在以什麼樣的方式進行工作,我們不得而知,討論這個問題也就沒什麼意義,我們只需要關心結果是否是我們所需要的就行了。

相關文章