@@ -202,10 +202,10 @@ def help_generate_np_gives_adversarial_example(self, ord, eps=.5,
202202 ** kwargs ):
203203 x_val , x_adv , delta = self .generate_adversarial_examples_np (ord , eps ,
204204 ** kwargs )
205- self .assertClose ( delta , eps )
205+ self .assertLess ( np . max ( np . abs ( delta - eps )), 1e-3 )
206206 orig_labs = np .argmax (self .sess .run (self .model .get_logits (x_val )), axis = 1 )
207207 new_labs = np .argmax (self .sess .run (self .model .get_logits (x_adv )), axis = 1 )
208- self .assertTrue (np .mean (orig_labs == new_labs ) < 0 .5 )
208+ self .assertLess (np .max ( np . mean (orig_labs == new_labs )), .5 )
209209
210210 def test_invalid_input (self ):
211211 x_val = - np .ones ((2 , 2 ), dtype = 'float32' )
@@ -241,7 +241,7 @@ def test_targeted_generate_np_gives_adversarial_example(self):
241241 except NotImplementedError :
242242 raise SkipTest ()
243243
244- self .assertClose ( delta , 0.5 )
244+ self .assertLessEqual ( np . max ( delta ) , 0.5001 )
245245
246246 new_labs = np .argmax (self .sess .run (self .model .get_logits (x_adv )), axis = 1 )
247247 self .assertTrue (np .mean (random_labs == new_labs ) > 0.7 )
@@ -255,7 +255,7 @@ def test_generate_np_can_be_called_with_different_eps(self):
255255 clip_min = - 5.0 , clip_max = 5.0 )
256256
257257 delta = np .max (np .abs (x_adv - x_val ), axis = 1 )
258- self .assertClose ( delta , eps )
258+ self .assertLessEqual ( np . max ( delta ) , eps + 1e-4 )
259259
260260 def test_generate_np_clip_works_as_expected (self ):
261261 x_val = np .random .rand (100 , 2 )
@@ -455,13 +455,13 @@ def test_attack_strength_np_batched(self):
455455 self .assertLess (np .mean (feed_labs == new_labs ), 0.1 )
456456
457457
458- class TestBasicIterativeMethod (CommonAttackProperties ):
458+ class TestProjectedGradientDescent (CommonAttackProperties ):
459459 def setUp (self ):
460- CommonAttackProperties .setUp (self )
460+ super ( TestProjectedGradientDescent , self ) .setUp ()
461461
462462 self .sess = tf .Session ()
463463 self .model = SimpleModel ()
464- self .attack = BasicIterativeMethod (self .model , sess = self .sess )
464+ self .attack = ProjectedGradientDescent (self .model , sess = self .sess )
465465
466466 def test_generate_np_gives_adversarial_example_linfinity (self ):
467467 self .help_generate_np_gives_adversarial_example (ord = np .infty , eps = .5 ,
@@ -510,61 +510,90 @@ def test_attack_strength(self):
510510
511511 orig_labs = np .argmax (self .sess .run (self .model .get_logits (x_val )), axis = 1 )
512512 new_labs = np .argmax (self .sess .run (self .model .get_logits (x_adv )), axis = 1 )
513- self .assertTrue (np .mean (orig_labs == new_labs ) < 0.1 )
513+ self .assertLess (np .mean (orig_labs == new_labs ), 0.1 )
514+
515+ def test_clip_eta (self ):
516+ x_val = np .random .rand (100 , 2 )
517+ x_val = np .array (x_val , dtype = np .float32 )
518+
519+ x_adv = self .attack .generate_np (x_val , eps = 1.0 , eps_iter = 0.1 ,
520+ nb_iter = 5 )
521+
522+ delta = np .max (np .abs (x_adv - x_val ), axis = 1 )
523+ self .assertLessEqual (np .max (delta ), 1. )
524+
525+ def test_generate_np_gives_clipped_adversarial_examples (self ):
526+ x_val = np .random .rand (100 , 2 )
527+ x_val = np .array (x_val , dtype = np .float32 )
528+
529+ x_adv = self .attack .generate_np (x_val , eps = 1.0 , eps_iter = 0.1 ,
530+ nb_iter = 5 ,
531+ clip_min = - 0.2 , clip_max = 0.3 ,
532+ sanity_checks = False )
533+
534+ self .assertLess (- 0.201 , np .min (x_adv ))
535+ self .assertLess (np .max (x_adv ), .301 )
536+
514537
515538 def test_generate_np_does_not_cache_graph_computation_for_nb_iter (self ):
516539 x_val = np .random .rand (100 , 2 )
517540 x_val = np .array (x_val , dtype = np .float32 )
518541
542+ # Call it once
519543 x_adv = self .attack .generate_np (x_val , eps = 1.0 , ord = np .inf ,
520544 clip_min = - 5.0 , clip_max = 5.0 ,
521545 nb_iter = 10 )
522546
523547 orig_labs = np .argmax (self .sess .run (self .model .get_logits (x_val )), axis = 1 )
524548 new_labs = np .argmax (self .sess .run (self .model .get_logits (x_adv )), axis = 1 )
525- self .assertTrue (np .mean (orig_labs == new_labs ) < 0.1 )
526549
550+ # Call it again
527551 ok = [False ]
528552 old_grads = tf .gradients
529-
530- def fn (* x , ** y ):
531- ok [0 ] = True
532- return old_grads (* x , ** y )
533-
534- tf .gradients = fn
535-
536- x_adv = self .attack .generate_np (x_val , eps = 1.0 , ord = np .inf ,
537- clip_min = - 5.0 , clip_max = 5.0 ,
538- nb_iter = 11 )
539-
553+ try :
554+ def fn (* x , ** y ):
555+ ok [0 ] = True
556+ return old_grads (* x , ** y )
557+
558+ tf .gradients = fn
559+
560+ x_adv = self .attack .generate_np (x_val , eps = 1.0 , ord = np .inf ,
561+ clip_min = - 5.0 , clip_max = 5.0 ,
562+ nb_iter = 11 )
563+ finally :
564+ tf .gradients = old_grads
565+
540566 orig_labs = np .argmax (self .sess .run (self .model .get_logits (x_val )), axis = 1 )
541567 new_labs = np .argmax (self .sess .run (self .model .get_logits (x_adv )), axis = 1 )
542- self .assertTrue (np .mean (orig_labs == new_labs ) < 0.1 )
543568
544- tf .gradients = old_grads
545569
546570 self .assertTrue (ok [0 ])
547571
572+ def test_multiple_initial_random_step (self ):
573+ """
574+ This test generates multiple adversarial examples until an adversarial
575+ example is generated with a different label compared to the original
576+ label. This is the procedure suggested in Madry et al. (2017).
548577
549- class TestMomentumIterativeMethod ( TestBasicIterativeMethod ):
550- def setUp ( self ):
551- super ( TestMomentumIterativeMethod , self ). setUp ( )
578+ This test will fail if an initial random step is not taken (error>0.5).
579+ """
580+ x_val = np . array ( np . random . rand ( 100 , 2 ), dtype = np . float32 )
552581
553- self .sess = tf .Session ()
554- self .model = SimpleModel ()
555- self .attack = MomentumIterativeMethod (self .model , sess = self .sess )
582+ orig_labs = np .argmax (self .sess .run (self .model .get_logits (x_val )), axis = 1 )
583+ new_labs_multi = orig_labs .copy ()
556584
557- def test_generate_np_can_be_called_with_different_decay_factor (self ):
558- x_val = np .random .rand (100 , 2 )
559- x_val = np .array (x_val , dtype = np .float32 )
585+ # Generate multiple adversarial examples
586+ for i in range (10 ):
587+ x_adv = self .attack .generate_np (x_val , eps = .5 , eps_iter = 0.05 ,
588+ clip_min = 0.5 , clip_max = 0.7 ,
589+ nb_iter = 2 , sanity_checks = False )
590+ new_labs = np .argmax (self .sess .run (self .model .get_logits (x_adv )), axis = 1 )
560591
561- for decay_factor in [0.0 , 0.5 , 1.0 ]:
562- x_adv = self .attack .generate_np (x_val , eps = 0.5 , ord = np .inf ,
563- decay_factor = decay_factor ,
564- clip_min = - 5.0 , clip_max = 5.0 )
592+ # Examples for which we have not found adversarial examples
593+ I = (orig_labs == new_labs_multi )
594+ new_labs_multi [I ] = new_labs [I ]
565595
566- delta = np .max (np .abs (x_adv - x_val ), axis = 1 )
567- self .assertClose (delta , 0.5 )
596+ self .assertLess (np .mean (orig_labs == new_labs_multi ), 0.5 )
568597
569598
570599class TestCarliniWagnerL2 (CleverHansTest ):
@@ -926,96 +955,57 @@ def test_generate_np_gives_clipped_adversarial_examples(self):
926955 self .assertTrue (- 0.201 < np .min (x_adv ))
927956 self .assertTrue (np .max (x_adv ) < .301 )
928957
929-
930- class TestMadryEtAl (CleverHansTest ):
958+ class TestMomentumIterativeMethod (TestProjectedGradientDescent ):
931959 def setUp (self ):
932- super (TestMadryEtAl , self ).setUp ()
933-
934- self .sess = tf .Session ()
935- self .model = SimpleModel ()
936- self .attack = MadryEtAl (self .model , sess = self .sess )
937-
938- def test_attack_strength (self ):
939- """
940- If clipping is not done at each iteration (not using clip_min and
941- clip_max), this attack fails by
942- np.mean(orig_labels == new_labels) == .5
943- """
944- x_val = np .random .rand (100 , 2 )
945- x_val = np .array (x_val , dtype = np .float32 )
946-
947- x_adv = self .attack .generate_np (x_val , eps = 1.0 , eps_iter = 0.05 ,
948- clip_min = 0.5 , clip_max = 0.7 ,
949- nb_iter = 5 , sanity_checks = False )
950-
951- orig_labs = np .argmax (self .sess .run (self .model .get_logits (x_val )), axis = 1 )
952- new_labs = np .argmax (self .sess .run (self .model .get_logits (x_adv )), axis = 1 )
953- self .assertLess (np .mean (orig_labs == new_labs ), 0.1 )
954-
955- def test_clip_eta (self ):
956- x_val = np .random .rand (100 , 2 )
957- x_val = np .array (x_val , dtype = np .float32 )
958-
959- x_adv = self .attack .generate_np (x_val , eps = 1.0 , eps_iter = 0.1 ,
960- nb_iter = 5 )
960+ super (TestMomentumIterativeMethod , self ).setUp ()
961961
962- delta = np .max (np .abs (x_adv - x_val ), axis = 1 )
963- self .assertTrue (np .all (delta <= 1. ))
962+ self .attack = MomentumIterativeMethod (self .model , sess = self .sess )
964963
965- def test_generate_np_gives_clipped_adversarial_examples (self ):
964+ def test_generate_np_can_be_called_with_different_decay_factor (self ):
966965 x_val = np .random .rand (100 , 2 )
967966 x_val = np .array (x_val , dtype = np .float32 )
968967
969- x_adv = self . attack . generate_np ( x_val , eps = 1 .0 , eps_iter = 0.1 ,
970- nb_iter = 5 ,
971- clip_min = - 0.2 , clip_max = 0.3 ,
972- sanity_checks = False )
968+ for decay_factor in [ 0 .0 , 0.5 , 1.0 ]:
969+ x_adv = self . attack . generate_np ( x_val , eps = 0.5 , ord = np . inf ,
970+ decay_factor = decay_factor ,
971+ clip_min = - 5.0 , clip_max = 5.0 )
973972
974- self . assertLess ( - 0.201 , np .min (x_adv ) )
975- self .assertLess ( np . max ( x_adv ), .301 )
973+ delta = np . max ( np .abs (x_adv - x_val ), axis = 1 )
974+ self .assertClose ( delta , 0.5 )
976975
977976 def test_multiple_initial_random_step (self ):
978- """
979- This test generates multiple adversarial examples until an adversarial
980- example is generated with a different label compared to the original
981- label. This is the procedure suggested in Madry et al. (2017).
982-
983- This test will fail if an initial random step is not taken (error>0.5).
984- """
985- x_val = np .random .rand (100 , 2 )
986- x_val = np .array (x_val , dtype = np .float32 )
987-
988- orig_labs = np .argmax (self .sess .run (self .model .get_logits (x_val )), axis = 1 )
989- new_labs_multi = orig_labs .copy ()
990-
991- # Generate multiple adversarial examples
992- for i in range (10 ):
993- x_adv = self .attack .generate_np (x_val , eps = .5 , eps_iter = 0.05 ,
994- clip_min = 0.5 , clip_max = 0.7 ,
995- nb_iter = 2 , sanity_checks = False )
996- new_labs = np .argmax (self .sess .run (self .model .get_logits (x_adv )), axis = 1 )
997-
998- # Examples for which we have not found adversarial examples
999- I = (orig_labs == new_labs_multi )
1000- new_labs_multi [I ] = new_labs [I ]
1001-
1002- self .assertLess (np .mean (orig_labs == new_labs_multi ), 0.5 )
977+ # There is no initial random step, so nothing to test here
978+ pass
1003979
1004980
1005- class TestProjectedGradientDescent ( TestMadryEtAl ):
981+ class TestMadryEtAl ( CleverHansTest ):
1006982 def setUp (self ):
1007- super (TestProjectedGradientDescent , self ).setUp ()
1008- self .attack = ProjectedGradientDescent (self .model , sess = self .sess )
983+ super (TestMadryEtAl , self ).setUp ()
984+ self .model = DummyModel ('madryetal_dummy_model' )
985+ self .sess = tf .Session ()
1009986
987+ def test_attack_can_be_constructed (self ):
988+ ok = True
989+ try :
990+ attack = MadryEtAl (self .model , sess = self .sess )
991+ except :
992+ ok = False
993+ self .assertTrue (ok )
1010994
1011- class TestBasicIterativeMethod (TestMadryEtAl ):
995+
996+ class TestBasicIterativeMethod (CleverHansTest ):
1012997 def setUp (self ):
1013998 super (TestBasicIterativeMethod , self ).setUp ()
1014- self .attack = BasicIterativeMethod (self .model , sess = self .sess )
999+ self .model = DummyModel ('bim_dummy_model' )
1000+ self .sess = tf .Session ()
10151001
1016- def test_multiple_initial_random_step (self ):
1017- # There is no initial random step, so nothing to test here
1018- pass
1002+ def test_attack_can_be_constructed (self ):
1003+ ok = True
1004+ try :
1005+ self .attack = BasicIterativeMethod (self .model , sess = self .sess )
1006+ except :
1007+ ok = False
1008+ self .assertTrue (ok )
10191009
10201010
10211011class TestFastFeatureAdversaries (CleverHansTest ):
0 commit comments