Autoencoder的Sequential与Functional API结果不一致问题排查与解决
函数式API实现自编码器与Sequential版本结果不一致问题
问题背景
在Aurélien Geron所著《Hands-On Machine Learning》第17章中,将教材里的Sequential自编码器示例转换为函数式API实现后,两者运行结果不一致,但原本预期结果应该完全一致。
教材中的Sequential示例代码
# 来源:《Hands-On Machine Learning》第17章示例 import tensorflow as tf tf.random.set_seed(42) # 确保CPU上的可复现性 encoder = tf.keras.Sequential([tf.keras.layers.Dense(2)]) decoder = tf.keras.Sequential([tf.keras.layers.Dense(3)]) autoencoder = tf.keras.Sequential([encoder, decoder]) optimizer = tf.keras.optimizers.SGD(learning_rate=0.5) autoencoder.compile(loss="mse", optimizer=optimizer) import numpy as np from scipy.spatial.transform import Rotation m = 60 X = np.zeros((m, 3)) # 初始化3D数据集 np.random.seed(42) angles = (np.random.rand(m) ** 3 + 0.5) * 2 * np.pi # 非均匀分布 X[:, 0], X[:, 1] = np.cos(angles), np.sin(angles) * 0.5 # 椭圆形状 X += 0.28 * np.random.randn(m, 3) # 添加噪声 X = Rotation.from_rotvec([np.pi / 29, -np.pi / 20, np.pi / 4]).apply(X) X_train = X + [0.2, 0, 0.2] # 轻微偏移 history = autoencoder.fit(X_train, X_train, epochs=500, verbose=False) codings = encoder.predict(X_train) fig = plt.figure(figsize=(4,3)) plt.plot(codings[:,0], codings[:, 1], "b.") plt.xlabel("$z_1$", fontsize=18) plt.ylabel("$z_2$", fontsize=18, rotation=0) plt.grid(True) save_fig("linear_autoencoder_pca_plot") plt.show()
运行结果图:
自行实现的函数式API代码
from tensorflow.keras.layers import Dense from tensorflow.keras import Input, Model input1 = Input(shape=3) x = Dense(2, activation='linear', name="intermediate")(input1) x = Dense(3, activation='linear')(x) model_autoencoder_funcAPI = Model(inputs=input1, outputs=x) optimizer1 = tf.keras.optimizers.SGD(learning_rate=0.5) model_autoencoder_funcAPI.compile(loss='mse', optimizer=optimizer1) history_funcAPI = model_autoencoder_funcAPI.fit(X_train, X_train, epochs=501) layer_name = 'intermediate' intermediate_layer_model = Model(inputs=input1, outputs=model_autoencoder_funcAPI.get_layer(layer_name).output) codings_autoencoder_funcAPI = intermediate_layer_model.predict(X_train) fig = plt.figure(figsize=(4,3)) plt.plot(codings_autoencoder_funcAPI[:,0], codings_autoencoder_funcAPI[:, 1], "b.") plt.xlabel("$z_1$", fontsize=18) plt.ylabel("$z_2$", fontsize=18, rotation=0) plt.grid(True) save_fig("ch17_linear_autoencoder_pca_plot_funcAPI") plt.show()
运行结果图:
问题解决方法
在函数式API代码的模型构建前添加tf.random.set_seed(42),保证模型权重初始化的随机种子与Sequential版本一致,修改后的代码开头如下:
import tensorflow as tf tf.random.set_seed(42) # 添加该行以保证可复现性 from tensorflow.keras.layers import Dense from tensorflow.keras import Input, Model input1 = Input(shape=3) # ... 后续代码不变
修改后,函数式API版本的运行结果与Sequential版本完全一致。
内容的提问来源于stack exchange,提问作者IKAHN
相关产品推荐
相关产品推荐

