Tensorflow 将参数传递到tf.keras.model中的model.predict
我有一个需要定制推理的模型,因此我修改了Tensorflow 将参数传递到tf.keras.model中的model.predict,tensorflow,machine-learning,keras,tensorflow2.0,tf.keras,Tensorflow,Machine Learning,Keras,Tensorflow2.0,Tf.keras,我有一个需要定制推理的模型,因此我修改了tf.keras.model类的predict\u步骤方法。我希望根据某些参数修改推断,是否有简单的方法让predict方法接收参数并将其传递给predict\u步骤函数 比如: class SimpleModel(tf.keras.Model): def __init__(self): super().__init__() self.threshold = None def call(self, inpu
tf.keras.model
类的predict\u步骤
方法。我希望根据某些参数修改推断,是否有简单的方法让predict
方法接收参数并将其传递给predict\u步骤
函数
比如:
class SimpleModel(tf.keras.Model):
def __init__(self):
super().__init__()
self.threshold = None
def call(self, inputs, training=None, mask=None):
return inputs
def predict(self, x, threshold=0.5, *args, **kwargs):
self.threshold = threshold
return super().predict(x, *args, **kwargs)
def predict_step(self, data):
return tf.greater(self(data, training=False), self.threshold)
if __name__ == "__main__":
x = tf.convert_to_tensor([0.0, 0.55, 0.85, 0.9])
model = SimpleModel()
model.predict(x, threshold=0.5)
model.predict(x, threshold=0.75)
该方法的问题在于,由于已经创建了predict\u步骤
,因此阈值不会改变
更新1:
这似乎有效,但不确定这是否是最好的方法:
class SimpleModel(tf.keras.Model):
def __init__(self):
super().__init__()
self.threshold = None
def call(self, inputs, training=None, mask=None):
return inputs
def predict(self, x, threshold=0.5, *args, **kwargs):
self.threshold = threshold
self.predict_function = None
return super().predict(x, *args, **kwargs)
def predict_step(self, data):
return tf.greater(self(data, training=False), self.threshold)
if __name__ == "__main__":
x = tf.convert_to_tensor([0.0, 0.55, 0.85, 0.9])
model = SimpleModel()
pred = model(x)
pred_1 = model.predict(x, threshold=0.5)
pred_2 = model.predict(x, threshold=0.75)
print(pred, pred_1, pred_2, sep="\n")
更新2:
在我发布了关于在图形模式下运行的predict\u步骤
函数的问题之后,解决问题的另一种方法似乎是设置模型的self.run\u=True
class SimpleModel(tf.keras.Model):
def __init__(self):
super().__init__()
self.run_eagerly = True
self.threshold = None
def call(self, inputs, training=None, mask=None):
return inputs
def predict(self, x, threshold=0.5, *args, **kwargs):
self.threshold = threshold
return super().predict(x, *args, **kwargs)
def predict_step(self, data):
return tf.greater(self(data, training=False), self.threshold)
if __name__ == "__main__":
x = tf.convert_to_tensor([0.0, 0.55, 0.85, 0.9])
model = SimpleModel()
pred_1 = model.predict(x, threshold=0.5)
pred_2 = model.predict(x, threshold=0.75)
print(pred_1, pred_2, sep="\n")
现在它不需要使用
tf.Variable
(可能由于急切模式而运行较慢)。由于不允许我发表评论,我只能直接给出一个可能非常不合适的答案
我对你的问题的理解不是如何多次调用predict\u step()
,而是如何使阈值可变。我的建议是将self.threshold
a[1 x 1]作为一个不可训练的变量
我正在考虑添加类似的内容
threshold = tf.Variable(.65,trainable=False, dtype='float32')
我认为你可以实现它的方式如下:
class SimpleModel(tf.keras.Model):
def __init__(self,threshold=.5):
super().__init__()
self.threshold = tf.Variable(threshold,trainable=False, dtype='float32')
def call(self, inputs, training=None, mask=None):
return inputs
def predict(self, x, threshold=0.5, *args, **kwargs):
self.threshold.assign(tf.convert_to_tensor(threshold,dtype='float32'))
self.predict_function = None
return super().predict(x, *args, **kwargs)
def predict_step(self, data):
out = tf.greater(self(data, training=False), self.threshold)
# self.threshold.assign( <Calculate new threshold here as a float32 tensor>)
return out
if __name__ == "__main__":
x = tf.convert_to_tensor([0.0, 0.55, 0.85, 0.9])
model = SimpleModel()
pred = model(x)
pred_1 = model.predict(x, threshold=0.5)
pred_2 = model.predict(x, threshold=0.75)
print(pred, pred_1, pred_2, sep="\n")
类SimpleModel(tf.keras.Model):
定义初始化(自,阈值=.5):
super()。\uuuu init\uuuuu()
self.threshold=tf.Variable(threshold,trainable=False,dtype='float32')
def呼叫(自我、输入、培训=无、掩码=无):
返回输入
def预测(自我,x,阈值=0.5,*args,**kwargs):
self.threshold.assign(tf.convert_to_tensor(threshold,dtype='float32'))
self.predict_函数=无
return super().predict(x,*args,**kwargs)
def预测步骤(自身、数据):
out=tf.更大(自我(数据,训练=假),自我阈值)
#self.threshold.assign()
返回
如果名称=“\uuuuu main\uuuuuuuu”:
x=tf。将_转换为_张量([0.0,0.55,0.85,0.9])
model=SimpleModel()
pred=模型(x)
pred_1=模型预测(x,阈值=0.5)
pred_2=模型预测(x,阈值=0.75)
打印(pred,pred_1,pred_2,sep=“\n”)
情况发生了变化:
初始化()中的
阈值
参数(可能不需要)
- 如果不希望出现上述情况,则必须将变量的实例化从
移动到\uuuu init\uuuu()
predict()
- 如果不希望出现上述情况,则必须将变量的实例化从
- 在
\uuu init\uuuu()中创建
tf.variable
self.threshold
- 不再立即返回
predict\u step()中的计算结果
- 在
predict\u步骤中为阈值重新计算步骤添加了注释占位符
这段代码已编译,但因为我正在处理我自己对您的查询的解释,所以我可能与您要查找的内容相去甚远。因为我不允许发表评论,所以我只能直接提供一个可能非常离谱的答案 我对你的问题的理解不是如何多次调用
predict\u step()
,而是如何使阈值可变。我的建议是将self.threshold
a[1 x 1]作为一个不可训练的变量
我正在考虑添加类似的内容
threshold = tf.Variable(.65,trainable=False, dtype='float32')
我认为你可以实现它的方式如下:
class SimpleModel(tf.keras.Model):
def __init__(self,threshold=.5):
super().__init__()
self.threshold = tf.Variable(threshold,trainable=False, dtype='float32')
def call(self, inputs, training=None, mask=None):
return inputs
def predict(self, x, threshold=0.5, *args, **kwargs):
self.threshold.assign(tf.convert_to_tensor(threshold,dtype='float32'))
self.predict_function = None
return super().predict(x, *args, **kwargs)
def predict_step(self, data):
out = tf.greater(self(data, training=False), self.threshold)
# self.threshold.assign( <Calculate new threshold here as a float32 tensor>)
return out
if __name__ == "__main__":
x = tf.convert_to_tensor([0.0, 0.55, 0.85, 0.9])
model = SimpleModel()
pred = model(x)
pred_1 = model.predict(x, threshold=0.5)
pred_2 = model.predict(x, threshold=0.75)
print(pred, pred_1, pred_2, sep="\n")
类SimpleModel(tf.keras.Model):
定义初始化(自,阈值=.5):
super()。\uuuu init\uuuuu()
self.threshold=tf.Variable(threshold,trainable=False,dtype='float32')
def呼叫(自我、输入、培训=无、掩码=无):
返回输入
def预测(自我,x,阈值=0.5,*args,**kwargs):
self.threshold.assign(tf.convert_to_tensor(threshold,dtype='float32'))
self.predict_函数=无
return super().predict(x,*args,**kwargs)
def预测步骤(自身、数据):
out=tf.更大(自我(数据,训练=假),自我阈值)
#self.threshold.assign()
返回
如果名称=“\uuuuu main\uuuuuuuu”:
x=tf。将_转换为_张量([0.0,0.55,0.85,0.9])
model=SimpleModel()
pred=模型(x)
pred_1=模型预测(x,阈值=0.5)
pred_2=模型预测(x,阈值=0.75)
打印(pred,pred_1,pred_2,sep=“\n”)
情况发生了变化:
初始化()中的
阈值
参数(可能不需要)
- 如果不希望出现上述情况,则必须将变量的实例化从
移动到\uuuu init\uuuu()
predict()
- 如果不希望出现上述情况,则必须将变量的实例化从
- 在
\uuu init\uuuu()中创建
tf.variable
self.threshold
- 不再立即返回
predict\u step()中的计算结果
- 在
predict\u步骤中为阈值重新计算步骤添加了注释占位符
这段代码已编译,但因为我正在处理我自己对您的查询的解释,所以我可能与您要查找的内容相去甚远。我对您要查找的内容有更好的了解。看看这个玩具的例子,看看它是否是你想要的
class SimpleModel(tf.keras.Model):
def __init__(self):
super().__init__()
def call(self, inputs, training=None, mask=None):
return inputs
def custom_predict(func):
def threshold_handler(self, x, threshold=None, *args, **kwargs):
if threshold is None:
return func(self, x, *args, **kwargs)
else:
vals = func(self, x, *args, **kwargs)
return list(filter(lambda x: x > threshold, vals))
return threshold_handler
# fancy way of saying predict = custom_predict(predict)
# really, it's running custom_predict masquerading as predict
@custom_predict
def predict(self, x, *args, **kwargs):
return super().predict(x, *args, **kwargs)
x = tf.convert_to_tensor([0.0, 0.55, 0.85, 0.9])
model = SimpleModel()
pred = model(x)
pred_0 = model.predict(x, steps=1)
pred_1 = model.predict(x, threshold=0.5, steps=1)
pred_2 = model.predict(x, threshold=0.75, steps=1)
print(pred, pred_0, pred_1, pred_2, sep="\n")
当然,当你可以在自己的预测函数中处理逻辑时,装饰师完全是过火了,但也许更高层次的想法会让你自己的想法在你想要如何处理的问题上流动起来。可定制性的另一个选项是使用回调(例如,请参阅fastai或Pytorch Lightning)。我对您的目标有一个更好的了解。看看这个玩具的例子,看看它是否是你想要的
class SimpleModel(tf.keras.Model):
def __init__(self):
super().__init__()
def call(self, inputs, training=None, mask=None):
return inputs
def custom_predict(func):
def threshold_handler(self, x, threshold=None, *args, **kwargs):
if threshold is None:
return func(self, x, *args, **kwargs)
else:
vals = func(self, x, *args, **kwargs)
return list(filter(lambda x: x > threshold, vals))
return threshold_handler
# fancy way of saying predict = custom_predict(predict)
# really, it's running custom_predict masquerading as predict
@custom_predict
def predict(self, x, *args, **kwargs):
return super().predict(x, *args, **kwargs)
x = tf.convert_to_tensor([0.0, 0.55, 0.85, 0.9])
model = SimpleModel()
pred = model(x)
pred_0 = model.predict(x, steps=1)
pred_1 = model.predict(x, threshold=0.5, steps=1)
pred_2 = model.predict(x, threshold=0.75, steps=1)
print(pred, pred_0, pred_1, pred_2, sep="\n")
当然,当你可以在自己的预测函数中处理逻辑时,装饰师完全是过火了,但也许更高层次的想法会让你自己的想法在你想要如何处理的问题上流动起来。可定制性的另一个选项是使用回调(