Python 你能反转Pytork神经网络并激活输出的输入吗?

Python 你能反转Pytork神经网络并激活输出的输入吗?,python,neural-network,pytorch,Python,Neural Network,Pytorch,我们能否激活神经网络的输出,以了解神经元如何连接到输入特征 如果我从PyTorch教程中选取一个基本NN示例。下面是一个f(x,y)训练示例 导入火炬 N、 D_in,H,D_out=64100010010 x=火炬。随机数(N,D_in) y=火炬。randn(N,D_out) 型号=torch.nn.Sequential( 火炬nn线性(D_in,H), torch.nn.ReLU(), 火炬nn线性(H,D_out), ) 损失=火炬.nn.mse损失(减少='sum') 学习率=1e-4

我们能否激活神经网络的输出,以了解神经元如何连接到输入特征

如果我从PyTorch教程中选取一个基本NN示例。下面是一个
f(x,y)
训练示例

导入火炬
N、 D_in,H,D_out=64100010010
x=火炬。随机数(N,D_in)
y=火炬。randn(N,D_out)
型号=torch.nn.Sequential(
火炬nn线性(D_in,H),
torch.nn.ReLU(),
火炬nn线性(H,D_out),
)
损失=火炬.nn.mse损失(减少='sum')
学习率=1e-4
对于范围(500)内的t:
y_pred=模型(x)
损失=损失\u fn(y\u pred,y)
模型0_梯度()
loss.backward()
使用手电筒。无梯度()
对于model.parameters()中的参数:
参数-=学习率*参数梯度
在我完成网络训练后,通过
x
输入预测
y
。是否可以反转经过训练的NN,以便它现在可以从
y
输入预测
x

我不希望
y
与训练
y
输出的原始输入匹配。因此,我希望看到模型激活了哪些功能以匹配
x
y


如果可能的话,我如何在不破坏所有权重和连接的情况下重新排列
顺序
模型?

如果我理解正确,这里有两个问题:

  • 是否有可能确定输入中哪些特征激活了神经元

  • 如果是,是否可以使用此信息从
    p(x | y)
    生成样本

  • 关于
    1
    ,确定神经元是否对输入特征
    x_i
    敏感的基本方法是计算该神经元的输出w.r.t
    x_i
    的梯度。高梯度将指示对特定输入元素的敏感性。关于这个主题有丰富的文献,例如,您可以查看引导反向传播或(后者是关于使用convnet进行分类的,但它确实包含有用的想法)

    至于
    2
    ,我认为你“扭转问题”的方法不正确。问题在于您的网络是有区别的,它的输出可以被看作是
    argmax_y p(y | x)
    。请注意,这是一个逐点估计,而不是分布的完整建模。然而,您感兴趣的反问题似乎是从

    p(x|y)=constant*p(y|x)p(x).
    
    你不知道如何从
    p(y | x)
    中取样,你也不知道
    p(x)
    。即使您使用一种方法来发现神经元和特定输入特征之间的相关性,您也只能发现哪些特征对网络预测更重要,但这取决于
    y
    的性质,这可能是不够的。考虑一个玩具实例,您的输入<代码> x>代码>是按照<代码> R^ 2 中的某个分布分布的2D点,其中输出<代码> y>代码>是二进制的,使得在R^ 2 < /代码>中的任何<代码>(a,b)被归类为<代码> 1 < /代码>如果<代码> A1。然后,判别网络可以学习垂直线
    x=1
    作为其决策边界。检查神经元和输入特征之间的相关性将表明,只有第一个坐标在预测中有用,但该信息不足以从输入的完整2d分布中进行采样


    我想那可能就是你想要的

    这是可能的,但仅限于非常特殊的情况。对于前馈网络(
    顺序
    ),每个层都需要可逆;这意味着以下参数将分别应用于每个层。与一层相关的变换是
    y=激活(W*x+b)
    ,其中
    W
    是权重矩阵,
    b
    是偏差向量。为了解决
    x
    问题,我们需要执行以下步骤:

  • 反向
    激活
    ;但并非所有的激活函数都有相反的结果。例如,
    ReLU
    函数在
    (-inf,0)
    上没有反转。另一方面,如果我们使用
    tanh
    ,我们可以使用它的逆函数,即
    0.5*log((1+x)/(1-x))
  • x
    求解
    W*x=逆激活(y)-b
    ;要存在唯一的解决方案,
    W
    必须具有类似的行和列秩,
    det(W)
    必须为非零。我们可以通过选择特定的网络结构来控制前者,而后者则取决于训练过程
  • 因此,要使神经网络可逆,它必须有一个非常特殊的结构:所有层必须有相同数量的输入和输出神经元(即平方权矩阵),并且激活函数都必须是可逆的

    代码:使用PyTorch,我们必须手动对网络进行反演,包括求解线性方程组以及求逆激活函数。考虑下面的一层神经网络的例子(因为每个步骤单独应用到1层以上的步骤是微不足道的):


    通过创建两个以相反顺序共享其层的独立
    顺序
    网络,这是完全可能的。尽管这只是颠倒了层的顺序,而不是计算步骤的顺序(因为每个层都执行
    激活(W*x+b)
    )。但要使其有意义,您需要能够反转
    激活
    功能,在您的示例中,使用
    ReLu
    ,这是不可能的,因为它在
    (.inf,inf)
    上没有反转。所以你需要更准确地说出“反向神经网络”的真正含义。你在寻找吗?@Shai这很酷,但我只是想在我学习的这个阶段反向神经网络。
    import torch
    
    N = 10  # number of samples
    n = 3   # number of neurons per layer
    
    x = torch.randn(N, n)
    
    model = torch.nn.Sequential(
        torch.nn.Linear(n, n), torch.nn.Tanh()
    )
    
    y = model(x)
    
    z = y  # use 'z' for the reverse result, start with the model's output 'y'.
    for step in list(model.children())[::-1]:
        if isinstance(step, torch.nn.Linear):
            z = z - step.bias[None, ...]
            z = z[..., None]  # 'torch.solve' requires N column vectors (i.e. shape (N, n, 1)).
            z = torch.solve(z, step.weight)[0]
            z = torch.squeeze(z)  # remove the extra dimension that we've added for 'torch.solve'.
        elif isinstance(step, torch.nn.Tanh):
            z = 0.5 * torch.log((1 + z) / (1 - z))
    
    print('Agreement between x and z: ', torch.dist(x, z))