單調神經網絡《 Monotonic Networks》及代碼實現

在金融風控領域當中,模型可解釋性相當重要。我對nips的論文《Monotonic Networks》當中的單調神經網絡進行了復現,在權重爲正的情況下,我們就稱該神經網絡爲單調神經網絡,因爲不管如何進行輸入,我們輸出都會呈現出單調性,也就是輸入越大,輸出越大。或者輸入越大,輸出越小。傳統的單調神經網絡設計十分簡單,而最簡單的則是僅有一層全連接神經網絡,且神經元的權重全部爲正/負,這樣就能夠保證神經網絡的單調性。同時,在論文《 Monotonic Networks》當中,提出了一種更爲創新的辦法,在神經網絡能夠保證所有的權重爲正/負的情況下,同時能夠實現模型更高的準確性。我們來看看他是怎麼實現的。

1.論文概述

在這裏展示了這樣一個模型,我們將其稱爲單調網絡。單調網絡通過對超平面組進行最大和最小操作來實現分段線性曲面。通過約束超平面權重的符號來強制執行單調性約束。可以使用通常與其他模型(例如前饋神經網絡)一起使用的基於梯度的優化方法來訓練單調網絡。 Armstrong (Armstrong et. al. 1996) 開發了一種稱爲自適應邏輯網絡的模型,它能夠強制執行單調性,並且似乎與這裏介紹的方法有一些相似之處。然而,自適應邏輯網絡只能通過商業軟件包獲得。訓練算法是專有的,尚未在學術期刊上完全披露。因此,單調網絡代表(據我們所知)在學術環境中呈現的第一個模型,該模型具有強制單調性的能力。

我們來看看這個神經網絡的架構如何:

該單調網絡具有前饋、三層(兩個隱藏層)架構。第一層單元計算輸入向量的不同線性組合。如果特定輸入需要增加單調性,則連接到該輸入的所有權重都被約束爲正。類似地,連接到需要降低單調性的輸入的權重被限制爲負數。第一層單元被分成若干組(每組的單元數量不一定相同)。對應於每個組的是第二層單元,它計算組內所有第一層單元的最大值。最終輸出單元計算所有組的最小值。該神經網絡的設計圖如下:

單調神經網絡設計圖

該神經網絡第一層是我們的輸入,第二層將我們輸入放到一個全連接層當中,同時,分爲3組(我們可以分爲k組,看k的取值,怎樣達到最好的模型識別準確率,你也可以嘗試4,5,6......)。在這三組當中,我們分別找到每一組當中神經元輸出最大的神經元,再將這些輸出最大的3個神經元進行比較,將這3個神經元當中輸出值最小的神經元作爲我們的輸出,最後通過sigmoid function,得到我們模型最好的輸出。下面是該神經網絡的數學表達式:

神經網絡的第一層

在以上公式當中, [公式] 表示第k組神經元的輸出。如果我們分爲了3組神經元,則k=3.

其中 [公式] 表示第k組神經元當中第j個神經元的權重大小。

而後面的 [公式] 則代表了偏執項。

假設我們令 [公式] 爲模型最後的輸出,則有公式:

如果我們面對的是一個分類問題,則可以將最後的輸入放進sigmoid function,公式如下:

以上就是這個神經網絡的整體實現。

2.代碼實現

代碼實現這一塊我使用了pytorch來做的實現,神經網絡架構可以編寫如下:

import torch 
from torch import nn
class MNET(nn.Module):
    def __init__(self):
        super().__init__()
        self.layer_one = nn.Linear(32, 64) #將64個神經元,分爲4組,每一組有16個神經元
        self.sigmoid = nn.Sigmoid()

    #forward這裏就是神經網絡的輸入了
    def forward(self, input_x):
        length=len(input_x)
        input_x = self.layer_one(input_x)
    
        group_one=input_x[:,:,:16] #shape:[10,1,16],一共有16組神經元
        group_two=input_x[:,:,:32]
        group_three=input_x[:,:,:48]
        group_four=input_x[:,:,:64]
        
        #然後取每一個group當中,輸出值最大的神經元

        max_one=self.find_max(group_one)
        max_two=self.find_max(group_two)
        max_three=self.find_max(group_three)
        max_four=self.find_max(group_four)
        
        #然後找到這4組數據的最小值.每一個數據,只選取4個數據當中的一個
        max_group=torch.cat((max_one,max_two),dim=1)#橫着拼
        max_group=torch.cat((max_group,max_three),dim=1)
        max_group=torch.cat((max_group,max_four),dim=1)
        
        return self.find_mini(max_group)
        
        
    def find_max(self,group):
        #這個找最大,的確應該在每一個數據當中找最大,如果每次在喂進的所有數據當中找最大,還是不靠譜的
        max_ret=torch.max(group,dim=2)
        return max_ret.values
    
    def find_mini(self,group):
        mini_ret=torch.min(group,dim=1)
        return mini_ret.values.unsqueeze(-1)

由於在訓練的過程當中,需要將所有的權重調整爲正,因此需要如下代碼調整權重的大小:

loss = criterion(out, var_y)
optimizer.zero_grad()
loss.backward()
optimizer.step()

for p in net.parameters():
    p.data.clamp_(0, 99)

好啦,今天的分享就到這裏啦!如果有收穫的話,不要忘了點贊和收藏呀!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章