Python 向tensorflow.keras模型中间层提供输入

Python 向tensorflow.keras模型中间层提供输入,python,tensorflow,keras,deep-learning,efficientnet,Python,Tensorflow,Keras,Deep Learning,Efficientnet,我正在尝试使用tensorflow.keras.applications EfficientNetB0实现hydranet体系结构。该体系结构的目标是将网络分为两部分(第一部分:主干,第二部分:头部)。然后,一个输入图像应该只向主干网馈送一次,并且它的输出应该被存储。之后,该输出应直接输入到头部(根据要分类的类的数量,可以有多个)。 最佳方法: 我不想为每个头部重新绘制整个模型 主干只能执行一次 如果已经查看此论坛帖子: 但是提出的解决方案要么需要对头部重新编码,要么不起作用 我尝试了以下方法:

我正在尝试使用tensorflow.keras.applications EfficientNetB0实现hydranet体系结构。该体系结构的目标是将网络分为两部分(第一部分:主干,第二部分:头部)。然后,一个输入图像应该只向主干网馈送一次,并且它的输出应该被存储。之后,该输出应直接输入到头部(根据要分类的类的数量,可以有多个)。 最佳方法:

  • 我不想为每个头部重新绘制整个模型
  • 主干只能执行一次
  • 如果已经查看此论坛帖子: 但是提出的解决方案要么需要对头部重新编码,要么不起作用

    我尝试了以下方法:

    from tensorflow.keras.applications import EfficientNetB0 as Net
    from tensorflow.keras.models import Model
    split_idx = 73
    input_shape = (250, 250, 3) # use depth=3 because imagenet is trained on RGB images
    model = Net(weights="imagenet", include_top = True)
    
    # Approach 1:
    
    # create the full network so we can train on it
    model_backbone = keras.models.Model(inputs=model.input, outputs=model.layers[split_idx].output)
    
    # create new model taking the output from backbone as input and creating final output of head
    model_head = keras.models.Model(inputs=model.layers[split_idx].output, 
                                    outputs=model.layers[-1].output)
    
    # Approach 2:
    # create function for feeding input through backbone
    # the function takes a normal input image as input and returns the output of the final backbone layer
    create_backbone_output = K.function([model.layers[0].input], model.layers[split_idx].output)
    
    # create function for feeding output of backbone through heads
    create_heads_output = K.function([model.layers[split_idx].output], 
                                      model.output)
    
    但当我尝试执行此操作时,两种方法都会出现“图形断开连接错误”:

    WARNING:tensorflow:Functional model inputs must come from `tf.keras.Input` (thus holding past layer 
    metadata), they cannot be the output of a previous non-Input layer. Here, a tensor specified as input 
    to "model_5" was not an Input tensor, it was generated by layer block3b_drop.
    Note that input tensors are instantiated via `tensor = tf.keras.Input(shape)`.
    The tensor that caused the issue was: block3b_drop/Identity:0
    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    <ipython-input-33-64dd6f6430a1> in <module>
      6 # create function for feeding output of backbone through heads
      7 create_heads_output = K.function([model.layers[split_idx].output], 
    ----> 8                                  model.output)
    
    ~\AppData\Roaming\Python\Python36\site-packages\tensorflow\python\keras\backend.py in 
    function(inputs, 
    outputs, updates, name, **kwargs)
    4067     from tensorflow.python.keras import models  # pylint: disable=g-import-not-at-top
    4068     from tensorflow.python.keras.utils import tf_utils  # pylint: disable=g-import-not-at-top
    -> 4069     model = models.Model(inputs=inputs, outputs=outputs)
    4070 
    4071     wrap_outputs = isinstance(outputs, list) and len(outputs) == 1
    
    ~\AppData\Roaming\Python\Python36\site-packages\tensorflow\python\training\tracking\base.py in 
    _method_wrapper(self, *args, **kwargs)
    515     self._self_setattr_tracking = False  # pylint: disable=protected-access
    516     try:
    --> 517       result = method(self, *args, **kwargs)
    518     finally:
    519       self._self_setattr_tracking = previous_value  # pylint: disable=protected-access
    
    ~\AppData\Roaming\Python\Python36\site-packages\tensorflow\python\keras\engine\functional.py in 
    __init__(self, inputs, outputs, name, trainable, **kwargs)
    118     generic_utils.validate_kwargs(kwargs, {})
    119     super(Functional, self).__init__(name=name, trainable=trainable)
    --> 120     self._init_graph_network(inputs, outputs)
    121 
    122   @trackable.no_automatic_dependency_tracking
    
    ~\AppData\Roaming\Python\Python36\site-packages\tensorflow\python\training\tracking\base.py in 
    _method_wrapper(self, *args, **kwargs)
    515     self._self_setattr_tracking = False  # pylint: disable=protected-access
    516     try:
    --> 517       result = method(self, *args, **kwargs)
    518     finally:
    519       self._self_setattr_tracking = previous_value  # pylint: disable=protected-access
    
    ~\AppData\Roaming\Python\Python36\site-packages\tensorflow\python\keras\engine\functional.py in 
    _init_graph_network(self, inputs, outputs)
    202     # Keep track of the network's nodes and layers.
    203     nodes, nodes_by_depth, layers, _ = _map_graph_network(
    --> 204         self.inputs, self.outputs)
    205     self._network_nodes = nodes
    206     self._nodes_by_depth = nodes_by_depth
    
    ~\AppData\Roaming\Python\Python36\site-packages\tensorflow\python\keras\engine\functional.py in 
    _map_graph_network(inputs, outputs)
    981                              'The following previous layers '
    982                              'were accessed without issue: ' +
    --> 983                              str(layers_with_complete_input))
    984         for x in nest.flatten(node.outputs):
    985           computable_tensors.add(id(x))
    
    ValueError: Graph disconnected: cannot obtain value for tensor 
    KerasTensor(type_spec=TensorSpec(shape=(None, 224, 224, 3), dtype=tf.float32, name='input_4'), 
    name='input_4', description="created by layer 'input_4'") at layer "rescaling_3". The following 
    previous layers were accessed without issue: []
    
    警告:tensorflow:功能模型输入必须来自`tf.keras.Input`(因此保持在图层上
    元数据),它们不能是前一个非输入层的输出。这里,指定为输入的张量
    “model_5”不是一个输入张量,它是由层块3b_drop生成的。
    注意,输入张量是通过“tensor=tf.keras.input(shape)”实例化的。
    导致问题的张量为:block3b_drop/Identity:0
    ---------------------------------------------------------------------------
    ValueError回溯(最近一次调用上次)
    在里面
    6#创建通过磁头馈送主干输出的功能
    7创建\u heads\u output=K.function([model.layers[split\u idx].output],
    ---->8型号(输出)
    中的~\AppData\Roaming\Python\Python36\site packages\tensorflow\Python\keras\backend.py
    功能(输入,
    输出、更新、名称,**kwargs)
    4067来自tensorflow.python.keras导入模型#pylint:disable=g-import-not-at-top
    4068从tensorflow.python.keras.utils导入tf_utils#pylint:disable=g-import-not-at-top
    ->4069模型=模型。模型(输入=输入,输出=输出)
    4070
    4071 wrap_输出=isinstance(输出,列表)和len(输出)=1
    中的~\AppData\Roaming\Python\Python36\site packages\tensorflow\Python\training\tracking\base.py
    _方法_包装器(self,*args,**kwargs)
    515 self._self_setattr_tracking=False#pylint:disable=protected access
    516试试:
    -->517结果=方法(自身、*args、**kwargs)
    518最后:
    519 self._self_setattr_tracking=上一个值#pylint:disable=受保护访问
    中的~\AppData\Roaming\Python\Python36\site packages\tensorflow\Python\keras\engine\functional.py
    __初始(自我、输入、输出、名称、可培训、**kwargs)
    118 generic_utils.validate_kwargs(kwargs,{})
    119超级(功能,自我)。\uuuuu初始(名称=名称,可培训=可培训)
    -->120自初始化图网络(输入、输出)
    121
    122@trackable.no\自动\依赖\跟踪
    中的~\AppData\Roaming\Python\Python36\site packages\tensorflow\Python\training\tracking\base.py
    _方法_包装器(self,*args,**kwargs)
    515 self._self_setattr_tracking=False#pylint:disable=protected access
    516试试:
    -->517结果=方法(自身、*args、**kwargs)
    518最后:
    519 self._self_setattr_tracking=上一个值#pylint:disable=受保护访问
    中的~\AppData\Roaming\Python\Python36\site packages\tensorflow\Python\keras\engine\functional.py
    _初始图网络(自身、输入、输出)
    202#跟踪网络的节点和层。
    203个节点,节点按深度,层,映射图网络(
    -->204自输入、自输出)
    205自网络节点=节点
    206 self.\u nodes\u by\u depth=nodes\u by\u depth
    中的~\AppData\Roaming\Python\Python36\site packages\tensorflow\Python\keras\engine\functional.py
    _映射图网络(输入、输出)
    981“以下前几层”
    982'已访问,没有问题:'+
    -->983 str(带完整输入的图层))
    984用于嵌套中的x。展平(节点输出):
    985可计算的_张量。加(id(x))
    ValueError:图形已断开连接:无法获取张量的值
    KerasTensor(type_spec=TensorSpec(shape=(None,224,224,3),dtype=tf.float32,name='input_4'),
    “重新缩放”层的name='input_4',description='由层'input_4'创建〕。以下
    访问以前的层时没有问题:[]
    
    我知道错误的根源是提供的张量不是输入张量。这个问题有什么解决办法吗?

    1。)这个模型不像你试图处理的那样循序渐进 ->split_idx+1是添加另一层的添加操作,必须添加到第一个输出和第二个输入

    block3b_drop (Dropout)          (None, 28, 28, 40)   0           block3b_project_bn[0][0]         
    __________________________________________________________________________________________________
    block3b_add (Add)               (None, 28, 28, 40)   0           block3b_drop[0][0]               
                                                                     block3a_project_bn[0][0]         
    __________________________________________________________________________________________________
    
    2.)添加所有需要的输入和给定的输出:

    second_input1 = keras.Input(shape=model.layers[split_idx].output.shape[1:])
    second_input2 = keras.Input(shape=model.get_layer(name='block3a_project_bn').output.shape[1:])
    
    3.)重新连接模型的其余部分 在这里,您需要添加一些内容,但我会给您一些片段,让您开始:

    for sequentially rewiring it it would be:
        tmp = [second_input1,second_input2]
        for l in range(split_idx+1, len(model.layers)):
            layer = model.layers[l]
            print(layer.name, layer.input)
            tmp = layer(tmp)
    
    在您的情况下,这还不够,您需要找到正确的输入,下面的snipped可以做到这一点。 找到正确的输入,要求输入到下一个输出(跟踪输出),然后通过图形进行处理

    for l in model.layers:
        # multiple inputs
        if type(l.input) is list:
            for li,lv in enumerate(l.input):
                print('o ', li, lv.name)
        else:
            print('- ', l.input.name)
    
    另一种便宜的方法是->将其另存为json,添加输入节点,删除未使用的节点。加载新的json文件,在这种情况下,您不需要重新布线