tensorflow中的自定义f1_分数度量
我想为tf.keras实现f1_分数指标tensorflow中的自定义f1_分数度量,tensorflow,machine-learning,keras,metrics,Tensorflow,Machine Learning,Keras,Metrics,我想为tf.keras实现f1_分数指标 from tensorflow.keras.models import Model, Sequential from tensorflow.keras.layers import Dense from tensorflow.keras.optimizers import Adam from tensorflow.keras.losses import binary_crossentropy from tensorflow.keras.metrics im
from tensorflow.keras.models import Model, Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.losses import binary_crossentropy
from tensorflow.keras.metrics import Accuracy, BinaryAccuracy
from sklearn.metrics import accuracy_score
import numpy as np
import tensorflow as tf
class F1_Score(tf.keras.metrics.Metric):
def __init__(self, name='f1_score', **kwargs):
super().__init__(name=name, **kwargs)
self.f1 = self.add_weight(name='f1', initializer='zeros')
def update_state(self, y_true, y_pred, sample_weight=None):
p = Precision(thresholds=0.5)(y_true, y_pred)
r = Recall(thresholds=0.5)(y_true, y_pred)
self.f1 = 2 * ((p * r) / (p + r + 1e-6))
def result(self):
return self.f1
def reset_states(self):
self.f1.assign(0)
model = Sequential([
Dense(64, activation='relu', input_shape=(784,)),
Dense(64, activation='relu'),
Dense(4, activation='sigmoid'),
])
x = np.random.normal(size=(10, 784))
y = np.random.choice(2, size=(10, 4))
model.compile(optimizer=Adam(0.001), loss='binary_crossentropy',
metrics=['accuracy', , F1_Score()])
model.fit(x[:1], y[:1], batch_size=1, epochs=1, verbose=1)
我有一个错误:
ValueError:tf.function-decorated函数试图创建变量
非首次通话
出现此错误是因为您希望在update_state函数期间实例化一些
tf.Variable
s。当从类Precision和Recall实例化对象时,您正在创建一些tf.Variable
s
实例化构造函数中的对象,并在update_state函数中调用它们:
F1级分数(tf.keras.metrics.Metric):
定义初始值(self,name='f1\u score',**kwargs):
super()
self.f1=self.add_weight(name='f1',initializer='zeros')
self.precision\u fn=精度(阈值=0.5)
自我回忆\u fn=回忆(阈值=0.5)
def更新状态(自身、y_真、y_pred、样本重量=无):
p=自精度fn(y\u真,y\u pred)
r=自我回忆(y_真,y_前)
#因为f1是一个变量,所以我们使用赋值
自我分配(2*((p*r)/(p+r+1e-6)))
def结果(自我):
返回self.f1
def复位_状态(自身):
#我们还需要重置精度和召回对象的状态
自精度重置状态()
自我回忆(fn)复位(states)
self.f1.assign(0)
行为说明: Tensorflow仅允许在第一次调用
tf.函数时创建变量,请参见:
函数仅允许在第一次调用时创建新的tf.Variable对象
Keras度量被包装在tf.function中,以允许与tensorflow v1兼容。您可以在
如果update\u state
不在eager/tf.function中且不是来自
内置公制,将其包装在tf.function
中。这是为了方便用户编写
v1中的自定义指标不需要担心控件依赖关系和
返回操作
您的类中还有另一个错误,即您重写了您在计算f1分数时创建的f1 tf.Variable
。要更新变量的值,需要使用assign
。我们一定不要忘记重置使用中的精度和召回度量对象的状态 您可以使用tensorflow插件
,它有一个用于F1分数的内置方法。(别忘了pip安装tensorflow插件
)
看看下面:
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.00001),
loss=tf.keras.losses.CategoricalCrossentropy(),
metrics=[tf.keras.metrics.CategoricalAccuracy(),
tfa.metrics.F1Score(num_classes=n_classes, average='macro'),
tfa.metrics.FBetaScore(beta=2.0, num_classes=n_classes, average='macro')])
如果确实存在多标签分类问题,可以将其更改为:
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.00001),
loss=tf.keras.losses.BinaryCrossentropy(),
metrics=[tf.keras.metrics.BinaryAccuracy(),
tfa.metrics.F1Score(num_classes=1, average='macro',threshold=0.5),
tfa.metrics.FBetaScore(beta=2.0, num_classes=1, average='macro',threshold=0.5)])
这是我对Tensorflow 2.0的代码评分f1:
class F1Score(tf.keras.metrics.Metric):
def __init__(self, name='F1Score', **kwargs):
super(F1Score, self).__init__(name=name, **kwargs)
self.f1score = self.add_weight(name='F1Score', initializer='zeros')
self.count = self.add_weight(name='F1ScoreCount', initializer='zeros')
def update_state(self, y_true, y_pred, sample_weight=None):
y_true = tf.cast(y_true, tf.bool)
y_pred = tf.cast(y_pred, tf.bool)
true_positives = tf.logical_and(tf.equal(y_true, True), tf.equal(y_pred, True))
true_positives = tf.cast(true_positives, self.dtype)
count_true_positives = tf.reduce_sum(true_positives)
possible_positives = tf.cast(y_true, self.dtype)
count_possible_positives = tf.reduce_sum(possible_positives)
predicted_positives = tf.cast(y_pred, self.dtype)
count_predicted_positives = tf.reduce_sum(predicted_positives)
precision = count_true_positives / (count_predicted_positives + K.epsilon())
recall = count_true_positives / (count_possible_positives + K.epsilon())
f1_cal = 2*(precision*recall)/(precision + recall + K.epsilon())
self.count.assign_add(1)
a = 1.0 / self.count
b = 1.0 - a
self.f1score.assign(a*f1_cal+b*self.f1score)
def result(self):
return self.f1score
顺便说一句,您是否尝试过使用内置指标来了解它们的工作原理?这些指标适用于二进制/多类/多标签分类。tfa.metrics.F1Score
和FBetaScore
之间的区别是什么?F1分数是FBetaScore的一种特殊情况,其中Beta==1。谢谢,你能看一下这个问题吗?我得到一个错误AttributeError:'Tensor'对象在reset_states()中没有属性'assign
!!我还使用了tf.compat.v1.assign
,得到了相同的结果error@BetterEnglish查看我的更新。我在你的代码中遗漏了一些错误。欢迎使用SO!请阅读,然后