【发布时间】:2021-09-21 15:04:23
【问题描述】:
*底部更新
我正在尝试使用 3 个类中的 2 个作为度量标准,因此 A、B、C 类中的 B 类和 C 类。
(其原始性质是我的模型在类中高度不平衡 [~90% 是 A 类],因此当我使用准确度时,每次预测 A 类时我得到 ~90% 的结果)
model.compile(
loss='sparse_categorical_crossentropy', #or categorical_crossentropy
optimizer=opt,
metrics=[tf.keras.metrics.Recall(class_id=1, name='recall_1'),tf.keras.metrics.Recall(class_id=2, name='recall_2')]
)
history = model.fit(train_x, train_y, batch_size=BATCH, epochs=EPOCHS, validation_data=(validation_x, validation_y), callbacks=[tensorboard, checkpoint])
这吐出了一个错误:
raise ValueError("Shapes %s and %s are incompatible" % (self, other))
ValueError: Shapes (None, 3) and (None, 1) are incompatible
模型摘要为:
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
lstm (LSTM) (None, 120, 32) 19328
_________________________________________________________________
dropout (Dropout) (None, 120, 32) 0
_________________________________________________________________
batch_normalization (BatchNo (None, 120, 32) 128
_________________________________________________________________
lstm_1 (LSTM) (None, 120, 32) 8320
_________________________________________________________________
dropout_1 (Dropout) (None, 120, 32) 0
_________________________________________________________________
batch_normalization_1 (Batch (None, 120, 32) 128
_________________________________________________________________
lstm_2 (LSTM) (None, 32) 8320
_________________________________________________________________
dropout_2 (Dropout) (None, 32) 0
_________________________________________________________________
batch_normalization_2 (Batch (None, 32) 128
_________________________________________________________________
dense (Dense) (None, 32) 1056
_________________________________________________________________
dropout_3 (Dropout) (None, 32) 0
_________________________________________________________________
dense_1 (Dense) (None, 3) 99
=================================================================
Total params: 37,507
Trainable params: 37,315
Non-trainable params: 192
请注意,如果使用,该模型可以正常工作,没有错误:
metrics=['accuracy']
但是this 和this 让我觉得有些东西没有按照 tf.metrics.SparseCategorical 的方式实现Recall()
来自
tf.metrics.SparseCategoricalAccuracy()
所以我转向了一个自定义指标,该指标陷入了其他问题的困境,因为我在类和装饰器方面非常文盲。
我从一个自定义指标示例中将其拼凑在一起(我不知道如何使用 sample_weight,所以我将其注释掉以备后用):
class RelevantRecall(tf.keras.metrics.Metric):
def __init__(self, name="Relevant_Recall", **kwargs):
super(RelevantRecall, self).__init__(name=name, **kwargs)
self.joined_recall = self.add_weight(name="B/C Recall", initializer="zeros")
def update_state(self, y_true, y_pred, sample_weight=None):
y_pred = tf.argmax(y_pred, axis=1)
report_dictionary = classification_report(y_true, y_pred, output_dict = True)
# if sample_weight is not None:
# sample_weight = tf.cast(sample_weight, "float32")
# values = tf.multiply(values, sample_weight)
# self.joined_recall.assign_add(tf.reduce_sum(values))
self.joined_recall.assign_add((float(report_dictionary['1.0']['recall'])+float(report_dictionary['2.0']['recall']))/2)
def result(self):
return self.joined_recall
def reset_states(self):
# The state of the metric will be reset at the start of each epoch.
self.joined_recall.assign(0.0)
model.compile(
loss='sparse_categorical_crossentropy', #or categorical_crossentropy
optimizer=opt,
metrics=[RelevantRecall()]
)
history = model.fit(train_x, train_y, batch_size=BATCH, epochs=EPOCHS, validation_data=(validation_x, validation_y), callbacks=[tensorboard, checkpoint])
这个目标是返回一个[recall(b)+recall(c)/2] 的指标。我想像metrics=[recall(b),recall(c)] 那样分别返回两次召回会更好,但无论如何我无法让前者工作。
我收到一个张量布尔错误:OperatorNotAllowedInGraphError: using a 'tf.Tensor' as a Python 'bool' is not allowed: AutoGraph did convert this function. This might indicate you are trying to use an unsupported feature.,我在谷歌搜索后添加了:@tf.function 在我的自定义指标类上方。
这导致了新旧类类型错误:
super(RelevantRecall, self).__init__(name=name, **kwargs)
TypeError: super() argument 1 must be type, not Function
由于类有一个对象,我没有看到我是如何实现的?
正如我所说,我对这方面的所有方面都很陌生,因此对于如何使用仅选择一个预测类的度量来实现(以及如何最好地实现)的任何帮助将不胜感激。
或
如果我完全错了,请告诉我/指导我找到正确的资源
理想情况下,我想采用以前使用tf.keras.metrics.Recall(class_id=1.... 的方法,因为如果它有效的话,这似乎是最简洁的方法。
当在模型的回调部分中使用类似的函数时,我能够获得每个类的召回,但这似乎更加密集,因为我必须在每个结束时对 val/test 数据进行 model.predict时代。 也不清楚这是否甚至告诉模型专注于改进所选类(即在度量与回调中实现它的差异)
回调代码:
class MetricsCallback(Callback):
def __init__(self, test_data, y_true):
# Should be the label encoding of your classes
self.y_true = y_true
self.test_data = test_data
def on_epoch_end(self, epoch, logs=None):
# Here we get the probabilities - longer process
y_pred = self.model.predict(self.test_data)
# Here we get the actual classes
y_pred = tf.argmax(y_pred,axis=1)
report_dictionary = classification_report(self.y_true, y_pred, output_dict = True)
print ("\n")
print (f"Accuracy: {report_dictionary['accuracy']} - Holds: {report_dictionary['0.0']['recall']} - Sells: {report_dictionary['1.0']['recall']} - Buys: {report_dictionary['2.0']['recall']}")
self._data = (float(report_dictionary['1.0']['recall'])+float(report_dictionary['2.0']['recall']))/2
return
metrics_callback = MetricsCallback(test_data = validation_x, y_true = validation_y)
history = model.fit(train_x, train_y, batch_size=BATCH, epochs=EPOCHS, validation_data=(validation_x, validation_y), callbacks=[tensorboard, checkpoint, metrics_callback)
更新 19/07/2021
- 我已将
categorical_crossentropy用于loss而不是sparse_categorical_crossentropy。 - 对我的类/目标数组进行一次热编码。
- 使用 tf 召回:
[tf.keras.metrics.Recall(class_id=1, name='recall_1')
我现在正在使用下面的代码。
train_y = tf.one_hot(train_y, 3)
validation_y = tf.one_hot(validation_y, 3)
test_y = tf.one_hot(test_y, 3)
model.compile(
loss='categorical_crossentropy',
optimizer=opt,
metrics=[tf.keras.metrics.Recall(class_id=1, name='No'),tf.keras.metrics.Recall(class_id=2, name='Yes')]
) #tf.keras.metrics.Recall(class_id=0, name='Wait')
history = model.fit(train_x, train_y, batch_size=BATCH, epochs=EPOCHS, validation_data=(validation_x, validation_y), callbacks=[tensorboard, checkpoint])
感谢Abhishek Prajapat
这实现了相同的总体目标,并且由于少量互斥类可能对性能的差异/影响非常小,
但是在大量互斥类的情况下,我仍然没有解决方案来使用sparse_categorical_crossentropy实现与上述相同的目标
【问题讨论】:
标签: python tensorflow machine-learning neural-network tf.keras