1818from __future__ import division
1919from __future__ import print_function
2020
21- import uuid
22-
21+ from threading import Thread
2322import tensorflow as tf
2423
2524from tensorflow .contrib .linear_optimizer .python .ops .sdca_ops import _sdca_ops
3130
3231_MAX_ITERATIONS = 100
3332_SHARD_NUMBERS = [None , 1 , 3 , 10 ]
34-
33+ _NUM_PARTITIONS = [ 2 , 4 ]
3534
3635def make_example_proto (feature_dict , target , value = 1.0 ):
3736 e = tf .train .Example ()
@@ -146,11 +145,6 @@ def get_binary_predictions_for_hinge(predictions):
146145 dtype = tf .int32 )
147146
148147
149- # Setup the single container shared across all tests. This is testing proper
150- # isolation across optimizers instantiated in each of the tests below.
151- CONTAINER = uuid .uuid4 ().hex
152-
153-
154148# TODO(sibyl-Mooth6ku): Add tests that exercise L1 and Shrinking.
155149# TODO(sibyl-vie3Poto): Refactor tests to avoid repetition of boilerplate code.
156150class SdcaModelTest (TensorFlowTestCase ):
@@ -184,8 +178,8 @@ def testSimple(self):
184178 symmetric_l1_regularization = 0 ,
185179 loss_type = 'logistic_loss' )
186180
187- lr = SdcaModel (CONTAINER , examples , variables , options ,
188- num_table_shards = num_shards )
181+ lr = SdcaModel (
182+ examples , variables , options , num_table_shards = num_shards )
189183 tf .initialize_all_variables ().run ()
190184 unregularized_loss = lr .unregularized_loss (examples )
191185 loss = lr .regularized_loss (examples )
@@ -211,6 +205,62 @@ def testSimple(self):
211205 rtol = 1e-2 ,
212206 atol = 1e-2 )
213207
208+ def testDistributedSimple (self ):
209+ # Setup test data
210+ example_protos = [
211+ make_example_proto ({'age' : [0 ],
212+ 'gender' : [0 ]}, 0 ),
213+ make_example_proto ({'age' : [1 ],
214+ 'gender' : [1 ]}, 1 ),
215+ ]
216+ example_weights = [1.0 , 1.0 ]
217+ for num_shards in _SHARD_NUMBERS :
218+ for num_partitions in _NUM_PARTITIONS :
219+ with self ._single_threaded_test_session ():
220+ examples = make_example_dict (example_protos , example_weights )
221+ variables = make_variable_dict (1 , 1 )
222+ options = dict (
223+ symmetric_l2_regularization = 1 ,
224+ symmetric_l1_regularization = 0 ,
225+ loss_type = 'logistic_loss' ,
226+ num_partitions = num_partitions )
227+
228+ lr = SdcaModel (
229+ examples , variables , options , num_table_shards = num_shards )
230+ tf .initialize_all_variables ().run ()
231+ unregularized_loss = lr .unregularized_loss (examples )
232+ loss = lr .regularized_loss (examples )
233+ predictions = lr .predictions (examples )
234+ self .assertAllClose (0.693147 , unregularized_loss .eval ())
235+ self .assertAllClose (0.693147 , loss .eval ())
236+
237+ train_op = lr .minimize ()
238+
239+ def Minimize ():
240+ with self ._single_threaded_test_session ():
241+ for _ in range (_MAX_ITERATIONS ):
242+ train_op .run ()
243+
244+ threads = []
245+ for _ in range (num_partitions ):
246+ threads .append (Thread (target = Minimize ))
247+ threads [- 1 ].start ()
248+
249+ for t in threads :
250+ t .join ()
251+
252+ # The high tolerance in unregularized_loss comparisons is due to the
253+ # fact that it's possible to trade off unregularized_loss vs.
254+ # regularization and still have a sum that is quite close to the
255+ # optimal regularized_loss value. SDCA's duality gap only ensures
256+ # that the regularized_loss is within 0.01 of optimal.
257+ # 0.525457 is the optimal regularized_loss.
258+ # 0.411608 is the unregularized_loss at that optimum.
259+ self .assertAllClose (0.411608 , unregularized_loss .eval (), atol = 0.05 )
260+ self .assertAllClose (0.525457 , loss .eval (), atol = 0.01 )
261+ predicted_labels = get_binary_predictions_for_logistic (predictions )
262+ self .assertAllEqual ([0 , 1 ], predicted_labels .eval ())
263+ self .assertTrue (lr .approximate_duality_gap ().eval () < 0.02 )
214264
215265 def testSimpleNoL2 (self ):
216266 # Same as test above (so comments from above apply) but without an L2.
@@ -233,8 +283,8 @@ def testSimpleNoL2(self):
233283 symmetric_l1_regularization = 0 ,
234284 loss_type = 'logistic_loss' )
235285
236- lr = SdcaModel (CONTAINER , examples , variables , options ,
237- num_table_shards = num_shards )
286+ lr = SdcaModel (
287+ examples , variables , options , num_table_shards = num_shards )
238288 tf .initialize_all_variables ().run ()
239289 unregularized_loss = lr .unregularized_loss (examples )
240290 loss = lr .regularized_loss (examples )
@@ -287,8 +337,8 @@ def testSomeUnweightedExamples(self):
287337 symmetric_l1_regularization = 0 ,
288338 loss_type = 'logistic_loss' )
289339
290- lr = SdcaModel (CONTAINER , examples , variables , options ,
291- num_table_shards = num_shards )
340+ lr = SdcaModel (
341+ examples , variables , options , num_table_shards = num_shards )
292342 tf .initialize_all_variables ().run ()
293343 unregularized_loss = lr .unregularized_loss (examples )
294344 loss = lr .regularized_loss (examples )
@@ -325,8 +375,8 @@ def testFractionalExampleLabel(self):
325375 symmetric_l1_regularization = 0 ,
326376 loss_type = 'logistic_loss' )
327377
328- lr = SdcaModel (CONTAINER , examples , variables , options ,
329- num_table_shards = num_shards )
378+ lr = SdcaModel (
379+ examples , variables , options , num_table_shards = num_shards )
330380 tf .initialize_all_variables ().run ()
331381 with self .assertRaisesOpError (
332382 'Only labels of 0.0 or 1.0 are supported right now.' ):
@@ -357,8 +407,8 @@ def testImbalanced(self):
357407 symmetric_l1_regularization = 0 ,
358408 loss_type = 'logistic_loss' )
359409
360- lr = SdcaModel (CONTAINER , examples , variables , options ,
361- num_table_shards = num_shards )
410+ lr = SdcaModel (
411+ examples , variables , options , num_table_shards = num_shards )
362412 tf .initialize_all_variables ().run ()
363413 unregularized_loss = lr .unregularized_loss (examples )
364414 loss = lr .regularized_loss (examples )
@@ -397,8 +447,8 @@ def testImbalancedWithExampleWeights(self):
397447 symmetric_l1_regularization = 0 ,
398448 loss_type = 'logistic_loss' )
399449
400- lr = SdcaModel (CONTAINER , examples , variables , options ,
401- num_table_shards = num_shards )
450+ lr = SdcaModel (
451+ examples , variables , options , num_table_shards = num_shards )
402452 tf .initialize_all_variables ().run ()
403453 unregularized_loss = lr .unregularized_loss (examples )
404454 loss = lr .regularized_loss (examples )
@@ -435,8 +485,8 @@ def testInstancesOfOneClassOnly(self):
435485 symmetric_l1_regularization = 0 ,
436486 loss_type = 'logistic_loss' )
437487
438- lr = SdcaModel (CONTAINER , examples , variables , options ,
439- num_table_shards = num_shards )
488+ lr = SdcaModel (
489+ examples , variables , options , num_table_shards = num_shards )
440490 tf .initialize_all_variables ().run ()
441491 unregularized_loss = lr .unregularized_loss (examples )
442492 loss = lr .regularized_loss (examples )
@@ -478,7 +528,7 @@ def testSimple(self):
478528 symmetric_l1_regularization = 0 ,
479529 loss_type = 'squared_loss' )
480530
481- lr = SdcaModel (CONTAINER , examples , variables , options )
531+ lr = SdcaModel (examples , variables , options )
482532 tf .initialize_all_variables ().run ()
483533 predictions = lr .predictions (examples )
484534 train_op = lr .minimize ()
@@ -523,7 +573,7 @@ def testL2Regularization(self):
523573 symmetric_l1_regularization = 0 ,
524574 loss_type = 'squared_loss' )
525575
526- lr = SdcaModel (CONTAINER , examples , variables , options )
576+ lr = SdcaModel (examples , variables , options )
527577 tf .initialize_all_variables ().run ()
528578 predictions = lr .predictions (examples )
529579
@@ -557,7 +607,7 @@ def testL1Regularization(self):
557607 options = dict (symmetric_l2_regularization = 1.0 ,
558608 symmetric_l1_regularization = 4.0 ,
559609 loss_type = 'squared_loss' )
560- lr = SdcaModel (CONTAINER , examples , variables , options )
610+ lr = SdcaModel (examples , variables , options )
561611 tf .initialize_all_variables ().run ()
562612 prediction = lr .predictions (examples )
563613 loss = lr .regularized_loss (examples )
@@ -593,7 +643,7 @@ def testFeatureValues(self):
593643 symmetric_l1_regularization = 0 ,
594644 loss_type = 'squared_loss' )
595645
596- lr = SdcaModel (CONTAINER , examples , variables , options )
646+ lr = SdcaModel (examples , variables , options )
597647 tf .initialize_all_variables ().run ()
598648 predictions = lr .predictions (examples )
599649
@@ -626,7 +676,7 @@ def testDenseFeaturesWithDefaultWeights(self):
626676 options = dict (symmetric_l2_regularization = 1.0 ,
627677 symmetric_l1_regularization = 0 ,
628678 loss_type = 'squared_loss' )
629- lr = SdcaModel (CONTAINER , examples , variables , options )
679+ lr = SdcaModel (examples , variables , options )
630680 tf .initialize_all_variables ().run ()
631681 predictions = lr .predictions (examples )
632682
@@ -656,7 +706,7 @@ def testDenseFeaturesWithArbitraryWeights(self):
656706 options = dict (symmetric_l2_regularization = 5.0 ,
657707 symmetric_l1_regularization = 0 ,
658708 loss_type = 'squared_loss' )
659- lr = SdcaModel (CONTAINER , examples , variables , options )
709+ lr = SdcaModel (examples , variables , options )
660710 tf .initialize_all_variables ().run ()
661711 predictions = lr .predictions (examples )
662712
@@ -700,7 +750,7 @@ def testSimple(self):
700750 options = dict (symmetric_l2_regularization = 1.0 ,
701751 symmetric_l1_regularization = 0 ,
702752 loss_type = 'hinge_loss' )
703- model = SdcaModel (CONTAINER , examples , variables , options )
753+ model = SdcaModel (examples , variables , options )
704754 tf .initialize_all_variables ().run ()
705755
706756 # Before minimization, the weights default to zero. There is no loss due
@@ -737,7 +787,7 @@ def testDenseFeaturesPerfectlySeparable(self):
737787 symmetric_l2_regularization = 1.0 ,
738788 symmetric_l1_regularization = 0 ,
739789 loss_type = 'hinge_loss' )
740- model = SdcaModel (CONTAINER , examples , variables , options )
790+ model = SdcaModel (examples , variables , options )
741791 tf .initialize_all_variables ().run ()
742792 predictions = model .predictions (examples )
743793 binary_predictions = get_binary_predictions_for_hinge (predictions )
@@ -767,7 +817,7 @@ def testDenseFeaturesSeparableWithinMargins(self):
767817 options = dict (symmetric_l2_regularization = 1.0 ,
768818 symmetric_l1_regularization = 0 ,
769819 loss_type = 'hinge_loss' )
770- model = SdcaModel (CONTAINER , examples , variables , options )
820+ model = SdcaModel (examples , variables , options )
771821 tf .initialize_all_variables ().run ()
772822 predictions = model .predictions (examples )
773823 binary_predictions = get_binary_predictions_for_hinge (predictions )
@@ -796,7 +846,7 @@ def testDenseFeaturesWeightedExamples(self):
796846 options = dict (symmetric_l2_regularization = 1.0 ,
797847 symmetric_l1_regularization = 0 ,
798848 loss_type = 'hinge_loss' )
799- model = SdcaModel (CONTAINER , examples , variables , options )
849+ model = SdcaModel (examples , variables , options )
800850 tf .initialize_all_variables ().run ()
801851 predictions = model .predictions (examples )
802852 binary_predictions = get_binary_predictions_for_hinge (predictions )
0 commit comments