• 单调神经网络《 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)
    

    好啦,今天的分享就到这里啦!如果有收获的话,不要忘了点赞和收藏呀!

  • 相关阅读:
    数字雨-贪吃蛇
    C语言入门9-2-模块大致一览
    C语言入门9-1-分类函数
    C语言入门8-数组-基本算法
    C语言入门7-程序设计方法基础-循环结构
    C语言入门6-选择结构--f语句-switch
    C语言入门5-键盘的输入和屏幕输出
    C语言入门4-运算符和表达式
    C语言入门3-C语言概述及数据类型
    Systemd 入门教程:命令篇
  • 原文地址:https://www.cnblogs.com/geeksongs/p/15884172.html
Copyright © 2020-2023  润新知