You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_loss.py 9.2 kB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. import math
  2. import unittest
  3. import torch
  4. import torch as tc
  5. import torch.nn.functional as F
  6. import fastNLP.core.losses as loss
  7. class TestLoss(unittest.TestCase):
  8. def test_case_1(self):
  9. loss_func = loss.LossFunc(F.nll_loss)
  10. nll_loss = loss.NLLLoss()
  11. y = tc.Tensor(
  12. [
  13. [.3, .4, .3],
  14. [.5, .3, .2],
  15. [.3, .6, .1],
  16. ]
  17. )
  18. gy = tc.LongTensor(
  19. [
  20. 0,
  21. 1,
  22. 2,
  23. ]
  24. )
  25. y = tc.log(y)
  26. los = loss_func({'input': y}, {'target': gy})
  27. losses = nll_loss({'input': y}, {'target': gy})
  28. r = -math.log(.3) - math.log(.3) - math.log(.1)
  29. r /= 3
  30. print("loss = %f" % (los))
  31. print("r = %f" % (r))
  32. print("nll_loss = %f" % (losses))
  33. self.assertEqual(int(los * 1000), int(r * 1000))
  34. def test_case_2(self):
  35. # 验证squash()的正确性
  36. log = math.log
  37. loss_func = loss.LossFromTorch("nll")
  38. y = tc.Tensor(
  39. [
  40. [[.3, .4, .3], [.3, .4, .3], ],
  41. [[.5, .3, .2], [.1, .2, .7], ],
  42. [[.3, .6, .1], [.2, .1, .7], ],
  43. ]
  44. )
  45. gy = tc.LongTensor(
  46. [
  47. [0, 2],
  48. [1, 2],
  49. [2, 1],
  50. ]
  51. )
  52. y = tc.log(y)
  53. # los = loss_func({'input': y}, {'target': gy})
  54. los = loss_func(y, gy)
  55. r = -log(.3) - log(.3) - log(.1) - log(.3) - log(.7) - log(.1)
  56. r /= 6
  57. self.assertEqual(int(los * 1000), int(r * 1000))
  58. def test_case_3(self):
  59. # 验证pack_padded_sequence()的正确性
  60. log = math.log
  61. loss_func = loss.NLLLoss()
  62. y = tc.Tensor(
  63. [
  64. [[.3, .4, .3], [.3, .2, .5], [.4, .5, .1, ], ],
  65. [[.5, .3, .2], [.1, .2, .7], [.0, .0, .0, ], ],
  66. [[.3, .6, .1], [.0, .0, .0], [.0, .0, .0, ], ],
  67. ]
  68. )
  69. gy = tc.LongTensor(
  70. [
  71. [0, 2, 1, ],
  72. [1, 2, 0, ],
  73. [2, 0, 0, ],
  74. ]
  75. )
  76. lens = [3, 2, 1]
  77. # pdb.set_trace()
  78. y = tc.log(y)
  79. yy = tc.nn.utils.rnn.pack_padded_sequence(y, lens, batch_first=True).data
  80. gyy = tc.nn.utils.rnn.pack_padded_sequence(gy, lens, batch_first=True).data
  81. los = loss_func({'input': yy}, {'target': gyy})
  82. r = -log(.3) - log(.5) - log(.5) - log(.3) - log(.7) - log(.1)
  83. r /= 6
  84. self.assertEqual(int(los * 1000), int(r * 1000))
  85. def test_case_4(self):
  86. # 验证unpad()的正确性
  87. log = math.log
  88. y = tc.Tensor(
  89. [
  90. [[.3, .4, .3], [.3, .2, .5], [.4, .5, .1, ], [.6, .3, .1, ], ],
  91. [[.5, .3, .2], [.1, .2, .7], [.0, .0, .0, ], [.0, .0, .0, ], ],
  92. [[.3, .6, .1], [.0, .0, .0], [.0, .0, .0, ], [.0, .0, .0, ], ],
  93. ]
  94. )
  95. gy = tc.LongTensor(
  96. [
  97. [0, 2, 1, 2, ],
  98. [1, 2, 0, 0, ],
  99. [2, 0, 0, 0, ],
  100. ]
  101. )
  102. lens = [4, 2, 1]
  103. y = tc.log(y)
  104. loss_func = loss.LossFromTorch("nll", pre_pro=["unpad"])
  105. los = loss_func(y, gy, lens=lens)
  106. r = -log(.1) - log(.3) - log(.5) - log(.5) - log(.3) - log(.7) - log(.1)
  107. r /= 7
  108. self.assertEqual(int(los * 1000), int(r * 1000))
  109. def test_case_5(self):
  110. # 验证mask()和make_mask()的正确性
  111. log = math.log
  112. y = tc.Tensor(
  113. [
  114. [[.5, .3, .2], [.1, .2, .7], [.0, .0, .0, ], [.0, .0, .0, ], ],
  115. [[.5, .4, .1], [.3, .2, .5], [.4, .5, .1, ], [.6, .1, .3, ], ],
  116. [[.3, .6, .1], [.3, .2, .5], [.0, .0, .0, ], [.0, .0, .0, ], ],
  117. ]
  118. )
  119. gy = tc.LongTensor(
  120. [
  121. [1, 2, 0, 0, ],
  122. [0, 2, 1, 2, ],
  123. [2, 1, 0, 0, ],
  124. ]
  125. )
  126. mask = tc.ByteTensor(
  127. [
  128. [1, 1, 0, 0, ],
  129. [1, 1, 1, 1, ],
  130. [1, 1, 0, 0, ],
  131. ]
  132. )
  133. y = tc.log(y)
  134. lens = [2, 4, 2]
  135. loss_func = loss.LossFromTorch("nll", pre_pro=["mask"])
  136. los = loss_func(y, gy, mask=mask)
  137. los2 = loss_func(y, gy, mask=loss.make_mask(lens, gy.size()[-1]))
  138. r = -log(.3) - log(.7) - log(.5) - log(.5) - log(.5) - log(.3) - log(.1) - log(.2)
  139. r /= 8
  140. self.assertEqual(int(los * 1000), int(r * 1000))
  141. self.assertEqual(int(los2 * 1000), int(r * 1000))
  142. def test_case_6(self):
  143. # 验证unpad_mask()的正确性
  144. log = math.log
  145. y = tc.Tensor(
  146. [
  147. [[.3, .4, .3], [.3, .2, .5], [.4, .5, .1, ], [.6, .3, .1, ], ],
  148. [[.5, .3, .2], [.1, .2, .7], [.0, .0, .0, ], [.0, .0, .0, ], ],
  149. [[.3, .6, .1], [.0, .0, .0], [.0, .0, .0, ], [.0, .0, .0, ], ],
  150. ]
  151. )
  152. gy = tc.LongTensor(
  153. [
  154. [0, 2, 1, 2, ],
  155. [1, 2, 0, 0, ],
  156. [2, 0, 0, 0, ],
  157. ]
  158. )
  159. lens = [4, 2, 1]
  160. # pdb.set_trace()
  161. y = tc.log(y)
  162. loss_func = loss.LossFromTorch("nll", pre_pro=["unpad_mask"])
  163. los = loss_func(y, gy, lens=lens)
  164. r = -log(.1) - log(.3) - log(.5) - log(.5) - log(.3) - log(.7) - log(.1)
  165. r /= 7
  166. self.assertEqual(int(los * 1000), int(r * 1000))
  167. def test_case_7(self):
  168. # 验证一些其他东西
  169. log = math.log
  170. y = tc.Tensor(
  171. [
  172. [[.3, .4, .3], [.3, .2, .5], [.4, .5, .1, ], [.6, .3, .1, ], ],
  173. [[.5, .3, .2], [.1, .2, .7], [.0, .0, .0, ], [.0, .0, .0, ], ],
  174. [[.3, .6, .1], [.0, .0, .0], [.0, .0, .0, ], [.0, .0, .0, ], ],
  175. ]
  176. )
  177. gy = tc.LongTensor(
  178. [
  179. [0, 2, 1, 2, ],
  180. [1, 2, 0, 0, ],
  181. [2, 0, 0, 0, ],
  182. ]
  183. )
  184. lens = [4, 2, 1]
  185. y = tc.log(y)
  186. loss_func = loss.LossFromTorch("nll", pre_pro=[], weight=tc.Tensor([1, 1, 0]))
  187. loss_func.add_pre_pro("unpad_mask")
  188. los = loss_func(y, gy, lens=lens)
  189. r = - log(.3) - log(.5) - log(.3)
  190. r /= 3
  191. self.assertEqual(int(los * 1000), int(r * 1000))
  192. def test_case_8(self):
  193. pass
  194. class TestLoss_v2(unittest.TestCase):
  195. def test_CrossEntropyLoss(self):
  196. ce = loss.CrossEntropyLoss(pred="my_predict", target="my_truth")
  197. a = torch.randn(3, 5, requires_grad=False)
  198. b = torch.empty(3, dtype=torch.long).random_(5)
  199. ans = ce({"my_predict": a}, {"my_truth": b})
  200. self.assertEqual(ans, torch.nn.functional.cross_entropy(a, b))
  201. def test_BCELoss(self):
  202. bce = loss.BCELoss(pred="my_predict", target="my_truth")
  203. a = torch.sigmoid(torch.randn((3, 5), requires_grad=False))
  204. b = torch.randn((3, 5), requires_grad=False)
  205. ans = bce({"my_predict": a}, {"my_truth": b})
  206. self.assertEqual(ans, torch.nn.functional.binary_cross_entropy(a, b))
  207. def test_L1Loss(self):
  208. l1 = loss.L1Loss(pred="my_predict", target="my_truth")
  209. a = torch.randn(3, 5, requires_grad=False)
  210. b = torch.randn(3, 5)
  211. ans = l1({"my_predict": a}, {"my_truth": b})
  212. self.assertEqual(ans, torch.nn.functional.l1_loss(a, b))
  213. def test_NLLLoss(self):
  214. l1 = loss.NLLLoss(pred="my_predict", target="my_truth")
  215. a = F.log_softmax(torch.randn(3, 5, requires_grad=False), dim=0)
  216. b = torch.tensor([1, 0, 4])
  217. ans = l1({"my_predict": a}, {"my_truth": b})
  218. self.assertEqual(ans, torch.nn.functional.nll_loss(a, b))
  219. class TestLosserError(unittest.TestCase):
  220. def test_losser1(self):
  221. # (1) only input, targets passed
  222. pred_dict = {"pred": torch.zeros(4, 3)}
  223. target_dict = {'target': torch.zeros(4).long()}
  224. los = loss.CrossEntropyLoss()
  225. print(los(pred_dict=pred_dict, target_dict=target_dict))
  226. #
  227. def test_losser2(self):
  228. # (2) with corrupted size
  229. pred_dict = {"pred": torch.zeros(16, 3)}
  230. target_dict = {'target': torch.zeros(16, 3).long()}
  231. los = loss.CrossEntropyLoss()
  232. # print(los(pred_dict=pred_dict, target_dict=target_dict))
  233. def test_losser3(self):
  234. # (2) with corrupted size
  235. pred_dict = {"pred": torch.zeros(16, 3), 'stop_fast_param':0}
  236. target_dict = {'target': torch.zeros(16).long()}
  237. los = loss.CrossEntropyLoss()
  238. print(los(pred_dict=pred_dict, target_dict=target_dict))
  239. def test_check_error(self):
  240. l1 = loss.NLLLoss(pred="my_predict", target="my_truth")
  241. a = F.log_softmax(torch.randn(3, 5, requires_grad=False), dim=0)
  242. b = torch.tensor([1, 0, 4])
  243. with self.assertRaises(Exception):
  244. ans = l1({"wrong_predict": a, "my": b}, {"my_truth": b})
  245. with self.assertRaises(Exception):
  246. ans = l1({"my_predict": a}, {"truth": b, "my": a})