Keras未实现F1-score
以前Keras的metrics是错的,原因是这是非streaming的计算方式;
Metrics
定义一个MSE作为metric如下,这是一个scalar常量值,并且在training或evaluation的时候,每个epoch看到的结果是该epoch下的每个batch的平均值;(is the average of the per-batch metric values for all batches see during a given epoch)
1 | def my_metric_fn(y_true, y_pred): |
但有时候我们想要的是在整个数据集上的metric,比如AUC等,所以上面的方法不适用,我们需要跨batches里,保持一个state,这个state记录我们最后要在总数据上计算的总metric;
做法是继承Metric
类,它可以跨batches的保持一个state:
1 | class BinaryTruePositives(tf.keras.metrics.Metric): |
add_metric()
接口如下:这样得到的是在每一个batch的平均值;(设置了aggregation='mean'
)- The quantity will then tracked under the name “activation_mean”. The value tracked will be the average of the per-batch metric metric values (as specified by
aggregation='mean'
).
1 | class DenseLike(Layer): |
Streaming Metrics
我们需要流式的度量计算(streaming metric or stateful metric),一个batch计算后,下一个batch的metric计算时考虑上之前的计算值,从而得到增量的metric计算值。
创建streaming metric的方法是继承keras.metrics.Metric class
:
- The constructor uses the
add_weight()
method to create the variables needed to keep track of the metric’s state over multiple batches; Keras tracks any tf.Variable that is set as an attribute - The
update_state()
method is called when you use an instance of this class as a function; - When you use the metric as a function, the
update_state()
method gets called first, then theresult()
method is called, and its output is returned. - We also implement the
get_config()
method to ensure the threshold gets saved along with the model. - When you define a metric using a simple function, Keras automatically calls it for each batch, and it keeps track of the mean during each epoch, just like we did manually. So the only benefit of our HuberMetric class is that the threshold will be saved. But of course, some metrics, like precision, cannot simply be averaged over batches: in those cases, there’s no other option than to implement a streaming metric.
1 | class HuberMetric(keras.metrics.Metric): |
Anothe example:
1 | class CategoricalTruePositives(keras.metrics.Metric): |
multiple inputs for metrics
1 | from keras.layers import * |