Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/tensorflow_addons/losses/npairs.py: 51%
39 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 npairs loss."""
17import tensorflow as tf
18from typeguard import typechecked
20from tensorflow_addons.utils.types import TensorLike
23@tf.keras.utils.register_keras_serializable(package="Addons")
24@tf.function
25def npairs_loss(y_true: TensorLike, y_pred: TensorLike) -> tf.Tensor:
26 """Computes the npairs loss between `y_true` and `y_pred`.
28 Npairs loss expects paired data where a pair is composed of samples from
29 the same labels and each pairs in the minibatch have different labels.
30 The loss takes each row of the pair-wise similarity matrix, `y_pred`,
31 as logits and the remapped multi-class labels, `y_true`, as labels.
33 The similarity matrix `y_pred` between two embedding matrices `a` and `b`
34 with shape `[batch_size, hidden_size]` can be computed as follows:
36 >>> a = tf.constant([[1, 2],
37 ... [3, 4],
38 ... [5, 6]], dtype=tf.float16)
39 >>> b = tf.constant([[5, 9],
40 ... [3, 6],
41 ... [1, 8]], dtype=tf.float16)
42 >>> y_pred = tf.matmul(a, b, transpose_a=False, transpose_b=True)
43 >>> y_pred
44 <tf.Tensor: shape=(3, 3), dtype=float16, numpy=
45 array([[23., 15., 17.],
46 [51., 33., 35.],
47 [79., 51., 53.]], dtype=float16)>
49 <... Note: constants a & b have been used purely for
50 example purposes and have no significant value ...>
52 See: http://www.nec-labs.com/uploads/images/Department-Images/MediaAnalytics/papers/nips16_npairmetriclearning.pdf
54 Args:
55 y_true: 1-D integer `Tensor` with shape `[batch_size]` of
56 multi-class labels.
57 y_pred: 2-D float `Tensor` with shape `[batch_size, batch_size]` of
58 similarity matrix between embedding matrices.
60 Returns:
61 npairs_loss: float scalar.
62 """
63 y_pred = tf.convert_to_tensor(y_pred)
64 y_true = tf.cast(y_true, y_pred.dtype)
66 # Expand to [batch_size, 1]
67 y_true = tf.expand_dims(y_true, -1)
68 y_true = tf.cast(tf.equal(y_true, tf.transpose(y_true)), y_pred.dtype)
69 y_true /= tf.math.reduce_sum(y_true, 1, keepdims=True)
71 loss = tf.nn.softmax_cross_entropy_with_logits(logits=y_pred, labels=y_true)
73 return tf.math.reduce_mean(loss)
76@tf.keras.utils.register_keras_serializable(package="Addons")
77@tf.function
78def npairs_multilabel_loss(y_true: TensorLike, y_pred: TensorLike) -> tf.Tensor:
79 r"""Computes the npairs loss between multilabel data `y_true` and `y_pred`.
81 Npairs loss expects paired data where a pair is composed of samples from
82 the same labels and each pairs in the minibatch have different labels.
83 The loss takes each row of the pair-wise similarity matrix, `y_pred`,
84 as logits and the remapped multi-class labels, `y_true`, as labels.
86 To deal with multilabel inputs, the count of label intersection
87 is computed as follows:
89 ```
90 L_{i,j} = | set_of_labels_for(i) \cap set_of_labels_for(j) |
91 ```
93 Each row of the count based label matrix is further normalized so that
94 each row sums to one.
96 `y_true` should be a binary indicator for classes.
97 That is, if `y_true[i, j] = 1`, then `i`th sample is in `j`th class;
98 if `y_true[i, j] = 0`, then `i`th sample is not in `j`th class.
100 The similarity matrix `y_pred` between two embedding matrices `a` and `b`
101 with shape `[batch_size, hidden_size]` can be computed as follows:
103 >>> a = tf.constant([[1, 2],
104 ... [3, 4],
105 ... [5, 6]], dtype=tf.float16)
106 >>> b = tf.constant([[5, 9],
107 ... [3, 6],
108 ... [1, 8]], dtype=tf.float16)
109 >>> y_pred = tf.matmul(a, b, transpose_a=False, transpose_b=True)
110 >>> y_pred
111 <tf.Tensor: shape=(3, 3), dtype=float16, numpy=
112 array([[23., 15., 17.],
113 [51., 33., 35.],
114 [79., 51., 53.]], dtype=float16)>
116 <... Note: constants a & b have been used purely for
117 example purposes and have no significant value ...>
119 See: http://www.nec-labs.com/uploads/images/Department-Images/MediaAnalytics/papers/nips16_npairmetriclearning.pdf
121 Args:
122 y_true: Either 2-D integer `Tensor` with shape
123 `[batch_size, num_classes]`, or `SparseTensor` with dense shape
124 `[batch_size, num_classes]`. If `y_true` is a `SparseTensor`, then
125 it will be converted to `Tensor` via `tf.sparse.to_dense` first.
127 y_pred: 2-D float `Tensor` with shape `[batch_size, batch_size]` of
128 similarity matrix between embedding matrices.
130 Returns:
131 npairs_multilabel_loss: float scalar.
132 """
133 y_pred = tf.convert_to_tensor(y_pred)
134 y_true = tf.cast(y_true, y_pred.dtype)
136 # Convert to dense tensor if `y_true` is a `SparseTensor`
137 if isinstance(y_true, tf.SparseTensor):
138 y_true = tf.sparse.to_dense(y_true)
140 # Enable efficient multiplication because y_true contains lots of zeros
141 # https://www.tensorflow.org/api_docs/python/tf/linalg/matmul
142 y_true = tf.linalg.matmul(
143 y_true, y_true, transpose_b=True, a_is_sparse=True, b_is_sparse=True
144 )
145 y_true /= tf.math.reduce_sum(y_true, 1, keepdims=True)
147 loss = tf.nn.softmax_cross_entropy_with_logits(logits=y_pred, labels=y_true)
149 return tf.math.reduce_mean(loss)
152@tf.keras.utils.register_keras_serializable(package="Addons")
153class NpairsLoss(tf.keras.losses.Loss):
154 """Computes the npairs loss between `y_true` and `y_pred`.
156 Npairs loss expects paired data where a pair is composed of samples from
157 the same labels and each pairs in the minibatch have different labels.
158 The loss takes each row of the pair-wise similarity matrix, `y_pred`,
159 as logits and the remapped multi-class labels, `y_true`, as labels.
161 The similarity matrix `y_pred` between two embedding matrices `a` and `b`
162 with shape `[batch_size, hidden_size]` can be computed as follows:
164 >>> a = tf.constant([[1, 2],
165 ... [3, 4],
166 ... [5, 6]], dtype=tf.float16)
167 >>> b = tf.constant([[5, 9],
168 ... [3, 6],
169 ... [1, 8]], dtype=tf.float16)
170 >>> y_pred = tf.matmul(a, b, transpose_a=False, transpose_b=True)
171 >>> y_pred
172 <tf.Tensor: shape=(3, 3), dtype=float16, numpy=
173 array([[23., 15., 17.],
174 [51., 33., 35.],
175 [79., 51., 53.]], dtype=float16)>
177 <... Note: constants a & b have been used purely for
178 example purposes and have no significant value ...>
180 See: http://www.nec-labs.com/uploads/images/Department-Images/MediaAnalytics/papers/nips16_npairmetriclearning.pdf
182 Args:
183 name: (Optional) name for the loss.
184 """
186 @typechecked
187 def __init__(self, name: str = "npairs_loss"):
188 super().__init__(reduction=tf.keras.losses.Reduction.NONE, name=name)
190 def call(self, y_true, y_pred):
191 return npairs_loss(y_true, y_pred)
194@tf.keras.utils.register_keras_serializable(package="Addons")
195class NpairsMultilabelLoss(tf.keras.losses.Loss):
196 r"""Computes the npairs loss between multilabel data `y_true` and `y_pred`.
198 Npairs loss expects paired data where a pair is composed of samples from
199 the same labels and each pairs in the minibatch have different labels.
200 The loss takes each row of the pair-wise similarity matrix, `y_pred`,
201 as logits and the remapped multi-class labels, `y_true`, as labels.
203 To deal with multilabel inputs, the count of label intersection
204 is computed as follows:
206 ```
207 L_{i,j} = | set_of_labels_for(i) \cap set_of_labels_for(j) |
208 ```
210 Each row of the count based label matrix is further normalized so that
211 each row sums to one.
213 `y_true` should be a binary indicator for classes.
214 That is, if `y_true[i, j] = 1`, then `i`th sample is in `j`th class;
215 if `y_true[i, j] = 0`, then `i`th sample is not in `j`th class.
217 The similarity matrix `y_pred` between two embedding matrices `a` and `b`
218 with shape `[batch_size, hidden_size]` can be computed as follows:
220 >>> a = tf.constant([[1, 2],
221 ... [3, 4],
222 ... [5, 6]], dtype=tf.float16)
223 >>> b = tf.constant([[5, 9],
224 ... [3, 6],
225 ... [1, 8]], dtype=tf.float16)
226 >>> y_pred = tf.matmul(a, b, transpose_a=False, transpose_b=True)
227 >>> y_pred
228 <tf.Tensor: shape=(3, 3), dtype=float16, numpy=
229 array([[23., 15., 17.],
230 [51., 33., 35.],
231 [79., 51., 53.]], dtype=float16)>
233 <... Note: constants a & b have been used purely for
234 example purposes and have no significant value ...>
236 See: http://www.nec-labs.com/uploads/images/Department-Images/MediaAnalytics/papers/nips16_npairmetriclearning.pdf
238 Args:
239 name: (Optional) name for the loss.
240 """
242 @typechecked
243 def __init__(self, name: str = "npairs_multilabel_loss"):
244 super().__init__(reduction=tf.keras.losses.Reduction.NONE, name=name)
246 def call(self, y_true, y_pred):
247 return npairs_multilabel_loss(y_true, y_pred)