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

如何获取大模型中子模型SimpleAE的latent space输出?

问题描述

我定义了如下SimpleAE自编码器类:

class SimpleAE(tf.keras.Model):
def __init__(self, latent_dim, bypass = False, trainable=True, **kwargs):
    super(SimpleAE,self).__init__(**kwargs)
    self.latent_dim = latent_dim
    self.bypass = bypass
    self.trainable = trainable
    self.quantizer = None
    
def get_config(self):
    config = super(SimpleAE,self).get_config().copy()
    config.update({'latent_dim':self.latent_dim, 'bypass':self.bypass, 'trainable':self.trainable, 
                   'quantizer':self.quantizer})        
    
    return config

def build(self,input_shape):   
    self.inputlayer = tf.keras.layers.InputLayer(input_shape=(input_shape[-1],))  # Initialize input layer
    self.encoder = tf.keras.layers.Dense(self.latent_dim,activation='linear', name="latentspace")
    self.decoder = tf.keras.layers.Dense(input_shape[-1], activation='linear')
    self.built = True
    
def call(self,x):
    if not self.built:
        self.build(x.shape)  # Ensure the model is built before calling
    # print("Test",flush=True)
    if self.bypass is False:
        xin = self.inputlayer(x)
        encoded = self.encoder(xin)
        decoded = self.decoder(encoded)
        return decoded
    else:
        return x

该类被嵌入到另一大模型中:

class Model():
def __init__(self, args, pca = None):   
    self.N = args.N
    self.L = args.L
    self.B = args.B
    self.H = args.H
    self.S = args.S
    self.P = args.P
    self.X = args.X
    self.R = args.R
    self.GPU = True #args.GPU
    self.skip = args.skip
    self.top = args.topology
    self.causal = args.causal
    self.duration = args.duration
    self.sample_rate = args.sample_rate
    self.model_name = self.top + "_auto_encoder"
    self.buffer_length = 10 #args.buffer_length
    self.save_latent = args.save_latent
    # self.pca = pca
    self.quantizer = None
             
    ...SOMEMODELSTUFF...
    
    self.AE_enc_left = SimpleAE(latent_dim=args.ae_enc_dim, bypass=args.bypass, trainable=True, name = "AE_Encoder_left")
    self.AE_enc_right = SimpleAE(latent_dim=args.ae_enc_dim, bypass=args.bypass, trainable=True, name = "AE_Encoder_right")
    self.AE_tcn_left = SimpleAE(latent_dim=args.ae_tcn_dim, bypass=args.bypass, trainable=True, name = "AE_TCN_left")
    self.AE_tcn_right = SimpleAE(latent_dim=args.ae_tcn_dim, bypass=args.bypass, trainable=True, name = "AE_TCN_right")
    
def call(self):
        input_left  = tf.keras.Input(shape = (None,), name = "Input_left")
        ... MOREMODELSTUFF ...
        
        enc_inp_r_quantized = self.AE_enc_right(output_of_submodel)
        enc_inp_l_quantized = self.AE_enc_left(output_of_submodel)
        ... FURTER  MODEL STUFF ...

我已预训练包含SimpleAE的整个大模型并加载权重:

model.load_weights(weights_file)
model.compile(loss=loss)

#sanity check
model.evaluate(valid_ds, verbose=0)
submodel = tf.keras.Model(inputs=[model.input], outputs=[model.get_layer("AE_Encoder_left").get_layer("latentspace").output])
print("test")

model.evaluate输出符合预期,权重加载正常,且autoencoder的bypass已设为False。但执行model.get_layer("AE_Encoder_left").get_layer("latentspace").output时,始终报错:

*** AttributeError: Layer latentspace has no inbound nodes.

我需要获取该autoencoder的latent space数据以训练量化器,请问如何正确获取大模型中SimpleAE类latentspace层的输出?

解决方案

问题根源

报错的核心原因是SimpleAE内部的latentspace层(即self.encoder)没有被Keras的模型计算图正确追踪——你在call方法里手动创建了InputLayer并连接,但这种方式没有将子层的连接关系注册到大模型的计算图中,导致Keras无法识别latentspace层的输入节点。

可行修正方案

方案1:修改SimpleAE实现,让子层自动注册到模型图

去掉call方法里的InputLayer,直接用输入张量连接各层,让Keras自动追踪层间关系:

class SimpleAE(tf.keras.Model):
    def __init__(self, latent_dim, bypass = False, trainable=True, **kwargs):
        super(SimpleAE,self).__init__(**kwargs)
        self.latent_dim = latent_dim
        self.bypass = bypass
        self.trainable = trainable
        self.quantizer = None
        # 提前定义encoder,decoder在build时根据输入形状初始化
        self.encoder = tf.keras.layers.Dense(self.latent_dim,activation='linear', name="latentspace")
        self.decoder = None
    
    def get_config(self):
        config = super(SimpleAE,self).get_config().copy()
        config.update({'latent_dim':self.latent_dim, 'bypass':self.bypass, 'trainable':self.trainable, 
                       'quantizer':self.quantizer})        
        return config

    def build(self,input_shape):   
        self.decoder = tf.keras.layers.Dense(input_shape[-1], activation='linear')
        self.built = True
    
    def call(self,x):
        if not self.built:
            self.build(x.shape)
        if self.bypass is False:
            encoded = self.encoder(x)  # 直接用输入张量连接encoder,无需额外InputLayer
            decoded = self.decoder(encoded)
            return decoded
        else:
            return x

修改后重新训练或加载权重,此时latentspace层的连接关系会被正确注册到大模型的计算图中,你原有的获取子层输出的代码即可正常运行。

方案2:不修改SimpleAE,构建大模型时直接记录中间输出

如果不想改动SimpleAE的代码,可以在大模型的call方法中,直接提取AE_enc_left的encoder输出张量并作为模型的额外输出:

def call(self):
    input_left  = tf.keras.Input(shape = (None,), name = "Input_left")
    ... MOREMODELSTUFF ...
    
    # 调用AE_enc_left时,拆分encoder和decoder的调用,记录latent输出
    ae_left = self.AE_enc_left
    encoded_left = ae_left.encoder(output_of_submodel)
    enc_inp_l_quantized = ae_left.decoder(encoded_left)
    
    # 同理处理AE_enc_right
    ae_right = self.AE_enc_right
    encoded_right = ae_right.encoder(output_of_submodel)
    enc_inp_r_quantized = ae_right.decoder(encoded_right)
    
    ... FURTER  MODEL STUFF ...
    
    # 将主输出和latent输出一起返回
    return [main_output, encoded_left]  # main_output为原模型的主输出

加载模型后,直接创建子模型提取对应的latent输出:

submodel = tf.keras.Model(inputs=[model.input], outputs=[model.output[1]])

方案3:用Keras后端函数直接计算latent输出

如果上述方案都无法实施,可以用tf.keras.backend.function直接构建输入到latent输出的计算函数:

# 获取目标层
ae_layer = model.get_layer("AE_Encoder_left")
latent_layer = ae_layer.get_layer("latentspace")

# 创建计算函数
get_latent = tf.keras.backend.function(
    inputs=[model.input],
    outputs=[latent_layer(ae_layer.input)]
)

# 用验证集数据计算latent空间数据
latent_data = get_latent(valid_ds)

内容的提问来源于stack exchange,提问作者user20780

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 03:17:34