为什么 Keras Tuners 的固定超参数会产生与静态值不同的结果?
Why do Keras Tuners' Fixed hyperparameters produce different results from static values?
即使我的模型应该有效地使用相同的参数,我的超调结果也大不相同,这取决于我是使用 hp.Fixed(key, value)
还是只使用 value
(其中 value
是说,一个整数)。我已经验证每个测试的重复运行都会在 instructions for reproducibility 之后产生相同的结果,并为所有适用的 layers/initializers/etc 设置种子。尽管说明上说它们不是必需的。
使用hp.Fixed(key, value)
使用value
查看所有超参数的 table,似乎 hp.Fixed
甚至什么都没做。正在测试所有超参数。
编辑:无论状态如何,我的自定义超模型的超参数都被 HyperbandTuner 忽略。
这是有问题的代码:
class MyModel(kt.HyperModel):
def __init__(self, **config):
self.config = config
self.seed = config.get('seed')
def build_model(self):
model = Sequential(name=self.name)
model.add(LSTM(self.units, name='LSTM'))
model.add(Dense(1, name='Output', kernel_initializer=GlorotUniform(seed=self.seed)))
model.compile(loss='mean_squared_error', metrics='mean_squared_error', sample_weight_mode='temporal')
return model
# If the user has supplied the parameter manually, use hp.Fixed()
# Otherwise, use the provided hyperparameter (default)
def _param(self, key, default=None):
value = self.config.get(key)
if value is not None:
return self.hp.Fixed(key, value)
else:
return default
def build(self, hp):
self.hp = hp
self.units = self._param('units', hp.Int('units', 1, 200, step=5))
return self.build_model()
好的,在进行更多挖掘之后我发现(特别是通过 this tutorial 声明超参数的方式)当您编写 hp.[Fixed|Choice|etc.]
时,您会立即声明这些超参数在搜索中的存在 space,无论该代码出现在何处。
将超参数声明视为特征class 方法,而不是 HyperTuner 从模型中获取的常规 Python 对象。
本质上,每个Fixed/Choice/etc。超参数方法同时在 HyperTuner class 后台的某处设置一个全局超参数,同时还返回一个常规变量 (Int/Float/String/Range/List/etc.),这样您仍然可以在 HyperTuner 最终覆盖它之前构建您的模型而不会出错搜索阶段。
我对此感到困惑,因为通常 hp
在 build_model()
方法或 kt.HyperModel
class 中显示为参数,其中调用被分配给局部变量然后传递给模型声明。
下面是对违规代码的修复:
class MyModel(kt.HyperModel):
def __init__(self, **config):
self.config = config
self.seed = config.get('seed')
def build_model(self):
model = Sequential(name=self.name)
model.add(LSTM(self.units, name='LSTM'))
model.add(Dense(1, name='Output', kernel_initializer=GlorotUniform(seed=self.seed)))
model.compile(loss='mean_squared_error', metrics='mean_squared_error', sample_weight_mode='temporal')
return model
# If the user has supplied the parameter manually, use hp.Fixed()
# Otherwise, use the provided hyperparameter (default)
def _param(self, key, default=None):
value = self.config.get(key)
if value is not None:
return self.hp.Fixed(key, value)
else:
return default()
def build(self, hp):
self.hp = hp
self.units = self._param('units', lambda: hp.Int('units', 1, 200, step=5))
return self.build_model()
即使我的模型应该有效地使用相同的参数,我的超调结果也大不相同,这取决于我是使用 hp.Fixed(key, value)
还是只使用 value
(其中 value
是说,一个整数)。我已经验证每个测试的重复运行都会在 instructions for reproducibility 之后产生相同的结果,并为所有适用的 layers/initializers/etc 设置种子。尽管说明上说它们不是必需的。
使用hp.Fixed(key, value)
使用value
查看所有超参数的 table,似乎 hp.Fixed
甚至什么都没做。正在测试所有超参数。
编辑:无论状态如何,我的自定义超模型的超参数都被 HyperbandTuner 忽略。
这是有问题的代码:
class MyModel(kt.HyperModel):
def __init__(self, **config):
self.config = config
self.seed = config.get('seed')
def build_model(self):
model = Sequential(name=self.name)
model.add(LSTM(self.units, name='LSTM'))
model.add(Dense(1, name='Output', kernel_initializer=GlorotUniform(seed=self.seed)))
model.compile(loss='mean_squared_error', metrics='mean_squared_error', sample_weight_mode='temporal')
return model
# If the user has supplied the parameter manually, use hp.Fixed()
# Otherwise, use the provided hyperparameter (default)
def _param(self, key, default=None):
value = self.config.get(key)
if value is not None:
return self.hp.Fixed(key, value)
else:
return default
def build(self, hp):
self.hp = hp
self.units = self._param('units', hp.Int('units', 1, 200, step=5))
return self.build_model()
好的,在进行更多挖掘之后我发现(特别是通过 this tutorial 声明超参数的方式)当您编写 hp.[Fixed|Choice|etc.]
时,您会立即声明这些超参数在搜索中的存在 space,无论该代码出现在何处。
将超参数声明视为特征class 方法,而不是 HyperTuner 从模型中获取的常规 Python 对象。
本质上,每个Fixed/Choice/etc。超参数方法同时在 HyperTuner class 后台的某处设置一个全局超参数,同时还返回一个常规变量 (Int/Float/String/Range/List/etc.),这样您仍然可以在 HyperTuner 最终覆盖它之前构建您的模型而不会出错搜索阶段。
我对此感到困惑,因为通常 hp
在 build_model()
方法或 kt.HyperModel
class 中显示为参数,其中调用被分配给局部变量然后传递给模型声明。
下面是对违规代码的修复:
class MyModel(kt.HyperModel):
def __init__(self, **config):
self.config = config
self.seed = config.get('seed')
def build_model(self):
model = Sequential(name=self.name)
model.add(LSTM(self.units, name='LSTM'))
model.add(Dense(1, name='Output', kernel_initializer=GlorotUniform(seed=self.seed)))
model.compile(loss='mean_squared_error', metrics='mean_squared_error', sample_weight_mode='temporal')
return model
# If the user has supplied the parameter manually, use hp.Fixed()
# Otherwise, use the provided hyperparameter (default)
def _param(self, key, default=None):
value = self.config.get(key)
if value is not None:
return self.hp.Fixed(key, value)
else:
return default()
def build(self, hp):
self.hp = hp
self.units = self._param('units', lambda: hp.Int('units', 1, 200, step=5))
return self.build_model()