{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Keras evaluation metric\n\nIf you are using Keras, this metric can be used to monitor the evaluation metric of this competition during training.\n\n[Original code](https://towardsdatascience.com/f-beta-score-in-keras-part-i-86ad190a252f)\n\n## Usage in *compile* method\n\n```python\n...\nmodel.compile(...,metrics=[StatefullBinaryFBeta()])\n...\n```","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.metrics import Metric\nimport tensorflow as tf","metadata":{"execution":{"iopub.status.busy":"2023-04-10T21:57:48.902321Z","iopub.execute_input":"2023-04-10T21:57:48.902739Z","iopub.status.idle":"2023-04-10T21:57:59.344451Z","shell.execute_reply.started":"2023-04-10T21:57:48.902702Z","shell.execute_reply":"2023-04-10T21:57:59.342820Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class StatefullBinaryFBeta(Metric):\n    def __init__(self, name='state_full_binary_fbeta', beta=0.5, threshold=0., epsilon=1e-7, **kwargs):\n        # initializing an object of the super class\n        super(StatefullBinaryFBeta, self).__init__(name=name, **kwargs)\n\n        # initializing state variables\n        self.tp = self.add_weight(name='tp', initializer='zeros') # initializing true positives \n        self.actual_positive = self.add_weight(name='fp', initializer='zeros') # initializing actual positives\n        self.predicted_positive = self.add_weight(name='fn', initializer='zeros') # initializing predicted positives\n\n        # initializing other atrributes that wouldn't be changed for every object of this class\n        self.beta_squared = beta**2 \n        self.threshold = threshold\n        self.epsilon = epsilon\n\n    def update_state(self, ytrue, ypred, sample_weight=None):\n        # casting ytrue and ypred as float dtype\n        ytrue = tf.cast(ytrue, tf.float32)\n        ypred = tf.keras.activations.sigmoid(tf.cast(ypred, tf.float32))\n\n        # setting values of ypred greater than the set threshold to 1 while those lesser to 0\n        ypred = tf.cast(tf.greater_equal(ypred, tf.constant(self.threshold)), tf.float32)\n\n        self.tp.assign_add(tf.reduce_sum(ytrue*ypred)) # updating true positives atrribute\n        self.predicted_positive.assign_add(tf.reduce_sum(ypred)) # updating predicted positive atrribute\n        self.actual_positive.assign_add(tf.reduce_sum(ytrue)) # updating actual positive atrribute\n\n    def result(self):\n        self.precision = self.tp/(self.predicted_positive+self.epsilon) # calculates precision\n        self.recall = self.tp/(self.actual_positive+self.epsilon) # calculates recall\n\n        # calculating fbeta\n        self.fb = (1+self.beta_squared)*self.precision*self.recall / (self.beta_squared*self.precision + self.recall + self.epsilon)\n\n        return self.fb\n\n    def reset_state(self):\n        self.tp.assign(0) # resets true positives to zero\n        self.predicted_positive.assign(0) # resets predicted positives to zero\n        self.actual_positive.assign(0) # resets actual positives to zero","metadata":{"execution":{"iopub.status.busy":"2023-04-10T21:57:59.346399Z","iopub.execute_input":"2023-04-10T21:57:59.347063Z","iopub.status.idle":"2023-04-10T21:57:59.360946Z","shell.execute_reply.started":"2023-04-10T21:57:59.347027Z","shell.execute_reply":"2023-04-10T21:57:59.359124Z"},"trusted":true},"execution_count":null,"outputs":[]}]}