如何在张量流中获得 class 0 的精度?
How to get precision for class 0 in tensorflow?
有没有一种方法可以使用 tf.keras.metrics.Precision
在二进制 class化模型中获得 class 0 的精度?
我尝试将 class_id
设置为 0,但它仍然给出 class 1.
的精度
我想使用回调保存具有最佳 class 0 精度值的模型,这是我在编译时需要一个精度指标的原因。
我使用 tf.keras.preprocessing.image_dataset_from_directory
创建我的数据集,train/validation/test 集的代码看起来相同(当然训练集和验证集被打乱):
ds_test = tf.keras.preprocessing.image_dataset_from_directory(
directory = test_path,
batch_size = my_batch_size,
image_size = (img_height, img_width),
shuffle = False
)
编译方法中添加精度指标:
model.compile(loss = tf.keras.losses.BinaryCrossentropy(),
optimizer = tf.keras.optimizers.Adam(...),
metrics = ["accuracy",
tf.keras.metrics.Precision(class_id = 0, name = "precision_0")
]
)
当使用 tensorflow model.evaluate
评估模型时,我得到的精度是 class 1 而不是 class 0:
precision_0: 0.9556
使用 sklearn.metrics.classification_report
我得到了两个 classes 的精度:
precision
0 0.9723
1 0.9556
我也想在 tensorflow 中获得 class 0 的精度,在本例中为 0.9723。有任何想法吗?
提前致谢!
您可以为此编写自定义指标。如果您使用 sigmoid
激活,那么作为预测结果,您会得到 概率 class 1.
一旦你subclass tf.keras.metrics.Metric
你可以改变这个:
class my_precision_class_0(tf.keras.metrics.Metric):
def __init__(self, threshold, name='my_precision_class_0', **kwargs):
super(my_precision_class_0, self).__init__(name=name, **kwargs)
self.true_positives = self.add_weight(name='tp', initializer='zeros')
self.false_positives = self.add_weight(name='fp', initializer='zeros')
self.threshold = threshold
def update_state(self, y_true, y_pred, sample_weight=None):
y_true_cls = tf.cast(tf.equal(y_true[:, 0], 0), tf.int64)
y_pred_cls = tf.cast(tf.less_equal(y_pred[:, 0], self.threshold), tf.int64)
true_positives = tf.math.count_nonzero(y_true_cls * y_pred_cls)
false_positives = tf.math.count_nonzero(y_pred_cls * (1 - y_true_cls))
self.true_positives.assign_add(tf.cast(true_positives, tf.float32))
self.false_positives.assign_add(tf.cast(false_positives, tf.float32))
def result(self):
return self.true_positives / (self.true_positives + self.false_positives)
def reset_states(self):
self.true_positives.assign(0)
self.false_positives.assign(0)
这是 y_pred_cls
使用 tf.less_equal
时发生的情况,同样的事情也适用于 y_true_cls
:
x = tf.constant([0.4, 4.0, 6.0])
y = tf.constant([0.5])
r = tf.math.less_equal(x, y) # --> [True, False, False]
tf.cast(r, tf.int64) # --> [1, 0, 0]
我们可以在编译中使用这个指标:
model = tf.keras.Sequential([
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(1, activation='sigmoid')
])
model.compile(optimizer='adam', loss='binary_crossentropy',
metrics=['accuracy', my_precision_class_0(threshold = 0.5),
tf.keras.metrics.Precision()])
model.fit(X, y, epochs=16)
model.evaluate(X, y, batch_size = 1)
# --> loss: 0.3370 - accuracy: 0.8790 - my_precision_class_0: 0.8983 - precision: 0.8617
from sklearn.metrics import classification_report
y_hat = (model.predict(X) > 0.5).astype(int)
print(classification_report(y, y_hat, digits=4))
precision recall f1-score support
0 0.8983 0.8531 0.8751 497
1 0.8617 0.9046 0.8826 503
accuracy 0.8790 1000
macro avg 0.8800 0.8788 0.8789 1000
weighted avg 0.8799 0.8790 0.8789 1000
我找到了一个可以简单解决我的问题的解决方法:
我使用 tf.keras.utils.image_dataset_from_directory
的 class_names
参数来定义 class 的顺序,添加我的“class 0”作为第二个 class:
"class_names:仅当"labels"为"inferred"时有效。这是class名称的显式列表(必须匹配子目录的名称)。用于控制顺序classes(否则使用字母数字顺序)。
创建数据集的修改代码:
ds_test = tf.keras.preprocessing.image_dataset_from_directory(
directory = test_path,
class_names = ["my_class_1", "my_class_0"]
batch_size = my_batch_size,
image_size = (img_height, img_width),
shuffle = False
)
不如定义自定义指标那么优雅,但它确实有效。
重要说明:这仅适用于二进制 classification!
有没有一种方法可以使用 tf.keras.metrics.Precision
在二进制 class化模型中获得 class 0 的精度?
我尝试将 class_id
设置为 0,但它仍然给出 class 1.
我想使用回调保存具有最佳 class 0 精度值的模型,这是我在编译时需要一个精度指标的原因。
我使用 tf.keras.preprocessing.image_dataset_from_directory
创建我的数据集,train/validation/test 集的代码看起来相同(当然训练集和验证集被打乱):
ds_test = tf.keras.preprocessing.image_dataset_from_directory(
directory = test_path,
batch_size = my_batch_size,
image_size = (img_height, img_width),
shuffle = False
)
编译方法中添加精度指标:
model.compile(loss = tf.keras.losses.BinaryCrossentropy(),
optimizer = tf.keras.optimizers.Adam(...),
metrics = ["accuracy",
tf.keras.metrics.Precision(class_id = 0, name = "precision_0")
]
)
当使用 tensorflow model.evaluate
评估模型时,我得到的精度是 class 1 而不是 class 0:
precision_0: 0.9556
使用 sklearn.metrics.classification_report
我得到了两个 classes 的精度:
precision
0 0.9723
1 0.9556
我也想在 tensorflow 中获得 class 0 的精度,在本例中为 0.9723。有任何想法吗? 提前致谢!
您可以为此编写自定义指标。如果您使用 sigmoid
激活,那么作为预测结果,您会得到 概率 class 1.
一旦你subclass tf.keras.metrics.Metric
你可以改变这个:
class my_precision_class_0(tf.keras.metrics.Metric):
def __init__(self, threshold, name='my_precision_class_0', **kwargs):
super(my_precision_class_0, self).__init__(name=name, **kwargs)
self.true_positives = self.add_weight(name='tp', initializer='zeros')
self.false_positives = self.add_weight(name='fp', initializer='zeros')
self.threshold = threshold
def update_state(self, y_true, y_pred, sample_weight=None):
y_true_cls = tf.cast(tf.equal(y_true[:, 0], 0), tf.int64)
y_pred_cls = tf.cast(tf.less_equal(y_pred[:, 0], self.threshold), tf.int64)
true_positives = tf.math.count_nonzero(y_true_cls * y_pred_cls)
false_positives = tf.math.count_nonzero(y_pred_cls * (1 - y_true_cls))
self.true_positives.assign_add(tf.cast(true_positives, tf.float32))
self.false_positives.assign_add(tf.cast(false_positives, tf.float32))
def result(self):
return self.true_positives / (self.true_positives + self.false_positives)
def reset_states(self):
self.true_positives.assign(0)
self.false_positives.assign(0)
这是 y_pred_cls
使用 tf.less_equal
时发生的情况,同样的事情也适用于 y_true_cls
:
x = tf.constant([0.4, 4.0, 6.0])
y = tf.constant([0.5])
r = tf.math.less_equal(x, y) # --> [True, False, False]
tf.cast(r, tf.int64) # --> [1, 0, 0]
我们可以在编译中使用这个指标:
model = tf.keras.Sequential([
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(1, activation='sigmoid')
])
model.compile(optimizer='adam', loss='binary_crossentropy',
metrics=['accuracy', my_precision_class_0(threshold = 0.5),
tf.keras.metrics.Precision()])
model.fit(X, y, epochs=16)
model.evaluate(X, y, batch_size = 1)
# --> loss: 0.3370 - accuracy: 0.8790 - my_precision_class_0: 0.8983 - precision: 0.8617
from sklearn.metrics import classification_report
y_hat = (model.predict(X) > 0.5).astype(int)
print(classification_report(y, y_hat, digits=4))
precision recall f1-score support
0 0.8983 0.8531 0.8751 497
1 0.8617 0.9046 0.8826 503
accuracy 0.8790 1000
macro avg 0.8800 0.8788 0.8789 1000
weighted avg 0.8799 0.8790 0.8789 1000
我找到了一个可以简单解决我的问题的解决方法:
我使用 tf.keras.utils.image_dataset_from_directory
的 class_names
参数来定义 class 的顺序,添加我的“class 0”作为第二个 class:
"class_names:仅当"labels"为"inferred"时有效。这是class名称的显式列表(必须匹配子目录的名称)。用于控制顺序classes(否则使用字母数字顺序)。
创建数据集的修改代码:
ds_test = tf.keras.preprocessing.image_dataset_from_directory(
directory = test_path,
class_names = ["my_class_1", "my_class_0"]
batch_size = my_batch_size,
image_size = (img_height, img_width),
shuffle = False
)
不如定义自定义指标那么优雅,但它确实有效。 重要说明:这仅适用于二进制 classification!