如何消除「UserWarning: The initializer GlorotUniform is unseeded」警告?
你提供的代码在运行bias_variance_decomp时会触发以下警告:
UserWarning: The initializer GlorotUniform is unseeded and being called multiple times, which will return identical values each time (even if the initializer is unseeded). Please update your code to provide a seed to the initializer, or avoid using the same initializer instance more than once.
原因是bias_variance_decomp会循环多次训练模型,但原代码仅创建了一个模型实例,默认的GlorotUniform初始化器未设置种子,重复调用会导致初始化值重复,触发TensorFlow的警告。
以下是两种可行的修改方案:
方案1:为初始化器显式设置种子
为每个Dense层的kernel_initializer和bias_initializer指定带独立种子的GlorotUniform实例,确保每次初始化生成不同的随机值:
import matplotlib.pyplot as plt import numpy as np import tensorflow as tf from tensorflow.keras.layers import Dense from tensorflow.keras.models import Sequential from tensorflow.keras.initializers import GlorotUniform from mlxtend.evaluate import bias_variance_decomp from mlxtend.data import boston_housing_data from sklearn.tree import DecisionTreeRegressor from sklearn.ensemble import BaggingRegressor from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error np.random.seed(16) tf.random.set_seed(16) X, y = boston_housing_data() X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=123, shuffle=True) # 为每个层的初始化器设置独立种子 model = Sequential() model.add(Dense(2048, activation='relu', kernel_initializer=GlorotUniform(seed=42), bias_initializer=GlorotUniform(seed=43))) model.add(Dense(512, activation='relu', kernel_initializer=GlorotUniform(seed=44), bias_initializer=GlorotUniform(seed=45))) model.add(Dense(32, activation='relu', kernel_initializer=GlorotUniform(seed=46), bias_initializer=GlorotUniform(seed=47))) model.add(Dense(1, activation='linear', kernel_initializer=GlorotUniform(seed=48), bias_initializer=GlorotUniform(seed=49))) optimizer = tf.keras.optimizers.Adam() model.compile(loss='mean_squared_error', optimizer=optimizer) model.fit(X_train, y_train, epochs=100, batch_size=32, verbose=0) mean_squared_error(model.predict(X_test), y_test) avg_expected_loss, avg_bias, avg_var = bias_variance_decomp( model, X_train, y_train, X_test, y_test, loss='mse', num_rounds=100, random_seed=16, epochs=100, batch_size=32, verbose=0) print('Average expected loss: %.3f' % avg_expected_loss) print('Average bias: %.3f' % avg_bias) print('Average variance: %.3f' % avg_var)
方案2:封装模型为函数(更推荐)
偏差-方差分解的核心逻辑是每次训练独立的模型实例,将模型定义封装成函数,让bias_variance_decomp每次迭代都创建全新模型,从根源上避免重复使用初始化器:
import matplotlib.pyplot as plt import numpy as np import tensorflow as tf from tensorflow.keras.layers import Dense from tensorflow.keras.models import Sequential from mlxtend.evaluate import bias_variance_decomp from mlxtend.data import boston_housing_data from sklearn.tree import DecisionTreeRegressor from sklearn.ensemble import BaggingRegressor from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error np.random.seed(16) tf.random.set_seed(16) X, y = boston_housing_data() X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=123, shuffle=True) # 将模型构建逻辑封装为函数 def build_model(): model = Sequential() model.add(Dense(2048, activation='relu')) model.add(Dense(512, activation='relu')) model.add(Dense(32, activation='relu')) model.add(Dense(1, activation='linear')) optimizer = tf.keras.optimizers.Adam() model.compile(loss='mean_squared_error', optimizer=optimizer) return model # 测试单个模型性能 model = build_model() model.fit(X_train, y_train, epochs=100, batch_size=32, verbose=0) mean_squared_error(model.predict(X_test), y_test) # 传入模型构建函数而非实例 avg_expected_loss, avg_bias, avg_var = bias_variance_decomp( build_model, X_train, y_train, X_test, y_test, loss='mse', num_rounds=100, random_seed=16, epochs=100, batch_size=32, verbose=0) print('Average expected loss: %.3f' % avg_expected_loss) print('Average bias: %.3f' % avg_bias) print('Average variance: %.3f' % avg_var)
方案说明
方案2更贴合偏差-方差分解的设计逻辑,每次迭代都生成全新模型,既保证了初始化的随机性,又彻底消除警告;方案1通过设置种子避免重复初始化值,但本质仍是复用同一模型实例,规范性不如方案2。
内容的提问来源于stack exchange,提问作者Boris Reif

