在金融風控領域當中,模型可解釋性相當重要。我對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)
好啦,今天的分享就到這裏啦!如果有收穫的話,不要忘了點贊和收藏呀!