i具有一个CNN对象检测模型,该模型具有两个带有张量名的头(输出('classification'
和'regression'
。
我想定义同时接受两个输出的度量函数,以便它查看回归预测来决定要保留哪些索引并使用的索引这些索引从分类预测中选择张量并计算一些度量。
我当前在此链接的帮助下定义的指标函数:
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 is
屏幕日志>:
信息:TensorFlow:损失= 0.0075738616,步骤= 31(11.941 sec(
信息:TensorFlow:global_step/sec:4.51218
信息:TensorFlow:损失= 0.01015341,步骤= 36(1.108 sec(
信息:TensorFlow:将40的检查点保存到/tmp/tmpcla2n3gy/model.ckpt。
信息:TensorFlow:调用model_fn。 == @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ============================================================= 张量(" iteratorGetNext:1",shape =(?,120087,5(,dtype = float32,设备=/设备:cpu:0( 张量("回归/concat:0",shape =(?,??,4(,dtype = float32( == @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ============================================================= == @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ============================================================= 张量(" iteratorGetNext:2",shape =(?,120087,2(,dtype = float32,设备=/设备:cpu:0( 张量("分类/concat:0",shape =(?,??,1(,dtype = float32( == @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ======================================================
信息:TensorFlow:完成拨打Model_fn。
信息:TensorFlow:开始评估2019-06-24T08:20:35Z 信息:TensorFlow:图形已完成。 2019-06-24 13:50:36.457345:i TensorFlow/core/councom_runtime/gpu/gpu_device.cc:1512]添加可见的GPU设备:0 2019-06-24 13:50:36.457398:i TensorFlow/core/councom_runtime/gpu/gpu_device.cc:984]设备互连streamExecutor与强度1 edge矩阵: 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/councom_runtime/gpu/gpu_device.cc:1115]创建了TensorFlow设备(/local-Host/poplica:0/task:0/taskMB内存( ->物理GPU(设备:0,名称:GeForce RTX 2080 TI,PCI总线ID:0000:01:00.0,计算能力:7.5(
信息:TensorFlow:从/TMP/tmpcla2n3gy/model.ckpt-40
还原参数信息:tensorflow:运行local_init_op。
信息:TensorFlow:运行local_init_op。
信息:TensorFlow:评估[10/100]
信息:TensorFlow:评估[20/100]
信息:TensorFlow:评估[30/100]
信息:TensorFlow:评估[40/100]
信息:TensorFlow:评估[50/100]
信息:TensorFlow:评估[60/100]
信息:TensorFlow:评估[70/100]
信息:TensorFlow:评估[80/100]
信息:TensorFlow:评估[90/100]
信息:TensorFlow:评估[100/100]
信息:TensorFlow:完成的评估2019-06-24-08:20:44
信息: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()
的回归,然后分类。但是我希望它通过回归和分类一起被调用一次您需要两个 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, ...)
如果您不需要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])], ...)
让我向您展示一种实现这一目标的优雅方法。
-
首先,定义包装您的度量的外部函数,以便您可以通过回归张量
reg_out
:def metric_func(reg_out): def metric(y_true, class_out): return your_metric(reg_out, class_out, y_true) return metric
-
接下来,通过设置产生它的图层的参数
name
来命名分类张量class_out
。例如:class_out = Dense(1, name='class_out')(something)
-
最后,设置Model.com的参数
metrics
如下:model.compile(..., metrics={'class_out': metric_func(reg_out)})