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

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.""" 

16 

17import tensorflow as tf 

18from typeguard import typechecked 

19 

20from tensorflow_addons.utils.types import TensorLike 

21 

22 

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`. 

27 

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. 

32 

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: 

35 

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)> 

48 

49 <... Note: constants a & b have been used purely for 

50 example purposes and have no significant value ...> 

51 

52 See: http://www.nec-labs.com/uploads/images/Department-Images/MediaAnalytics/papers/nips16_npairmetriclearning.pdf 

53 

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. 

59 

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) 

65 

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) 

70 

71 loss = tf.nn.softmax_cross_entropy_with_logits(logits=y_pred, labels=y_true) 

72 

73 return tf.math.reduce_mean(loss) 

74 

75 

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`. 

80 

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. 

85 

86 To deal with multilabel inputs, the count of label intersection 

87 is computed as follows: 

88 

89 ``` 

90 L_{i,j} = | set_of_labels_for(i) \cap set_of_labels_for(j) | 

91 ``` 

92 

93 Each row of the count based label matrix is further normalized so that 

94 each row sums to one. 

95 

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. 

99 

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: 

102 

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)> 

115 

116 <... Note: constants a & b have been used purely for 

117 example purposes and have no significant value ...> 

118 

119 See: http://www.nec-labs.com/uploads/images/Department-Images/MediaAnalytics/papers/nips16_npairmetriclearning.pdf 

120 

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. 

126 

127 y_pred: 2-D float `Tensor` with shape `[batch_size, batch_size]` of 

128 similarity matrix between embedding matrices. 

129 

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) 

135 

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) 

139 

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) 

146 

147 loss = tf.nn.softmax_cross_entropy_with_logits(logits=y_pred, labels=y_true) 

148 

149 return tf.math.reduce_mean(loss) 

150 

151 

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`. 

155 

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. 

160 

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: 

163 

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)> 

176 

177 <... Note: constants a & b have been used purely for 

178 example purposes and have no significant value ...> 

179 

180 See: http://www.nec-labs.com/uploads/images/Department-Images/MediaAnalytics/papers/nips16_npairmetriclearning.pdf 

181 

182 Args: 

183 name: (Optional) name for the loss. 

184 """ 

185 

186 @typechecked 

187 def __init__(self, name: str = "npairs_loss"): 

188 super().__init__(reduction=tf.keras.losses.Reduction.NONE, name=name) 

189 

190 def call(self, y_true, y_pred): 

191 return npairs_loss(y_true, y_pred) 

192 

193 

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`. 

197 

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. 

202 

203 To deal with multilabel inputs, the count of label intersection 

204 is computed as follows: 

205 

206 ``` 

207 L_{i,j} = | set_of_labels_for(i) \cap set_of_labels_for(j) | 

208 ``` 

209 

210 Each row of the count based label matrix is further normalized so that 

211 each row sums to one. 

212 

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. 

216 

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: 

219 

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)> 

232 

233 <... Note: constants a & b have been used purely for 

234 example purposes and have no significant value ...> 

235 

236 See: http://www.nec-labs.com/uploads/images/Department-Images/MediaAnalytics/papers/nips16_npairmetriclearning.pdf 

237 

238 Args: 

239 name: (Optional) name for the loss. 

240 """ 

241 

242 @typechecked 

243 def __init__(self, name: str = "npairs_multilabel_loss"): 

244 super().__init__(reduction=tf.keras.losses.Reduction.NONE, name=name) 

245 

246 def call(self, y_true, y_pred): 

247 return npairs_multilabel_loss(y_true, y_pred)