Keras 更改有关历元的自定义损耗参数和NN参数
我有一个Keras模型,定义方式如下(尽量只保留必要的部分): 我跟在后面 这是使用带有tf后端的Keras上的Keras 更改有关历元的自定义损耗参数和NN参数,keras,parameters,loss-function,Keras,Parameters,Loss Function,我有一个Keras模型,定义方式如下(尽量只保留必要的部分): 我跟在后面 这是使用带有tf后端的Keras上的fit generator()实现的。显然,我在加载模型时会遇到问题,因为温度是共享编码的。 也, 我希望更新损耗函数和模型中有关历元数的温度参数 我如何定义这样的控制信号 我已经把它变成了一个完整的例子,说明了一种方法 您可以为损失函数创建一个类 class TemperatureLossFunction: def __init__(self, temperature):
fit generator()
实现的。显然,我在加载模型时会遇到问题,因为温度
是共享编码的。
也,
我希望更新损耗函数和模型中有关历元数的温度参数
我如何定义这样的控制信号 我已经把它变成了一个完整的例子,说明了一种方法
您可以为损失函数创建一个类
class TemperatureLossFunction:
def __init__(self, temperature):
self.temperature = temperature
def loss_fun(self, y_truth, y_pred):
return self.temperature*keras.losses.mse(y_truth, y_pred)
def setTemperature(self, t, session=None):
if session:
session.run(self.temperature.assign( t )
elif tensorflow.get_default_session():
tensorflow.get_default_session().run(self.temperature.assign( t ))
class TemperatureLossCallback(keras.callbacks.Callback):
def __init__(self, temp_lf):
self.temp_lf = temp_lf
def on_epoch_end(self, epoch, params):
self.temp_lf.setTemperature(epoch)
我创建了两种方法来处理这个问题,第一种方法创建并保存模型
def init(session):
global temperature #global for serialization issues
temperature = tensorflow.Variable(5.0)
tlo = TemperatureLossFunction(temperature)
inp = keras.layers.Input((4,4))
l1 = keras.layers.Lambda( lambda x: temperature*x )
op = l1(inp)
m = keras.models.Model(inputs=[inp], outputs=[op])
m.compile( optimizer = keras.optimizers.SGD(0.01), loss=tlo.loss_fun)
#make sure the session is the one your using!
session.run(temperature.initializer)
我运行的第一个测试确保我们正在更改值
m.evaluate( numpy.ones((1, 4, 4)), numpy.zeros((1, 4, 4)) )
session.run(temperature.assign(1))
m.evaluate( numpy.ones((1, 4, 4)), numpy.zeros((1, 4, 4)) )
我运行的第二个测试确保我们可以通过回调更改值
cb = TemperatureLossCallback(tlo)
def gen():
for i in range(10):
yield numpy.ones((1, 4, 4)), numpy.zeros((1, 4, 4))
m.fit_generator(
gen(), steps_per_epoch=1, epochs=10, callbacks=[cb]
)
m.save("junk.h5")
最后,演示如何重新加载文件
def restart(session):
global temperature
temperature = tensorflow.Variable(5.0)
tlo = TemperatureLossFunction(temperature)
loss_fun = tlo.loss_fun
m = keras.models.load_model(
"junk.h5",
custom_objects = {"loss_fun":tlo.loss_fun}
)
session.run(temperature.initializer)
m.evaluate( numpy.ones((1, 4, 4)), numpy.zeros((1, 4, 4)) )
session.run(temperature.assign(1))
m.evaluate( numpy.ones( (1, 4, 4) ), numpy.zeros( ( 1, 4, 4) ) )
这正是我用来启动程序的完整性代码
import sys
if __name__=="__main__":
sess = tensorflow.Session()
with sess.as_default():
if "restart" in sys.argv:
restart(sess)
else:
init(sess)
这种方法的一个缺点是,如果运行它,您将看到温度变量不会从模型文件中加载。它接受代码中指定的值
从正面来看,损失函数和层都引用了相同的变量
我发现保存变量值的一种方法是创建一个新层,并使用该变量作为新层的权重
class VLayer(keras.layers.Layer):
def __init__(self, *args, **kwargs):
super().__init__(**kwargs)
def build(self, input_shape):
self.v1 = self.add_weight(
dtype="float32",
shape = (),
trainable=False,
initializer="zeros"
)
def call(self, x):
return x*self.v1
def setValue(self, val):
self.set_weights( numpy.array([val]) )
现在,加载模型时,将加载权重。不幸的是,我找不到一种方法将重量与负载变量联系起来。因此将有两个变量,一个用于损失函数,一个用于层。不过,这两个参数都可以通过回调进行设置。因此,我觉得这种方法更可靠。这对我来说很重要。我希望稍后加载模型并使用它进行预测。这会给我带来麻烦吗?@havakok当你加载模型并编译时,它会很好。这意味着,如果你开始训练,然后尝试重新开始训练,会有一些不同。对于预测来说,这很好,因为预测不使用训练/优化器值,它只使用经过训练的权重。那么,你需要一个新的答案吗?不,我只是想给matt一笔赏金,感谢他的帮助。
class VLayer(keras.layers.Layer):
def __init__(self, *args, **kwargs):
super().__init__(**kwargs)
def build(self, input_shape):
self.v1 = self.add_weight(
dtype="float32",
shape = (),
trainable=False,
initializer="zeros"
)
def call(self, x):
return x*self.v1
def setValue(self, val):
self.set_weights( numpy.array([val]) )