tensorflow - 如何将卷积神经网络从 Keras 模型对象提取到 Networkx DiGraph 对象,并将权重作为边缘属性?

标签 tensorflow keras conv-neural-network networkx

我有兴趣使用 Networkx Python包执行network analysisconvolutional neural networks .为了实现这一点,我想提取 edgeweight信息来自 Keras model objects并将它们放入 Networkx Digraph object它可以在哪里 (1) written to a graphml file (2) 受制于 Networkx 中可用的图形分析工具。

在进一步深入之前,让我澄清一下以及如何考虑 pooling .池化(例如: maxaverage )意味着 convolution 中的条目window将是 aggregated , 在我想创建的图表中使用“哪个”条目时产生歧义。为了解决这个问题,我希望图表中包含所有可能的选择,因为我可以稍后根据需要对此进行说明。

为了举例,让我们考虑使用 VGG16 来做这件事。 . Keras使 access the weight 变得非常容易s 在循环 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 是过滤器的数量。每个过滤器都有一个偏差项,因此这些行中的最后一个元组也将等于过滤器的数量。

虽然我已经 read explanations关于卷积神经网络中的卷积在概念上的行为方式,当我开始处理模型对象中层的形状时,我似乎有一个心理障碍。

一旦我知道如何遍历 Keras 模型的边缘,使用 Networkx 我应该能够轻松地编写 Networkx 对象的构造。用于此的代码可能大致类似于以下内容,其中 keras_edges是一个包含格式为 (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') 

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

最佳答案

由于 Keras 没有边元素,而 Keras 节点似乎完全不同(Keras 节点在使用时是一个完整的层,它是模型图中显示的层)

因此,假设您使用的是尽可能小的图像(等于内核大小),并且您正在手动创建节点(抱歉,我不知道它在 networkx 中是如何工作的):

对于卷积:

  • i输入 channel (输入图像中的 channel )
  • o输出 channel (在 keras 中选择的过滤器数量)
  • kernel_size = (x, y)

  • 您已经知道形状的权重 (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)
    

    关于tensorflow - 如何将卷积神经网络从 Keras 模型对象提取到 Networkx DiGraph 对象,并将权重作为边缘属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61017099/

    相关文章:

    python - 如何在 tf.data.Dataset.map() 中使用 Keras 的 predict_on_batch?

    tensorflow - 在这个 tensorflow 示例中纪元如何工作

    python - Keras 成本函数尝试将预测张量舍入到最接近的整数时出错

    tensorflow - 基于过去和 future 值的每个时间序列步骤的二元分类

    python - tf.nn.conv2D 中的 channel 是什么?

    TensorFlow:我的(广义)骰子损失实现有什么问题?

    python - Keras BatchNormalization 未初始化值

    machine-learning - 使用梯度下降的神经网络

    machine-learning - 如何使用 train_on_batch 检查学习率 [Keras]

    python - 如何在 TensorFlow 的 eager 执行中使用 Keras.applications 的 ResNeXt?