You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Keras中‘Graph disconnected:无法获取张量值’错误?

Pix2Pix模型构建中Graph disconnected错误的解决方法

问题描述

运行Pix2Pix模型时出现如下错误:

ValueError: Graph disconnected: cannot obtain value for tensor Tensor("input_1:0", shape=(None, 256, 256, 3), dtype=float32) at layer "conv2d". The following previous layers were accessed without issue: []

报错栈跟踪信息:

Traceback (most recent call last):
  File "C:/Users/sanjay.g/PycharmProjects/Rethinking_Net/MIMO_Model2.py", line 99, in <module>
    gan = Pix2Pix()
  File "C:/Users/sanjay.g/PycharmProjects/Rethinking_Net/MIMO_Model2.py", line 21, in __init__
    self.generator = self.build_generator
  File "C:/Users/sanjay.g/PycharmProjects/Rethinking_Net/MIMO_Model2.py", line 97, in build_generator
    return Model(b3, S3)
  File "C:\Users\sanjay.g\Miniconda3\envs\pythonProject1\lib\site-packages\tensorflow\python\keras\engine\training.py", line 242, in __new__
    return functional.Functional(*args, **kwargs)
  File "C:\Users\sanjay.g\Miniconda3\envs\pythonProject1\lib\site-packages\tensorflow\python\training\tracking\base.py", line 457, in _method_wrapper
    result = method(self, *args, **kwargs)
  File "C:\Users\sanjay.g\Miniconda3\envs\pythonProject1\lib\site-packages\tensorflow\python\keras\engine\functional.py", line 115, in __init__
    self._init_graph_network(inputs, outputs)
  File "C:\Users\sanjay.g\Miniconda3\envs\pythonProject1\lib\site-packages\tensorflow\python\training\tracking\base.py", line 457, in _method_wrapper
    result = method(self, *args, **kwargs)
  File "C:\Users\sanjay.g\Miniconda3\envs\pythonProject1\lib\site-packages\tensorflow\python\keras\engine\functional.py", line 190, in _init_graph_network
    nodes, nodes_by_depth, layers, _ = _map_graph_network(
  File "C:\Users\sanjay.g\Miniconda3\envs\pythonProject1\lib\site-packages\tensorflow\python\keras\engine\functional.py", line 926, in _map_graph_network
    raise ValueError('Graph disconnected: '
ValueError: Graph disconnected: cannot obtain value for tensor Tensor("input_1:0", shape=(None, 256, 256, 3), dtype=float32) at layer "conv2d". The following previous layers were accessed without issue: []

模型代码:

from __future__ import print_function, division

import tensorflow as tf
from tensorflow.keras.layers import Input, Dense, Reshape, Flatten, Dropout, Concatenate
from tensorflow.keras.layers import BatchNormalization, Activation, ZeroPadding2D
from tensorflow.keras.models import Sequential, Model
from data_loader import DataLoader
from tensorflow.keras.layers import Conv2D, LeakyReLU, UpSampling2D, ReLU, Conv2DTranspose

class Pix2Pix():
    def __init__(self):
        # Input shape
        self.img_rows = 256
        self.img_cols = 256
        self.channels = 3
        self.img_shape = (self.img_rows, self.img_cols, self.channels)
        self.dataset_name = 'nayadata'
        self.data_loader = DataLoader(dataset_name=self.dataset_name, img_res=(self.img_rows, self.img_cols))
        self.gf = 32
        self.df = 32
        self.generator = self.build_generator
        img_A = Input(shape=self.img_shape)
        img_B = Input(shape=self.img_shape)
        fake_A = self.generator(img_B)
        self.combined = Model(inputs=[img_A, img_B], outputs=[fake_A])

    @property
    def build_generator(self):
        def convolutionLayer(layer_input, filters, kernel_size=3, stride=1, relu=True, bn=False, tran=False, bias=True):
            if bn and bias:
                bias = False
            if tran:
                d = Conv2DTranspose(filters, kernel_size=kernel_size, strides=stride, padding='same', use_bias=bias)(layer_input)
            else:
                d = Conv2D(filters, kernel_size=kernel_size, strides=stride, padding='same', use_bias=bias)(layer_input)
            if relu:
                d = ReLU()(d)
            if bn:
                d = BatchNormalization()(d)
            return d

        def residualBlocks(layer_input, filters, kernel_size=3, stride=1):
            d = convolutionLayer(layer_input, filters, kernel_size=kernel_size, stride=stride, relu=True)
            d = convolutionLayer(d, filters, kernel_size=kernel_size, stride=stride, relu=False)
            return d

        def SCM_Block(layer_input, filters, kernel_size=3, stride=1, relu=True, bn=False, tran=False, bias=True):
            d = convolutionLayer(layer_input, filters, kernel_size=kernel_size, stride=stride, relu=True)
            d = convolutionLayer(d, filters, kernel_size=kernel_size - 2, stride=stride, relu=True)
            d = convolutionLayer(d, filters, kernel_size=kernel_size, stride=stride, relu=True)
            d = convolutionLayer(d, filters, kernel_size=kernel_size - 2, stride=stride, relu=True)
            return d

        def eBlock(layer_input, filters, num_res=8):
            e = layer_input
            for num1 in range(num_res):
                e = residualBlocks(e, filters, kernel_size=3, stride=1)
            return e

        def dBlock(layer_input, filters, num_res=8):
            d = layer_input
            for num1 in range(num_res):
                d = residualBlocks(d, filters, kernel_size=3, stride=1)
            return d

        # Input Image
        b1 = Input(shape=self.img_shape)
        b2 = tf.image.resize(b1, [128, 128])
        b3 = tf.image.resize(b2, [64, 64])
        print(b3.shape)
        # Downsampling
        d1 = eBlock(b1, self.gf)
        #print(d1.shape)
        d1 = Conv2D(self.gf, kernel_size=3, strides=2, padding='same')(d1)
        #print(d1.shape)
        b_scm1 = SCM_Block(b2, self.gf)
        #print(b_scm1.shape)
        d2 = Concatenate()([b_scm1, d1])
        #print(d2.shape)
        d2 = eBlock(d2, self.gf*2)
        #print(d2.shape)

        d2 = Conv2D(self.gf*2, kernel_size=3, strides=2, padding='same')(d2)
        #print(d2.shape)
        b_scm2 = SCM_Block(b3, self.gf*2)
        #print(b_scm2.shape)
        d3 = Concatenate()([b_scm2, d2])
        #print(d3.shape)
        d3 = eBlock(d3, self.gf * 4)
        print(d3.shape)

        # # Upsampling
        u3 = dBlock(d3, self.gf * 4)
        print(u3.shape)
        S3 = Conv2D(3, kernel_size=3, strides=1, padding='same')(u3)
        print(S3.shape)
        return Model(b3, S3)
if __name__ == '__main__':
    gan = Pix2Pix()
    gan.train(epochs=201, batch_size=4, sample_interval=50)

错误原因及解决方法

核心问题

  1. 生成器输入输出链路断裂:生成器的计算逻辑从b1(256x256输入)开始,但最终返回的模型却把b3(64x64下采样图)作为输入。Keras无法建立b3到输出S3的完整连接——因为S3依赖的所有上游张量最终都追溯到b1,而b1没有被纳入模型输入,导致计算图断开。

  2. build_generator定义错误:使用@property装饰器后,self.build_generator返回的是函数本身,而非构建好的模型实例。后续调用self.generator(img_B)时,函数内部自行创建的b1和外部传入的img_B完全无关,进一步加剧了图断开问题。

修复步骤

1. 修正生成器的输入

将生成器的输入改为原始的b1,确保计算链路完整:

# 原代码
return Model(b3, S3)
# 修改为
return Model(b1, S3)

2. 移除@property装饰器,将build_generator改为普通方法

删除@property,让build_generator成为可调用的方法:

# 原代码
@property
def build_generator(self):
# 修改为
def build_generator(self):

同时在__init__中调用方法构建生成器:

# 原代码
self.generator = self.build_generator
# 修改为
self.generator = self.build_generator()

3. 让生成器接受外部传入的输入张量

如果需要生成器使用外部的img_B作为输入,调整build_generator结构,让它接受输入张量参数:

def build_generator(self, input_tensor):
    # 移除内部的b1 = Input(shape=self.img_shape)
    b1 = input_tensor
    b2 = tf.image.resize(b1, [128, 128])
    b3 = tf.image.resize(b2, [64, 64])
    # 其余计算逻辑保持不变
    # ...
    return Model(input_tensor, S3)

然后在__init__中调用:

img_B = Input(shape=self.img_shape)
self.generator = self.build_generator(img_B)
fake_A = self.generator(img_B)

完整修正后的关键代码片段

class Pix2Pix():
    def __init__(self):
        # 其他初始化代码不变
        self.gf = 32
        self.df = 32
        img_A = Input(shape=self.img_shape)
        img_B = Input(shape=self.img_shape)
        # 传入img_B构建生成器
        self.generator = self.build_generator(img_B)
        fake_A = self.generator(img_B)
        self.combined = Model(inputs=[img_A, img_B], outputs=[fake_A])

    def build_generator(self, input_tensor):
        # 内部辅助函数保持不变
        def convolutionLayer(layer_input, filters, kernel_size=3, stride=1, relu=True, bn=False, tran=False, bias=True):
            if bn and bias:
                bias = False
            if tran:
                d = Conv2DTranspose(filters, kernel_size=kernel_size, strides=stride, padding='same', use_bias=bias)(layer_input)
            else:
                d = Conv2D(filters, kernel_size=kernel_size, strides=stride, padding='same', use_bias=bias)(layer_input)
            if relu:
                d = ReLU()(d)
            if bn:
                d = BatchNormalization()(d)
            return d

        def residualBlocks(layer_input, filters, kernel_size=3, stride=1):
            d = convolutionLayer(layer_input, filters, kernel_size=kernel_size, stride=stride, relu=True)
            d = convolutionLayer(d, filters, kernel_size=kernel_size, stride=stride, relu=False)
            return d

        def SCM_Block(layer_input, filters, kernel_size=3, stride=1, relu=True, bn=False, tran=False, bias=True):
            d = convolutionLayer(layer_input, filters, kernel_size=kernel_size, stride=stride, relu=True)
            d = convolutionLayer(d, filters, kernel_size=kernel_size - 2, stride=stride, relu=True)
            d = convolutionLayer(d, filters, kernel_size=kernel_size, stride=stride, relu=True)
            d = convolutionLayer(d, filters, kernel_size=kernel_size - 2, stride=stride, relu=True)
            return d

        def eBlock(layer_input, filters, num_res=8):
            e = layer_input
            for num1 in range(num_res):
                e = residualBlocks(e, filters, kernel_size=3, stride=1)
            return e

        def dBlock(layer_input, filters, num_res=8):
            d = layer_input
            for num1 in range(num_res):
                d = residualBlocks(d, filters, kernel_size=3, stride=1)
            return d

        # 使用外部传入的输入张量
        b1 = input_tensor
        b2 = tf.image.resize(b1, [128, 128])
        b3 = tf.image.resize(b2, [64, 64])
        # 后续计算逻辑不变
        d1 = eBlock(b1, self.gf)
        d1 = Conv2D(self.gf, kernel_size=3, strides=2, padding='same')(d1)
        b_scm1 = SCM_Block(b2, self.gf)
        d2 = Concatenate()([b_scm1, d1])
        d2 = eBlock(d2, self.gf*2)

        d2 = Conv2D(self.gf*2, kernel_size=3, strides=2, padding='same')(d2)
        b_scm2 = SCM_Block(b3, self.gf*2)
        d3 = Concatenate()([b_scm2, d2])
        d3 = eBlock(d3, self.gf * 4)

        u3 = dBlock(d3, self.gf * 4)
        S3 = Conv2D(3, kernel_size=3, strides=1, padding='same')(u3)
        # 返回以外部输入为起点的模型
        return Model(input_tensor, S3)

额外注意事项

  • 确保所有张量操作都在连续的计算链路中,避免出现孤立的张量节点。
  • 检查生成器输出尺寸是否与输入一致,符合Pix2Pix的任务要求。

内容的提问来源于stack exchange,提问作者Sanjay Kumar Gupta Res Scholar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 14:15:30