How to calculate F1 Macro in Keras?

后端 未结 6 1698
逝去的感伤
逝去的感伤 2020-11-28 23:13

i\'ve tried to use the codes given from Keras before they\'re removed. Here\'s the code :

def precision(y_true, y_pred):
    true_positives = K.sum(K.round(K         


        
6条回答
  •  臣服心动
    2020-11-28 23:20

    This is a streaming custom f1_score metric that I made using subclassing. It works for TensorFlow 2.0 beta but I haven't tried it on other versions. What it's doing it keeping track of true positives, predicted positives, and all possible positives throughout the whole epoch and then calculating the f1 score at the end of the epoch. I think the other answers are only giving the f1 score for each batch which isn't really the best metric when we really want the f1 score of the all the data.

    I got a raw unedited copy of Aurélien Geron new book Hands-On Machine Learning with Scikit-Learn & Tensorflow 2.0 and highly recommend it. This is how I learned how to this f1 custom metric using sub-classes. It's hands down the most comprehensive TensorFlow book I've ever seen. TensorFlow is seriously a pain in the butt to learn and this guy lays down the coding groundwork to learn a lot.

    FYI: In the Metrics, I had to put the parenthesis in f1_score() or else it wouldn't work.

    pip install tensorflow==2.0.0-beta1

    from sklearn.model_selection import train_test_split
    import tensorflow as tf
    from tensorflow import keras
    import numpy as np
    
    def create_f1():
        def f1_function(y_true, y_pred):
            y_pred_binary = tf.where(y_pred>=0.5, 1., 0.)
            tp = tf.reduce_sum(y_true * y_pred_binary)
            predicted_positives = tf.reduce_sum(y_pred_binary)
            possible_positives = tf.reduce_sum(y_true)
            return tp, predicted_positives, possible_positives
        return f1_function
    
    
    class F1_score(keras.metrics.Metric):
        def __init__(self, **kwargs):
            super().__init__(**kwargs) # handles base args (e.g., dtype)
            self.f1_function = create_f1()
            self.tp_count = self.add_weight("tp_count", initializer="zeros")
            self.all_predicted_positives = self.add_weight('all_predicted_positives', initializer='zeros')
            self.all_possible_positives = self.add_weight('all_possible_positives', initializer='zeros')
    
        def update_state(self, y_true, y_pred,sample_weight=None):
            tp, predicted_positives, possible_positives = self.f1_function(y_true, y_pred)
            self.tp_count.assign_add(tp)
            self.all_predicted_positives.assign_add(predicted_positives)
            self.all_possible_positives.assign_add(possible_positives)
    
        def result(self):
            precision = self.tp_count / self.all_predicted_positives
            recall = self.tp_count / self.all_possible_positives
            f1 = 2*(precision*recall)/(precision+recall)
            return f1
    
    X = np.random.random(size=(1000, 10))     
    Y = np.random.randint(0, 2, size=(1000,))
    X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.2)
    
    model = keras.models.Sequential([
        keras.layers.Dense(5, input_shape=[X.shape[1], ]),
        keras.layers.Dense(1, activation='sigmoid')
    ])
    
    model.compile(loss='binary_crossentropy', optimizer='SGD', metrics=[F1_score()])
    
    history = model.fit(X_train, y_train, epochs=5, validation_data=(X_test, y_test))
    

提交回复
热议问题