Keras中重复赋值变量x为何未覆盖中间层信息?
关于TensorFlow Functional API中变量x重复赋值仍能保留层结构的疑问
输入代码
encoder_input = keras.Input(shape=(28, 28, 1), name="img") x = layers.Conv2D(16, 3, activation="relu")(encoder_input) x = layers.Conv2D(32, 3, activation="relu")(x) x = layers.MaxPooling2D(3)(x) x = layers.Conv2D(32, 3, activation="relu")(x) x = layers.Conv2D(16, 3, activation="relu")(x) encoder_output = layers.GlobalMaxPooling2D()(x) encoder = keras.Model(encoder_input, encoder_output, name="encoder") encoder.summary() x = layers.Reshape((4, 4, 1))(encoder_output) x = layers.Conv2DTranspose(16, 3, activation="relu")(x) x = layers.Conv2DTranspose(32, 3, activation="relu")(x) x = layers.UpSampling2D(3)(x) x = layers.Conv2DTranspose(16, 3, activation="relu")(x) decoder_output = layers.Conv2DTranspose(1, 3, activation="relu")(x) autoencoder = keras.Model(encoder_input, decoder_output, name="autoencoder") autoencoder.summary()
输出结果
Model: "encoder" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= img (InputLayer) [(None, 28, 28, 1)] 0 _________________________________________________________________ conv2d (Conv2D) (None, 26, 26, 16) 160 _________________________________________________________________ conv2d_1 (Conv2D) (None, 24, 24, 32) 4640 _________________________________________________________________ max_pooling2d (MaxPooling2D) (None, 8, 8, 32) 0 _________________________________________________________________ conv2d_2 (Conv2D) (None, 6, 6, 32) 9248 _________________________________________________________________ conv2d_3 (Conv2D) (None, 4, 4, 16) 4624 _________________________________________________________________ global_max_pooling2d (Global (None, 16) 0 ================================================================= Total params: 18,672 Trainable params: 18,672 Non-trainable params: 0 _________________________________________________________________ Model: "autoencoder" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= img (InputLayer) [(None, 28, 28, 1)] 0 _________________________________________________________________ conv2d (Conv2D) (None, 26, 26, 16) 160 _________________________________________________________________ conv2d_1 (Conv2D) (None, 24, 24, 32) 4640 _________________________________________________________________ max_pooling2d (MaxPooling2D) (None, 8, 8, 32) 0 _________________________________________________________________ conv2d_2 (Conv2D) (None, 6, 6, 32) 9248 _________________________________________________________________ conv2d_3 (Conv2D) (None, 4, 4, 16) 4624 _________________________________________________________________ global_max_pooling2d (Global (None, 16) 0 _________________________________________________________________ reshape (Reshape) (None, 4, 4, 1) 0 _________________________________________________________________ conv2d_transpose (Conv2DTran (None, 6, 6, 16) 160 _________________________________________________________________ conv2d_transpose_1 (Conv2DTr (None, 8, 8, 32) 4640 _________________________________________________________________ up_sampling2d (UpSampling2D) (None, 24, 24, 32) 0 _________________________________________________________________ conv2d_transpose_2 (Conv2DTr (None, 26, 26, 16) 4624 _________________________________________________________________ conv2d_transpose_3 (Conv2DTr (None, 28, 28, 1) 145 ================================================================= Total params: 28,241 Trainable params: 28,241 Non-trainable params: 0 _________________________________________________________________
问题
为何每次调用新层时,变量x未被覆盖?调用encoder.summary()时能追踪到完整的层结构,但重复赋值x理当丢失中间层信息,这些信息究竟存储在何处?
解答
这是TensorFlow Functional API的核心工作机制决定的:
- 当你执行
layers.Conv2D(...)(input_tensor)这类操作时,**不是在修改x变量,而是创建了一个全新</think_never_used_51bce0c785ca2f68081bfa7d91973934> - 变量x只是一个"指针",每次赋值只是让x指向最新生成的那个张量节点而已,之前的节点并没有被销毁——因为它们已经被纳入了从
encoder_input到encoder_output的完整计算路径中,这些连接关系和层信息都存在TensorFlow的内部计算图结构里,和x变量的引用无关。 - 当你创建
keras.Model(encoder_input, encoder_output)时,Keras会从输出节点出发,反向追溯所有依赖的上游节点,把整个路径上的所有层和张量连接都提取出来,组成完整的模型结构,所以summary()能显示所有中间层。 - 后面重新给x赋值时,只是在从
encoder_output开始构建新的计算分支,和之前的编码器路径互不影响,因为之前的连接关系已经被固定在计算图里了,不会因为x的引用改变而消失。
内容的提问来源于stack exchange,提问作者user19580074
相关产品推荐
相关产品推荐

