Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/tensorflow_addons/metrics/hamming.py: 38%
29 statements
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-03 07:57 +0000
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-03 07:57 +0000
1# Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14# ==============================================================================
15"""Implements Hamming distance and loss."""
17import tensorflow as tf
18from tensorflow_addons.metrics.utils import MeanMetricWrapper
19from tensorflow_addons.utils.types import FloatTensorLike, TensorLike, AcceptableDTypes
21from typeguard import typechecked
22from typing import Union, Optional
25def hamming_distance(actuals: TensorLike, predictions: TensorLike) -> tf.Tensor:
26 """Computes hamming distance.
28 Hamming distance is for comparing two binary strings.
29 It is the number of bit positions in which two bits
30 are different.
32 Args:
33 actuals: actual target value.
34 predictions: predicted value.
36 Returns:
37 hamming distance: float.
39 Usage:
41 >>> y_true = np.array([1, 1, 0, 0, 1, 0, 1, 0, 0, 1], dtype=np.int32)
42 >>> y_pred = np.array([1, 0, 0, 0, 1, 0, 0, 1, 0, 1], dtype=np.int32)
43 >>> hamming_distance(y_true, y_pred).numpy()
44 0.3
46 """
47 result = tf.not_equal(actuals, predictions)
48 not_eq = tf.reduce_sum(tf.cast(result, tf.float32))
49 ham_distance = tf.math.divide_no_nan(not_eq, len(result))
50 return ham_distance
53def hamming_loss_fn(
54 y_true: TensorLike,
55 y_pred: TensorLike,
56 threshold: Union[FloatTensorLike, None],
57 mode: str,
58) -> tf.Tensor:
59 """Computes hamming loss.
61 Hamming loss is the fraction of wrong labels to the total number
62 of labels.
64 In multi-class classification, hamming loss is calculated as the
65 hamming distance between `y_true` and `y_pred`.
66 In multi-label classification, hamming loss penalizes only the
67 individual labels.
69 Args:
70 y_true: actual target value.
71 y_pred: predicted target value.
72 threshold: Elements of `y_pred` greater than threshold are
73 converted to be 1, and the rest 0. If threshold is
74 None, the argmax is converted to 1, and the rest 0.
75 mode: multi-class or multi-label.
77 Returns:
78 hamming loss: float.
79 """
80 if mode not in ["multiclass", "multilabel"]:
81 raise TypeError("mode must be either multiclass or multilabel]")
83 if threshold is None:
84 threshold = tf.reduce_max(y_pred, axis=-1, keepdims=True)
85 # make sure [0, 0, 0] doesn't become [1, 1, 1]
86 # Use abs(x) > eps, instead of x != 0 to check for zero
87 y_pred = tf.logical_and(y_pred >= threshold, tf.abs(y_pred) > 1e-12)
88 else:
89 y_pred = y_pred > threshold
91 y_true = tf.cast(y_true, tf.int32)
92 y_pred = tf.cast(y_pred, tf.int32)
94 if mode == "multiclass":
95 nonzero = tf.cast(tf.math.count_nonzero(y_true * y_pred, axis=-1), tf.float32)
96 return 1.0 - nonzero
98 else:
99 nonzero = tf.cast(tf.math.count_nonzero(y_true - y_pred, axis=-1), tf.float32)
100 return nonzero / y_true.get_shape()[-1]
103class HammingLoss(MeanMetricWrapper):
104 """Computes hamming loss.
106 Hamming loss is the fraction of wrong labels to the total number
107 of labels.
109 In multi-class classification, hamming loss is calculated as the
110 hamming distance between `y_true` and `y_pred`.
111 In multi-label classification, hamming loss penalizes only the
112 individual labels.
114 Args:
115 threshold: Elements of `y_pred` greater than threshold are
116 converted to be 1, and the rest 0. If threshold is
117 None, the argmax is converted to 1, and the rest 0.
118 mode: multi-class or multi-label.
119 name: (Optional) string name of the metric instance.
120 dtype: (Optional) data type of the metric result.
122 Usage:
124 >>> # multi-class hamming loss
125 >>> metric = HammingLoss(mode='multiclass', threshold=0.6)
126 >>> y_true = np.array([[1.0, 0.0, 0.0, 0.0],
127 ... [0.0, 0.0, 1.0, 0.0],
128 ... [0.0, 0.0, 0.0, 1.0],
129 ... [0.0, 1.0, 0.0, 0.0]], dtype=np.float32)
130 >>> y_pred = np.array([[0.8, 0.1, 0.1, 0.0],
131 ... [0.2, 0.0, 0.8, 0.0],
132 ... [0.05, 0.05, 0.1, 0.8],
133 ... [1.0, 0.0, 0.0, 0.0]], dtype=np.float32)
134 >>> metric.update_state(y_true, y_pred)
135 <tf.Variable 'UnreadVariable' shape=() dtype=float32, numpy=4.0>
136 >>> metric.result().numpy()
137 0.25
138 >>> # multi-label hamming loss
139 >>> metric = HammingLoss(mode='multilabel', threshold=0.8)
140 >>> y_true = np.array([[1, 0, 1, 0],
141 ... [0, 1, 0, 1],
142 ... [0, 0, 0, 1]], dtype=np.int32)
143 >>> y_pred = np.array([[0.82, 0.5, 0.90, 0],
144 ... [0, 1, 0.4, 0.98],
145 ... [0.89, 0.79, 0, 0.3]], dtype=np.float32)
146 >>> metric.update_state(y_true, y_pred)
147 <tf.Variable 'UnreadVariable' shape=() dtype=float32, numpy=3.0>
148 >>> metric.result().numpy()
149 0.16666667
150 """
152 @typechecked
153 def __init__(
154 self,
155 mode: str,
156 name: str = "hamming_loss",
157 threshold: Optional[FloatTensorLike] = None,
158 dtype: AcceptableDTypes = None,
159 **kwargs,
160 ):
161 super().__init__(
162 hamming_loss_fn, name=name, dtype=dtype, mode=mode, threshold=threshold
163 )