簡體   English   中英

在神經網絡中獲得“神經元邊緣神經元”值的有效方法

[英]Efficient way to get "neuron-edge-neuron" values in a neural network

我正在研究一個可視化網絡項目,我試圖在交互式圖中繪制多個節點-邊緣-節點值。

我有幾個神經網絡(這是一個例子):

import torch
import torch.nn as nn
import torch.optim as optim

class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.fc1 = nn.Linear(1, 2)
        self.fc2 = nn.Linear(2, 3)
        self.fc3 = nn.Linear(3, 1)

    def forward(self, x):
        x1 = self.fc1(x)
        x = torch.relu(x1)
        x2 = self.fc2(x)
        x = torch.relu(x2)
        x3 = self.fc3(x)
        return x3, x2, x1

net = Model()

如何以有效的方式獲取網絡中的node-edge-nodeneuron-edge-neuron )值? 其中一些網絡具有大量參數。 請注意,對於第一層,它將是input-edge-neuron而不是neuron-edge-neuron

我嘗試在fc層(即x1,x2,x3 )之后保存每個節點值x1,x2,x3這樣我就不必重新計算它們,但我不確定如何處理邊緣並將它們以有效的方式與相應的神經元匹配.

我正在尋找的輸出是node-edge-node值列表的列表。 盡管如果更容易,它也可以是張量的張量。 例如,在上面的網絡中,第一層有 2 個三元組(1x2),第二層有 6 個(2x3),最后一層有 3 個三元組(3x1)。 問題是以有效的方式將節點(即神經元)值(一個來自第 n-1 層,一個來自第 n 層)與相應的邊匹配。

您只需遍歷 named_pa​​rameters 集合即可列出火炬模型的所有權重:

for name, param in model.named_parameters():
    print(name, param)

懺悔:讓我們首先說我修改了你的代碼以使其方便。 你可以按照原來的形式做任何事情。 我還改變了特定數量的神經元只是為了玩耍(我相信你可以將它們恢復回來)。

我創建了一個summary對象(由.forward()函數返回),其中包含網絡的整個執行跟蹤,即 *每一層的(input, weight, output)元組。

class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.fc1 = nn.Linear(3, 5)
        self.fc2 = nn.Linear(5, 7)
        self.fc3 = nn.Linear(7, 2)

    def forward(self, x):
        summary = []
        running_x = x
        for layer in self.children():
            out = layer(running_x)
            # triplet of (input, weight, output) for each layer
            summary.append((running_x, layer.weight, out))
            running_x = out

        return summary

model = Model()
batch_size = 32
X = torch.rand(batch_size, 3)
summary = model(X)

核心邏輯只有這么多

for L in summary: # iterate over the (ip, weight, out) tuple for each layer
    ip, weight, out = L # unpack them
    
    ip = ip[:, :, None, None].repeat(1, 1, out.shape[-1], 1)
    weight = weight.T[None, :, :, None].repeat(batch_size, 1, 1, 1)
    out = out[:, None, :, None].repeat(1, ip.shape[1], 1, 1)
    triplets = torch.cat([ip, weight, out], -1)

所以triplets變量(每層一個)就是你要找的。 它有一個尺寸

(batch_size, layer_in_dim, layer_out_dim, 3)

讓我們具體看看第一層的triplets

>> triplets.shape
(32, 3, 5, 3)

例如,給定樣本索引b = 12 ,輸入神經元索引i = 1和輸出神經元索引j = 3 ,您正好有node-edge-node元組

>> triplets[b][i][j]
tensor([0.7080, 0.3442, 0.7344], ...)

驗證:讓我們手動驗證正確性。

12個采樣的1 ST尺寸是

# Its the first layer we are looking, so input comes from user
>> X[12][1]
tensor(0.7080) 

查看。

之間的連接權重1 ST輸入神經元和3為第一層RD輸出神經

>> model.fc1.weight.T[1][3] # weight matrix is transposed, so had to do .T
tensor(0.3442, ...)

查看。

可以從其激活張量中檢索第12個樣本的第3神經元的輸出

>> _, _, out = summary[0] # first layer's output tensor
>> out[12][3]
tensor(0.7344, ...)

還要檢查。


我希望這就是你想要的。 如果需要更多信息/更改,請隨時發表評論。 我不認為它可以變得更有效率。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM