【问题标题】:Error when combine two keras sequential models inside one functional model: AttributeError: 'NoneType' object has no attribute '_inbound_nodes'在一个功能模型中组合两个 keras 顺序模型时出错:AttributeError: 'NoneType' object has no attribute '_inbound_nodes'
【发布时间】:2019-07-17 19:34:05
【问题描述】:

我分别构建了两个keras序列模型,并使用keras函数api将两个模型结合起来。在它们之间,我应用了数据重新打包,调整了通过两个顺序模型的数据的大小。

当我进行组合时,存在错误。 但我不太明白哪个对象在“NoneType”中。

另一个问题是,我在进行数据张量重新打包时将所有零放在占位符内。当我运行 model.fit 时,它会被真实数据取代,还是会保持为零? 将两个序列模型与张量调整之间的组合完全不适用吗?

# I use a keras sequential model to define the 2d model "base_model_SRCNN"
# I define the 3d model still using keras sequential model as "SRnet_3d_model"

ip = Input(shape = (TARGET_HEIGHT, TARGET_WIDTH, 1))
SRCNN_network = base_model_SRCNN(FILENAME, TARGET_HEIGHT, TARGET_WIDTH) (ip)
#----------------------------pack frame one by one---------------------------------------
...
# In this section, I re-pack the output tensor of SRCNN_network,
# the resulted new tensor is called "package_set_tensor"
# I've checked and ensure the type of "package_set_tensor" is a tensor, and the shape is (294, 5, 352, 288, 1)
#---------------------------build 3dSRnet model--------------------------------------------
SRnet_layer = SRnet_3d_model(AMOUNT, DEPTH, TARGET_HEIGHT, TARGET_WIDTH)(package_set_tensor)

#--------------------------test the result of combination----------------------------------
combined_model = Model(inputs = ip, outputs = SRnet_layer)

#I 've checked the type of SRnet_layer and ip are <class 'tensorflow.python.framework.ops.Tensor'>

编辑

#here's the lambda layer I defined:
def repacking(x):
    #----------------------------get shape from input tensor---------------------------------
    (AMOUNT, TARGET_HEIGHT, TARGET_WIDTH, tmp) = x.shape
    AMOUNT = keras.backend.shape(x)[0]#will return an empty tensor
    # or using 'list(x.shape)[0]' to return a Nontype object
    DEPTH = 5
    #AMOUNT = 26
    #----------------------------pack frame one by one---------------------------------------
    FIRST = True
    HALF_RANGE = math.floor(DEPTH/2)

    for i in range(AMOUNT):
        if (i - HALF_RANGE) < 0 or (i + HALF_RANGE) >= AMOUNT:
            AMOUNT = AMOUNT - 1
        else:
            if DEPTH%2 == 0:
                RANGE = range(i - HALF_RANGE, i + HALF_RANGE)
            else:
                RANGE = range(i - HALF_RANGE, i + HALF_RANGE + 1)

            for j in RANGE:
                frame = x[j, :, :, :]  #(352, 288, 1), type = tensor
                frame = tf.reshape(frame,(1, TARGET_HEIGHT, TARGET_WIDTH))

                if j == i - HALF_RANGE:
                    package = frame
                else:   
                    package = tf.concat([package, frame], 0)

            if FIRST == True:
                package_set = package
                FIRST = False
            else:
                package_set = tf.concat([package_set, package], 0)

    package_set = tf.reshape(package_set, (AMOUNT, DEPTH, TARGET_HEIGHT, TARGET_WIDTH, 1))   #(294, 5, 352, 288, 1)
    return package_set

但是batch_size(我命名为AMOUNT)信息不能作为for-loop索引。应该怎么做才能使用呢?

Traceback (most recent call last):
  File "main.py", line 71, in <module>
    model = combined(FILENAME, AMOUNT, DEPTH, TARGET_HEIGHT, TARGET_WIDTH)
  File "/home/user1/REUS/image-reconstruction/code/functional/model_build_up.py", line 132, in combined
    combined_model = Model(inputs = ip, outputs = SRnet_layer)
  File "/home/user1/.conda/envs/tf-cpu/lib/python3.7/site-packages/keras/legacy/interfaces.py", line 91, in wrapper
    return func(*args, **kwargs)
  File "/home/user1/.conda/envs/tf-cpu/lib/python3.7/site-packages/keras/engine/network.py", line 93, in __init__
    self._init_graph_network(*args, **kwargs)
  File "/home/user1/.conda/envs/tf-cpu/lib/python3.7/site-packages/keras/engine/network.py", line 231, in _init_graph_network
    self.inputs, self.outputs)
  File "/home/user1/.conda/envs/tf-cpu/lib/python3.7/site-packages/keras/engine/network.py", line 1366, in _map_graph_network
    tensor_index=tensor_index)
  File "/home/user1/.conda/envs/tf-cpu/lib/python3.7/site-packages/keras/engine/network.py", line 1353, in build_map
    node_index, tensor_index)
  File "/home/user1/.conda/envs/tf-cpu/lib/python3.7/site-packages/keras/engine/network.py", line 1325, in build_map
    node = layer._inbound_nodes[node_index]
AttributeError: 'NoneType' object has no attribute '_inbound_nodes'

【问题讨论】:

    标签: python tensorflow keras tensor


    【解决方案1】:

    Keras 层(模型表现为层)将 keras 层作为输入,而不是张量。

    您需要将 Layer 参数传递给 SRnet_3d_model 而不是张量。

    举个简单的例子:

    inp = Input(shape=(2,))
    out = Dense(1, activation='sigmoid')(inp)
    model = Model(inp, out)
    

    上面的变量inp 是一个输入层,它包含一个占位符张量,但还包含用于构建图形的附加信息。例如,当构建输出层 out 时,keras 会参考祖先层(恰好是 inp,这是 Dense.call 的参数)以确定该层的输入尺寸。

    因此,在构建 keras 模型时,您需要始终根据层进行操作(模型是 Layer 的子类,可以视为复杂层)。

    在某些情况下,现有层无法提供足够的功能。然后您有两个选择:Lambda 层或用户定义的层。 Lambda 层允许您以最小的开销在层内使用后端操作(或原始 tf 操作)。当您希望图层拥有自己的变量/权重时,需要自定义图层。

    Lambda 层的一个简单示例是张量切片操作,例如:

    Lambda(lambda x: x[:, 0])
    

    请注意,在张量级别,您需要考虑批量维度。上面的 lambda 示例假设输入维度为 (batch_size, n_features),并返回一个带有暗淡 (batch_size, 1) 的张量。

    【讨论】:

    • 所以问题是SRnet_layer 不是我可以用作输出的张量吗?这意味着数据类型(张量)对模型构造很重要,对吧?
    • 没有问题,package_set_tensor 是一个张量,它需要是一个层。这就是SRnet_3d_model.call() 的论点
    • 所以基本思路是我应该在中间使用lambda定义一个数据重新打包的层,然后这个层的输出可以顺利传递给SRnet_3d_model,对吧?
    • 我不确定您所说的“数据重新打包”是什么意思,但如果它是像切片/连接张量这样的操作,那么可以。例如Lambda(lambda x: x[:, 0]) 是获得结果的第一个特征的完全有效的方法;但是您需要 Lambda 包装来维护图形结构。请注意,在 lambda 内部,您必须考虑批处理维度。因此,例如上面的张量切片示例假设 (batch_size, n_features) 的二维张量。
    • 在 lambda 层内部,我正在尝试获取批处理大小以运行 for 循环。当我做AMOUNT = keras.backend.shape(x)[0] 时,AMOUNT 就像Tensor("lambda_1/strided_slice:0", shape=(), dtype=int32),意味着批量大小为空。如果我确实想做for i in range(AMOUNT)(这也需要我将类型从张量更改为整数),我该怎么办?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-24
    • 2020-11-28
    • 1970-01-01
    • 2022-12-15
    • 2017-10-20
    • 2017-03-08
    • 1970-01-01
    相关资源
    最近更新 更多