本文介绍了如何从Keras模型对象到Networkx DiGraph对象提取卷积神经网络,同时将权重作为边缘属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对使用 Networkx Python 包来执行网络分析" rel ="nofollow noreferrer">卷积神经网络.为此,我想提取 edge 和信息,来自 Keras模型对象,并将它们放入 Networkx Digraph对象可能位于的位置(1) ,并且(2)使用Networkx中可用的图形分析工具.

I'm interested in using the Networkx Python package to perform network analysis on convolutional neural networks. To achieve this I want to extract the edge and weight information from Keras model objects and put them into a Networkx Digraph object where it can be (1) written to a graphml file and (2) be subject to the graph analysis tools available in Networkx.

在进一步介绍之前,让我澄清一下以及如何考虑 pooling .池化(例如: max 平均值)表示卷积 窗口将被聚合,从而在要使用哪个"条目上产生歧义在我要创建的图形中.为了解决这个问题,我希望图表中包含所有可能的选择,以便以后可以根据需要进行解释.

Before jumping in further, let me clarify and how to consider pooling. Pooling (examples: max, or average) means that the entries within a convolution window will be aggregated, creating an ambiguity on 'which' entry would be used in the graph I want to create. To resolve this, I would like every possible choice included in the graph as I can account for this later as needed.

为了举例说明,让我们考虑使用 VGG16 进行此操作. Keras 使访问权重,同时循环遍历图层.

For the sake of example, let's consider doing this with VGG16. Keras makes it pretty easy to access the weights while looping over the layers.

from keras.applications.vgg16 import VGG16

model = VGG16()

for layer_index, layer in enumerate(model.layers):
    GW = layer.get_weights()
    if layer_index == 0:
        print(layer_index, layer.get_config()['name'], layer.get_config()['batch_input_shape'])
    elif GW:
        W, B =  GW
        print(layer_index, layer.get_config()['name'], W.shape, B.shape)
    else:
        print(layer_index, layer.get_config()['name'])

将打印以下内容:

0 input_1 (None, 224, 224, 3)
1 block1_conv1 (3, 3, 3, 64) (64,)
2 block1_conv2 (3, 3, 64, 64) (64,)
3 block1_pool
4 block2_conv1 (3, 3, 64, 128) (128,)
5 block2_conv2 (3, 3, 128, 128) (128,)
6 block2_pool
7 block3_conv1 (3, 3, 128, 256) (256,)
8 block3_conv2 (3, 3, 256, 256) (256,)
9 block3_conv3 (3, 3, 256, 256) (256,)
10 block3_pool
11 block4_conv1 (3, 3, 256, 512) (512,)
12 block4_conv2 (3, 3, 512, 512) (512,)
13 block4_conv3 (3, 3, 512, 512) (512,)
14 block4_pool
15 block5_conv1 (3, 3, 512, 512) (512,)
16 block5_conv2 (3, 3, 512, 512) (512,)
17 block5_conv3 (3, 3, 512, 512) (512,)
18 block5_pool
19 flatten
20 fc1 (25088, 4096) (4096,)
21 fc2 (4096, 4096) (4096,)
22 predictions (4096, 1000) (1000,)

对于卷积层,我已经读过元组将表示(filter_x,filter_y,filter_z,num_filters),其中filter_x,filter_y,filter_z给出过滤器的形状,而num_filters是过滤器的数量.每个过滤器都有一个偏差项,因此这些行中的最后一个元组也将等于过滤器的数量.

For the convolutional layers, I've read that the tuples will represent (filter_x, filter_y, filter_z, num_filters) where filter_x, filter_y, filter_z give the shape of the filter and num_filters is the number of filters. There's one bias term for each filter, so the last tuple in these rows will also equal the number of filters.

虽然我已经阅读有关如何使用的解释卷积神经网络中的卷积在概念上表现良好,当我要处理模型对象中各层的形状时,似乎有一个心理障碍.

While I've read explanations of how the convolutions within a convolutional neural network behave conceptually, I seem to be having a mental block when I get to handling the shapes of the layers in the model object.

一旦我知道如何遍历Keras模型的边缘,使用Networkx,我应该能够轻松地对Networkx对象的构造进行编码.用于此目的的代码可能大致类似于以下内容,其中keras_edges是可迭代的,包含格式为(in_node,out_node,edge_weight)的元组.

Once I know how to loop over the edges of the Keras model, with Networkx I should be able to easily code the construction of the Networkx object. The code for this might loosely resemble something like this, where keras_edges is an iterable that contains tuples formatted as (in_node, out_node, edge_weight).

import networkx as nx

g = nx.DiGraph()

g.add_weighted_edges_from(keras_edges)

nx.write_graphml(g, 'vgg16.graphml') 

具体来说,如何以上述方式考虑层的形状和池化的方式遍历所有边缘?

So to be specific, how do I loop over all the edges in a way that accounts for the shape of the layers and the pooling in the way I described above?

推荐答案

由于Keras没有edge元素,并且Keras节点似乎完全不同(当使用Keras节点时,它是整个图层,因此模型图中显示的图层)

Since Keras doesn't have an edge element, and a Keras node seems to be something totally different (a Keras node is an entire layer when it's used, it's the layer as presented in the graph of the model)

因此,假设您正在使用最小的映像(等于内核大小),并且正在手动创建节点(对不起,我不知道它在networkx中的工作原理):

So, assuming you are using the smallest image possible (which is equal to the kernel size), and that you're creating nodes manually (sorry, I don't know how it works in networkx):

对于一个卷积:

  • 具有i个输入通道(图像中出现的通道)
  • 具有o个输出通道(在keras中选择的过滤器数量)
  • 具有kernel_size = (x, y)
  • Has i input channels (channels in the image that comes in)
  • Has o output channels (the selected number of filters in keras)
  • Has kernel_size = (x, y)

您已经知道形状为(x, y, i, o)的砝码.

You already know the weights, which are shaped (x, y, i, o).

您会有类似的内容:

#assuming a node here is one pixel from one channel only:

#kernel sizes x and y
kSizeX = weights.shape[0]
kSizeY = weights.shape[1]

#in and out channels
inChannels = weights.shape[2]
outChannels = weights.shape[3]

#slide steps x
stepsX = image.shape[0] - kSizeX + 1
stepsY = image.shape[1] - kSizeY + 1


#stores the final results
all_filter_results = []

for ko in range(outChannels): #for each output filter

    one_image_results = np.zeros((stepsX, stepsY))

    #for each position of the sliding window 
    #if you used the smallest size image, start here
    for pos_x in range(stepsX):      
        for pos_y in range(stepsY):

            #storing the results of a single step of a filter here:
            one_slide_nodes = []

            #for each weight in the filter
            for kx in range(kSizeX):
                for ky in range(kSizeY):
                    for ki in range(inChannels):

                        #the input node is a pixel in a single channel
                        in_node = image[pos_x + kx, pos_y + ky, ki]

                        #one multiplication, single weight x single pixel
                        one_slide_nodes.append(weights[kx, ky, ki, ko] * in_node)

                        #so, here, you have in_node and weights

            #the results of each step in the slide is the sum of one_slide_nodes:
            slide_result = sum(one_slide_nodes)
            one_image_results[pos_x, pos_y] = slide_result   
    all_filter_results.append(one_image_results)

这篇关于如何从Keras模型对象到Networkx DiGraph对象提取卷积神经网络,同时将权重作为边缘属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-12 02:31