From 8977b7a708d3742194bc3850e71ab9723161bde0 Mon Sep 17 00:00:00 2001 From: Vasilis Vryniotis Date: Thu, 5 Nov 2020 12:38:47 +0000 Subject: [PATCH 01/10] Simplify the ACCEPT=True logic in assertExpected(). --- test/common_utils.py | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/test/common_utils.py b/test/common_utils.py index 5368018e971..27930b8e330 100644 --- a/test/common_utils.py +++ b/test/common_utils.py @@ -128,32 +128,23 @@ def remove_prefix_suffix(text, prefix, suffix): subname_output = " ({})".format(subname) expected_file += "_expect.pkl" - def accept_output(update_type): - print("Accepting {} for {}{}:\n\n{}".format(update_type, munged_id, subname_output, output)) - torch.save(output, expected_file) - MAX_PICKLE_SIZE = 50 * 1000 # 50 KB - binary_size = os.path.getsize(expected_file) - self.assertTrue(binary_size <= MAX_PICKLE_SIZE) - try: expected = torch.load(expected_file) except IOError as e: if e.errno != errno.ENOENT: raise - elif ACCEPT: - accept_output("output") - return - else: + elif not ACCEPT: raise RuntimeError( ("I got this output for {}{}:\n\n{}\n\n" "No expect file exists; to accept the current output, run:\n" "python {} {} --accept").format(munged_id, subname_output, output, __main__.__file__, munged_id)) if ACCEPT: - try: - self.assertEqual(output, expected, prec=prec) - except Exception: - accept_output("updated output") + print("Accepting updated output for {}{}:\n\n{}".format(munged_id, subname_output, output)) + torch.save(output, expected_file) + MAX_PICKLE_SIZE = 50 * 1000 # 50 KB + binary_size = os.path.getsize(expected_file) + self.assertTrue(binary_size <= MAX_PICKLE_SIZE) else: self.assertEqual(output, expected, prec=prec) From 23c153c304766a73f14e7b426d29750dd29c832b Mon Sep 17 00:00:00 2001 From: Vasilis Vryniotis Date: Thu, 5 Nov 2020 13:21:31 +0000 Subject: [PATCH 02/10] Separate the expected filename estimation from assertExpected --- test/common_utils.py | 58 ++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/test/common_utils.py b/test/common_utils.py index 27930b8e330..e5713dc0832 100644 --- a/test/common_utils.py +++ b/test/common_utils.py @@ -88,24 +88,7 @@ def is_iterable(obj): class TestCase(unittest.TestCase): precision = 1e-5 - def assertExpected(self, output, subname=None, prec=None, strip_suffix=None): - r""" - Test that a python value matches the recorded contents of a file - derived from the name of this test and subname. The value must be - pickable with `torch.save`. This file - is placed in the 'expect' directory in the same directory - as the test script. You can automatically update the recorded test - output using --accept. - - If you call this multiple times in a single function, you must - give a unique subname each time. - - strip_suffix allows different tests that expect similar numerics, e.g. - "test_xyz_cuda" and "test_xyz_cpu", to use the same pickled data. - test_xyz_cuda would pass strip_suffix="_cuda", test_xyz_cpu would pass - strip_suffix="_cpu", and they would both use a data file name based on - "test_xyz". - """ + def _get_expected_file(self, subname=None, strip_suffix=None): def remove_prefix_suffix(text, prefix, suffix): if text.startswith(prefix): text = text[len(prefix):] @@ -128,24 +111,41 @@ def remove_prefix_suffix(text, prefix, suffix): subname_output = " ({})".format(subname) expected_file += "_expect.pkl" - try: - expected = torch.load(expected_file) - except IOError as e: - if e.errno != errno.ENOENT: - raise - elif not ACCEPT: - raise RuntimeError( - ("I got this output for {}{}:\n\n{}\n\n" - "No expect file exists; to accept the current output, run:\n" - "python {} {} --accept").format(munged_id, subname_output, output, __main__.__file__, munged_id)) + if not ACCEPT and not os.path.exists(expected_file): + raise RuntimeError( + ("No expect file exists for {}{}; to accept the current output, run:\n" + "python {} {} --accept").format(munged_id, subname_output, __main__.__file__, munged_id)) + + return expected_file + + def assertExpected(self, output, subname=None, prec=None, strip_suffix=None): + r""" + Test that a python value matches the recorded contents of a file + derived from the name of this test and subname. The value must be + pickable with `torch.save`. This file + is placed in the 'expect' directory in the same directory + as the test script. You can automatically update the recorded test + output using --accept. + + If you call this multiple times in a single function, you must + give a unique subname each time. + + strip_suffix allows different tests that expect similar numerics, e.g. + "test_xyz_cuda" and "test_xyz_cpu", to use the same pickled data. + test_xyz_cuda would pass strip_suffix="_cuda", test_xyz_cpu would pass + strip_suffix="_cpu", and they would both use a data file name based on + "test_xyz". + """ + expected_file = self._get_expected_file(subname, strip_suffix) if ACCEPT: - print("Accepting updated output for {}{}:\n\n{}".format(munged_id, subname_output, output)) + print("Accepting updated output for {}:\n\n{}".format(os.path.basename(expected_file), output)) torch.save(output, expected_file) MAX_PICKLE_SIZE = 50 * 1000 # 50 KB binary_size = os.path.getsize(expected_file) self.assertTrue(binary_size <= MAX_PICKLE_SIZE) else: + expected = torch.load(expected_file) self.assertEqual(output, expected, prec=prec) def assertEqual(self, x, y, prec=None, message='', allow_inf=False): From ecec6c2c8ce3dc60acb7bb72ef244365c2aa6050 Mon Sep 17 00:00:00 2001 From: Vasilis Vryniotis Date: Thu, 5 Nov 2020 14:02:10 +0000 Subject: [PATCH 03/10] Unflatten expected values. --- ...er.test_fasterrcnn_resnet50_fpn_expect.pkl | Bin 3326 -> 4109 bytes ....test_keypointrcnn_resnet50_fpn_expect.pkl | Bin 30725 -> 31841 bytes ...ter.test_retinanet_resnet50_fpn_expect.pkl | Bin 1357 -> 1357 bytes test/test_models.py | 17 +++++++---------- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/test/expect/ModelTester.test_fasterrcnn_resnet50_fpn_expect.pkl b/test/expect/ModelTester.test_fasterrcnn_resnet50_fpn_expect.pkl index 3e4fc8ec64157f8ef6fc6e23d88b074217a4b10a..d7ec101a64b3e25261a00bdfb7f4dde8360c8376 100644 GIT binary patch literal 4109 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 N6C*FtGynbEe****v9ACC literal 30725 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 Ip|8yC|9ZFpI{*Lx diff --git a/test/expect/ModelTester.test_retinanet_resnet50_fpn_expect.pkl b/test/expect/ModelTester.test_retinanet_resnet50_fpn_expect.pkl index 548b0a22e1c1c46f1b9fc4d3a4b99a2d5ad542c0..869b3647782abd9f22103bfdd2399ee710c2c3d0 100644 GIT binary patch delta 306 zcmX@hb(U+wG9F_iBV!Xw3sVzQbF+z?Qek`xa|;WL$;ynuPytILV?zUz$xVz}ESYv% z<&!rsnh79lb#vlknEZ_?MMZ{zjUllpIU}3Z;b2`{7lP@r9DL61Oz)ivCmdR2qS_*S;DuViX9g7yD#^jqUB>>&+P|yGX delta 308 zcmX@hb(U+wG9Du%b7MnG6AME_Q=^HSQbBwp6C-mAGgCvO$;ynuFa>6oKn0VV7`0gL z?0iPFxI8P%ycU$wvTcE?AqJlN!V1hfMO5KQOURVs=uIVUS};EK1JE zEKAi-Ni0d!H#9Loc88mj6iB_)B&H~Feg`R!Hz$6E$%V{@5SJ`twwkQP uA~pFJvk0o=Q&_YVWSAJ>y3uTcc<2JNmck0$ion4#c^!)uqr>EzEF}PjidE(S diff --git a/test/test_models.py b/test/test_models.py index e27021c4337..ed53a2bcd54 100644 --- a/test/test_models.py +++ b/test/test_models.py @@ -147,10 +147,10 @@ def _test_segmentation_model(self, name, dev): def _test_detection_model(self, name, dev): set_rng_seed(0) kwargs = {} - if "retinanet" in name: + if "retinanet" in name: # TODO: consider removing kwargs["score_thresh"] = 0.013 model = models.detection.__dict__[name](num_classes=50, pretrained_backbone=False, **kwargs) - if "keypointrcnn" in name or "retinanet" in name: + if "keypointrcnn" in name or "retinanet" in name: # TODO: consider removing overwrite_eps(model, 0.0) model.eval().to(device=dev) input_shape = (3, 300, 300) @@ -164,14 +164,13 @@ def check_out(out): self.assertEqual(len(out), 1) def subsample_tensor(tensor): - num_elems = tensor.numel() + num_elems = tensor.size(0) num_samples = 20 if num_elems <= num_samples: return tensor - flat_tensor = tensor.flatten() ith_index = num_elems // num_samples - return flat_tensor[ith_index - 1::ith_index] + return tensor[ith_index - 1::ith_index] def compute_mean_std(tensor): # can't compute mean of integral tensor @@ -180,14 +179,15 @@ def compute_mean_std(tensor): std = torch.std(tensor) return {"mean": mean, "std": std} - if name == "maskrcnn_resnet50_fpn": + if name == "maskrcnn_resnet50_fpn": # TODO: consider removing # maskrcnn_resnet_50_fpn numerically unstable across platforms, so for now # compare results with mean and std test_value = map_nested_tensor_object(out, tensor_map_fn=compute_mean_std) # mean values are small, use large prec self.assertExpected(test_value, prec=.01, strip_suffix="_" + dev) else: - self.assertExpected(map_nested_tensor_object(out, tensor_map_fn=subsample_tensor), + test_sample = map_nested_tensor_object(out, tensor_map_fn=subsample_tensor) + self.assertExpected(test_sample, prec=0.01, strip_suffix="_" + dev) @@ -200,9 +200,6 @@ def compute_mean_std(tensor): self.assertEqual(scripted_out[0]["scores"], out[0]["scores"]) # labels currently float in script: need to investigate (though same result) self.assertEqual(scripted_out[0]["labels"].to(dtype=torch.long), out[0]["labels"]) - self.assertTrue("boxes" in out[0]) - self.assertTrue("scores" in out[0]) - self.assertTrue("labels" in out[0]) # don't check script because we are compiling it here: # TODO: refactor tests # self.check_script(model, name) From f2ac3215e2a442dff93cd5b959ecd9e59482766e Mon Sep 17 00:00:00 2001 From: Vasilis Vryniotis Date: Thu, 5 Nov 2020 14:37:52 +0000 Subject: [PATCH 04/10] Assert for duplicate scores if primary check fails. --- test/test_models.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/test/test_models.py b/test/test_models.py index ed53a2bcd54..1aa116d2169 100644 --- a/test/test_models.py +++ b/test/test_models.py @@ -187,9 +187,26 @@ def compute_mean_std(tensor): self.assertExpected(test_value, prec=.01, strip_suffix="_" + dev) else: test_sample = map_nested_tensor_object(out, tensor_map_fn=subsample_tensor) - self.assertExpected(test_sample, - prec=0.01, - strip_suffix="_" + dev) + prec = 0.01 + strip_suffix = "_" + dev + try: + # We first try to assert the entire output if possible. This is not + # only the best way to assert results but also handles the cases + # where we need to create a new expected result. + self.assertExpected(test_sample, prec=prec,strip_suffix=strip_suffix) + except AssertionError: + # Unfortunately detection models are flaky due to the unstable sort + # in NMS. If matching across all outputs fails, use the same approach + # as in NMSTester.test_nms_cuda to see if this is caused by duplicate + # scores. + expected_file = self._get_expected_file(strip_suffix=strip_suffix) + expected = torch.load(expected_file) + self.assertEqual(test_sample[0]["scores"], expected[0]["scores"], prec=prec) + + # Note: Fmassa proposed turning off NMS by adapting the threshold + # and then using the Hungarian algorithm as in DETR to find the + # best match between output and expected boxes and eliminate some + # of the flakiness. Worth exploring. check_out(out) From 7ae01df15cdeffe7d6d31da823ff325ba57b1be9 Mon Sep 17 00:00:00 2001 From: Vasilis Vryniotis Date: Thu, 5 Nov 2020 15:39:40 +0000 Subject: [PATCH 05/10] Remove custom exceptions for algorithms and add a compact function for shrinking large ouputs. --- test/common_utils.py | 10 +-- ...er.test_fasterrcnn_resnet50_fpn_expect.pkl | Bin 4109 -> 4109 bytes ....test_keypointrcnn_resnet50_fpn_expect.pkl | Bin 31841 -> 11755 bytes ...ster.test_maskrcnn_resnet50_fpn_expect.pkl | Bin 1005 -> 4705 bytes ...ter.test_retinanet_resnet50_fpn_expect.pkl | Bin 1357 -> 9677 bytes test/test_models.py | 67 +++++++++--------- 6 files changed, 39 insertions(+), 38 deletions(-) diff --git a/test/common_utils.py b/test/common_utils.py index e5713dc0832..a1ecee24f20 100644 --- a/test/common_utils.py +++ b/test/common_utils.py @@ -113,8 +113,8 @@ def remove_prefix_suffix(text, prefix, suffix): if not ACCEPT and not os.path.exists(expected_file): raise RuntimeError( - ("No expect file exists for {}{}; to accept the current output, run:\n" - "python {} {} --accept").format(munged_id, subname_output, __main__.__file__, munged_id)) + ("No expect file exists for {}; to accept the current output, run:\n" + "python {} {} --accept").format(os.path.basename(expected_file), __main__.__file__, munged_id)) return expected_file @@ -139,11 +139,13 @@ def assertExpected(self, output, subname=None, prec=None, strip_suffix=None): expected_file = self._get_expected_file(subname, strip_suffix) if ACCEPT: - print("Accepting updated output for {}:\n\n{}".format(os.path.basename(expected_file), output)) + filename = {os.path.basename(expected_file)} + print("Accepting updated output for {}:\n\n{}".format(filename, output)) torch.save(output, expected_file) MAX_PICKLE_SIZE = 50 * 1000 # 50 KB binary_size = os.path.getsize(expected_file) - self.assertTrue(binary_size <= MAX_PICKLE_SIZE) + if binary_size > MAX_PICKLE_SIZE: + raise RuntimeError("The output for {}, is larger than 50kb".format(filename)) else: expected = torch.load(expected_file) self.assertEqual(output, expected, prec=prec) diff --git a/test/expect/ModelTester.test_fasterrcnn_resnet50_fpn_expect.pkl b/test/expect/ModelTester.test_fasterrcnn_resnet50_fpn_expect.pkl index d7ec101a64b3e25261a00bdfb7f4dde8360c8376..878b9f5d43182eb03c96f63087095f1796b063aa 100644 GIT binary patch delta 310 zcmeBG=vA1ojK|Ex(A3hv)WpEj%wXcCN*LeR00<_VGde&8Oe`%e%`7H2GitG%?M&C3 zyphpN0HPHlz0)|FupV@NDY&d4lF)lW$* zNz^wqF+jH7%}IzM3I;ZRXDntD=Vx$+Ybi@DD$dN$b91r>nW;b7fX@ixmNY)A$*=gN uChy`CL3OPPzm~!RW(K$kXqH0!IDt<~!GIm7B5=S=&g0i&yfAqte+dAE2UL^* delta 299 zcmeBG=vA1ojK{>>+``b@z|hRt%wpoEN*LeF(!$hivN@vzOu*F8*u-RVGou#Ek>igy zPTt69CV;Hf&54s?b2)o4o3adp8AD=GazH=!)Gs5mn}&&^4mVe&&}`Nh($ diff --git a/test/expect/ModelTester.test_keypointrcnn_resnet50_fpn_expect.pkl b/test/expect/ModelTester.test_keypointrcnn_resnet50_fpn_expect.pkl index c67b194677feb0c3c2eb161c7ac8ab5a65cad430..18e14836238173c32fc75a906756dbf407728957 100644 GIT binary patch literal 11755 zcmeHtcTiSI_V!CgM6!V7BvFtY4A=AAMwFl+DguhA2#5iE0kbF>1;hk8X2&q*oU@LY z6~%z4D3SybNg@a;d@nPzyUy(FR_*uqudBLl-CNyHpL2v(NB_ss`Sy{oqH6?+H zU~+8Ow5Yk^{ijZjpKLRG#!L@hK@j|>mM9(~6eI}6%mbxF2vcI_hsO!U!{TE^6Kz80 z#7E7HlM9UvpE4(E=G4&m@aVXh*wDH5azY7n^FSHVggDX2$&ukg$=|2QdCZKN96$Q^ zk8(n(Kt<6QJ4ai4M>iK+S4SsD7kgWwbfARjYuM~LLYWb(#Nvgrqr8>8)x0Isg*`+M zv2>x_vaqn2nKQ$~;-g}smd>)@uyo^v zdj3NFz#bw}XM``99TOEDA15?O5E_~XisUAk6+SsyX!IxI-DBoVnHm01@{RvRzMG4k zors6sf~%IwEP{w>IZ;+ z@j`2Vq0O8?r5}k6{euPl|BVGsc1{kCuC5ODZq7p6X)+^rNyiKAMtQr7gs7Y@wD%s{ zElY>riF1q>I{6Eo=S;To^OljFwP&oJP+TDB?tcGKfpr8@e^TK7zbVqc`0l}r34)g{ z+{4vb|HAd@^D{U3&1TMi=_bxTeoCpc9tpF!I*TlBx_%aC@II5%tj^>{ z2WN7_jx6T_@|JVH@yofy{>!fX-t^AkqUzJR7w^+Kg*)k-RYp2D$ugZg)tSbr9Zusk7pHNR!ZdF8lr*k(VjAZe zlE$5XlFE6UOy%Q zyA!$d8xy&`%Mv+-!HL{r%|uRCDUmA(Tgn|8wUkq|S<2N~EagaTDc5K767IIg67Chh zglp_d;GQQZaI0JrxG1LtPN`%u*Dc<$$^HFSi3tSV{lAIV^goFAcN6vCjsD`R{^Yp+ zc+n8)YIpm;=l}8H|McMB?V#Hp&zoO^foRX|?*Gjm)&IsG|Fv&>@G5^}j~h~wS?Q82 zw#zM(HLTBNl}9*U>(OA=S(eQU1nbzFid6PVDTFx607)~wt1{V%Yo%TI?pS`cr$^vEi2EQ#8g94`R$YAnS!rna9!}hOj5+d|C0%d90iMc^h2W z(!IUe?5m^L)#WqT+_t&QPcEK4zLLa3)6-ad;#4NbWwP6Q;@MB<^O)SZNY>ft!GTTohfx5_4Z-WlarXEr5r0Z&tM;hTC$6$ zAM)zOnQZpKM&99dE}Pxy!*3l{z_(1zmeWrZCM8C1yT%I16+(X9=k* z*orzoCVk3-zx6GO`L9)AYMluzAj_Ziv&m*AcUH3vlJcxihYC}>Y{(3pX0ZD3NBqI* z$1r-F1RGHFmgh!A@B?x(nHRT~w-(7~P2U7oicS27p4M#T>m|%&QWiU? zpTQEO^4QV2Gg#_cKh|2F^qc+|IZk3r#4U!qbMjuXN;XiA!ts~soa92CVy0L?+vk(}OjR%42C`oY`x&m;9Q= zzHI1uPgb&JHv4ozo*6GnWfA+MnAM)CtbCmTQ_x9bM>ou7a?J`XqV^MC(_qT_?HbQI zM}URtzvC+-MzC6uY;P^w$DbPoMw^O%vseFYWfo-|${XG@XA|`_Sno$xZ20SKSRxu@ zT35nbzK>=-7G$!KrisirIhPe{O=k-fGTHC}3)zRxwd}UIJ$pK~iT^cbI4jH_&jO8J z@oNv><6q2^V5Y-{GOJ^;yek{V;yhOKgQUZl&*We>%{`0N?Vrx>HRdv}RnEMpyaAiW zXY(VXqu3I&P(H;?os|`2@OL)bvsTXnJ|N{QUuPj;B||5$6E}M>iqB$uf9}Ihq~)>o zR$vXY*P^K~kX2_?^8;uk-|3vm`d`oBw_C4eXO_sZfYWv?(aeaYuS#bxkIrDb3~oTr zJe3`{f6O-=?ZI@?e3@H+?ZCcC&rlTB;6&aYh8pM4oLoF(R1u>F^A^QVs!OFlc8{kA_fZMZ?AV6MCW zxBbcaZ}%rrO!QkwBpu=tEHm}GD6MtL3W%1mS|IhV*h{gW5^^2-ia1lB;Qp$Il)UX3 zbso4(QO2$~^4yoouGG*oZ*6=!Zh*msJ~Vv8awO=2w(m{ZC!hAXp*saKDiB-!s5dg!2z#6v1r7w3rx z)j{|W`;-RveNCS?+@fVtE>P1lf})6`p`N* zlRo!Z2p8+G)S{?|!=vtynTQYbuQ-ANeIVImD4gjIMU_<1)6BEf;p7afen}+0{R^4q zs$kM86O26&NPR{B(!cx*S=-B@BCd+!uKQw(Y9G{%kcZy_b?DcuBkOsq$s$33*afnP zd}l_Jj?~Zr*-}ams-)vTnUF;@(3JX-PH!us5wEvU^&S-{I$EK)AprS5yFl^m6O#D+ zk+!JilVOP;3R45ftw&^2xtPb*DOr$5Hlkr%ii!Qr~VRm&38AXhOAXpuWW5*)J zZ#b^MdPoabH_(K{Cp74z8~l4GQFuiM)x>F_-~N7xG!Gz~h8!&1+(J7;dSdJG&opr8 zSeQ&xLsg;)Hhnk8cke}%Y`mYMzCWb-zgXhak^U64w3$>h1sIuXf<Cq|^~9C!O%DESq+i?5Aj9EluwnhG)7Q9p2eQ zAHB4&FGUZ6jw$qf$U-a@mqtK~2G*#)q4$e=;muArXt|Dre9R#DTE8H(_DV|hyG!DV zgHf?4fgYUrKqtm1VC$QH2%a#Ntk%Y*V@($`*;txpc;hpR#1YaD2&{=1x zD7=hx^KZ~s-V;rpGpXRGPn0-F1&O=+;X>_Ls**`V@xTspo!3i5PXh&Hhv0mFJ-G5V z(BC7HLvlLB_u4~gf$JX@geNBIkO_xnc|PmzI<@xQfE>31FC0MUyJ@Y4*@@I6p&x z+YevUHMvJ*`dJsr9=h>#|Evhq_wnwZbbILyh&Ebk+6W;6$|k3*)%0Dm*i7llC+Wy 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 QrNX=C$O^j0|33Er0lpe_+yDRo literal 31841 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 N6C*FtGynbEe****v9ACC diff --git a/test/expect/ModelTester.test_maskrcnn_resnet50_fpn_expect.pkl b/test/expect/ModelTester.test_maskrcnn_resnet50_fpn_expect.pkl index c05342100a36b9f4973c1e154edcd379d94e8e9b..f2406f8cabb24e48b842a760e1863e9714873449 100644 GIT binary patch literal 4705 zcmeHLX;f547JfiOLxV~X4I-PYjS51uq){k%_cjPLVuL|(w}lo6Nb~3hG!7XQ0YR2# z7Zenus1sB)I#Ds0h#EyDYKYMok4i?zeZjbI^BP=$sF}>4`7u-H)TvXi>VEfox9)pi zRY}BJ9E#G_rG8foDI-dn92FavDjO9oRZ5+c;u8X(KQ*OS$@yN zq+|w%Gaq)rE28AdY(z}D;bVKe&`T^AHvu!G8_V=1)=)K;*^(|Sb0uRD&RBK@cdk?s zuVAdwnPL1$cFm}{GHD`X-HW(Lo-#W@_L{oQ8|nftccD<|?j~?yY*}|~*zCf@l%r#} z8+#?=5YF(s0;^C)GmbC$_6G2B5qNy$?#>MF1{l!;V5E|93TK>CQl!ojF;_Qx!lNII zG$~45CGX5IGs?DChK=g8(g9%AC);|ZURTF--3RpU`VtVIr|I42eu4wp`t*|rgJG?m zKiv>f46ft*(-Z0=!1OCZX9aJ96-zDYThr`O-#UW+i+&*fg?G`emVx-d#G6*x3eaP#HQnOlkGG>I(Jwp~Vt(~qKLg^3%XFORO-loD^Kxz6xXBZv zO#9)O7GGRAwS*?^)8CZUPA>2sF#p}r`NdKk)?KKmzV%jtKw3tEZHVb6e zk+S&0AMaWv(kJNY7$h2x9o2r=WD|~a+A^^7w-$KdlY=&i$6;#8QarUX3HQ1@1EbXn z{6yaxi?}-I5$c9*+5OP;kT+hjK;6=h3C#E`wBVHht`l3)bYWq8q3Pth>7y zgys48lY0p?PEp}a34<#)oP}zk5`Vd1jwVfcuy;}(rhHrlqRv8`UtdqVbhzW?hTXKG z!))AD;R~@&!|<_n2n>x8V^V|%jQutTuT)Hc3jciEl$V6bH?BZsodO?b8e>?}4#>Na zgPjiFK}%LXYAopo?PGi(=%@)ST3OG&$8HF5%|VMrM_}67r6_ojLl+%I6mn~6UCu(> zF=!k8G%+9SjoWA=yF>6`WIptlkHQ!GRiK+W1wV-i0&kTg?z%PsqILvg^TrNP$24cE zkd18x-W)WC9-ZZgLcJo|_GA!_tq4Xd0}(zm8;3LM7UEx9DfIUkf}7H{(73@1JE~;3 zX=*-w#Ht)Q4srN1KMQVslZQv_${=ZA5jHGHzyi4jo`{sAVfiquZ1lt_P9j{%_~5j! zL$LkmDBPlBk6IT5XnJ)l8l*YF&Z0bQT@eD2x<&Yq=5_I#d+Z|HR$z)_GrdZX3(ajm z(i4LY!f4Y9x~XI&8cp0xPyZ|&zt6OX=kd+B|!t78lG&pRDcW(aTm(20N+AJeF;Peb!e=Hj2 zpLzne@p3RM9*U=qyWy$RBQblPC-RL$vCb+1bYA{|KtPejNXoQ*}AHu!E*CDi81E~T#Y~9MiHRpp-)RK;zlmz6AU4(w8Qt)pn zE1==52+J~7LudICTx%UgXM~-DqyxEhNTwkgdHbTyJqP5w0-9e6#pY-eoc&!W8vZmC zGi_9u^|3zYsmyW1?*6!wqOrqGga=O^gijS?@xB=kFMTx{lkNC8v(X2C{#t@NbW$+* z^c9$RBMr6XM%Z>i1g$fh;Il*t_#NTkj_b~F_`6{s|J(~Yxt~MSQ(dgK+XY8N23WdN zA160_A&AkNeQ<4c4%&l1KK&{m&mQ99V{bEj zDA30CkMEh+H~-i?_u%ugG0fYARnZHF{4MrB+FdfkTel8b`&60>Vb0&0fZz|+>i7Cp zf6aFLt#PToY90&roKI12#MJeDJe=Roq}OV_}^+tYh5i#)2JoeR@RU!1~tTZ z-U?E5dpQ|jv7ChMt0smi)ubY(nw*eSlL6bSi07s%GNZbR94f3L+<+>gY+Xjow^WiB zMU`a!hn3`nb|vYktRU^%%gMzRGODJ8$mW-jw7Df@ZEOh{ z;ax(ad2IiAF^POwOj0ivllra2#CT0Ham^?u&9TL#!?&2^YZsHi$0{=FHx=>dRFVD7 zDq=HBMQ%B%$XH_)@wr$;9yb<|iR+4pSy2(8tcu9e=Y^!^Rv{tB3W>9{keoSIK;qg8 zNYjx5QainX_)RV#>O7Q^yZ=;aP?Wm9FAweCl80}$$N^yeZ{(qkTCCafzuu1Q4#PX+ z@JHi)f-yf!9+J*rXaDiLd_o7Z;&JVaP6mB&{%1bwZ0YO7f<%h{}#p4NR&e|?d9 zs$*{?L%p{my;kPFNIi9~H`20qA-&YrzDPa)l)aHmcyHtMMkV_q^<3lLNLB{#L1M2W z`XcpQOZD~1o6^X3Uq$?7hDgLZIPVX&Ik|u0S z5EEUvGbSdkT(Wn`pWx1&iP6ZOL=zXDNtsd|?&2or>-~OTPtIA(ZiwEWcej3zKK?j2 zTw2S{{>5bAj%Fvkx# z6zW-$_x#o(6zlnr^m#7l9yMvJ=~^x5T@Nu~0WuL}B_cHZr+XmAn;_WS4{WDohTQd- zXa=+qx?a=dw8i|uTv0?QND?VBd}b|DD8}!_89!`z^nR?0&`bJjRZTYJYE74`iebP3 zlCzgX5H~WJJN#a~XMB9!#_l|7b8L=@cY`JkXmiH3xd;ar;L!7V=;QOyPx4C?fBdk6 zxlYkZk+qtEa2RmXPzSw7(0dfU$3jx@tOoTM3`THVa)f^&x~A4-MXo3^oJd1nv>_)E zGK7#}XTNBpV(1E->T;b%*BNx34T-R1u_p}9MKIExT-KGUs#aAEM$?S-cJg^-TtLRf zeUnvm8gQx0bs1e_=(>VUGusbvu2KZ!`$ShX-7w0E0av>q*AOy+kjej}byd@9wTh}4 zQ0j6`p-VNycp;_4Lnx+{cq39f z(%C**%JjtN+smyl#qV!#bm~_++5R!Onbcob2OrIApOgC2_M0hn^H);OIb$T6T}kS# e9qHlg4>zYfyse#~;gLxzsfVoV6Sv<#nEngfR}9$z diff --git a/test/expect/ModelTester.test_retinanet_resnet50_fpn_expect.pkl b/test/expect/ModelTester.test_retinanet_resnet50_fpn_expect.pkl index 869b3647782abd9f22103bfdd2399ee710c2c3d0..1bffc79fd074e2834f4faf987c0db38f72f7670c 100644 GIT binary patch literal 9677 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 RYkYc%=QLAkjQ=C{e*l0Nj+Foa literal 1357 zcma)6&ui0g6#u5_FXL>xsdLV5yJ@Z3b#1qGP-IIbm#<*#EYzWtG!0EKHv1-N6-3cP z=XMnY55v<=;>nA<`v<6a76hS}9d{P}ev@=2kqjR^!Z&%J&-;AedwD#h!vMtN;2%qY z2_WdAtn{V%wqOdm%?B#SCcuWro`>!u@Dx#*Mg%jow8xTxLZYc*V6NFS71dyxy430^ zYP)GlT|?8G{Q`sNOr{aT00Tz~9SMbP2*atGV6NLQ85C(Gam+#~Un~@grIqqxX>oZ8 zMH@7JD{l5s433#7ej5Tv!|)b50mG2mLd>=(YN{%UrlNHX=9b=;bg6wq5lsf2yj(*V zbE<|CjVQ@4YC2Y&l(8T=Ec+9dm&@fcO35)un`qohG(Z!O8lcnLGT}O7qO&zLX>qAS zOHvJV&gOD1bW`hgj_xz%z0XRaxR5WQ^EUmoLw|wLr*|y+857Oc&|FW*@h}!wu4f;~ z6ad8ez`mtH!qc~TU;Q|iarJQW%lEbRbe4Uyv(N4&hwL!+bM5mXQ{81gvd^BZSMz&1 zn|e58U(dW}U%sQNM8}U02cPn|c*Kv>5e?E|m6c;dSVyQ-uZ+|6O7r)f3gLdSwEAld z^AbOfI~%}l*OX%~y6)&1Sl{G;j=l7s z={JfD$@KMYr%o~x=OJZ@82yv(uBY&KulfH_Kib`^v_D%Kmo zWOdrl<3zD?E%wuR0O4^tGc{vbczio_BF!h`l0f b1{=naRRs>586lr}7$NHeV 30: + return compute_mean_std(tensor) + else: + return subsample_tensor(tensor) + def subsample_tensor(tensor): num_elems = tensor.size(0) num_samples = 20 @@ -179,34 +185,27 @@ def compute_mean_std(tensor): std = torch.std(tensor) return {"mean": mean, "std": std} - if name == "maskrcnn_resnet50_fpn": # TODO: consider removing - # maskrcnn_resnet_50_fpn numerically unstable across platforms, so for now - # compare results with mean and std - test_value = map_nested_tensor_object(out, tensor_map_fn=compute_mean_std) - # mean values are small, use large prec - self.assertExpected(test_value, prec=.01, strip_suffix="_" + dev) - else: - test_sample = map_nested_tensor_object(out, tensor_map_fn=subsample_tensor) - prec = 0.01 - strip_suffix = "_" + dev - try: - # We first try to assert the entire output if possible. This is not - # only the best way to assert results but also handles the cases - # where we need to create a new expected result. - self.assertExpected(test_sample, prec=prec,strip_suffix=strip_suffix) - except AssertionError: - # Unfortunately detection models are flaky due to the unstable sort - # in NMS. If matching across all outputs fails, use the same approach - # as in NMSTester.test_nms_cuda to see if this is caused by duplicate - # scores. - expected_file = self._get_expected_file(strip_suffix=strip_suffix) - expected = torch.load(expected_file) - self.assertEqual(test_sample[0]["scores"], expected[0]["scores"], prec=prec) - - # Note: Fmassa proposed turning off NMS by adapting the threshold - # and then using the Hungarian algorithm as in DETR to find the - # best match between output and expected boxes and eliminate some - # of the flakiness. Worth exploring. + output = map_nested_tensor_object(out, tensor_map_fn=compact) + prec = 0.01 + strip_suffix = "_" + dev + try: + # We first try to assert the entire output if possible. This is not + # only the best way to assert results but also handles the cases + # where we need to create a new expected result. + self.assertExpected(output, prec=prec, strip_suffix=strip_suffix) + except AssertionError: + # Unfortunately detection models are flaky due to the unstable sort + # in NMS. If matching across all outputs fails, use the same approach + # as in NMSTester.test_nms_cuda to see if this is caused by duplicate + # scores. + expected_file = self._get_expected_file(strip_suffix=strip_suffix) + expected = torch.load(expected_file) + self.assertEqual(output[0]["scores"], expected[0]["scores"], prec=prec) + + # Note: Fmassa proposed turning off NMS by adapting the threshold + # and then using the Hungarian algorithm as in DETR to find the + # best match between output and expected boxes and eliminate some + # of the flakiness. Worth exploring. check_out(out) From 83b2682ebedaa8265cf135d8614ab2016fd3e01d Mon Sep 17 00:00:00 2001 From: Vasilis Vryniotis Date: Thu, 5 Nov 2020 15:43:00 +0000 Subject: [PATCH 06/10] Removing unused variables. --- test/common_utils.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/common_utils.py b/test/common_utils.py index a1ecee24f20..9f0d6a2dcf7 100644 --- a/test/common_utils.py +++ b/test/common_utils.py @@ -105,10 +105,8 @@ def remove_prefix_suffix(text, prefix, suffix): "expect", munged_id) - subname_output = "" if subname: expected_file += "_" + subname - subname_output = " ({})".format(subname) expected_file += "_expect.pkl" if not ACCEPT and not os.path.exists(expected_file): From 4b59173d225a03fe0295593f3d1e18ad13903d6d Mon Sep 17 00:00:00 2001 From: Vasilis Vryniotis Date: Thu, 5 Nov 2020 16:31:39 +0000 Subject: [PATCH 07/10] Add warning and comments. --- test/test_models.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/test_models.py b/test/test_models.py index 5192c6c3db0..457ae1bbcab 100644 --- a/test/test_models.py +++ b/test/test_models.py @@ -9,6 +9,7 @@ from torchvision import models import unittest import random +import warnings def set_rng_seed(seed): @@ -148,6 +149,7 @@ def _test_detection_model(self, name, dev): set_rng_seed(0) kwargs = {} if "retinanet" in name: + # Reduce the default threshold to ensure the returned boxes are not empty. kwargs["score_thresh"] = 0.01 model = models.detection.__dict__[name](num_classes=50, pretrained_backbone=False, **kwargs) model.eval().to(device=dev) @@ -206,6 +208,12 @@ def compute_mean_std(tensor): # and then using the Hungarian algorithm as in DETR to find the # best match between output and expected boxes and eliminate some # of the flakiness. Worth exploring. + warnings.warn( + "The complete output in {} did not match exactly. " + "This is likely due to test flakiness, but you may " + "want to check manually if you introduce significant " + "changes to the codebase.".format(self._testMethodName), + RuntimeWarning) check_out(out) From f908aef992d9887b90fa5689e1b8e7bbd91f50d7 Mon Sep 17 00:00:00 2001 From: Vasilis Vryniotis Date: Thu, 5 Nov 2020 17:10:46 +0000 Subject: [PATCH 08/10] Re-enable all autocast unit-test for detection and marking the tests as skipped in partial validation. --- test/test_models.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/test/test_models.py b/test/test_models.py index 457ae1bbcab..c68a7fdd954 100644 --- a/test/test_models.py +++ b/test/test_models.py @@ -89,14 +89,10 @@ def get_available_video_models(): # trying autocast. However, they still try an autocasted forward pass, so they still ensure # autocast coverage suffices to prevent dtype errors in each model. autocast_flaky_numerics = ( - "fasterrcnn_resnet50_fpn", "inception_v3", - "keypointrcnn_resnet50_fpn", - "maskrcnn_resnet50_fpn", "resnet101", "resnet152", "wide_resnet101_2", - "retinanet_resnet50_fpn", ) @@ -208,12 +204,12 @@ def compute_mean_std(tensor): # and then using the Hungarian algorithm as in DETR to find the # best match between output and expected boxes and eliminate some # of the flakiness. Worth exploring. - warnings.warn( - "The complete output in {} did not match exactly. " - "This is likely due to test flakiness, but you may " - "want to check manually if you introduce significant " - "changes to the codebase.".format(self._testMethodName), - RuntimeWarning) + msg = "The complete output in {} did not match exactly. " \ + "This is likely due to test flakiness, but you may " \ + "want to check manually if you introduce significant " \ + "changes to the codebase.".format(self._testMethodName) + warnings.warn(msg, RuntimeWarning) + raise unittest.SkipTest(msg) check_out(out) From 3ae8f0922cc92b11744cb0a1f32cef035238de6d Mon Sep 17 00:00:00 2001 From: Vasilis Vryniotis Date: Thu, 5 Nov 2020 17:21:18 +0000 Subject: [PATCH 09/10] Move test skip at the end. --- test/test_models.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/test/test_models.py b/test/test_models.py index c68a7fdd954..19e9ae3abcd 100644 --- a/test/test_models.py +++ b/test/test_models.py @@ -204,14 +204,11 @@ def compute_mean_std(tensor): # and then using the Hungarian algorithm as in DETR to find the # best match between output and expected boxes and eliminate some # of the flakiness. Worth exploring. - msg = "The complete output in {} did not match exactly. " \ - "This is likely due to test flakiness, but you may " \ - "want to check manually if you introduce significant " \ - "changes to the codebase.".format(self._testMethodName) - warnings.warn(msg, RuntimeWarning) - raise unittest.SkipTest(msg) + return False # Partial validation performed - check_out(out) + return True # Full validation performed + + full_validation = check_out(out) scripted_model = torch.jit.script(model) scripted_model.eval() @@ -230,7 +227,15 @@ def compute_mean_std(tensor): out = model(model_input) # See autocast_flaky_numerics comment at top of file. if name not in autocast_flaky_numerics: - check_out(out) + full_validation &= check_out(out) + + if not full_validation: + msg = "The complete output in {} did not match exactly. " \ + "This is likely due to test flakiness, but you may " \ + "want to check manually if you introduce significant " \ + "changes to the codebase.".format(self._testMethodName) + warnings.warn(msg, RuntimeWarning) + raise unittest.SkipTest(msg) def _test_detection_model_validation(self, name): set_rng_seed(0) From 496cf21e7009ce92e5fcc45d43ca6bad4c0f119f Mon Sep 17 00:00:00 2001 From: Vasilis Vryniotis Date: Thu, 5 Nov 2020 18:32:50 +0000 Subject: [PATCH 10/10] Changing the warning message. --- test/test_models.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_models.py b/test/test_models.py index 19e9ae3abcd..7a8e1d83b6e 100644 --- a/test/test_models.py +++ b/test/test_models.py @@ -230,10 +230,10 @@ def compute_mean_std(tensor): full_validation &= check_out(out) if not full_validation: - msg = "The complete output in {} did not match exactly. " \ - "This is likely due to test flakiness, but you may " \ - "want to check manually if you introduce significant " \ - "changes to the codebase.".format(self._testMethodName) + msg = "The output of {} could only be partially validated. " \ + "This is likely due to unit-test flakiness, but you may " \ + "want to do additional manual checks if you made " \ + "significant changes to the codebase.".format(self._testMethodName) warnings.warn(msg, RuntimeWarning) raise unittest.SkipTest(msg)