我有一个CNN对象检测模型,该模型具有两个带有张量名称'classification'
和'regression'
的头(输出)。
我想定义一个度量标准函数,该函数同时接受两个输出,以便它可以查看回归预测,以确定要保留和使用的索引这些索引以从分类预测中选择张量并计算一些指标。
我目前在this link的帮助下定义的指标函数:
from tensorflow.python.keras.metrics import MeanMetricWrapper
class Accuracy2(MeanMetricWrapper):
def __init__(self, name='dummyAccuracy', dtype=None):
super(Accuracy2, self).__init__(metric_calculator_func, name, dtype=dtype)
self.true_positives = self.add_weight(name='lol', initializer='zeros')
@classmethod
def from_config(cls, config):
if 'fn' in config:
config.pop('fn')
return super(Accuracy2, cls).from_config(config)
def update_state(self, y_true, y_pred, sample_weight=None):
print("==@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@===")
print("Y-True {}".format(y_true))
print("Y-Pred {}".format(y_pred))
print("==@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@===")
update_ops = [self.true_positives.assign_add(1.0)]
return tf.group(update_ops)
def result(self):
return self.true_positives
def reset_states(self):
# The state of the metric will be reset at the start of each epoch.
self.true_positives.assign(0.)
我在模型编译期间将其称为:
training_model.compile(
loss={
'regression' : regression_loss(),
'classification': classification_loss()
},
optimizer=keras.optimizers.Adam(lr=lr, clipnorm=0.001),
metrics=[Accuracy2()]
)
tf.estimator.train_and_evaluate 期间的屏幕日志为:
INFO:tensorflow:损失= 0.0075738616,步长= 31(11.941秒)
INFO:tensorflow:global_step / sec:4.51218
INFO:tensorflow:损失= 0.01015341,步长= 36(1.108秒)
INFO:tensorflow:将40个检查点保存到/tmp/tmpcla2n3gy/model.ckpt中。
INFO:tensorflow:调用model_fn。 == @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ===== Tensor(“ IteratorGetNext:1”,shape =(?, 120087,5),dtype = float32,device = / device:CPU:0) 张量(“ regression / concat:0”,shape =(?,?,4),dtype = float32) == @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ===== == @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ===== Tensor(“ IteratorGetNext:2”,shape =(?, 120087,2),dtype = float32,device = / device:CPU:0) Tensor(“ classification / concat:0”,shape =(?,?,1),dtype = float32) == @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ===
INFO:tensorflow:完成调用model_fn。
INFO:tensorflow:于2019-06-24T08:20:35Z开始评估 INFO:tensorflow:Graph已完成。 2019-06-24 13:50:36.457345:I tensorflow / core / common_runtime / gpu / gpu_device.cc:1512]添加可见的gpu设备:0 2019-06-24 13:50:36.457398:I tensorflow / core / common_runtime / gpu / gpu_device.cc:984]具有强度1边缘矩阵的设备互连StreamExecutor: 2019-06-24 13:50:36.457419:I tensorflow / core / common_runtime / gpu / gpu_device.cc:990] 0 2019-06-24 13:50:36.457425:I tensorflow / core / common_runtime / gpu / gpu_device.cc:1003] 0:N 2019-06-24 13:50:36.457539:I tensorflow / core / common_runtime / gpu / gpu_device.cc:1115]创建了TensorFlow设备(/ job:localhost /副本:0 /任务:0 /设备:GPU:0和9855 MB内存)->物理GPU(设备:0,名称:GeForce RTX 2080 Ti,pci总线ID:0000:01:00.0,计算能力:7.5)
INFO:tensorflow:从/tmp/tmpcla2n3gy/model.ckpt-40恢复参数
INFO:tensorflow:正在运行local_init_op。
INFO:tensorflow:已运行local_init_op。
INFO:tensorflow:评估[10/100]
INFO:tensorflow:评估[20/100]
INFO:tensorflow:评估[30/100]
INFO:tensorflow:评估[40/100]
INFO:tensorflow:评估[50/100]
INFO:tensorflow:评估[60/100]
INFO:tensorflow:评估[70/100]
INFO:tensorflow:评估[80/100]
INFO:tensorflow:评估[90/100]
INFO:tensorflow:评估[100/100]
INFO:tensorflow:在2019-06-24-08:20:44完成评估
INFO:tensorflow:全局步骤40的保存格:_focal = 0.0016880237,_smooth_l1 = 0.0,dummyAccuracy = 100.0,global_step = 40,损失= 0.0016880237
此行:
==@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@===
Tensor("IteratorGetNext:1", shape=(?, 120087, 5), dtype=float32, device=/device:CPU:0)
Tensor("regression/concat:0", shape=(?, ?, 4), dtype=float32)
==@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@===
==@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@===
Tensor("IteratorGetNext:2", shape=(?, 120087, 2), dtype=float32, device=/device:CPU:0)
Tensor("classification/concat:0", shape=(?, ?, 1), dtype=float32)
==@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@===
显示Accuracy2()
两次被调用两次,分别是回归和分类。
但我希望通过将回归和分类一起添加到其中
答案 0 :(得分:1)
y_true
值这是一个丑陋的答案,但是....
您必须制作一个图层才能为您计算指标。使用Lambda
:
鉴于regOut
和classOut
是您在模型创建中的输出张量,而不是像Model(inputs, [regOut,classOut])
这样的模型创建,您将:
def metricFunc(modelOutputs):
regressionOutput = modelOutputs[0]
classOutput = modelOuptuts[1]
#calculate metric
return calculatedMetric
metricTensor = Lambda(metricFunc, name='metric_layer')([regOut,classOut])
使指标成为模型的输出:
model = Model(inputs, [regOut, classOut, metricTensor])
创建虚拟损失和虚拟指标进行编译:
def dummyLoss(true,pred):
return K.zeros(K.shape(true)[:1])
def dummyMetric(true,pred):
return pred
正在编译:
model.compile(loss = [regLoss, classLoss, dummyLoss],
metrics={'metric_layer':dummyMetric},
optimizer=...)
这还要求您为metricTensor
使用虚拟张量进行训练:
model.fit(x_train, [y_reg,y_class,np.zeros(y_reg.shape[:1])], ...)
答案 1 :(得分:1)
y_true
值作为度量标准。在这种情况下,我们将需要整理数据,以便可以将其合并为单个数组。 这将需要固定大小的输出。
假设您有regOut
和classOut
作为张量。如果它们是2D,只需串联它们,否则:
regOut = Flatten()(regOut) #only if regOut is 3D or more
classOut = Flatten()(classOut) #only if classOut is 3D or more
out = Concatenate()([regOut,classOut])
使用以下单个输出制作模型:
model = Model(inputs, out)
对数据集执行相同操作
y_reg_train = y_reg_train.reshape((y_reg_train.shape[0], -1))
y_class_train = y_clas_trains.reshape((y_class_train.shape[0], -1))
y_train = np.concatenate([y_reg_train, y_class_train], axis=-1)
#same for y_val
然后创建一个将两者分开的指标:
def metric(y_true, y_pred):
reg_true = y_true[:,:flattened_size_of_reg]
class_true = y_true[:, flattened_size_of_reg:]
reg_pred = y_pred[:,:flattened_size_of_reg]
class_pred = y_pred[:, flattened_size_of_reg:]
#calculate the metric
return value
使用组合输出进行训练:
model.fit(x_train, y_train, ...)
答案 2 :(得分:0)
让我向您展示实现此目标的一种优雅方法。
首先,定义一个包装度量标准的外部函数,以便您可以传递回归张量reg_out
:
def metric_func(reg_out):
def metric(y_true, class_out):
return your_metric(reg_out, class_out, y_true)
return metric
接下来,通过设置产生它的层的参数class_out
来命名分类张量name
。例如:
class_out = Dense(1, name='class_out')(something)
最后,如下设置model.compile的参数metrics
:
model.compile(...,
metrics={'class_out': metric_func(reg_out)})