-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathvae.sublime-workspace
More file actions
872 lines (872 loc) · 281 KB
/
Copy pathvae.sublime-workspace
File metadata and controls
872 lines (872 loc) · 281 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
{
"auto_complete":
{
"selected_items":
[
[
"validation",
"validation_data\t(training_v1.py)"
],
[
"call",
"callbacks\tabc"
],
[
"batch",
"batch_sz\tabc"
],
[
"data",
"data_generator\tabc"
],
[
"Dat",
"DataGenerator\t(data_generator.py)"
],
[
"train",
"train_evts\tabc"
],
[
"read_co",
"read_constituents_parts_from_dir"
],
[
"dat",
"data_reader\tabc"
],
[
"yi",
"yield\t(dataset_ops.py)"
],
[
"da",
"data_reader\tabc"
],
[
"test",
"test_evts_j2\tabc"
],
[
"test_e",
"test_evts_j1\tabc"
],
[
"tes",
"test_evts_j2\tabc"
],
[
"num",
"numpy\tabc"
],
[
"pr",
"print\t(main_predict.py)"
],
[
"img-local",
"img-local-54\t(sample_factory.py)"
]
]
},
"buffers":
[
{
"contents": "import os\n\nimport POfAH.sample_dict as sd\nimport analysis.analysis_jet_feature as ajf\nimport util.experiment as ex\nimport POfAH.jet_sample as js\nimport util.event_sample as es\nimport util.plotting as up\nimport POfAH.util.sample_factory as sf\n\n\nrun_n = 101\ndata_sample = 'particle-local'\n\nexperiment = ex.Experiment(run_n).setup(fig_dir=True)\npaths = sf.SamplePathFactory(experiment, data_sample)\n\n\n# ********************************************************\n# read in training data ( events )\n# ********************************************************\n\nqcd_sample = js.JetSample.from_input_file('qcdSide',paths.qcd_file_path)\nscikit_qcd_sample = ajf.dijet_sample_from_dijet_sample(qcd_sample)\nptjj = [j.pt for j in scikit_qcd_sample]\n\nup.plot_hist(ptjj, title='ptjj', plot_name='ptjj_dist', fig_dir=experiment.fig_dir, xlim=(-1,10), bins=3000)\n\n\n\n# scikit dijet sample from particle sample\nevent_sample = es.EventSample.from_input_file('GtoWW30br','../data/events/RSGraviton_WW_BROAD_13TeV_PU40_3.0TeV_concat_10K.h5')\nj1_particles, j2_particles = event_sample.get_particles()\nj1_scikit = ajf.jet_sample_from_particle_sample(j1_particles)\nj2_scikit = ajf.jet_sample_from_particle_sample(j2_particles)\njj_scikit = [j1+j2 for j1,j2 in zip(j1_scikit,j2_scikit)]\nmjj_scikit = [j.mass for j in jj_scikit]\nptjj_scikit = [j.pt for j in jj_scikit]\n\n# original dijet sample\njet_sample = js.JetSample.from_input_file('GtoWW30br','../data/events/RSGraviton_WW_BROAD_13TeV_PU40_3.0TeV_concat_10K.h5')\n#scikit dijet sample from original dijet sample\njet_sample_scikit = ajf.dijet_sample_from_dijet_sample(jet_sample)\nmjj_scikit_from_orig = [j.mass for j in jet_sample_scikit]\nptjj_scikit_from_orig = [j.pt for j in jet_sample_scikit]\n\nup.plot_hist(mjj_scikit,title='mjj scikit',plot_name='hist_mjj_scikit',fig_dir=experiment.fig_dir)\nup.plot_hist(jet_sample['mJJ'],title='mjj original',plot_name='hist_mjj_original',fig_dir=experiment.fig_dir)\nup.plot_hist(mjj_scikit_from_orig,title='mjj scikit from original',plot_name='hist_mjj_scikit_from_original',fig_dir=experiment.fig_dir)\n\nup.plot_hist(ptjj_scikit,title='ptjj scikit',plot_name='hist_ptjj_scikit',fig_dir=experiment.fig_dir)\nup.plot_hist(ptjj_scikit_from_orig,title='ptjj scikit from original',plot_name='hist_ptjj_scikit_from_original',fig_dir=experiment.fig_dir)\n\nexit()\n\n\n# select model\nexperiment = ex.Experiment(run_n=45)\n\n# read in original and reconstructed datasets\n\nsample_original_id = 'GtoWW35br'\njet_sample_original = js.JetSample.from_input_file(sample_original_id, os.path.join(sd.base_dir_events, sd.file_names[sample_original_id]+'_mjj_cut_concat_200K.h5'))\n\nsample_reco_id = 'GtoWW35brReco'\nevt_sample_reco = es.EventSample.from_input_file(sample_reco_id,os.path.join(experiment.result_dir, sd.file_names[sample_reco_id]+'.h5'))\nj1_reco_particles, j2_reco_particles = evt_sample_reco.get_particles()\n\n# compute jets from particles\nj1_reco = ajf.jet_sample_from_particle_sample(j1_reco_particles)\nj2_reco = ajf.jet_sample_from_particle_sample(j2_reco_particles)\njj_reco = [j1+j2 for j1,j2 in zip(j1_reco,j2_reco)]\n# get dijet mass and dijet pt\nm_jj_reco = [ event_jj.mass for event_jj in jj_reco]\npt_jj_reco = [ event_jj.pt for event_jj in jj_reco]\n\n# compute dijet pt for original data sample\njj_orig = ajf.dijet_sample_from_dijet_sample(jet_sample_original)\nm_jj_orig_scikit = [event.mass for event in jj_orig]\nm_jj_orig = jet_sample_original['mJJ']\npt_jj_orig_scikit = [event.pt for event in jj_orig]\n\nup.plot_hist([m_jj_orig,m_jj_orig_scikit,m_jj_reco],xlabel='mJJ',title='mJJ distribution',plot_name='hist_jet_feature_mjj',legend=['orig','orig scikit','reco'],fig_dir=experiment.fig_dir)\nup.plot_hist([pt_jj_orig_scikit,pt_jj_reco],xlabel='ptJJ',title='ptJJ distribution',plot_name='hist_jet_feature_ptjj',legend=['orig scikit','reco'],fig_dir=experiment.fig_dir)\n",
"file": "main_analysis_jet_features.py",
"file_size": 3835,
"file_write_time": 132411175850000000,
"settings":
{
"buffer_size": 3835,
"line_ending": "Unix"
}
},
{
"contents": "import setGPU\n\nfrom vae.vae_model import VAE\nfrom vae.vae_highres_model import VAE_HR\nimport vae.losses as lo\nimport pofah.util.input_data_reader as idr\nimport pofah.util.sample_factory as sf\nimport pofah.jet_sample as js\nimport pofah.util.experiment as ex\n\n\n# ********************************************************\n# runtime params\n# ********************************************************\n\nrun_n = 4\ndata_sample = 'img-local-54'\n\nexperiment = ex.Experiment(run_n).setup(result_dir=True)\npaths = sf.SamplePathFactory(experiment,data_sample)\n\n# ********************************************\n# load model\n# ********************************************\n\nvae = VAE(run=run_n, model_dir=experiment.model_dir)\nvae.load()\n\n# ********************************************\n# read test data (images)\n# ********************************************\n\n#sample_ids = ['qcdSide', 'qcdSig', 'GtoWW15na', 'GtoWW15br', 'GtoWW25na', 'GtoWW25br', 'GtoWW35na', 'GtoWW35br', 'GtoWW45na', 'GtoWW45br']\nsample_ids = ['GtoWW25br', 'GtoWW35na']\n\nfor sample_id in sample_ids:\n\n data_reader = idr.InputDataReader(paths.sample_path(sample_id))\n test_img_j1, test_img_j2 = data_reader.read_images( )\n\n\n # *******************************************************\n # predict test data\n # *******************************************************\n\n print('-'*10, 'predicting', '-'*10)\n reco_img_j1, z_mean_j1, z_log_var_j1 = vae.predict_with_latent( test_img_j1 )\n reco_img_j2, z_mean_j2, z_log_var_j2 = vae.predict_with_latent( test_img_j2 )\n\n # *******************************************************\n # compute losses\n # *******************************************************\n\n print('-'*10, 'computing losses', '-'*10)\n losses_j1 = lo.compute_loss_of_prediction_mse_kl(test_img_j1, reco_img_j1, z_mean_j1, z_log_var_j1, input_size=54)\n losses_j2 = lo.compute_loss_of_prediction_mse_kl(test_img_j2, reco_img_j2, z_mean_j2, z_log_var_j2, input_size=54)\n\n # *******************************************************\n # add losses to DataSample and save\n # *******************************************************\n\n predicted_sample = js.JetSample.from_feature_array(sample_id, *data_reader.read_dijet_features())\n \n for loss, label in zip( losses_j1, ['j1TotalLoss', 'j1RecoLoss', 'j1KlLoss']):\n predicted_sample.add_feature(label,loss)\n for loss, label in zip( losses_j2, ['j2TotalLoss', 'j2RecoLoss', 'j2KlLoss']):\n predicted_sample.add_feature(label,loss)\n\n predicted_sample.dump(paths.result_path(sample_id + 'Reco'))\n\n",
"file": "main_predict.py",
"file_size": 2651,
"file_write_time": 132411920700000000,
"settings":
{
"buffer_size": 2651,
"line_ending": "Unix"
}
},
{
"file": "main_train_particle_vae.py",
"settings":
{
"buffer_size": 4018,
"encoding": "UTF-8",
"line_ending": "Unix"
}
},
{
"contents": "import unittest\nimport os\nimport math\nimport pofah.path_constants.sample_dict_file_parts_input_baby as sdi\nimport util.data_generator as dage\n\n\n'''\ntest obsolete: generator returns only one sample at a time\n'''\n\nclass DataGeneratorTestCase(unittest.TestCase):\n\n\tdef setUp(self):\n\t\tsample_id = 'qcdSig'\n\t\tself.path = os.path.join(sdi.path_dict['base_dir'], sdi.path_dict['sample_dir'][sample_id])\n\t\tself.batch_sz = 1024\n\t\tself.samples_n_total = 116096*2 # 116096 events * 2 jets\n\t\tself.generator = dage.DataGenerator(path=self.path, batch_sz=self.batch_sz)\n\t\n\tdef test_num_events_read(self):\n\t\tn_total_read = 0\n\t\tfor (constituents, _) in self.generator():\n\t\t\tn_batch_read = len(constituents)\n\t\t\tn_total_read += n_batch_read\n\t\t\t# check batch_sz samples in each batch\n\t\t\tself.assertEqual(n_batch_read, self.batch_sz)\n\t\t# check all samples read\n\t\tself.assertGreaterEqual(n_total_read, self.samples_n_total)\n\t\t# check batch padding\n\t\tself.assertEqual(math.ceil(self.samples_n_total/self.batch_sz)*self.batch_sz, n_total_read)\n\n\n\tdef test_shape_events_read(self):\n\t\tfor (constituents, _) in self.generator():\n\t\t\tself.assertEqual(constituents.shape, (self.batch_sz, 100, 3))\n\n\tdef test_num_events_read_max_n(self):\n\t\tmax_n = 3000\n\t\tmax_n_generator = dage.DataGenerator(path=self.path, batch_sz=self.batch_sz, max_n=max_n)\n\t\tn_total_read = 0\n\t\tfor (constituents, _) in max_n_generator():\n\t\t\tn_total_read += len(constituents)\n\t\tself.assertLess(max_n-n_total_read, self.batch_sz)\n\t\tself.assertEqual(n_total_read%self.batch_sz,0)\n\t\tself.assertGreater(n_total_read, 0)\n\n\nif __name__ == '__main__':\n\tunittest.main()\n",
"file": "tests/test_data_generator.py",
"file_size": 1603,
"file_write_time": 132514817300000000,
"settings":
{
"buffer_size": 1603,
"encoding": "UTF-8",
"line_ending": "Unix"
}
},
{
"file": "vae/vae_particle.py",
"settings":
{
"buffer_size": 5233,
"encoding": "UTF-8",
"line_ending": "Unix"
}
},
{
"file": "vae/vae_base.py",
"settings":
{
"buffer_size": 3726,
"line_ending": "Unix"
}
},
{
"contents": "# Copyright 2015 The TensorFlow Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ==============================================================================\n\"\"\"V1 Training-related part of the Keras engine.\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nimport collections\n\nimport numpy as np\n\nfrom tensorflow.python import tf2\nfrom tensorflow.python.data.ops import dataset_ops\nfrom tensorflow.python.data.ops import iterator_ops\nfrom tensorflow.python.distribute import distribution_strategy_context\nfrom tensorflow.python.eager import context\nfrom tensorflow.python.eager import def_function\nfrom tensorflow.python.eager import monitoring\nfrom tensorflow.python.framework import composite_tensor\nfrom tensorflow.python.framework import composite_tensor_utils\nfrom tensorflow.python.framework import constant_op\nfrom tensorflow.python.framework import ops\nfrom tensorflow.python.framework import sparse_tensor\nfrom tensorflow.python.framework import tensor_shape\nfrom tensorflow.python.framework import tensor_spec\nfrom tensorflow.python.framework import tensor_util\nfrom tensorflow.python.framework import type_spec\nfrom tensorflow.python.keras import backend as K\nfrom tensorflow.python.keras import losses\nfrom tensorflow.python.keras import metrics as metrics_module\nfrom tensorflow.python.keras import optimizers\nfrom tensorflow.python.keras.distribute import distributed_training_utils\nfrom tensorflow.python.keras.engine import network\nfrom tensorflow.python.keras.engine import training as training_lib\nfrom tensorflow.python.keras.engine import training_arrays\nfrom tensorflow.python.keras.engine import training_distributed\nfrom tensorflow.python.keras.engine import training_eager\nfrom tensorflow.python.keras.engine import training_generator\nfrom tensorflow.python.keras.engine import training_utils\nfrom tensorflow.python.keras.mixed_precision.experimental import loss_scale_optimizer\nfrom tensorflow.python.keras.optimizer_v2 import optimizer_v2\nfrom tensorflow.python.keras.saving.saved_model import model_serialization\nfrom tensorflow.python.keras.utils import data_utils\nfrom tensorflow.python.keras.utils import losses_utils\nfrom tensorflow.python.keras.utils.mode_keys import ModeKeys\nfrom tensorflow.python.ops import array_ops\nfrom tensorflow.python.ops import math_ops\nfrom tensorflow.python.ops.losses import util as tf_losses_utils\nfrom tensorflow.python.platform import tf_logging as logging\nfrom tensorflow.python.training.tracking import base as trackable\nfrom tensorflow.python.training.tracking import layer_utils as trackable_layer_utils\nfrom tensorflow.python.util import deprecation\nfrom tensorflow.python.util import nest\nfrom tensorflow.python.util import tf_inspect\nfrom tensorflow.python.util.compat import collections_abc\n\ntry:\n from scipy.sparse import issparse # pylint: disable=g-import-not-at-top\nexcept ImportError:\n issparse = None\n\n_keras_api_gauge = monitoring.BoolGauge('/tensorflow/api/keras/model_v1',\n 'keras model v1 usage', 'method')\n\n\nclass Model(training_lib.Model):\n \"\"\"`Model` groups layers into an object with training and inference features.\n\n There are two ways to instantiate a `Model`:\n\n 1 - With the \"functional API\", where you start from `Input`,\n you chain layer calls to specify the model's forward pass,\n and finally you create your model from inputs and outputs:\n\n ```python\n import tensorflow as tf\n\n inputs = tf.keras.Input(shape=(3,))\n x = tf.keras.layers.Dense(4, activation=tf.nn.relu)(inputs)\n outputs = tf.keras.layers.Dense(5, activation=tf.nn.softmax)(x)\n model = tf.keras.Model(inputs=inputs, outputs=outputs)\n ```\n\n 2 - By subclassing the `Model` class: in that case, you should define your\n layers in `__init__` and you should implement the model's forward pass\n in `call`.\n\n ```python\n import tensorflow as tf\n\n class MyModel(tf.keras.Model):\n\n def __init__(self):\n super(MyModel, self).__init__()\n self.dense1 = tf.keras.layers.Dense(4, activation=tf.nn.relu)\n self.dense2 = tf.keras.layers.Dense(5, activation=tf.nn.softmax)\n\n def call(self, inputs):\n x = self.dense1(inputs)\n return self.dense2(x)\n\n model = MyModel()\n ```\n\n If you subclass `Model`, you can optionally have\n a `training` argument (boolean) in `call`, which you can use to specify\n a different behavior in training and inference:\n\n ```python\n import tensorflow as tf\n\n class MyModel(tf.keras.Model):\n\n def __init__(self):\n super(MyModel, self).__init__()\n self.dense1 = tf.keras.layers.Dense(4, activation=tf.nn.relu)\n self.dense2 = tf.keras.layers.Dense(5, activation=tf.nn.softmax)\n self.dropout = tf.keras.layers.Dropout(0.5)\n\n def call(self, inputs, training=False):\n x = self.dense1(inputs)\n if training:\n x = self.dropout(x, training=training)\n return self.dense2(x)\n\n model = MyModel()\n ```\n \"\"\"\n\n def __init__(self, *args, **kwargs):\n super(Model, self).__init__(*args, **kwargs)\n _keras_api_gauge.get_cell('model_v1').set(True)\n # initializing _distribution_strategy here since it is possible to call\n # predict on a model without compiling it.\n self._distribution_strategy = None\n self._compile_time_distribution_strategy = None\n if (ops.executing_eagerly_outside_functions() and\n distribution_strategy_context.has_strategy()):\n self._set_strategy(\n distribution_strategy_context.get_strategy())\n\n # This flag is used to track if the user is using the deprecated path of\n # passing distribution strategy to compile rather than creating the model\n # under distribution strategy scope.\n self._compile_distribution = False\n\n self._run_eagerly = None\n self._experimental_run_tf_function = (\n ops.executing_eagerly_outside_functions())\n\n self._v1_compile_was_called = False\n\n @trackable.no_automatic_dependency_tracking\n def _set_strategy(self, strategy):\n self._compile_time_distribution_strategy = strategy\n\n def get_weights(self):\n \"\"\"Retrieves the weights of the model.\n\n Returns:\n A flat list of Numpy arrays.\n \"\"\"\n strategy = (self._distribution_strategy or\n self._compile_time_distribution_strategy)\n if strategy:\n with strategy.scope():\n return network.Network.get_weights(self)\n return network.Network.get_weights(self)\n\n def load_weights(self, filepath, by_name=False, skip_mismatch=False):\n \"\"\"Loads all layer weights, either from a TensorFlow or an HDF5 weight file.\n\n If `by_name` is False weights are loaded based on the network's\n topology. This means the architecture should be the same as when the weights\n were saved. Note that layers that don't have weights are not taken into\n account in the topological ordering, so adding or removing layers is fine as\n long as they don't have weights.\n\n If `by_name` is True, weights are loaded into layers only if they share the\n same name. This is useful for fine-tuning or transfer-learning models where\n some of the layers have changed.\n\n Only topological loading (`by_name=False`) is supported when loading weights\n from the TensorFlow format. Note that topological loading differs slightly\n between TensorFlow and HDF5 formats for user-defined classes inheriting from\n `tf.keras.Model`: HDF5 loads based on a flattened list of weights, while the\n TensorFlow format loads based on the object-local names of attributes to\n which layers are assigned in the `Model`'s constructor.\n\n Arguments:\n filepath: String, path to the weights file to load. For weight files in\n TensorFlow format, this is the file prefix (the same as was passed\n to `save_weights`).\n by_name: Boolean, whether to load weights by name or by topological\n order. Only topological loading is supported for weight files in\n TensorFlow format.\n skip_mismatch: Boolean, whether to skip loading of layers where there is\n a mismatch in the number of weights, or a mismatch in the shape of\n the weight (only valid when `by_name=True`).\n\n Returns:\n When loading a weight file in TensorFlow format, returns the same status\n object as `tf.train.Checkpoint.restore`. When graph building, restore\n ops are run automatically as soon as the network is built (on first call\n for user-defined classes inheriting from `Model`, immediately if it is\n already built).\n\n When loading weights in HDF5 format, returns `None`.\n\n Raises:\n ImportError: If h5py is not available and the weight file is in HDF5\n format.\n ValueError: If `skip_mismatch` is set to `True` when `by_name` is\n `False`.\n \"\"\"\n if distributed_training_utils.is_tpu_strategy(self._distribution_strategy):\n if (self._distribution_strategy.extended.steps_per_run > 1 and\n (not network._is_hdf5_filepath(filepath))): # pylint: disable=protected-access\n raise ValueError('Load weights is not yet supported with TPUStrategy '\n 'with steps_per_run greater than 1.')\n return super(Model, self).load_weights(filepath, by_name, skip_mismatch)\n\n @trackable.no_automatic_dependency_tracking\n def compile(self,\n optimizer='rmsprop',\n loss=None,\n metrics=None,\n loss_weights=None,\n sample_weight_mode=None,\n weighted_metrics=None,\n target_tensors=None,\n distribute=None,\n **kwargs):\n \"\"\"Configures the model for training.\n\n Arguments:\n optimizer: String (name of optimizer) or optimizer instance.\n See `tf.keras.optimizers`.\n loss: String (name of objective function), objective function or\n `tf.keras.losses.Loss` instance. See `tf.keras.losses`. An objective\n function is any callable with the signature\n `scalar_loss = fn(y_true, y_pred)`. If the model has multiple\n outputs, you can use a different loss on each output by passing a\n dictionary or a list of losses. The loss value that will be\n minimized by the model will then be the sum of all individual\n losses.\n metrics: List of metrics to be evaluated by the model during training\n and testing. Typically you will use `metrics=['accuracy']`.\n To specify different metrics for different outputs of a\n multi-output model, you could also pass a dictionary, such as\n `metrics={'output_a': 'accuracy', 'output_b': ['accuracy', 'mse']}`.\n You can also pass a list (len = len(outputs)) of lists of metrics\n such as `metrics=[['accuracy'], ['accuracy', 'mse']]` or\n `metrics=['accuracy', ['accuracy', 'mse']]`.\n loss_weights: Optional list or dictionary specifying scalar\n coefficients (Python floats) to weight the loss contributions\n of different model outputs.\n The loss value that will be minimized by the model\n will then be the *weighted sum* of all individual losses,\n weighted by the `loss_weights` coefficients.\n If a list, it is expected to have a 1:1 mapping\n to the model's outputs. If a tensor, it is expected to map\n output names (strings) to scalar coefficients.\n sample_weight_mode: If you need to do timestep-wise\n sample weighting (2D weights), set this to `\"temporal\"`.\n `None` defaults to sample-wise weights (1D).\n If the model has multiple outputs, you can use a different\n `sample_weight_mode` on each output by passing a\n dictionary or a list of modes.\n weighted_metrics: List of metrics to be evaluated and weighted\n by sample_weight or class_weight during training and testing.\n target_tensors: By default, Keras will create placeholders for the\n model's target, which will be fed with the target data during\n training. If instead you would like to use your own\n target tensors (in turn, Keras will not expect external\n Numpy data for these targets at training time), you\n can specify them via the `target_tensors` argument. It can be\n a single tensor (for a single-output model), a list of tensors,\n or a dict mapping output names to target tensors.\n distribute: NOT SUPPORTED IN TF 2.0, please create and compile the\n model under distribution strategy scope instead of passing it to\n compile.\n **kwargs: Any additional arguments.\n\n Raises:\n ValueError: In case of invalid arguments for\n `optimizer`, `loss`, `metrics` or `sample_weight_mode`.\n \"\"\"\n self._run_eagerly = kwargs.pop('run_eagerly', None)\n self._experimental_run_tf_function = kwargs.pop(\n 'experimental_run_tf_function', True)\n self._v1_compile_was_called = True\n\n # Prepare Session arguments (legacy).\n kwargs.pop('cloning', None) # Legacy DistStrat argument, never used.\n allowed_kwargs = {'feed_dict', 'fetches', 'options', 'run_metadata'}\n unknown_kwargs = set(kwargs.keys()) - allowed_kwargs\n if unknown_kwargs:\n raise TypeError(\n 'Invalid keyword argument(s) in `compile`: %s' % (unknown_kwargs,))\n self._function_kwargs = kwargs\n if self._function_kwargs:\n self._experimental_run_tf_function = False\n if self.run_eagerly:\n raise ValueError(\n 'Session keyword arguments are not supported '\n 'when `run_eagerly=True`. You passed the following '\n 'Session arguments: %s' % (self._function_kwargs,))\n\n self._set_optimizer(optimizer)\n is_any_keras_optimizer_v1 = any(\n (isinstance(opt, optimizers.Optimizer)\n and not isinstance(opt, optimizers.TFOptimizer)\n ) for opt in nest.flatten(self.optimizer))\n\n if is_any_keras_optimizer_v1 and ops.executing_eagerly_outside_functions():\n raise ValueError('`tf.compat.v1.keras` Optimizer (', optimizer, ') is '\n 'not supported when eager execution is enabled. Use a '\n '`tf.keras` Optimizer instead, or disable eager '\n 'execution.')\n\n if ((target_tensors is not None)\n or not ops.executing_eagerly_outside_functions()):\n # Fallback out of things that aren't supported with v2 loops\n self._experimental_run_tf_function = False\n\n if distribute is not None:\n if tf2.enabled() or self._experimental_run_tf_function:\n raise ValueError(\n 'Distribute argument in compile is not available in TF 2.0 please '\n 'create the model under the distribution strategy scope.')\n logging.warning('Distribute argument in compile is deprecated please '\n 'create the model under the distribution strategy scope.')\n self._distribution_strategy = distribute\n self._compile_distribution = True\n else:\n if distribution_strategy_context.has_strategy():\n # When the user builds the model in the DS scope and cross replica\n # context we want distribution strategy to be set but when building the\n # replica copies of the models internally we should not be compiling\n # with distribution strategy and use the default compilation path.\n if distribution_strategy_context.in_cross_replica_context():\n self._distribution_strategy = (\n distribution_strategy_context.get_strategy())\n\n if not self._experimental_run_tf_function:\n self._validate_compile_param_for_distribution_strategy(self.run_eagerly,\n sample_weight_mode,\n target_tensors,\n weighted_metrics)\n # We've disabled automatic dependency tracking for this method, but do want\n # to add a checkpoint dependency on the optimizer if it's trackable.\n if isinstance(self.optimizer, trackable.Trackable):\n self._track_trackable(\n self.optimizer, name='optimizer', overwrite=True)\n self.loss = loss or {}\n self.loss_weights = loss_weights\n self.sample_weight_mode = sample_weight_mode\n self._compile_metrics = metrics or []\n self._compile_weighted_metrics = weighted_metrics\n if self.run_eagerly and target_tensors is not None:\n raise ValueError(\n 'target_tensors argument is not supported when '\n 'running a model eagerly.')\n\n # _training_endpoints contains a list of _TrainingEndpoint object, which has\n # all the model output/target/loss and related metadata.\n self._training_endpoints = []\n\n # Used to freeze the behavior of the Model once `compile` has been called.\n self._compiled_trainable_state = self._get_trainable_state()\n\n # Set tf.distribute.Strategy specific parameters.\n self._distributed_model_cache = {}\n self._distributed_function_cache = {}\n\n # Clear any `_eager_losses` that was added.\n self._clear_losses()\n\n if (not context.executing_eagerly() and\n self._distribution_strategy is not None):\n # Ensures a Session is created and configured correctly for Distribution\n # Strategy.\n K.configure_and_create_distributed_session(self._distribution_strategy)\n # Initialize model metric attributes.\n self._init_metric_attributes()\n if not self.built or not self.inputs or not self.outputs:\n # Model is not compilable because it does not know its number of inputs\n # and outputs, nor their shapes and names. We will compile after the first\n # time the model gets called on training data.\n return\n self._is_compiled = True\n _keras_api_gauge.get_cell('compile_v1').set(True)\n\n # Prepare list of loss functions, same size of model outputs.\n self.loss_functions = training_utils.prepare_loss_functions(\n self.loss, self.output_names)\n\n target_tensors = self._process_target_tensor_for_compile(target_tensors)\n\n for o, n, l, t in zip(self.outputs, self.output_names,\n self.loss_functions, target_tensors):\n endpoint = _TrainingEndpoint(o, n, l)\n endpoint.create_training_target(t, run_eagerly=self.run_eagerly)\n self._training_endpoints.append(endpoint)\n\n # Prepare list loss weights, same size of model outputs.\n training_utils.prepare_loss_weights(self._training_endpoints, loss_weights)\n\n # Initialization for Eager mode execution.\n if self.run_eagerly:\n self._compile_eagerly(metrics, weighted_metrics, sample_weight_mode)\n return\n\n with K.get_graph().as_default():\n # Save all metric attributes per output of the model.\n self._cache_output_metric_attributes(metrics, weighted_metrics)\n\n # Set metric attributes on model.\n self._set_metric_attributes()\n\n # Invoke metric functions (unweighted) for all the outputs.\n self._handle_metrics(\n self.outputs,\n targets=self._targets,\n skip_target_masks=self._prepare_skip_target_masks(),\n masks=self._prepare_output_masks())\n\n # Prepare sample weight modes. List with the same length as model outputs.\n training_utils.prepare_sample_weight_modes(\n self._training_endpoints, sample_weight_mode)\n\n # Creates the model loss and weighted metrics sub-graphs.\n self._compile_weights_loss_and_weighted_metrics()\n\n # Functions for train, test and predict will\n # be compiled lazily when required.\n # This saves time when the user is not using all functions.\n self.train_function = None\n self.test_function = None\n self.predict_function = None\n\n # Collected trainable weights, sorted in topological order.\n self._collected_trainable_weights = self.trainable_weights\n\n # Validate all variables were correctly created in distribution scope.\n if self._distribution_strategy and not self._compile_distribution:\n for v in self.variables:\n strategy = self._distribution_strategy\n if not strategy.extended.variable_created_in_scope(v):\n raise ValueError(\n 'Variable (%s) was not created in the distribution strategy '\n 'scope of (%s). It is most likely due to not all layers or '\n 'the model or optimizer being created outside the distribution '\n 'strategy scope. Try to make sure your code looks similar '\n 'to the following.\\n'\n 'with strategy.scope():\\n'\n ' model=_create_model()\\n'\n ' model.compile(...)'% (v, strategy))\n\n @trackable.no_automatic_dependency_tracking\n def _init_distributed_function_cache_if_not_compiled(self):\n if not hasattr(self, '_distributed_function_cache'):\n self._distributed_function_cache = {}\n\n @property\n def metrics(self):\n \"\"\"Returns the model's metrics added using `compile`, `add_metric` APIs.\"\"\"\n metrics = []\n if self._is_compiled:\n metrics += self._compile_metric_functions\n metrics.extend(self._metrics)\n metrics.extend(_get_metrics_from_layers(self._layers))\n return metrics\n\n @property\n def metrics_names(self):\n \"\"\"Returns the model's display labels for all outputs.\"\"\"\n\n # This property includes all output names including `loss` and per-output\n # losses for backward compatibility.\n metrics_names = ['loss']\n if self._is_compiled:\n # Add output loss metric names to the metric names list.\n if len(self._training_endpoints) > 1:\n metrics_names.extend([\n e.loss_name()\n for e in self._training_endpoints\n if not e.should_skip_target()\n ])\n\n # Add all metric names.\n metrics_names += [m.name for m in self.metrics]\n return metrics_names\n\n @property\n def run_eagerly(self):\n \"\"\"Settable attribute indicating whether the model should run eagerly.\n\n Running eagerly means that your model will be run step by step,\n like Python code. Your model might run slower, but it should become easier\n for you to debug it by stepping into individual layer calls.\n\n By default, we will attempt to compile your model to a static graph to\n deliver the best execution performance.\n\n Returns:\n Boolean, whether the model should run eagerly.\n \"\"\"\n if self._run_eagerly is True and not context.executing_eagerly():\n raise ValueError('You can only set `run_eagerly=True` if eager execution '\n 'is enabled.')\n if not self.dynamic:\n if self._run_eagerly is None:\n # Respect `tf.config.experimental_run_functions_eagerly` unless\n # `run_eagerly` was explicitly passed to `compile`.\n return def_function.RUN_FUNCTIONS_EAGERLY\n else:\n return self._run_eagerly\n else:\n if not context.executing_eagerly():\n raise ValueError('Your model contains layers that can only be '\n 'successfully run in eager execution (layers '\n 'constructed with `dynamic=True`). '\n 'You must enable eager execution with '\n '`tf.enable_eager_execution()`.')\n if self._run_eagerly is False:\n # TODO(fchollet): consider using py_func to enable this.\n raise ValueError('Your model contains layers that can only be '\n 'successfully run in eager execution (layers '\n 'constructed with `dynamic=True`). '\n 'You cannot set `run_eagerly=False`.')\n return context.executing_eagerly()\n\n @run_eagerly.setter\n def run_eagerly(self, value):\n self._run_eagerly = value\n\n def _select_training_loop(self, inputs):\n \"\"\"Select training loop for fit/eval/predict based on the inputs.\"\"\"\n # TODO(kaftan) or TODO(scottzhu): This check should eventually be nicely\n # integrated into the data adapters in the v2 loop. We can't do this yet\n # because we currently have to fall back for unhandled data types.\n if isinstance(inputs, (iterator_ops.Iterator,\n iterator_ops.OwnedIterator)):\n raise ValueError('For performance reasons Keras `fit`, `evaluate` and'\n '`predict` accept tf.data `Datasets` as input but not '\n 'iterators that have been manually generated from '\n 'Datasets by users. Please directly pass in the '\n 'original `Dataset` object instead of passing in '\n '`iter(dataset)`.')\n\n # Case 1: distribution strategy.\n if self._distribution_strategy:\n if self._in_multi_worker_mode():\n return training_distributed.DistributionMultiWorkerTrainingLoop(\n training_distributed.DistributionSingleWorkerTrainingLoop())\n else:\n return training_distributed.DistributionSingleWorkerTrainingLoop()\n\n # Case 2: generator-like. Input is Python generator, or Sequence object,\n # or a non-distributed Dataset or iterator in eager execution.\n if data_utils.is_generator_or_sequence(inputs):\n return training_generator.GeneratorOrSequenceTrainingLoop()\n if training_utils.is_eager_dataset_or_iterator(inputs):\n return training_generator.EagerDatasetOrIteratorTrainingLoop()\n\n # Case 3: Symbolic tensors or Numpy array-like.\n # This includes Datasets and iterators in graph mode (since they\n # generate symbolic tensors).\n if self.run_eagerly:\n return training_generator.GeneratorLikeTrainingLoop()\n else:\n return training_arrays.ArrayLikeTrainingLoop()\n\n def fit(self,\n x=None,\n y=None,\n batch_size=None,\n epochs=1,\n verbose=1,\n callbacks=None,\n validation_split=0.,\n validation_data=None,\n shuffle=True,\n class_weight=None,\n sample_weight=None,\n initial_epoch=0,\n steps_per_epoch=None,\n validation_steps=None,\n validation_freq=1,\n max_queue_size=10,\n workers=1,\n use_multiprocessing=False,\n **kwargs):\n \"\"\"Trains the model for a fixed number of epochs (iterations on a dataset).\n\n Arguments:\n x: Input data. It could be:\n - A Numpy array (or array-like), or a list of arrays\n (in case the model has multiple inputs).\n - A TensorFlow tensor, or a list of tensors\n (in case the model has multiple inputs).\n - A dict mapping input names to the corresponding array/tensors,\n if the model has named inputs.\n - A `tf.data` dataset. Should return a tuple\n of either `(inputs, targets)` or\n `(inputs, targets, sample_weights)`.\n - A generator or `keras.utils.Sequence` returning `(inputs, targets)`\n or `(inputs, targets, sample weights)`.\n y: Target data. Like the input data `x`,\n it could be either Numpy array(s) or TensorFlow tensor(s).\n It should be consistent with `x` (you cannot have Numpy inputs and\n tensor targets, or inversely). If `x` is a dataset, generator,\n or `keras.utils.Sequence` instance, `y` should\n not be specified (since targets will be obtained from `x`).\n batch_size: Integer or `None`.\n Number of samples per gradient update.\n If unspecified, `batch_size` will default to 32.\n Do not specify the `batch_size` if your data is in the\n form of symbolic tensors, datasets,\n generators, or `keras.utils.Sequence` instances (since they generate\n batches).\n epochs: Integer. Number of epochs to train the model.\n An epoch is an iteration over the entire `x` and `y`\n data provided.\n Note that in conjunction with `initial_epoch`,\n `epochs` is to be understood as \"final epoch\".\n The model is not trained for a number of iterations\n given by `epochs`, but merely until the epoch\n of index `epochs` is reached.\n verbose: 0, 1, or 2. Verbosity mode.\n 0 = silent, 1 = progress bar, 2 = one line per epoch.\n Note that the progress bar is not particularly useful when\n logged to a file, so verbose=2 is recommended when not running\n interactively (eg, in a production environment).\n callbacks: List of `keras.callbacks.Callback` instances.\n List of callbacks to apply during training.\n See `tf.keras.callbacks`.\n validation_split: Float between 0 and 1.\n Fraction of the training data to be used as validation data.\n The model will set apart this fraction of the training data,\n will not train on it, and will evaluate\n the loss and any model metrics\n on this data at the end of each epoch.\n The validation data is selected from the last samples\n in the `x` and `y` data provided, before shuffling. This argument is\n not supported when `x` is a dataset, generator or\n `keras.utils.Sequence` instance.\n validation_data: Data on which to evaluate\n the loss and any model metrics at the end of each epoch.\n The model will not be trained on this data.\n `validation_data` will override `validation_split`.\n `validation_data` could be:\n - tuple `(x_val, y_val)` of Numpy arrays or tensors\n - tuple `(x_val, y_val, val_sample_weights)` of Numpy arrays\n - dataset\n For the first two cases, `batch_size` must be provided.\n For the last case, `validation_steps` could be provided.\n shuffle: Boolean (whether to shuffle the training data\n before each epoch) or str (for 'batch').\n 'batch' is a special option for dealing with the\n limitations of HDF5 data; it shuffles in batch-sized chunks.\n Has no effect when `steps_per_epoch` is not `None`.\n class_weight: Optional dictionary mapping class indices (integers)\n to a weight (float) value, used for weighting the loss function\n (during training only).\n This can be useful to tell the model to\n \"pay more attention\" to samples from\n an under-represented class.\n sample_weight: Optional Numpy array of weights for\n the training samples, used for weighting the loss function\n (during training only). You can either pass a flat (1D)\n Numpy array with the same length as the input samples\n (1:1 mapping between weights and samples),\n or in the case of temporal data,\n you can pass a 2D array with shape\n `(samples, sequence_length)`,\n to apply a different weight to every timestep of every sample.\n In this case you should make sure to specify\n `sample_weight_mode=\"temporal\"` in `compile()`. This argument is not\n supported when `x` is a dataset, generator, or\n `keras.utils.Sequence` instance, instead provide the sample_weights\n as the third element of `x`.\n initial_epoch: Integer.\n Epoch at which to start training\n (useful for resuming a previous training run).\n steps_per_epoch: Integer or `None`.\n Total number of steps (batches of samples)\n before declaring one epoch finished and starting the\n next epoch. When training with input tensors such as\n TensorFlow data tensors, the default `None` is equal to\n the number of samples in your dataset divided by\n the batch size, or 1 if that cannot be determined. If x is a\n `tf.data` dataset, and 'steps_per_epoch'\n is None, the epoch will run until the input dataset is exhausted.\n This argument is not supported with array inputs.\n validation_steps: Only relevant if `validation_data` is provided and\n is a `tf.data` dataset. Total number of steps (batches of\n samples) to draw before stopping when performing validation\n at the end of every epoch. If 'validation_steps' is None, validation\n will run until the `validation_data` dataset is exhausted. In the\n case of a infinite dataset, it will run into a infinite loop.\n If 'validation_steps' is specified and only part of the dataset\n will be consumed, the evaluation will start from the beginning of\n the dataset at each epoch. This ensures that the same validation\n samples are used every time.\n validation_freq: Only relevant if validation data is provided. Integer\n or `collections_abc.Container` instance (e.g. list, tuple, etc.).\n If an integer, specifies how many training epochs to run before a\n new validation run is performed, e.g. `validation_freq=2` runs\n validation every 2 epochs. If a Container, specifies the epochs on\n which to run validation, e.g. `validation_freq=[1, 2, 10]` runs\n validation at the end of the 1st, 2nd, and 10th epochs.\n max_queue_size: Integer. Used for generator or `keras.utils.Sequence`\n input only. Maximum size for the generator queue.\n If unspecified, `max_queue_size` will default to 10.\n workers: Integer. Used for generator or `keras.utils.Sequence` input\n only. Maximum number of processes to spin up\n when using process-based threading. If unspecified, `workers`\n will default to 1. If 0, will execute the generator on the main\n thread.\n use_multiprocessing: Boolean. Used for generator or\n `keras.utils.Sequence` input only. If `True`, use process-based\n threading. If unspecified, `use_multiprocessing` will default to\n `False`. Note that because this implementation relies on\n multiprocessing, you should not pass non-picklable arguments to\n the generator as they can't be passed easily to children processes.\n **kwargs: Used for backwards compatibility.\n\n Returns:\n A `History` object. Its `History.history` attribute is\n a record of training loss values and metrics values\n at successive epochs, as well as validation loss values\n and validation metrics values (if applicable).\n\n Raises:\n RuntimeError: If the model was never compiled.\n ValueError: In case of mismatch between the provided input data\n and what the model expects.\n \"\"\"\n _keras_api_gauge.get_cell('fit_v1').set(True)\n # Legacy support\n if 'nb_epoch' in kwargs:\n logging.warning(\n 'The `nb_epoch` argument in `fit` has been renamed `epochs`.')\n epochs = kwargs.pop('nb_epoch')\n if kwargs:\n raise TypeError('Unrecognized keyword arguments: ' + str(kwargs))\n self._assert_compile_was_called()\n self._check_call_args('fit')\n\n func = self._select_training_loop(x)\n return func.fit(\n self,\n x=x,\n y=y,\n batch_size=batch_size,\n epochs=epochs,\n verbose=verbose,\n callbacks=callbacks,\n validation_split=validation_split,\n validation_data=validation_data,\n shuffle=shuffle,\n class_weight=class_weight,\n sample_weight=sample_weight,\n initial_epoch=initial_epoch,\n steps_per_epoch=steps_per_epoch,\n validation_steps=validation_steps,\n validation_freq=validation_freq,\n max_queue_size=max_queue_size,\n workers=workers,\n use_multiprocessing=use_multiprocessing)\n\n def evaluate(self,\n x=None,\n y=None,\n batch_size=None,\n verbose=1,\n sample_weight=None,\n steps=None,\n callbacks=None,\n max_queue_size=10,\n workers=1,\n use_multiprocessing=False):\n \"\"\"Returns the loss value & metrics values for the model in test mode.\n\n Computation is done in batches.\n\n Arguments:\n x: Input data. It could be:\n - A Numpy array (or array-like), or a list of arrays\n (in case the model has multiple inputs).\n - A TensorFlow tensor, or a list of tensors\n (in case the model has multiple inputs).\n - A dict mapping input names to the corresponding array/tensors,\n if the model has named inputs.\n - A `tf.data` dataset.\n - A generator or `keras.utils.Sequence` instance.\n y: Target data. Like the input data `x`,\n it could be either Numpy array(s) or TensorFlow tensor(s).\n It should be consistent with `x` (you cannot have Numpy inputs and\n tensor targets, or inversely).\n If `x` is a dataset, generator or\n `keras.utils.Sequence` instance, `y` should not be specified (since\n targets will be obtained from the iterator/dataset).\n batch_size: Integer or `None`.\n Number of samples per gradient update.\n If unspecified, `batch_size` will default to 32.\n Do not specify the `batch_size` if your data is in the\n form of symbolic tensors, dataset,\n generators, or `keras.utils.Sequence` instances (since they generate\n batches).\n verbose: 0 or 1. Verbosity mode.\n 0 = silent, 1 = progress bar.\n sample_weight: Optional Numpy array of weights for\n the test samples, used for weighting the loss function.\n You can either pass a flat (1D)\n Numpy array with the same length as the input samples\n (1:1 mapping between weights and samples),\n or in the case of temporal data,\n you can pass a 2D array with shape\n `(samples, sequence_length)`,\n to apply a different weight to every timestep of every sample.\n In this case you should make sure to specify\n `sample_weight_mode=\"temporal\"` in `compile()`. This argument is not\n supported when `x` is a dataset, instead pass\n sample weights as the third element of `x`.\n steps: Integer or `None`.\n Total number of steps (batches of samples)\n before declaring the evaluation round finished.\n Ignored with the default value of `None`.\n If x is a `tf.data` dataset and `steps` is\n None, 'evaluate' will run until the dataset is exhausted.\n This argument is not supported with array inputs.\n callbacks: List of `keras.callbacks.Callback` instances.\n List of callbacks to apply during evaluation.\n See [callbacks](/api_docs/python/tf/keras/callbacks).\n max_queue_size: Integer. Used for generator or `keras.utils.Sequence`\n input only. Maximum size for the generator queue.\n If unspecified, `max_queue_size` will default to 10.\n workers: Integer. Used for generator or `keras.utils.Sequence` input\n only. Maximum number of processes to spin up when using\n process-based threading. If unspecified, `workers` will default\n to 1. If 0, will execute the generator on the main thread.\n use_multiprocessing: Boolean. Used for generator or\n `keras.utils.Sequence` input only. If `True`, use process-based\n threading. If unspecified, `use_multiprocessing` will default to\n `False`. Note that because this implementation relies on\n multiprocessing, you should not pass non-picklable arguments to\n the generator as they can't be passed easily to children processes.\n\n Returns:\n Scalar test loss (if the model has a single output and no metrics)\n or list of scalars (if the model has multiple outputs\n and/or metrics). The attribute `model.metrics_names` will give you\n the display labels for the scalar outputs.\n\n Raises:\n ValueError: in case of invalid arguments.\n \"\"\"\n _keras_api_gauge.get_cell('evaluate_v1').set(True)\n self._assert_compile_was_called()\n self._check_call_args('evaluate')\n\n func = self._select_training_loop(x)\n return func.evaluate(\n self,\n x=x,\n y=y,\n batch_size=batch_size,\n verbose=verbose,\n sample_weight=sample_weight,\n steps=steps,\n callbacks=callbacks,\n max_queue_size=max_queue_size,\n workers=workers,\n use_multiprocessing=use_multiprocessing)\n\n def predict(self,\n x,\n batch_size=None,\n verbose=0,\n steps=None,\n callbacks=None,\n max_queue_size=10,\n workers=1,\n use_multiprocessing=False):\n \"\"\"Generates output predictions for the input samples.\n\n Computation is done in batches.\n\n Arguments:\n x: Input samples. It could be:\n - A Numpy array (or array-like), or a list of arrays\n (in case the model has multiple inputs).\n - A TensorFlow tensor, or a list of tensors\n (in case the model has multiple inputs).\n - A `tf.data` dataset.\n - A generator or `keras.utils.Sequence` instance.\n batch_size: Integer or `None`.\n Number of samples per gradient update.\n If unspecified, `batch_size` will default to 32.\n Do not specify the `batch_size` if your data is in the\n form of symbolic tensors, dataset,\n generators, or `keras.utils.Sequence` instances (since they generate\n batches).\n verbose: Verbosity mode, 0 or 1.\n steps: Total number of steps (batches of samples)\n before declaring the prediction round finished.\n Ignored with the default value of `None`. If x is a `tf.data`\n dataset and `steps` is None, `predict` will\n run until the input dataset is exhausted.\n callbacks: List of `keras.callbacks.Callback` instances.\n List of callbacks to apply during prediction.\n See [callbacks](/api_docs/python/tf/keras/callbacks).\n max_queue_size: Integer. Used for generator or `keras.utils.Sequence`\n input only. Maximum size for the generator queue.\n If unspecified, `max_queue_size` will default to 10.\n workers: Integer. Used for generator or `keras.utils.Sequence` input\n only. Maximum number of processes to spin up when using\n process-based threading. If unspecified, `workers` will default\n to 1. If 0, will execute the generator on the main thread.\n use_multiprocessing: Boolean. Used for generator or\n `keras.utils.Sequence` input only. If `True`, use process-based\n threading. If unspecified, `use_multiprocessing` will default to\n `False`. Note that because this implementation relies on\n multiprocessing, you should not pass non-picklable arguments to\n the generator as they can't be passed easily to children processes.\n\n\n Returns:\n Numpy array(s) of predictions.\n\n Raises:\n ValueError: In case of mismatch between the provided\n input data and the model's expectations,\n or in case a stateful model receives a number of samples\n that is not a multiple of the batch size.\n \"\"\"\n _keras_api_gauge.get_cell('predict_v1').set(True)\n self._check_call_args('predict')\n\n func = self._select_training_loop(x)\n return func.predict(\n self,\n x=x,\n batch_size=batch_size,\n verbose=verbose,\n steps=steps,\n callbacks=callbacks,\n max_queue_size=max_queue_size,\n workers=workers,\n use_multiprocessing=use_multiprocessing)\n\n def reset_metrics(self):\n \"\"\"Resets the state of metrics.\"\"\"\n metrics = self._get_training_eval_metrics()\n for m in metrics:\n m.reset_states()\n\n # Reset metrics on all the distributed (cloned) models.\n if self._distribution_strategy:\n distributed_training_utils._reset_metrics(self) # pylint: disable=protected-access\n\n def train_on_batch(self,\n x,\n y=None,\n sample_weight=None,\n class_weight=None,\n reset_metrics=True):\n \"\"\"Runs a single gradient update on a single batch of data.\n\n Arguments:\n x: Input data. It could be:\n - A Numpy array (or array-like), or a list of arrays\n (in case the model has multiple inputs).\n - A TensorFlow tensor, or a list of tensors\n (in case the model has multiple inputs).\n - A dict mapping input names to the corresponding array/tensors,\n if the model has named inputs.\n - A `tf.data` dataset.\n y: Target data. Like the input data `x`, it could be either Numpy\n array(s) or TensorFlow tensor(s). It should be consistent with `x`\n (you cannot have Numpy inputs and tensor targets, or inversely). If\n `x` is a dataset, `y` should not be specified\n (since targets will be obtained from the iterator).\n sample_weight: Optional array of the same length as x, containing\n weights to apply to the model's loss for each sample. In the case of\n temporal data, you can pass a 2D array with shape (samples,\n sequence_length), to apply a different weight to every timestep of\n every sample. In this case you should make sure to specify\n sample_weight_mode=\"temporal\" in compile(). This argument is not\n supported when `x` is a dataset.\n class_weight: Optional dictionary mapping class indices (integers) to a\n weight (float) to apply to the model's loss for the samples from this\n class during training. This can be useful to tell the model to \"pay\n more attention\" to samples from an under-represented class.\n reset_metrics: If `True`, the metrics returned will be only for this\n batch. If `False`, the metrics will be statefully accumulated across\n batches.\n\n Returns:\n Scalar training loss\n (if the model has a single output and no metrics)\n or list of scalars (if the model has multiple outputs\n and/or metrics). The attribute `model.metrics_names` will give you\n the display labels for the scalar outputs.\n\n Raises:\n ValueError: In case of invalid user-provided arguments.\n \"\"\"\n self._assert_compile_was_called()\n self._check_call_args('train_on_batch')\n\n # If at this point we are in the replica context, then it is okay to execute\n # the Eager code path. The expected way to get here is to call `fit` that\n # calls `train_on_batch` on each replica.\n if (self._distribution_strategy and\n distribution_strategy_context.in_cross_replica_context()):\n raise NotImplementedError('`train_on_batch` is not supported for models '\n 'distributed with tf.distribute.Strategy.')\n # Validate and standardize user data.\n x, y, sample_weights = self._standardize_user_data(\n x, y, sample_weight=sample_weight, class_weight=class_weight,\n extract_tensors_from_dataset=True)\n\n # If `self._distribution_strategy` is True, then we are in a replica context\n # at this point because of the check above. `train_on_batch` is being run\n # for each replica by `self._distribution_strategy` and the same code path\n # as Eager is expected to be taken.\n if self.run_eagerly or self._distribution_strategy:\n output_dict = training_eager.train_on_batch(\n self,\n x,\n y,\n sample_weights=sample_weights,\n output_loss_metrics=self._output_loss_metrics)\n outputs = (output_dict['total_loss'] + output_dict['output_losses']\n + output_dict['metrics'])\n outputs = [_non_none_constant_value(v) for v in outputs] # pylint: disable=protected-access\n else:\n x = training_utils.ModelInputs(x).as_list()\n ins = x + list(y or []) + list(sample_weights or [])\n\n if not isinstance(K.symbolic_learning_phase(), int):\n ins += [True] # Add learning phase value.\n\n self._update_sample_weight_modes(sample_weights=sample_weights)\n self._make_train_function()\n outputs = self.train_function(ins) # pylint: disable=not-callable\n\n if reset_metrics:\n self.reset_metrics()\n\n if len(outputs) == 1:\n return outputs[0]\n return outputs\n\n def test_on_batch(self, x, y=None, sample_weight=None, reset_metrics=True):\n \"\"\"Test the model on a single batch of samples.\n\n Arguments:\n x: Input data. It could be:\n - A Numpy array (or array-like), or a list of arrays\n (in case the model has multiple inputs).\n - A TensorFlow tensor, or a list of tensors\n (in case the model has multiple inputs).\n - A dict mapping input names to the corresponding array/tensors,\n if the model has named inputs.\n - A `tf.data` dataset.\n y: Target data. Like the input data `x`,\n it could be either Numpy array(s) or TensorFlow tensor(s).\n It should be consistent with `x` (you cannot have Numpy inputs and\n tensor targets, or inversely). If `x` is a dataset `y` should\n not be specified (since targets will be obtained from the iterator).\n sample_weight: Optional array of the same length as x, containing\n weights to apply to the model's loss for each sample.\n In the case of temporal data, you can pass a 2D array\n with shape (samples, sequence_length),\n to apply a different weight to every timestep of every sample.\n In this case you should make sure to specify\n sample_weight_mode=\"temporal\" in compile(). This argument is not\n supported when `x` is a dataset.\n reset_metrics: If `True`, the metrics returned will be only for this\n batch. If `False`, the metrics will be statefully accumulated across\n batches.\n\n Returns:\n Scalar test loss (if the model has a single output and no metrics)\n or list of scalars (if the model has multiple outputs\n and/or metrics). The attribute `model.metrics_names` will give you\n the display labels for the scalar outputs.\n\n Raises:\n ValueError: In case of invalid user-provided arguments.\n \"\"\"\n self._assert_compile_was_called()\n self._check_call_args('test_on_batch')\n\n if (self._distribution_strategy and\n distribution_strategy_context.in_cross_replica_context()):\n raise NotImplementedError('`test_on_batch` is not supported for models '\n 'distributed with tf.distribute.Strategy.')\n # Validate and standardize user data.\n x, y, sample_weights = self._standardize_user_data(\n x, y, sample_weight=sample_weight, extract_tensors_from_dataset=True)\n\n # If `self._distribution_strategy` is True, then we are in a replica context\n # at this point.\n if self.run_eagerly or self._distribution_strategy:\n output_dict = training_eager.test_on_batch(\n self,\n x,\n y,\n sample_weights=sample_weights,\n output_loss_metrics=self._output_loss_metrics)\n outputs = (output_dict['total_loss'] + output_dict['output_losses']\n + output_dict['metrics'])\n outputs = [_non_none_constant_value(v) for v in outputs] # pylint: disable=protected-access\n else:\n x = training_utils.ModelInputs(x).as_list()\n inputs = x + list(y or []) + list(sample_weights or [])\n\n self._update_sample_weight_modes(sample_weights=sample_weights)\n self._make_test_function()\n outputs = self.test_function(inputs) # pylint: disable=not-callable\n\n if reset_metrics:\n self.reset_metrics()\n\n if len(outputs) == 1:\n return outputs[0]\n return outputs\n\n def predict_on_batch(self, x):\n \"\"\"Returns predictions for a single batch of samples.\n\n Arguments:\n x: Input data. It could be:\n - A Numpy array (or array-like), or a list of arrays\n (in case the model has multiple inputs).\n - A TensorFlow tensor, or a list of tensors\n (in case the model has multiple inputs).\n - A `tf.data` dataset.\n\n Returns:\n Numpy array(s) of predictions.\n\n Raises:\n ValueError: In case of mismatch between given number of inputs and\n expectations of the model.\n \"\"\"\n self._check_call_args('predict_on_batch')\n\n if (self._distribution_strategy and\n distribution_strategy_context.in_cross_replica_context()):\n raise NotImplementedError(\n '`predict_on_batch` is not supported for models distributed with'\n ' tf.distribute.Strategy.')\n # Validate and standardize user data.\n inputs, _, _ = self._standardize_user_data(\n x, extract_tensors_from_dataset=True)\n # If `self._distribution_strategy` is True, then we are in a replica context\n # at this point.\n if self.run_eagerly or self._distribution_strategy:\n inputs = training_utils.cast_if_floating_dtype(inputs)\n if isinstance(inputs, collections_abc.Sequence):\n # Unwrap lists with only one input, as we do when training on batch\n if len(inputs) == 1:\n inputs = inputs[0]\n\n return self(inputs) # pylint: disable=not-callable\n\n self._make_predict_function()\n outputs = self.predict_function(inputs)\n\n if len(outputs) == 1:\n return outputs[0]\n return outputs\n\n @deprecation.deprecated(\n None, 'Please use Model.fit, which supports generators.')\n def fit_generator(self,\n generator,\n steps_per_epoch=None,\n epochs=1,\n verbose=1,\n callbacks=None,\n validation_data=None,\n validation_steps=None,\n validation_freq=1,\n class_weight=None,\n max_queue_size=10,\n workers=1,\n use_multiprocessing=False,\n shuffle=True,\n initial_epoch=0):\n \"\"\"Fits the model on data yielded batch-by-batch by a Python generator.\n\n DEPRECATED:\n `Model.fit` now supports generators, so there is no longer any need to use\n this endpoint.\n \"\"\"\n return self.fit(\n generator,\n steps_per_epoch=steps_per_epoch,\n epochs=epochs,\n verbose=verbose,\n callbacks=callbacks,\n validation_data=validation_data,\n validation_steps=validation_steps,\n validation_freq=validation_freq,\n class_weight=class_weight,\n max_queue_size=max_queue_size,\n workers=workers,\n use_multiprocessing=use_multiprocessing,\n shuffle=shuffle,\n initial_epoch=initial_epoch)\n\n @deprecation.deprecated(\n None, 'Please use Model.evaluate, which supports generators.')\n def evaluate_generator(self,\n generator,\n steps=None,\n callbacks=None,\n max_queue_size=10,\n workers=1,\n use_multiprocessing=False,\n verbose=0):\n \"\"\"Evaluates the model on a data generator.\n\n DEPRECATED:\n `Model.evaluate` now supports generators, so there is no longer any need\n to use this endpoint.\n \"\"\"\n self._check_call_args('evaluate_generator')\n\n return self.evaluate(\n generator,\n steps=steps,\n max_queue_size=max_queue_size,\n workers=workers,\n use_multiprocessing=use_multiprocessing,\n verbose=verbose,\n callbacks=callbacks)\n\n @deprecation.deprecated(\n None, 'Please use Model.predict, which supports generators.')\n def predict_generator(self,\n generator,\n steps=None,\n callbacks=None,\n max_queue_size=10,\n workers=1,\n use_multiprocessing=False,\n verbose=0):\n \"\"\"Generates predictions for the input samples from a data generator.\n\n DEPRECATED:\n `Model.predict` now supports generators, so there is no longer any need\n to use this endpoint.\n \"\"\"\n return self.predict(\n generator,\n steps=steps,\n max_queue_size=max_queue_size,\n workers=workers,\n use_multiprocessing=use_multiprocessing,\n verbose=verbose,\n callbacks=callbacks)\n\n def _check_call_args(self, method_name):\n \"\"\"Check that `call` has only one positional arg.\"\"\"\n # Always allow first arg, regardless of arg name.\n fullargspec = self._call_full_argspec\n if fullargspec.defaults:\n positional_args = fullargspec.args[:-len(fullargspec.defaults)]\n else:\n positional_args = fullargspec.args\n if 'training' in positional_args:\n positional_args.remove('training')\n\n # self and first arg can be positional.\n if len(positional_args) > 2:\n extra_args = positional_args[2:]\n raise ValueError(\n 'Models passed to `' + method_name + '` can only have `training` '\n 'and the first argument in `call` as positional arguments, '\n 'found: ' + str(extra_args) + '.')\n\n def _set_optimizer(self, optimizer):\n \"\"\"Sets self.optimizer.\n\n Sets self.optimizer to `optimizer`, potentially wrapping it with a\n LossScaleOptimizer.\n\n Args:\n optimizer: The optimizer(s) to assign to self.optimizer.\n \"\"\"\n if isinstance(optimizer, (list, tuple)):\n self.optimizer = [optimizers.get(opt) for opt in optimizer]\n else:\n self.optimizer = optimizers.get(optimizer)\n\n if (self._dtype_policy.loss_scale is not None and\n not isinstance(self.optimizer,\n loss_scale_optimizer.LossScaleOptimizer)):\n if isinstance(self.optimizer, list):\n raise ValueError('When a dtype policy with a loss scale is used, you '\n 'can only pass a single optimizer. Using policy %s '\n 'and got optimizers: %s' %\n self._dtype_policy, self.optimizer)\n if not isinstance(self.optimizer, optimizer_v2.OptimizerV2):\n raise ValueError('\"optimizer\" must be an instance of '\n 'tf.keras.optimizers.Optimizer when a dype policy '\n 'with a loss scale used, but got: %s. Using policy: '\n '%s' %\n (self.optimizer, self._dtype_policy))\n self.optimizer = loss_scale_optimizer.LossScaleOptimizer(\n self.optimizer, self._dtype_policy.loss_scale)\n if (isinstance(self.optimizer, loss_scale_optimizer.LossScaleOptimizer) and\n self._dtype_policy.loss_scale and\n self.optimizer.loss_scale != self._dtype_policy.loss_scale):\n logging.warning('LossScale of LossScaleOptimizer passed to compile (%s) '\n 'is not the same as the dtype policy\\'s loss scale (%s). '\n 'Because the dtype policy has a loss scale, you should '\n 'pass an optimizer that is not wrapped with a '\n 'LossScaleOptimizer,'\n % (self.optimizer.loss_scale,\n self._dtype_policy.loss_scale))\n\n def _prepare_validation_data(self, validation_data, batch_size,\n validation_steps):\n \"\"\"Unpack and check the validation data.\"\"\"\n val_x, val_y, val_sample_weights = training_utils.unpack_validation_data(\n validation_data)\n return self._standardize_user_data(\n val_x,\n val_y,\n sample_weight=val_sample_weights,\n batch_size=batch_size,\n steps=validation_steps,\n steps_name='validation_steps')\n\n def _validate_compile_param_for_distribution_strategy(\n self, run_eagerly, sample_weight_mode, target_tensors, weighted_metrics):\n # Validate that arguments passed by the user to `compile` are supported by\n # tf.distribute.Strategy.\n if self._distribution_strategy:\n if sample_weight_mode:\n raise NotImplementedError('sample_weight_mode is not supported with '\n 'tf.distribute.Strategy.')\n if weighted_metrics:\n raise NotImplementedError('weighted_metrics is not supported with '\n 'tf.distribute.Strategy.')\n if target_tensors:\n raise ValueError('target_tensors is not supported with '\n 'tf.distribute.Strategy.')\n\n if run_eagerly:\n raise ValueError(\n 'We currently do not support enabling `run_eagerly` with '\n 'distribution strategy.')\n\n if (distributed_training_utils.is_distributing_by_cloning(self) and\n (not self.built or not self.inputs or not self.outputs)):\n raise ValueError(\n 'We currently do not support distribution strategy with a '\n '`Sequential` model that is created without `input_shape`/'\n '`input_dim` set in its first layer or a subclassed model.')\n\n def _process_target_tensor_for_compile(self, target_tensors):\n if self.run_eagerly:\n # target tensor is not supported with run_eagerly. Create a list with None\n # as placeholder for each output.\n return [None for _ in self.output_names]\n\n if target_tensors is not None and not (isinstance(target_tensors, list) and\n target_tensors == []): # pylint: disable=g-explicit-bool-comparison\n if isinstance(target_tensors, list):\n if len(target_tensors) != len(self.outputs):\n raise ValueError(\n 'When passing a list as `target_tensors`, '\n 'it should have one entry per model output. '\n 'The model has %s outputs, but you passed target_tensors=%s' %\n (len(self.outputs), target_tensors))\n elif isinstance(target_tensors, dict):\n unexpected_target_tensor_names = set(target_tensors.keys()).difference(\n self.output_names)\n if unexpected_target_tensor_names:\n raise ValueError(\n 'Unknown entry in `target_tensors` dictionary: \"{name}\". '\n 'Only expected the following keys: {keys}'.format(\n name=unexpected_target_tensor_names,\n keys=str(self.output_names)))\n tmp_target_tensors = []\n for name in self.output_names:\n tmp_target_tensors.append(target_tensors.get(name, None))\n target_tensors = tmp_target_tensors\n elif tensor_util.is_tensor(target_tensors):\n target_tensors = [target_tensors]\n else:\n raise TypeError('Expected `target_tensors` to be a list or tuple or '\n 'dict or a single tensor, but got:', target_tensors)\n else:\n # In case target tensor is empty or None, create a list with Nones\n # that has same length as self.output_names. With that, the None check of\n # target tensor can be skipped downstream.\n target_tensors = [None for _ in self.output_names]\n return target_tensors\n\n def _compile_eagerly(self, metrics, weighted_metrics, sample_weight_mode):\n # Prepare sample weight modes. List with the same length as model outputs.\n training_utils.prepare_sample_weight_modes(\n self._training_endpoints, sample_weight_mode)\n # Prepare sample weights.\n self._prepare_sample_weights()\n # Save all metric attributes per output of the model.\n self._cache_output_metric_attributes(metrics, weighted_metrics)\n self.total_loss = None\n # Set metric attributes on model.\n self._set_metric_attributes()\n\n self._collected_trainable_weights = self.trainable_weights\n\n def _update_sample_weight_modes(self, sample_weights=None):\n \"\"\"Updates sample weight modes based on training/eval inputs.\n\n Sample weight placeholders will be created for all or no outputs\n based on whether sample_weight is provided for any output.\n\n If model contains `_sample_weight_modes` we check if the input\n `sample_weights` corresponds to the sample weight modes.\n 1. Set sample weight mode to be 'temporal' for output i, if `compile`\n sample_weight_mode was set to `temporal` and sample weight inputs\n are given for one or more outputs.\n 2. Set sample weight mode to be 'samplewise' for output i, if `compile`\n sample_weight_mode was not set and sample weight inputs are given for\n one or more outputs.\n 3. Reset sample weight mode to None for output i if sample weight mode\n was set but there is no sample weight input.\n\n Args:\n sample_weights: List of sample weights of the same length as model outputs\n or None.\n \"\"\"\n if not self._is_compiled:\n return\n if sample_weights and any(s is not None for s in sample_weights):\n for endpoint in self._training_endpoints:\n endpoint.sample_weight_mode = (\n endpoint.sample_weight_mode or 'samplewise')\n else:\n for endpoint in self._training_endpoints:\n endpoint.sample_weight_mode = None\n\n def _recompile_weights_loss_and_weighted_metrics(self):\n if not self._is_compiled:\n return False\n recompile = any([e.sample_weights_mismatch()\n for e in self._training_endpoints])\n\n if recompile:\n self._compile_weights_loss_and_weighted_metrics()\n return recompile\n\n @trackable.no_automatic_dependency_tracking\n def _compile_weights_loss_and_weighted_metrics(self, sample_weights=None):\n \"\"\"Compiles the model loss and weighted metric sub-graphs.\n\n This may be used to set graph tensors as sample weights (instead of creating\n placeholders). This functionality is necessary for\n `tf.keras.estimator.model_to_estimator`, which calls Keras models in a v1\n graph, and creates iterator tensors for inputs, targets, and sample weights.\n\n Args:\n sample_weights: List of tensors to use as the sample weights. Must be the\n same length as the number of outputs. If left as `None`, placeholders\n are used instead.\n \"\"\"\n with K.get_graph().as_default():\n if sample_weights is not None:\n self._update_sample_weight_modes(sample_weights)\n self._prepare_sample_weights(sample_weights)\n\n masks = self._prepare_output_masks()\n\n # Compute weighted metrics.\n self._handle_metrics(\n self.outputs,\n targets=self._targets,\n skip_target_masks=self._prepare_skip_target_masks(),\n sample_weights=self.sample_weights,\n masks=masks,\n return_weighted_metrics=True)\n\n # Compute total loss.\n # Used to keep track of the total loss value (stateless).\n # eg., total_loss = loss_weight_1 * output_1_loss_fn(...) +\n # loss_weight_2 * output_2_loss_fn(...) +\n # layer losses.\n self.total_loss = self._prepare_total_loss(masks)\n\n def _prepare_skip_target_masks(self):\n \"\"\"Boolean mask for whether the target in the output list should be skipped.\n\n If the loss function corresponding to a model output is None, then this\n output will be skipped during total loss calculation and feed targets\n preparation.\n\n Returns:\n A boolean list for whether the corresponding target in the output list\n should be skipped during loss calculation.\n \"\"\"\n return [l is None for l in self.loss_functions]\n\n def _prepare_output_masks(self):\n \"\"\"Returns masks corresponding to model outputs.\"\"\"\n return [getattr(x, '_keras_mask', None) for x in self.outputs]\n\n def _prepare_total_loss(self, masks):\n \"\"\"Computes total loss from loss functions.\n\n Arguments:\n masks: List of mask values corresponding to each model output.\n\n Returns:\n A list of loss weights of python floats.\n\n Raises:\n TypeError: If model run_eagerly is True.\n \"\"\"\n if self.run_eagerly:\n raise TypeError('total loss can not be computed when compiled with '\n 'run_eagerly = True.')\n loss_list = []\n with K.name_scope('loss'):\n for endpoint, mask in zip(self._training_endpoints, masks):\n if endpoint.should_skip_target():\n continue\n y_true = endpoint.training_target.target\n y_pred = endpoint.output\n loss_fn = endpoint.loss_fn\n loss_weight = endpoint.loss_weight\n loss_name = endpoint.loss_name()\n sample_weight = endpoint.sample_weight\n\n with K.name_scope(loss_name):\n if mask is not None:\n mask = math_ops.cast(mask, y_pred.dtype)\n # Update weights with mask.\n if sample_weight is None:\n sample_weight = mask\n else:\n # Update dimensions of weights to match with mask if possible.\n mask, _, sample_weight = (\n tf_losses_utils.squeeze_or_expand_dimensions(\n mask, sample_weight=sample_weight))\n sample_weight *= mask\n\n if hasattr(loss_fn, 'reduction'):\n per_sample_losses = loss_fn.call(y_true, y_pred)\n weighted_losses = losses_utils.compute_weighted_loss(\n per_sample_losses,\n sample_weight=sample_weight,\n reduction=losses_utils.ReductionV2.NONE)\n loss_reduction = loss_fn.reduction\n\n # `AUTO` loss reduction defaults to `SUM_OVER_BATCH_SIZE` for all\n # compile use cases.\n if loss_reduction == losses_utils.ReductionV2.AUTO:\n loss_reduction = losses_utils.ReductionV2.SUM_OVER_BATCH_SIZE\n\n # Compute the stateless loss value.\n output_loss = losses_utils.reduce_weighted_loss(\n weighted_losses, reduction=loss_reduction)\n else:\n # Compute the stateless loss value for a custom loss class.\n # Here we assume that the class takes care of loss reduction\n # because if this class returns a vector value we cannot\n # differentiate between use case where a custom optimizer\n # expects a vector loss value vs unreduced per-sample loss value.\n output_loss = loss_fn(y_true, y_pred, sample_weight=sample_weight)\n loss_reduction = losses_utils.ReductionV2.SUM_OVER_BATCH_SIZE\n\n if len(self.outputs) > 1:\n # Keep track of stateful result tensor for the loss.\n endpoint.output_loss_metric(output_loss)\n\n # Scale output loss for distribution. For custom losses we assume\n # reduction was mean.\n if loss_reduction == losses_utils.ReductionV2.SUM_OVER_BATCH_SIZE:\n output_loss = losses_utils.scale_loss_for_distribution(output_loss)\n\n loss_list.append(loss_weight * output_loss)\n if not loss_list and not self.losses:\n raise ValueError('The model cannot be compiled '\n 'because it has no loss to optimize.')\n\n # Add regularization penalties and other layer-specific losses.\n custom_losses = self.get_losses_for(None) + self.get_losses_for(\n self.inputs)\n if custom_losses:\n total_custom_loss = math_ops.add_n(\n losses_utils.cast_losses_to_common_dtype(custom_losses))\n loss_list.append(\n losses_utils.scale_loss_for_distribution(total_custom_loss))\n\n loss_list = losses_utils.cast_losses_to_common_dtype(loss_list)\n if loss_list:\n total_loss = math_ops.add_n(loss_list)\n else:\n total_loss = 0.\n return total_loss\n\n def _get_callback_model(self):\n \"\"\"Returns the Callback Model for this Model.\"\"\"\n\n if hasattr(self, '_replicated_model') and self._replicated_model:\n # When using training_distributed, we set the callback model\n # to an instance of the `DistributedModel` that we create in\n # the `compile` call. The `DistributedModel` is initialized\n # with the first replicated model. We need to set the callback\n # model to a DistributedModel to allow us to override saving\n # and loading weights when we checkpoint the model during training.\n return self._replicated_model\n if hasattr(self, 'callback_model') and self.callback_model:\n return self.callback_model\n return self\n\n @trackable.no_automatic_dependency_tracking\n def _make_callback_model(self, grouped_model):\n first_replicated_model = self._distribution_strategy.unwrap(\n grouped_model)[0]\n # We initialize the callback model with the first replicated model.\n self._replicated_model = DistributedCallbackModel(first_replicated_model)\n self._replicated_model.set_original_model(self)\n\n def _validate_or_infer_batch_size(self, batch_size, steps, x):\n \"\"\"Validates that the `batch_size` provided is consistent with InputLayer.\n\n It's possible that the user specified a static batch size in their\n InputLayer. If so, this method checks the provided `batch_size` and `x`\n arguments are consistent with this static batch size. Also, if\n `batch_size` is `None`, this method will attempt to infer the batch size\n from the static batch size of the InputLayer. Lastly, ValueError will be\n raised if `x` is a tf.data.Dataset and `batch_size` is specified as we\n expect users to provide batched datasets.\n\n Arguments:\n batch_size: The batch_size provided as an argument to\n fit/evaluate/predict.\n steps: The steps provided as an argument to fit/evaluate/predict.\n x: The data passed as `x` to fit/evaluate/predict.\n\n Returns:\n The validated batch_size, auto-inferred from the first layer if not\n provided.\n \"\"\"\n if (isinstance(x, (dataset_ops.DatasetV1,\n dataset_ops.DatasetV2,\n data_utils.Sequence)) or\n tf_inspect.isgenerator(x)):\n if batch_size is not None:\n raise ValueError(\n 'The `batch_size` argument must not be specified for the given '\n 'input type. Received input: {}, batch_size: {}'.format(\n x, batch_size))\n return\n\n # Avoids the override in Sequential.layers which filters Input layers.\n # (Which are often the very layers that we're after.)\n layers = trackable_layer_utils.filter_empty_layer_containers(self._layers)\n first_layer = next(layers, None)\n if first_layer:\n # The per-replica static batch size.\n static_batch_size = training_utils.get_static_batch_size(first_layer)\n if static_batch_size is not None:\n\n # Determine number of times the user-supplied batch size will be split.\n if (self._distribution_strategy and\n distributed_training_utils.global_batch_size_supported(\n self._distribution_strategy)):\n num_splits_for_ds = self._distribution_strategy.num_replicas_in_sync\n else:\n num_splits_for_ds = 1\n\n # Check `batch_size` argument is consistent with InputLayer.\n if batch_size is not None:\n if batch_size % num_splits_for_ds != 0:\n raise ValueError('The `batch_size` argument ({}) must be divisible '\n 'the by number of replicas ({})'.format(\n batch_size, num_splits_for_ds))\n per_replica_batch_size = batch_size // num_splits_for_ds\n\n if per_replica_batch_size != static_batch_size:\n raise ValueError('The `batch_size` argument value {} is '\n 'incompatible with the specified batch size of '\n 'your Input Layer: {}'.format(\n per_replica_batch_size, static_batch_size))\n\n # Check Dataset/Iterator batch size is consistent with InputLayer.\n if isinstance(x, (dataset_ops.DatasetV2, iterator_ops.Iterator,\n iterator_ops.OwnedIterator)):\n ds_batch_size = tensor_shape.as_dimension(\n nest.flatten(dataset_ops.get_legacy_output_shapes(x))[0][0]).value\n if ds_batch_size is not None:\n if ds_batch_size % num_splits_for_ds != 0:\n raise ValueError(\n 'The batch output shape of your `Dataset` {} '\n 'cannot be divisible by number of replicas {}'.format(\n ds_batch_size, num_splits_for_ds))\n\n ds_per_replica_batch_size = ds_batch_size // num_splits_for_ds\n if ds_per_replica_batch_size != static_batch_size:\n raise ValueError('The batch output shape of your `Dataset` is '\n '{}, which is incompatible with the specified '\n 'batch size of your Input Layer: {}'.format(\n ds_per_replica_batch_size,\n static_batch_size))\n\n # Set inferred batch size from the InputLayer.\n if steps is None:\n batch_size = static_batch_size * num_splits_for_ds\n\n if batch_size is None and steps is None:\n # Backwards compatibility\n batch_size = 32\n return batch_size\n\n def _prepare_sample_weights(self, sample_weights=None):\n \"\"\"Sets sample weight attribute on the model.\"\"\"\n # List with the same length as model outputs.\n if sample_weights is not None:\n if len(sample_weights) != len(self._training_endpoints):\n raise ValueError('Provided sample weights must have same length as the '\n 'number of outputs. Expected: {}, got: {}.'.format(\n len(self._training_endpoints),\n len(sample_weights)))\n else:\n sample_weights = [None] * len(self._training_endpoints)\n for endpoint, weight in zip(self._training_endpoints, sample_weights):\n endpoint.populate_sample_weight(weight, endpoint.sample_weight_mode)\n\n def _cache_output_metric_attributes(self, metrics, weighted_metrics):\n \"\"\"Caches metric name and function attributes for every model output.\"\"\"\n output_shapes = []\n for output in self.outputs:\n if output is None or output.shape.rank is None:\n output_shapes.append(None)\n else:\n output_shapes.append(output.shape.as_list())\n self._per_output_metrics = training_utils.collect_per_output_metric_info(\n metrics, self.output_names, output_shapes, self.loss_functions)\n self._per_output_weighted_metrics = (\n training_utils.collect_per_output_metric_info(\n weighted_metrics,\n self.output_names,\n output_shapes,\n self.loss_functions,\n is_weighted=True))\n\n def _add_unique_metric_name(self, metric_name, output_index):\n \"\"\"Makes the metric name unique and adds it to the model's metric name list.\n\n If there are multiple outputs for which the metrics are calculated, the\n metric names have to be made unique by appending an integer.\n\n Arguments:\n metric_name: Metric name that corresponds to the metric specified by the\n user. For example: 'acc'.\n output_index: The index of the model output for which the metric name is\n being added.\n\n Returns:\n string, name of the model's unique metric name\n \"\"\"\n if len(self.output_names) > 1:\n metric_name = '%s_%s' % (self.output_names[output_index], metric_name)\n j = 1\n base_metric_name = metric_name\n while metric_name in self.metrics_names:\n metric_name = '%s_%d' % (base_metric_name, j)\n j += 1\n\n return metric_name\n\n def _init_metric_attributes(self):\n \"\"\"Initialized model metric attributes.\"\"\"\n # List of stateful metric functions. Used for resetting metric state during\n # training/eval.\n self._compile_metric_functions = []\n\n def _set_per_output_metric_attributes(self, metrics_dict, output_index):\n \"\"\"Sets the metric attributes on the model for the given output.\n\n Arguments:\n metrics_dict: A dict with metric names as keys and metric fns as values.\n output_index: The index of the model output for which the metric\n attributes are added.\n\n Returns:\n Metrics dict updated with unique metric names as keys.\n \"\"\"\n updated_metrics_dict = collections.OrderedDict()\n for metric_name, metric_fn in metrics_dict.items():\n metric_name = self._add_unique_metric_name(metric_name, output_index)\n\n # Update the name on the metric class to be the unique generated name.\n metric_fn._name = metric_name # pylint: disable=protected-access\n updated_metrics_dict[metric_name] = metric_fn\n # Keep track of metric name and function.\n self._compile_metric_functions.append(metric_fn)\n return updated_metrics_dict\n\n def _set_metric_attributes(self):\n \"\"\"Sets the metric attributes on the model for all the model outputs.\"\"\"\n updated_per_output_metrics = []\n updated_per_output_weighted_metrics = []\n for i, endpoint in enumerate(self._training_endpoints):\n if endpoint.should_skip_target():\n updated_per_output_metrics.append(self._per_output_metrics[i])\n updated_per_output_weighted_metrics.append(\n self._per_output_weighted_metrics[i])\n continue\n updated_per_output_metrics.append(\n self._set_per_output_metric_attributes(self._per_output_metrics[i],\n i))\n updated_per_output_weighted_metrics.append(\n self._set_per_output_metric_attributes(\n self._per_output_weighted_metrics[i], i))\n\n # Create a metric wrapper for each output loss. This computes mean of an\n # output loss across mini-batches (irrespective of how we reduce within a\n # batch).\n if len(self._training_endpoints) > 1:\n for endpoint in self._training_endpoints:\n if not endpoint.should_skip_target():\n endpoint.output_loss_metric = metrics_module.Mean(\n name=endpoint.loss_name())\n\n self._per_output_metrics = updated_per_output_metrics\n self._per_output_weighted_metrics = updated_per_output_weighted_metrics\n\n def _handle_per_output_metrics(self,\n metrics_dict,\n y_true,\n y_pred,\n mask,\n weights=None):\n \"\"\"Calls metric functions for a single output.\n\n Arguments:\n metrics_dict: A dict with metric names as keys and metric fns as values.\n y_true: Target output.\n y_pred: Predicted output.\n mask: Computed mask value for the current output.\n weights: Weights to be applied on the current output.\n\n Returns:\n A list of metric result tensors.\n \"\"\"\n metric_results = []\n for metric_name, metric_fn in metrics_dict.items():\n with K.name_scope(metric_name):\n metric_result = training_utils.call_metric_function(\n metric_fn, y_true, y_pred, weights=weights, mask=mask)\n metric_results.append(metric_result)\n return metric_results\n\n def _handle_metrics(self,\n outputs,\n targets=None,\n skip_target_masks=None,\n sample_weights=None,\n masks=None,\n return_weighted_metrics=False,\n return_weighted_and_unweighted_metrics=False):\n \"\"\"Handles calling metric functions.\n\n Arguments:\n outputs: List of outputs (predictions).\n targets: List of targets.\n skip_target_masks: Optional. List of boolean for whether the corresponding\n target should be ignored or not.\n sample_weights: Optional list of sample weight arrays.\n masks: List of computed output mask values.\n return_weighted_metrics: Flag that indicates whether weighted metrics\n should be computed instead of unweighted metrics. This flag is ignored\n when `return_weighted_and_unweighted_metrics` is enabled.\n return_weighted_and_unweighted_metrics: Flag that is used to indicate\n whether both weighted and unweighted metrics should be computed. When\n this is not enabled, we use `return_weighted_metrics` param to indicate\n whether weighted or unweighted metrics should be returned.\n\n Returns:\n A list of metric result tensors.\n \"\"\"\n # TODO(scottzhu): Update this to use the new training_endpoints. Currently\n # the eager and graph logic is bit different.\n skip_target_masks = skip_target_masks or [False] * len(outputs)\n metric_results = []\n with K.name_scope('metrics'):\n # Invoke all metrics added using `compile`.\n for i in range(len(outputs)):\n if skip_target_masks[i]:\n continue\n output = outputs[i] if outputs else None\n target = targets[i] if targets else None\n output_mask = masks[i] if masks else None\n\n if (return_weighted_and_unweighted_metrics or\n not return_weighted_metrics):\n metric_results.extend(\n self._handle_per_output_metrics(self._per_output_metrics[i],\n target, output, output_mask))\n if return_weighted_and_unweighted_metrics or return_weighted_metrics:\n metric_results.extend(\n self._handle_per_output_metrics(\n self._per_output_weighted_metrics[i],\n target,\n output,\n output_mask,\n weights=sample_weights[i] if sample_weights else None))\n return metric_results\n\n def _check_trainable_weights_consistency(self):\n \"\"\"Check trainable weights count consistency.\n\n This will raise a warning if `trainable_weights` and\n `_collected_trainable_weights` are inconsistent (i.e. have different\n number of parameters).\n Inconsistency will typically arise when one modifies `model.trainable`\n without calling `model.compile` again.\n \"\"\"\n if not hasattr(self, '_collected_trainable_weights'):\n return\n\n if len(self.trainable_weights) != len(self._collected_trainable_weights):\n logging.log_first_n(\n logging.WARN, 'Discrepancy between trainable weights and collected'\n ' trainable weights, did you set `model.trainable`'\n ' without calling `model.compile` after ?', 1)\n\n def _make_train_function(self):\n has_recompiled = self._recompile_weights_loss_and_weighted_metrics()\n self._check_trainable_weights_consistency()\n if isinstance(self.optimizer, list):\n raise ValueError('The `optimizer` in `compile` should be a single '\n 'optimizer.')\n # If we have re-compiled the loss/weighted metric sub-graphs then create\n # train function even if one exists already. This is because\n # `_feed_sample_weights` list has been updated on re-compile.\n if getattr(self, 'train_function', None) is None or has_recompiled:\n # Restore the compiled trainable state.\n current_trainable_state = self._get_trainable_state()\n self._set_trainable_state(self._compiled_trainable_state)\n\n inputs = (self._feed_inputs +\n self._feed_targets +\n self._feed_sample_weights)\n if not isinstance(K.symbolic_learning_phase(), int):\n inputs += [K.symbolic_learning_phase()]\n\n with K.get_graph().as_default():\n with K.name_scope('training'):\n # Training updates\n updates = self.optimizer.get_updates(\n params=self._collected_trainable_weights, loss=self.total_loss)\n # Unconditional updates\n updates += self.get_updates_for(None)\n # Conditional updates relevant to this model\n updates += self.get_updates_for(self.inputs)\n\n metrics = self._get_training_eval_metrics()\n metrics_tensors = [\n m._call_result for m in metrics if hasattr(m, '_call_result') # pylint: disable=protected-access\n ]\n\n with K.name_scope('training'):\n # Gets loss and metrics. Updates weights at each call.\n fn = K.function(\n inputs, [self.total_loss] + metrics_tensors,\n updates=updates,\n name='train_function',\n **self._function_kwargs)\n setattr(self, 'train_function', fn)\n\n # Restore the current trainable state\n self._set_trainable_state(current_trainable_state)\n\n def _make_test_function(self):\n has_recompiled = self._recompile_weights_loss_and_weighted_metrics()\n # If we have re-compiled the loss/weighted metric sub-graphs then create\n # test function even if one exists already. This is because\n # `_feed_sample_weights` list has been updated on re-compile.\n if getattr(self, 'test_function', None) is None or has_recompiled:\n inputs = (self._feed_inputs +\n self._feed_targets +\n self._feed_sample_weights)\n\n with K.get_graph().as_default():\n metrics = self._get_training_eval_metrics()\n metrics_tensors = [\n m._call_result for m in metrics if hasattr(m, '_call_result') # pylint: disable=protected-access\n ]\n\n with K.name_scope('evaluation'):\n updates = self.state_updates\n # Return loss and metrics, no gradient updates.\n # Does update the network states.\n fn = K.function(\n inputs, [self.total_loss] + metrics_tensors,\n updates=updates,\n name='test_function',\n **self._function_kwargs)\n setattr(self, 'test_function', fn)\n\n def _make_predict_function(self):\n if not hasattr(self, 'predict_function'):\n self.predict_function = None\n if self.predict_function is None:\n inputs = self._feed_inputs\n # Gets network outputs. Does not update weights.\n # Does update the network states.\n kwargs = getattr(self, '_function_kwargs', {})\n with K.name_scope(ModeKeys.PREDICT):\n self.predict_function = K.function(\n inputs,\n self.outputs,\n updates=self.state_updates,\n name='predict_function',\n **kwargs)\n\n def _make_execution_function(self, mode):\n if mode == ModeKeys.TRAIN:\n self._make_train_function()\n return self.train_function\n if mode == ModeKeys.TEST:\n self._make_test_function()\n return self.test_function\n if mode == ModeKeys.PREDICT:\n self._make_predict_function()\n return self.predict_function\n\n def _distribution_standardize_user_data(self,\n x,\n y=None,\n sample_weight=None,\n class_weight=None,\n batch_size=None,\n validation_split=0,\n shuffle=False,\n epochs=1,\n allow_partial_batch=False):\n \"\"\"Runs validation checks on input and target data passed by the user.\n\n This is called when using tf.distribute.Strategy to train, evaluate or serve\n the model.\n\n Args:\n x: Input data. A numpy array or `tf.data` dataset.\n y: Target data. A numpy array or None if x is a `tf.data` dataset.\n sample_weight: An optional sample-weight array passed by the user to\n weight the importance of each sample in `x`.\n class_weight: An optional class-weight array by the user to\n weight the importance of samples in `x` based on the class they belong\n to, as conveyed by `y`.\n batch_size: Integer batch size. If provided, it is used to run additional\n validation checks on stateful models.\n validation_split: Float between 0 and 1.\n Fraction of the training data to be used as validation data.\n shuffle: Boolean whether to shuffle the training data before each epoch.\n epochs: Integer epochs. If > 1, repeat the numpy training data epochs\n times when converting to training dataset.\n allow_partial_batch: Boolean whether to enforce that all batches have the\n same size.\n\n Returns:\n Dataset instance.\n\n Raises:\n ValueError: In case of invalid user-provided data.\n RuntimeError: If the model was never compiled.\n \"\"\"\n if class_weight:\n raise NotImplementedError('`class_weight` is currently not supported '\n 'when using tf.distribute.Strategy.')\n\n if (sample_weight is not None and sample_weight.all() and\n distributed_training_utils.is_tpu_strategy(\n self._distribution_strategy)):\n raise NotImplementedError('`sample_weight` is currently not supported '\n 'when using TPUStrategy.')\n\n # Validates `steps` and `shuffle` arguments right at the beginning\n # since we use it to construct the dataset object.\n # TODO(anjalisridhar): Remove this check once we refactor the\n # _standardize_user_data code path. This check is already present elsewhere\n # in the codebase.\n if isinstance(x, dataset_ops.DatasetV2):\n if shuffle:\n training_utils.verify_dataset_shuffled(x)\n\n strategy = self._distribution_strategy\n with strategy.scope():\n # We should be sure to call get_session() inside the strategy.scope()\n # so the strategy can affect the session options.\n if ops.executing_eagerly_outside_functions():\n session = None\n else:\n session = K.get_session()\n\n first_x_value = nest.flatten(x)[0]\n if isinstance(first_x_value, np.ndarray):\n x = training_utils.list_to_tuple(x)\n if y is not None:\n y = training_utils.list_to_tuple(y)\n if sample_weight is not None:\n sample_weight = training_utils.list_to_tuple(sample_weight)\n in_tuple = (x, y, sample_weight)\n else:\n in_tuple = (x, y)\n else:\n in_tuple = x\n\n ds = strategy.extended.experimental_make_numpy_dataset(in_tuple,\n session=session)\n if shuffle:\n # We want a buffer size that is larger than the batch size provided by\n # the user and provides sufficient randomness. Note that larger\n # numbers introduce more memory usage based on the size of each\n # sample.\n ds = ds.shuffle(max(1024, batch_size * 8))\n if epochs > 1:\n ds = ds.repeat(epochs)\n\n # We need to use the drop_remainder argument to get a known static\n # input shape which is required for TPUs.\n drop_remainder = (not allow_partial_batch and\n strategy.extended.experimental_require_static_shapes)\n\n # TODO(b/131720208): We still drop remainder here if number of examples\n # is divisible by batch size, as sometimes dynamic padder will time out\n # with keras.metrics.CategoricalAccuracy() metric.\n if distributed_training_utils.is_tpu_strategy(\n strategy) and not drop_remainder:\n dataset_size = first_x_value.shape[0]\n if dataset_size % batch_size == 0:\n drop_remainder = True\n\n x = ds.batch(batch_size, drop_remainder=drop_remainder)\n else:\n assert isinstance(x, dataset_ops.DatasetV2)\n training_utils.validate_dataset_input(x, y, sample_weight,\n validation_split)\n return x\n\n def _standardize_user_data(self,\n x,\n y=None,\n sample_weight=None,\n class_weight=None,\n batch_size=None,\n check_steps=False,\n steps_name='steps',\n steps=None,\n validation_split=0,\n shuffle=False,\n extract_tensors_from_dataset=False):\n \"\"\"Runs validation checks on input and target data passed by the user.\n\n Also standardizes the data to lists of arrays, in order.\n\n Also builds and compiles the model on the fly if it is a subclassed model\n that has never been called before (and thus has no inputs/outputs).\n\n This is a purely internal method, subject to refactoring at any time.\n\n Args:\n x: Input data. It could be:\n - A Numpy array (or array-like), or a list of arrays\n (in case the model has multiple inputs).\n - A TensorFlow tensor, or a list of tensors\n (in case the model has multiple inputs).\n - A dict mapping input names to the corresponding array/tensors,\n if the model has named inputs.\n - A `tf.data` dataset.\n y: Target data. Like the input data `x`,\n it could be either Numpy array(s) or TensorFlow tensor(s).\n It should be consistent with `x` (you cannot have Numpy inputs and\n tensor targets, or inversely). If `x` is a dataset, `y` should not be\n specified (since targets will be obtained from the iterator).\n sample_weight: An optional sample-weight array passed by the user to\n weight the importance of each sample in `x`.\n class_weight: An optional class-weight array by the user to\n weight the importance of samples in `x` based on the class they belong\n to, as conveyed by `y`. If both `sample_weight` and `class_weight` are\n provided, the weights are multiplied.\n batch_size: Integer batch size. If provided, it is used to run additional\n validation checks on stateful models.\n check_steps: boolean, True if we want to check for validity of `steps` and\n False, otherwise. For example, when we are standardizing one batch of\n data for train_on_batch/predict_on_batch/test_on_batch APIs, `steps`\n value is not required and we should not check for its validity in these\n cases.\n steps_name: The public API's parameter name for `steps`.\n steps: Integer or `None`. Total number of steps (batches of samples) to\n execute.\n validation_split: Float between 0 and 1.\n Fraction of the training data to be used as validation data.\n shuffle: Boolean whether to shuffle the training data before each epoch.\n extract_tensors_from_dataset: Boolean. When `x` is a dataset instance,\n this indicates whether to extract actual tensors from the dataset or\n instead output the dataset instance itself.\n Set to True when calling from `train_on_batch`/etc.\n\n Returns:\n A tuple of 3: inputs (arrays or dicts, depending on whether `x` was a dict\n or not), target arrays, sample-weight arrays.\n If the model's input and targets are symbolic, these lists are empty\n (since the model takes no user-provided data, instead the data comes\n from the symbolic inputs/targets).\n\n Raises:\n ValueError: In case of invalid user-provided data.\n RuntimeError: If the model was never compiled.\n \"\"\"\n if isinstance(x, (dataset_ops.DatasetV1, dataset_ops.DatasetV2)):\n # Graph mode dataset. We'll pass the dataset as-is (unless\n # `extract_tensors_from_dataset` is True, in which case we extract\n # the tensors from the dataset and we output them.\n training_utils.validate_dataset_input(x, y, sample_weight,\n validation_split)\n if shuffle:\n training_utils.verify_dataset_shuffled(x)\n\n is_dataset = True\n if extract_tensors_from_dataset:\n # We do this for `train_on_batch`/etc.\n x, y, sample_weight = training_utils.extract_tensors_from_dataset(x)\n elif isinstance(x, iterator_ops.Iterator):\n # Graph mode iterator. We extract the symbolic tensors.\n training_utils.validate_dataset_input(x, y, sample_weight,\n validation_split)\n iterator = x\n x, y, sample_weight = training_utils.unpack_iterator_input(iterator)\n is_dataset = True\n else:\n is_dataset = False\n\n # Validates `steps` argument based on x's type.\n if check_steps:\n training_utils.check_steps_argument(x, steps, steps_name)\n\n # First, we build the model on the fly if necessary.\n if not self.inputs:\n all_inputs, y_input, dict_inputs = self._build_model_with_inputs(x, y)\n is_build_called = True\n else:\n all_inputs = []\n # Whether this is a subclassed model that expects dictionary inputs\n # rather than list inputs (e.g. FeatureColumn-based models).\n dict_inputs = isinstance(self.inputs, dict)\n is_build_called = False\n y_input = y\n\n # Second, we compile the model on the fly if necessary, mostly for subclass\n # models.\n is_compile_called = False\n if not self._is_compiled and self.optimizer:\n self._compile_from_inputs(all_inputs, y_input, x, y)\n is_compile_called = True\n\n # In graph mode, if we had just set inputs and targets as symbolic tensors\n # by invoking build and compile on the model respectively, we do not have to\n # feed anything to the model. Model already has input and target data as\n # part of the graph.\n # Note: in this case, `any` and `all` are equivalent since we disallow\n # mixed symbolic/value inputs.\n\n # self.run_eagerly is not free to compute, so we want to reuse the value.\n run_eagerly = self.run_eagerly\n\n if (not run_eagerly and is_build_called and is_compile_called and\n not is_dataset and any(_is_symbolic_tensor(v) for v in all_inputs)):\n return [], [], None\n\n return self._standardize_tensors(\n x, y, sample_weight,\n run_eagerly=run_eagerly,\n dict_inputs=dict_inputs,\n is_dataset=is_dataset,\n class_weight=class_weight,\n batch_size=batch_size)\n\n def _standardize_tensors(self, x, y, sample_weight, run_eagerly, dict_inputs,\n is_dataset, class_weight=None, batch_size=None):\n if run_eagerly:\n # In eager mode, do not do shape validation\n # since the network has no input nodes (placeholders) to be fed.\n feed_input_names = self.input_names\n feed_input_shapes = None\n elif not self._is_graph_network:\n # Case: symbolic-mode subclassed network. Do not do shape validation.\n feed_input_names = self._feed_input_names\n feed_input_shapes = None\n else:\n # Case: symbolic-mode graph network.\n # In this case, we run extensive shape validation checks.\n feed_input_names = self._feed_input_names\n feed_input_shapes = self._feed_input_shapes\n\n # Standardize the inputs.\n if not isinstance(x, (dataset_ops.DatasetV1, dataset_ops.DatasetV2)):\n # TODO(fchollet): run static checks with dataset output shape(s).\n x = training_utils.standardize_input_data(\n x,\n feed_input_names,\n feed_input_shapes,\n check_batch_axis=False, # Don't enforce the batch size.\n exception_prefix='input')\n\n # Get typespecs for the input data and sanitize it if necessary.\n # TODO(momernick): This should be capable of doing full input validation\n # at all times - validate that this is so and refactor the standardization\n # code.\n if isinstance(x, dataset_ops.DatasetV2):\n x_shapes = dataset_ops.get_structure(x)\n if isinstance(x_shapes, tuple):\n # If the output of a Dataset is a tuple, we assume it's either of the\n # form (x_data, y_data) or (x_data, y_data, sample_weights). In either\n # case, we only care about x_data here.\n x_shapes = x_shapes[0]\n else:\n flat_inputs = nest.flatten(x, expand_composites=False)\n flat_expected_inputs = nest.flatten(self.inputs, expand_composites=False)\n converted_x = []\n for (a, b) in zip(flat_inputs, flat_expected_inputs):\n converted_x.append(_convert_scipy_sparse_tensor(a, b))\n x = nest.pack_sequence_as(x, converted_x, expand_composites=False)\n\n def _type_spec_from_value(value):\n \"\"\"Grab type_spec without converting array-likes to tensors.\"\"\"\n if isinstance(value, composite_tensor.CompositeTensor):\n return value._type_spec # pylint: disable=protected-access\n # Get a TensorSpec for array-like data without\n # converting the data to a Tensor\n if hasattr(value, 'shape') and hasattr(value, 'dtype'):\n return tensor_spec.TensorSpec(value.shape, value.dtype)\n else:\n return type_spec.type_spec_from_value(value)\n\n x_shapes = nest.map_structure(_type_spec_from_value, x)\n\n flat_inputs = nest.flatten(x_shapes, expand_composites=False)\n flat_expected_inputs = nest.flatten(self.inputs, expand_composites=False)\n for (a, b) in zip(flat_inputs, flat_expected_inputs):\n nest.assert_same_structure(a, b, expand_composites=True)\n\n if y is not None:\n # Prepare self._sample_weight_modes. List with the same length as\n # model outputs.\n training_utils.prepare_sample_weight_modes(self._training_endpoints,\n self.sample_weight_mode)\n feed_output_names = self._feed_output_names\n feed_sample_weight_modes = self._sample_weight_modes\n if not self._is_graph_network:\n feed_output_shapes = None\n else:\n feed_output_shapes = self._feed_output_shapes\n\n # Standardize the outputs.\n y = training_utils.standardize_input_data(\n y,\n feed_output_names,\n # Don't enforce target shapes to match output shapes.\n # Precise checks will be run in `check_loss_and_target_compatibility`.\n shapes=None,\n check_batch_axis=False, # Don't enforce the batch size.\n exception_prefix='target')\n\n # Generate sample-wise weight values given the `sample_weight` and\n # `class_weight` arguments.\n sample_weights = training_utils.standardize_sample_weights(\n sample_weight, feed_output_names)\n class_weights = training_utils.standardize_class_weights(\n class_weight, feed_output_names)\n\n sample_weights = [\n training_utils.standardize_weights(ref, sw, cw, mode)\n for (ref, sw, cw, mode) in zip(y, sample_weights, class_weights,\n feed_sample_weight_modes)\n ]\n # Check that all arrays have the same length.\n if not self._distribution_strategy:\n training_utils.check_array_lengths(x, y, sample_weights)\n if self._is_graph_network and not run_eagerly:\n # Additional checks to avoid users mistakenly using improper loss fns.\n training_utils.check_loss_and_target_compatibility(\n y, self._feed_loss_fns, feed_output_shapes)\n\n sample_weights, _, _ = training_utils.handle_partial_sample_weights(\n y, sample_weights, feed_sample_weight_modes, check_all_flat=True)\n else:\n y = []\n sample_weights = None\n\n if self.stateful and batch_size and not is_dataset:\n # Check that for stateful networks, number of samples is a multiple\n # of the static batch size.\n if x[0].shape[0] % batch_size != 0:\n raise ValueError('In a stateful network, '\n 'you should only pass inputs with '\n 'a number of samples that can be '\n 'divided by the batch size. Found: ' +\n str(x[0].shape[0]) + ' samples')\n\n # If dictionary inputs were provided, we return a dictionary as well.\n if dict_inputs and not isinstance(x, (dataset_ops.DatasetV1,\n dataset_ops.DatasetV2)):\n x = dict(zip(feed_input_names, x))\n return x, y, sample_weights\n\n def _build_model_with_inputs(self, inputs, targets):\n \"\"\"Build the model (set model inputs/outputs), mainly for subclass model.\"\"\"\n processed_inputs = []\n is_dict_inputs = False\n orig_inputs = inputs\n # We need to use `inputs` to set the model inputs.\n # If input data is a dataset iterator in graph mode or if it is an eager\n # iterator and only one batch of samples is required, we fetch the data\n # tensors from the iterator and then standardize them.\n if isinstance(inputs, (dataset_ops.DatasetV1, dataset_ops.DatasetV2)):\n inputs, targets, _ = training_utils.extract_tensors_from_dataset(inputs)\n # We type-check that `inputs` and `targets` are either single arrays\n # or lists of arrays, and extract a flat list of inputs from the passed\n # structure.\n training_utils.validate_input_types(inputs, orig_inputs)\n\n if isinstance(inputs, (list, tuple)):\n processed_inputs += list(inputs)\n elif isinstance(inputs, dict):\n is_dict_inputs = True\n keys = sorted(inputs.keys())\n processed_inputs = [inputs[k] for k in keys]\n else:\n processed_inputs.append(inputs)\n # Now that we have a flat set of inputs, we make sure that none of them\n # are CompositeTensors or CompositeTensorValues of any type (or scipy\n # sparse arrays, which we treat as SparseTensor values). We cannot safely\n # infer input data from an arbitrary composite tensor, so we don't try -\n # users should explicitly add composite tensor inputs to their subclassed\n # models.\n for input_tensor in processed_inputs:\n if composite_tensor_utils.is_composite_or_composite_value(input_tensor):\n # TODO(b/132691975): Document subclass-model CT input handling.\n raise ValueError(\n 'All SparseTensor and RaggedTensor inputs must be explicitly '\n 'declared using a keras.Input() with sparse=True or ragged=True. '\n 'We found an undeclared input %s. For Sequential models, please '\n 'add a keras.Input() as your first Layer. For subclassed models, '\n 'please call self._set_inputs() on your input set, which you can '\n 'create using keras.Input() for each input to your model.' %\n (input_tensor,))\n # Build the model using the retrieved inputs (value or symbolic).\n # If values are generated from a dataset, then in symbolic-mode\n # placeholders will be created to match the value shapes.\n if isinstance(orig_inputs, (dataset_ops.DatasetV1, dataset_ops.DatasetV2,\n iterator_ops.Iterator)):\n if not self.inputs:\n # For subclassed models, a robust input spec is not available so we\n # must cast to the model dtype.\n inputs = training_utils.cast_if_floating_dtype(inputs, self.dtype)\n\n def create_tensor_spec(t):\n return tensor_spec.TensorSpec(t.shape, t.dtype)\n\n cast_inputs = nest.map_structure(create_tensor_spec, inputs)\n elif training_utils.has_tensors(inputs):\n cast_inputs = training_utils.cast_if_floating_dtype(inputs)\n else:\n cast_inputs = inputs\n self._set_inputs(cast_inputs)\n return processed_inputs, targets, is_dict_inputs\n\n def _compile_from_inputs(self, all_inputs, target, orig_inputs, orig_target):\n if target is not None:\n # We need to use `y` to set the model targets.\n if training_utils.has_tensors(target):\n target = training_utils.cast_if_floating_dtype_and_mismatch(\n target, self.outputs)\n training_utils.validate_input_types(target, orig_target,\n allow_dict=False, field_name='target')\n if isinstance(target, (list, tuple)):\n all_inputs += list(target)\n else:\n all_inputs.append(target)\n # Type check that all inputs are *either* value *or* symbolic.\n # TODO(fchollet): this check could be removed in Eager mode?\n if any(tensor_util.is_tensor(v) for v in all_inputs):\n if not all(tensor_util.is_tensor(v) for v in all_inputs):\n raise ValueError('Do not pass inputs that mix Numpy arrays and '\n 'TensorFlow tensors. '\n 'You passed: x=' + str(orig_inputs) +\n '; y=' + str(orig_target))\n is_dataset = isinstance(orig_inputs, (dataset_ops.DatasetV1,\n dataset_ops.DatasetV2,\n iterator_ops.Iterator))\n if is_dataset or context.executing_eagerly():\n target_tensors = None\n else:\n # Handle target tensors if any passed.\n if target is not None:\n if not isinstance(target, (list, tuple)):\n target = [target]\n target_tensors = [v for v in target if _is_symbolic_tensor(v)]\n else:\n target_tensors = None\n\n self.compile(\n optimizer=self.optimizer,\n loss=self.loss,\n metrics=self._compile_metrics,\n weighted_metrics=self._compile_weighted_metrics,\n loss_weights=self.loss_weights,\n target_tensors=target_tensors,\n sample_weight_mode=self.sample_weight_mode,\n run_eagerly=self.run_eagerly,\n experimental_run_tf_function=self._experimental_run_tf_function)\n\n # TODO(omalleyt): Consider changing to a more descriptive function name.\n def _set_inputs(self, inputs, outputs=None, training=None):\n \"\"\"Set model's input and output specs based on the input data received.\n\n This is to be used for Model subclasses, which do not know at instantiation\n time what their inputs look like.\n\n Args:\n inputs: Single array, or list of arrays. The arrays could be placeholders,\n Numpy arrays, data tensors, or TensorSpecs.\n - if placeholders: the model is built on top of these placeholders,\n and we expect Numpy data to be fed for them when calling `fit`/etc.\n - if Numpy data or TensorShapes: we create placeholders matching the\n TensorShapes or shapes of the Numpy arrays. We expect Numpy data to be\n fed for these placeholders when calling `fit`/etc.\n - if data tensors: the model is built on top of these tensors.\n We do not expect any Numpy data to be provided when calling `fit`/etc.\n outputs: None, a data tensor, or a list of tensors. If None, the\n outputs will be determined by invoking `self.call()`, otherwise the\n provided value will be used.\n training: Boolean or None. Only relevant in symbolic mode. Specifies\n whether to build the model's graph in inference mode (False), training\n mode (True), or using the Keras learning phase (None).\n Raises:\n ValueError: If dict inputs are passed to a Sequential Model where the\n first layer isn't FeatureLayer.\n \"\"\"\n self._set_save_spec(inputs)\n inputs = self._set_input_attrs(inputs)\n\n if outputs is None:\n kwargs = {}\n if self._expects_training_arg:\n # In V2 mode, feeding `training=None` is not allowed because any value\n # explicitly passed by the user is respected, even `None`.`\n if training is None and not ops.executing_eagerly_outside_functions():\n training = K.learning_phase()\n if training is not None:\n kwargs['training'] = training\n try:\n outputs = self(inputs, **kwargs)\n except NotImplementedError:\n # This Model or a submodel is dynamic and hasn't overridden\n # `compute_output_shape`.\n outputs = None\n\n self._set_output_attrs(outputs)\n\n @trackable.no_automatic_dependency_tracking\n def _set_input_attrs(self, inputs):\n \"\"\"Sets attributes related to the inputs of the Model.\"\"\"\n if self.inputs:\n raise ValueError('Model inputs are already set.')\n\n if self.__class__.__name__ == 'Sequential' and not self.built:\n if tensor_util.is_tensor(inputs):\n input_shape = (None,) + tuple(inputs.shape.as_list()[1:])\n elif isinstance(inputs, tensor_shape.TensorShape):\n input_shape = (None,) + tuple(inputs.as_list()[1:])\n elif isinstance(inputs, dict):\n # We assert that the first layer is a FeatureLayer.\n if not training_utils.is_feature_layer(self.layers[0]):\n raise ValueError('Passing a dictionary input to a Sequential Model '\n 'which doesn\\'t have FeatureLayer as the first layer'\n ' is an error.')\n input_shape = (None,)\n else:\n input_shape = (None,) + tuple(inputs.shape[1:])\n self._build_input_shape = input_shape\n\n # Cast inputs to the compute dtype. This is primarily used\n # when saving to determine the correct dtype in the input signature.\n inputs = self._maybe_cast_inputs(inputs)\n\n # On-the-fly setting of symbolic model inputs (either by using the tensor\n # provided, or by creating a placeholder if Numpy data was provided).\n model_inputs = training_utils.ModelInputs(inputs)\n inputs = model_inputs.get_symbolic_inputs()\n self.inputs = model_inputs.get_symbolic_inputs(return_single_as_list=True)\n self.input_names = model_inputs.get_input_names()\n\n self._feed_inputs = []\n self._feed_input_names = []\n self._feed_input_shapes = []\n\n for k, v in model_inputs.as_dict():\n if K.is_placeholder(v):\n self._feed_input_names.append(k)\n self._feed_inputs.append(v)\n self._feed_input_shapes.append(K.int_shape(v))\n\n return inputs\n\n @trackable.no_automatic_dependency_tracking\n def _set_output_attrs(self, outputs):\n \"\"\"Sets attributes related to the outputs of the Model.\"\"\"\n # NOTE(taylorrobie): This convention cannot be changed without updating the\n # data adapter since it assumes nest.flatten ordering.\n outputs = nest.flatten(outputs)\n self.outputs = outputs\n self.output_names = training_utils.generic_output_names(outputs)\n # TODO(scottzhu): Should we cleanup the self._training_endpoints here?\n self.built = True\n\n @property\n def _targets(self):\n \"\"\"The output target tensors for the model.\"\"\"\n return [\n e.training_target.target\n for e in self._training_endpoints\n if e.has_training_target()\n ]\n\n @property\n def _feed_targets(self):\n return [\n e.training_target.target\n for e in self._training_endpoints\n if e.has_feedable_training_target()\n ]\n\n @property\n def _feed_output_names(self):\n return [\n e.output_name\n for e in self._training_endpoints\n if e.has_feedable_training_target()\n ]\n\n @property\n def _feed_output_shapes(self):\n return [\n e.feed_output_shape\n for e in self._training_endpoints\n if e.has_feedable_training_target()\n ]\n\n @property\n def _feed_loss_fns(self):\n return [\n e.loss_fn\n for e in self._training_endpoints\n if e.has_feedable_training_target()\n ]\n\n @property\n def _loss_weights_list(self):\n return [e.loss_weight for e in self._training_endpoints]\n\n @property\n def _output_loss_metrics(self):\n if hasattr(self, '_training_endpoints'):\n return [\n e.output_loss_metric\n for e in self._training_endpoints\n if e.output_loss_metric is not None\n ]\n return None\n\n @property\n def sample_weights(self):\n return [e.sample_weight for e in self._training_endpoints]\n\n @property\n def _sample_weight_modes(self):\n return [e.sample_weight_mode for e in self._training_endpoints]\n\n @property\n def _feed_sample_weights(self):\n return [e.sample_weight for e in self._training_endpoints\n if e.sample_weight is not None]\n\n def _maybe_load_initial_epoch_from_ckpt(self, initial_epoch, mode):\n \"\"\"Maybe load initial epoch from ckpt considering possible worker recovery.\n\n Refer to tensorflow/python/keras/distribute/multi_worker_training_state.py\n for more information.\n\n Arguments:\n initial_epoch: The original initial_epoch user passes in in `fit()`.\n mode: The mode for running `model.fit()`.\n\n Returns:\n If the training is recovering from previous failure under multi-worker\n training setting, return the epoch the training is supposed to continue\n at. Otherwise, return the `initial_epoch` the user passes in.\n \"\"\"\n if self._training_state is not None:\n return self._training_state.maybe_load_initial_epoch_from_ckpt(\n initial_epoch, mode)\n return initial_epoch\n\n def _get_training_eval_metrics(self):\n \"\"\"Returns all the metrics that are to be reported.\n\n This includes the output loss metrics, compile metrics/weighted metrics,\n add_metric metrics.\n \"\"\"\n metrics = []\n metrics.extend(getattr(self, '_output_loss_metrics', None) or [])\n metrics.extend(getattr(self, 'metrics', None) or [])\n return metrics\n\n def _assert_compile_was_called(self):\n # Checks whether `compile` has been called. If it has been called,\n # then the optimizer is set. This is different from whether the\n # model is compiled\n # (i.e. whether the model is built and its inputs/outputs are set).\n if not self._compile_was_called:\n raise RuntimeError('You must compile your model before '\n 'training/testing. '\n 'Use `model.compile(optimizer, loss)`.')\n\n def _in_multi_worker_mode(self):\n \"\"\"Method to infer if this `Model` is working in multi-worker settings.\n\n Multi-worker training refers to the setup where the training is\n distributed across multiple workers, as opposed to the case where\n only a local process performs the training. This function is\n used to infer for example whether or not a distribute coordinator\n should be run, and thus TensorFlow servers should be started for\n communication with other servers in the cluster, or whether or not\n saving/restoring checkpoints is relevant for preemption fault tolerance.\n\n Experimental. Signature and implementation are subject to change.\n\n Returns:\n Whether this model indicates it's working in multi-worker settings.\n \"\"\"\n strategy = self._get_distribution_strategy()\n return strategy and strategy.extended._in_multi_worker_mode() # pylint: disable=protected-access\n\n def _get_distribution_strategy(self):\n # If the model was compiled under the scope of a `tf.distribute.Strategy',\n # `self._distribution_strategy` would have been set and model should infer\n # that as the used strategy (even if it's out of strategy scope already).\n strategy = self._distribution_strategy\n\n # Otherwise, use the strategy whose scope this is in.\n if not strategy and distribution_strategy_context.has_strategy():\n strategy = distribution_strategy_context.get_strategy()\n\n return strategy\n\n @property\n def _trackable_saved_model_saver(self):\n return model_serialization.ModelSavedModelSaver(self)\n\n def _get_compile_args(self):\n self._assert_compile_was_called()\n kwargs = {\n 'loss': self.loss,\n 'metrics': self._compile_metrics,\n 'loss_weights': self.loss_weights,\n 'sample_weight_mode': self.sample_weight_mode,\n 'weighted_metrics': self._compile_weighted_metrics,\n }\n return kwargs\n\n @property\n def _compile_was_called(self):\n return self._v1_compile_was_called\n\n\nclass DistributedCallbackModel(Model):\n \"\"\"Model that is used for callbacks with tf.distribute.Strategy.\"\"\"\n\n def __init__(self, model):\n super(DistributedCallbackModel, self).__init__()\n self.optimizer = model.optimizer\n\n def set_original_model(self, orig_model):\n self._original_model = orig_model\n\n def save_weights(self, filepath, overwrite=True, save_format=None):\n self._replicated_model.save_weights(filepath, overwrite=overwrite,\n save_format=save_format)\n\n def save(self, filepath, overwrite=True, include_optimizer=True):\n # save weights from the distributed model to the original model\n distributed_model_weights = self.get_weights()\n self._original_model.set_weights(distributed_model_weights)\n # TODO(anjalisridhar): Do we need to save the original model here?\n # Saving the first replicated model works as well.\n self._original_model.save(filepath, overwrite=True, include_optimizer=False)\n\n def load_weights(self, filepath, by_name=False):\n self._original_model.load_weights(filepath, by_name=False)\n # Copy the weights from the original model to each of the replicated models.\n orig_model_weights = self._original_model.get_weights()\n distributed_training_utils.set_weights(\n self._original_model._distribution_strategy, self, # pylint: disable=protected-access\n orig_model_weights)\n\n def __getattr__(self, item):\n # Whitelisted attributes of the model that can be accessed by the user\n # during a callback.\n if item not in ('_setattr_tracking', '_layers'):\n logging.warning('You are accessing attribute ' + item + ' of the '\n 'DistributedCallbackModel that may not have been set '\n 'correctly.')\n return super(DistributedCallbackModel, self).__getattr__(item)\n\n\nclass _TrainingEndpoint(object):\n \"\"\"A container for the training output/target and related entities.\n\n In the case of model with multiple outputs, there is a one-to-one mapping\n between model output (y_pred), model target (y_true), loss, metrics etc.\n By unifying these entities into one class, different entity can access\n information between each other, rather than currently access different list of\n attributes of the model.\n \"\"\"\n\n def __init__(self,\n output,\n output_name,\n loss_fn,\n loss_weight=None,\n training_target=None,\n output_loss_metric=None,\n sample_weight=None,\n sample_weight_mode=None):\n \"\"\"Initialize the _TrainingEndpoint.\n\n Note that the output and output_name should be stable as long as the model\n structure doesn't change. The training_target suppose to be mutable since\n the information is provided via `compile()`\n\n Args:\n output: the output tensor of the model.\n output_name: the unique name of the output tensor.\n loss_fn: the loss function for the output tensor.\n loss_weight: float, the weights for the loss.\n training_target: the _TrainingTarget for the model.\n output_loss_metric: the metric object for the loss function.\n sample_weight: the weights for how a sample is weighted during metric and\n loss calculation. Could be None.\n sample_weight_mode: string, 'temporal', 'samplewise' or None. The mode for\n how the sample_weight is populated.\n \"\"\"\n self._output = output\n self._output_name = output_name\n self._loss_fn = loss_fn\n self._loss_weight = loss_weight\n self._training_target = training_target\n self._output_loss_metric = output_loss_metric\n self._sample_weight = sample_weight\n self._sample_weight_mode = sample_weight_mode\n\n @property\n def output(self):\n return self._output\n\n @property\n def output_name(self):\n return self._output_name\n\n @property\n def shape(self):\n return K.int_shape(self.output)\n\n @property\n def loss_fn(self):\n return self._loss_fn\n\n @property\n def loss_weight(self):\n return self._loss_weight\n\n @loss_weight.setter\n def loss_weight(self, value):\n self._loss_weight = value\n\n @property\n def training_target(self):\n return self._training_target\n\n @training_target.setter\n def training_target(self, value):\n self._training_target = value\n\n def create_training_target(self, target, run_eagerly=False):\n \"\"\"Create training_target instance and update the self.training_target.\n\n Note that the input target should just be a tensor or None, and\n corresponding training target will be created based on the output and\n loss_fn.\n\n Args:\n target: the target tensor for the current output. Could be None.\n run_eagerly: boolean, whether the model is in run_eagerly mode.\n\n Raises:\n ValueError if the training_target field for the current instance has\n already been populated.\n \"\"\"\n if self.has_training_target():\n raise ValueError('The training_target field for the _TrainingEndpoint '\n 'instance has already been populated')\n if run_eagerly:\n # When run_eagerly, the target tensor is ignored, and the None placeholder\n # is created instead.\n self.training_target = _TrainingTarget(\n None, feedable=True, skip_target_weights=False)\n return\n\n if self.should_skip_target():\n self.training_target = _TrainingTarget(None)\n else:\n if target is not None and not K.is_placeholder(target):\n feedable = False\n skip_target_weights = True\n else:\n feedable = True\n skip_target_weights = False\n\n if target is None:\n target_dtype = losses.LABEL_DTYPES_FOR_LOSSES.get(\n self.loss_fn, K.dtype(self.output))\n\n target = K.placeholder(\n ndim=len(self.shape),\n name=self.output_name + '_target',\n sparse=K.is_sparse(self.output),\n dtype=target_dtype)\n\n self.training_target = _TrainingTarget(\n target,\n feedable=feedable,\n skip_target_weights=skip_target_weights)\n\n @property\n def output_loss_metric(self):\n return self._output_loss_metric\n\n @output_loss_metric.setter\n def output_loss_metric(self, value):\n self._output_loss_metric = value\n\n @property\n def sample_weight(self):\n return self._sample_weight\n\n @sample_weight.setter\n def sample_weight(self, value):\n self._sample_weight = value\n\n @property\n def sample_weight_mode(self):\n return self._sample_weight_mode\n\n @sample_weight_mode.setter\n def sample_weight_mode(self, value):\n self._sample_weight_mode = value\n\n def should_skip_target(self):\n return self._loss_fn is None\n\n def should_skip_target_weights(self):\n return (self.should_skip_target() or self.training_target is None or\n self.training_target.skip_target_weights)\n\n def has_training_target(self):\n return self.training_target is not None\n\n def has_feedable_training_target(self):\n return (not self.should_skip_target() and\n self.training_target is not None and self.training_target.feedable)\n\n def loss_name(self):\n if self._loss_fn is not None:\n return self._output_name + '_loss'\n return None\n\n @property\n def feed_output_shape(self):\n \"\"\"The output shape for the feedable target.\"\"\"\n if not self.has_feedable_training_target():\n return None\n\n if ((isinstance(self.loss_fn, losses.LossFunctionWrapper) and\n self.loss_fn.fn == losses.sparse_categorical_crossentropy)) or (\n isinstance(self.loss_fn, losses.SparseCategoricalCrossentropy)):\n if K.image_data_format() == 'channels_first':\n return (self.shape[0], 1) + self.shape[2:]\n else:\n return self.shape[:-1] + (1,)\n elif (not isinstance(self.loss_fn, losses.Loss) or\n (isinstance(self.loss_fn, losses.LossFunctionWrapper) and\n (getattr(losses, self.loss_fn.fn.__name__, None) is None))):\n # If the given loss is not an instance of the `Loss` class (custom\n # class) or if the loss function that is wrapped is not in the\n # `losses` module, then it is a user-defined loss and we make no\n # assumptions about it.\n return None\n else:\n return self.shape\n\n def sample_weights_mismatch(self):\n \"\"\"Check if the sample weight and the mode match or not.\"\"\"\n # If there is a mismatch between sample weight mode and the placeholders\n # created, then recompile the sub-graphs that depend on sample weights.\n return (\n (self.sample_weight_mode is not None and self.sample_weight is None) or\n (self.sample_weight_mode is None and self.sample_weight is not None))\n\n def populate_sample_weight(self, sample_weight, sample_weight_mode):\n \"\"\"Populate the sample weight and based on the sample weight mode.\"\"\"\n if (sample_weight is None and\n (self.should_skip_target_weights() or sample_weight_mode is None or\n context.executing_eagerly())):\n self._sample_weight = None\n return\n\n assert sample_weight_mode in ['temporal', 'samplewise']\n if sample_weight_mode == 'temporal':\n default_value = [[1.]]\n shape = [None, None]\n else:\n # sample_weight_mode == 'samplewise'\n default_value = [1.]\n shape = [None]\n\n if sample_weight is not None:\n if not sample_weight.shape.is_compatible_with(shape):\n raise ValueError('Received sample weight with shape {}. Expected shape '\n '{}.'.format(sample_weight.shape, shape))\n self._sample_weight = sample_weight\n else:\n self._sample_weight = array_ops.placeholder_with_default(\n constant_op.constant(default_value, dtype=K.floatx()),\n shape=shape,\n name=self.output_name + '_sample_weights')\n\n\nclass _TrainingTarget(object):\n \"\"\"Container for a target tensor (y_true) and its metadata (shape, loss...).\n\n Arguments:\n target: A target tensor for the model. It may be `None` if the\n output is excluded from loss computation. It is still kept as None\n since each output of the model should have a corresponding target. If\n the target is None, the rest of the attributes will be None as well.\n feedable: Boolean, whether the target is feedable (requires data to be\n passed in `fit` or `train_on_batch`), or not (model compiled with\n `target_tensors` argument).\n skip_target_weights: Boolean, whether the target should be skipped during\n weights calculation.\n \"\"\"\n\n def __init__(self, target, feedable=False, skip_target_weights=True):\n self._target = target\n self._feedable = feedable\n self._skip_target_weights = skip_target_weights\n\n @property\n def target(self):\n return self._target\n\n @property\n def feedable(self):\n return self._feedable\n\n @property\n def skip_target_weights(self):\n return self._skip_target_weights\n\n\ndef _is_symbolic_tensor(x):\n return tensor_util.is_tensor(x) and not isinstance(x, ops.EagerTensor)\n\n\ndef _convert_scipy_sparse_tensor(value, expected_input):\n \"\"\"Handle scipy sparse tensor conversions.\n\n This method takes a value 'value' and returns the proper conversion. If\n value is a scipy sparse tensor and the expected input is a dense tensor,\n we densify 'value'. If value is a scipy sparse tensor and the expected input\n is a TF SparseTensor, we convert 'value' to a SparseTensor. If 'value' is\n not a scipy sparse tensor, or scipy is not imported, we pass it through\n unchanged.\n\n Arguments:\n value: An object that may be a scipy sparse tensor\n expected_input: The expected input placeholder.\n\n Returns:\n The possibly-converted 'value'.\n \"\"\"\n if issparse is not None and issparse(value):\n if ops.is_dense_tensor_like(expected_input):\n if ops.executing_eagerly_outside_functions():\n # In TF2 we do not silently densify sparse matrices.\n raise ValueError('A SciPy sparse matrix was passed to a model '\n 'that expects dense inputs. Please densify your '\n 'inputs first, such as by calling `x.toarray().')\n return value.toarray()\n else:\n sparse_coo = value.tocoo()\n row, col = sparse_coo.row, sparse_coo.col\n data, shape = sparse_coo.data, sparse_coo.shape\n indices = np.concatenate((np.expand_dims(row, 1), np.expand_dims(col, 1)),\n 1)\n return sparse_tensor.SparseTensor(indices, data, shape)\n else:\n return value\n\n\ndef _get_metrics_from_layers(layers):\n \"\"\"Returns list of metrics from the given layers.\n\n This will not include the `compile` metrics of a model layer.\n\n Arguments:\n layers: List of layers.\n\n Returns:\n List of metrics.\n \"\"\"\n metrics = []\n layers = trackable_layer_utils.filter_empty_layer_containers(layers)\n for layer in layers:\n if isinstance(layer, Model):\n # We cannot call 'metrics' on the model because we do not want to\n # include the metrics that were added in compile API of a nested model.\n metrics.extend(layer._metrics) # pylint: disable=protected-access\n metrics.extend(_get_metrics_from_layers(layer.layers))\n else:\n metrics.extend(layer.metrics)\n return metrics\n\n\ndef _non_none_constant_value(v):\n constant_value = tensor_util.constant_value(v)\n return constant_value if constant_value is not None else v\n",
"file": "venv/lib/python3.6/site-packages/tensorflow/python/keras/engine/training_v1.py",
"file_size": 137170,
"file_write_time": 132394892070000000,
"settings":
{
"buffer_size": 137170,
"line_ending": "Unix"
}
},
{
"contents": "# Copyright 2018 The TensorFlow Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ==============================================================================\n\"\"\"Part of the Keras training engine related to Python generators of array data.\n\"\"\"\n# pylint: disable=protected-access\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nimport functools\nimport math\n\nimport numpy as np\n\nfrom tensorflow.python.data.ops import dataset_ops\nfrom tensorflow.python.data.ops import iterator_ops\nfrom tensorflow.python.eager import context\nfrom tensorflow.python.framework import errors\nfrom tensorflow.python.keras import backend\nfrom tensorflow.python.keras import callbacks as cbks\nfrom tensorflow.python.keras.engine import training_utils\nfrom tensorflow.python.keras.utils import data_utils\nfrom tensorflow.python.keras.utils import generic_utils\nfrom tensorflow.python.keras.utils.mode_keys import ModeKeys\nfrom tensorflow.python.platform import tf_logging as logging\nfrom tensorflow.python.util import nest\n\n\ndef model_iteration(model,\n data,\n steps_per_epoch=None,\n epochs=1,\n verbose=1,\n callbacks=None,\n validation_data=None,\n validation_steps=None,\n validation_freq=1,\n class_weight=None,\n max_queue_size=10,\n workers=1,\n use_multiprocessing=False,\n shuffle=False,\n initial_epoch=0,\n mode=ModeKeys.TRAIN,\n batch_size=None,\n steps_name='steps',\n **kwargs):\n \"\"\"Loop function for arrays of data with modes TRAIN/TEST/PREDICT.\n\n Arguments:\n model: Keras Model instance.\n data: Either a tuple of NumPy/Tensor inputs (i.e. `(x,)` or `(x, y)` or\n `(x, y, sample_weights)`) or a generator or\n `keras.utils.data_utils.Sequence` object or Eager Iterator or Dataset.\n steps_per_epoch: Total number of steps (batches of samples) before\n declaring one epoch finished and starting the next epoch. Ignored with\n the default value of `None`.\n epochs: Number of times to iterate over the data.\n verbose: 0, 1, or 2. Verbosity mode.\n 0 = silent, 1 = progress bar, 2 = one line per epoch.\n Note that the progress bar is not particularly useful when\n logged to a file, so verbose=2 is recommended when not running\n interactively (eg, in a production environment).\n callbacks: List of callbacks to be called during training.\n validation_data: Either a tuple of NumPy/Tensor inputs (i.e. `(x,)` or\n `(x, y)` or `(x, y, sample_weights)`) or a generator or\n `keras.utils.data_utils.Sequence` object or Eager Iterator or Dataset.\n validation_steps: Total number of steps (batches of samples) before\n declaring validation finished.\n validation_freq: Only relevant if validation data is provided. Integer or\n `collections.abc.Container` instance (e.g. list, tuple, etc.). If an\n integer, specifies how many training epochs to run before a new\n validation run is performed, e.g. `validation_freq=2` runs\n validation every 2 epochs. If a Container, specifies the epochs on\n which to run validation, e.g. `validation_freq=[1, 2, 10]` runs\n validation at the end of the 1st, 2nd, and 10th epochs.\n class_weight: Dictionary mapping class indices to a weight for the class.\n max_queue_size: Integer. Maximum size for the generator queue. If\n unspecified, `max_queue_size` will default to 10.\n workers: Integer. Maximum number of processes to spin up when using\n process-based threading. If unspecified, `workers` will default to 1. If\n 0, will execute the generator on the main thread.\n use_multiprocessing: Boolean. If `True`, use process-based threading. If\n unspecified, `use_multiprocessing` will default to `False`. Note that\n because this implementation relies on multiprocessing, you should not\n pass non-picklable arguments to the generator as they can't be passed\n easily to children processes.\n shuffle: Boolean. Whether to shuffle the order of the batches at the\n beginning of each epoch. Only used with instances of `Sequence`\n (`keras.utils.Sequence`). Has no effect when `steps_per_epoch` is not\n `None`.\n initial_epoch: Epoch at which to start training (useful for resuming a\n previous training run).\n mode: One of ModeKeys.TRAIN/ModeKeys.TEST/ModeKeys.PREDICT.\n batch_size: Integer batch size or None if unknown. Will only be used if\n `data` is in NumPy/Tensor format.\n steps_name: The string name of the steps argument, either `steps`,\n `validation_steps`, or `steps_per_epoch`. Only used for error message\n formatting.\n **kwargs: Additional arguments for backwards compatibility. `steps` is\n accepted as an alias for `steps_per_epoch`.\n\n Returns:\n - In TRAIN mode: `History` object.\n - In TEST mode: Evaluation metrics.\n - In PREDICT mode: Outputs of the Model called on inputs.\n\n Raises:\n ValueError: in case of invalid arguments.\n \"\"\"\n if 'steps' in kwargs:\n steps_per_epoch = kwargs['steps']\n\n # Determine the number of steps per epoch and whether we should reset the\n # dataset at the end of each epoch.\n reset_dataset_after_each_epoch = False\n original_dataset = None\n is_dataset = isinstance(data, (dataset_ops.DatasetV2, dataset_ops.DatasetV1))\n if is_dataset:\n original_dataset = data\n if steps_per_epoch is None:\n reset_dataset_after_each_epoch = True\n steps_per_epoch = training_utils.infer_steps_for_dataset(\n model, data, steps_per_epoch, epochs=epochs, steps_name=steps_name)\n\n # Convert to a format that supports `next(generator)`.\n generator, steps_per_epoch = convert_to_generator_like(\n data,\n steps_per_epoch=steps_per_epoch,\n batch_size=batch_size,\n epochs=epochs - initial_epoch,\n shuffle=shuffle)\n\n do_validation = validation_data is not None\n is_sequence = isinstance(generator, data_utils.Sequence)\n _validate_arguments(is_sequence, is_dataset, use_multiprocessing, workers,\n steps_per_epoch, validation_data, validation_steps, mode,\n kwargs)\n\n batch_function = _make_execution_function(\n model, mode, class_weight=class_weight)\n\n # Create the queue for the generator.\n enqueuer = None\n if not is_dataset:\n generator, enqueuer = _make_enqueued_generator(\n generator,\n workers=workers,\n use_multiprocessing=use_multiprocessing,\n max_queue_size=max_queue_size,\n shuffle=shuffle)\n\n num_samples_or_steps, use_steps = _get_num_samples_or_steps(\n data, steps_per_epoch)\n\n count_mode = 'steps' if use_steps else 'samples'\n callbacks = cbks.configure_callbacks(\n callbacks,\n model,\n do_validation=do_validation,\n epochs=epochs,\n steps_per_epoch=steps_per_epoch,\n batch_size=batch_size,\n samples=num_samples_or_steps,\n count_mode=count_mode,\n verbose=verbose,\n mode=mode)\n\n if mode == ModeKeys.PREDICT:\n aggregator = training_utils.OutputsAggregator(True, steps=steps_per_epoch)\n else:\n aggregator = training_utils.MetricsAggregator(True, steps=steps_per_epoch)\n\n should_set_learning_phase = context.executing_eagerly() and model.run_eagerly\n if should_set_learning_phase:\n learning_phase_scope = backend.eager_learning_phase_scope(\n 1 if mode == ModeKeys.TRAIN else 0)\n learning_phase_scope.__enter__()\n\n callbacks.model.stop_training = False\n callbacks._call_begin_hook(mode)\n\n initial_epoch = model._maybe_load_initial_epoch_from_ckpt(initial_epoch, mode)\n\n for epoch in range(initial_epoch, epochs):\n if callbacks.model.stop_training:\n break\n\n # Setup work for each epoch.\n model.reset_metrics()\n epoch_logs = {}\n if mode == ModeKeys.TRAIN:\n callbacks.on_epoch_begin(epoch, epoch_logs)\n\n if steps_per_epoch is None:\n # Loop over dataset until `OutOfRangeError` is raised.\n target_steps = np.inf\n else:\n # Loop over dataset for the specified number of steps.\n target_steps = steps_per_epoch\n\n step = 0\n while step < target_steps:\n batch_data = _get_next_batch(generator)\n if batch_data is None:\n if is_dataset:\n # The dataset passed by the user ran out of batches.\n # Now we know the cardinality of the dataset.\n # If steps_per_epoch was specified, then running out of data is\n # unexpected, so we stop training and inform the user.\n if steps_per_epoch:\n callbacks.model.stop_training = True\n logging.warning(\n 'Your dataset ran out of data; interrupting training. '\n 'Make sure that your dataset can generate at least '\n '`%s * epochs` batches (in this case, %d batches). '\n 'You may need to use the repeat() function when '\n 'building your dataset.'\n % (steps_name, steps_per_epoch * epochs))\n elif step > 0:\n steps_per_epoch = step\n aggregator.steps = steps_per_epoch\n else:\n # We ran out of batches while the user passed an iterator (legacy).\n callbacks.model.stop_training = True\n logging.warning(\n 'Your dataset iterator ran out of data; '\n 'interrupting training. Make sure that your iterator '\n 'can generate at least `%s * epochs` '\n 'batches (in this case, %d batches). You may need to'\n 'use the repeat() function when building your '\n 'dataset.' % (steps_name, steps_per_epoch * epochs))\n break\n\n # `batch_size` used for validation data if validation\n # data is NumPy/EagerTensors.\n batch_size = int(nest.flatten(batch_data)[0].shape[0])\n\n # Callbacks batch begin.\n batch_logs = {'batch': step, 'size': batch_size}\n callbacks._call_batch_hook(mode, 'begin', step, batch_logs)\n\n is_deferred = not model._is_compiled\n batch_outs = batch_function(*batch_data)\n if not isinstance(batch_outs, list):\n batch_outs = [batch_outs]\n\n if step == 0:\n aggregator.create(batch_outs)\n\n if is_deferred:\n # Set callbacks params. We do this here when model is compiled only\n # in the first iteration of this loop (deferred build scenario).\n cbks.set_callback_parameters(\n callbacks,\n model,\n do_validation=do_validation,\n batch_size=batch_size,\n epochs=epochs,\n steps_per_epoch=steps_per_epoch,\n samples=num_samples_or_steps,\n verbose=verbose,\n mode=mode)\n\n # Aggregate results.\n aggregator.aggregate(batch_outs)\n\n # Callbacks batch end.\n batch_logs = cbks.make_logs(model, batch_logs, batch_outs, mode)\n callbacks._call_batch_hook(mode, 'end', step, batch_logs)\n step += 1\n\n if callbacks.model.stop_training:\n break\n\n aggregator.finalize()\n results = aggregator.results\n epoch_logs = cbks.make_logs(model, epoch_logs, results, mode)\n if len(results) == 1:\n results = results[0]\n\n # Run the test loop every epoch during training.\n if (do_validation and\n training_utils.should_run_validation(validation_freq, epoch) and\n not callbacks.model.stop_training):\n val_results = model_iteration(\n model,\n validation_data,\n steps_per_epoch=validation_steps,\n batch_size=batch_size,\n class_weight=class_weight,\n workers=workers,\n use_multiprocessing=use_multiprocessing,\n max_queue_size=max_queue_size,\n callbacks=callbacks,\n verbose=verbose,\n mode=ModeKeys.TEST,\n steps_name='validation_steps')\n\n if not isinstance(val_results, list):\n val_results = [val_results]\n epoch_logs = cbks.make_logs(\n model, epoch_logs, val_results, mode, prefix='val_')\n\n if mode == ModeKeys.TRAIN:\n # Epochs only apply to `fit`.\n callbacks.on_epoch_end(epoch, epoch_logs)\n\n # Recreate dataset iterator for the next epoch.\n if reset_dataset_after_each_epoch and epoch < epochs - 1:\n generator = dataset_ops.make_one_shot_iterator(original_dataset)\n\n model._successful_loop_finish = True\n callbacks._call_end_hook(mode)\n\n if enqueuer is not None:\n enqueuer.stop()\n\n if should_set_learning_phase:\n learning_phase_scope.__exit__(None, None, None)\n\n if mode == ModeKeys.TRAIN:\n return model.history\n return results\n\n\n# Maintain compatibility with the existing names.\nfit_generator = functools.partial(model_iteration, mode=ModeKeys.TRAIN)\nevaluate_generator = functools.partial(\n model_iteration, mode=ModeKeys.TEST, shuffle=False)\npredict_generator = functools.partial(\n model_iteration, mode=ModeKeys.PREDICT, shuffle=False)\n\n\ndef _get_next_batch(generator):\n \"\"\"Retrieves the next batch of input data.\"\"\"\n try:\n generator_output = next(generator)\n except (StopIteration, errors.OutOfRangeError):\n return None\n\n if not isinstance(generator_output, tuple):\n # Always wrap in a tuple.\n generator_output = (generator_output,)\n if len(generator_output) not in [1, 2, 3]:\n raise ValueError(\n 'Output of generator should be a tuple of 1 or 2 or 3 '\n 'elements: (input,) or (input, target) or '\n '(input, target, sample_weights). Received {}'.format(generator_output))\n return generator_output\n\n\ndef _validate_arguments(is_sequence, is_dataset, use_multiprocessing, workers,\n steps_per_epoch, validation_data, validation_steps,\n mode, kwargs):\n \"\"\"Raises errors if arguments are invalid.\n\n Arguments:\n is_sequence: Boolean, whether data is a `keras.utils.data_utils.Sequence`\n instance.\n is_dataset: Boolean, whether data is a dataset instance.\n use_multiprocessing: Boolean. If `True`, use process-based threading. If\n unspecified, `use_multiprocessing` will default to `False`. Note that\n because this implementation relies on multiprocessing, you should not pass\n non-picklable arguments to the generator as they can't be passed easily to\n children processes.\n workers: Integer. Maximum number of processes to spin up when using\n process-based threading. If unspecified, `workers` will default to 1. If\n 0, will execute the generator on the main thread.\n steps_per_epoch: Total number of steps (batches of samples) before declaring\n one epoch finished and starting the next epoch. Ignored with the default\n value of `None`.\n validation_data: Either a tuple of NumPy/Tensor inputs (i.e. `(x,)` or `(x,\n y)` or `(x, y, sample_weights)`) or a generator or\n `keras.utils.data_utils.Sequence` object or Eager Iterator or Dataset.\n validation_steps: Total number of steps (batches of samples) before\n declaring validation finished.\n mode: One of ModeKeys.TRAIN/ModeKeys.TEST/ModeKeys.PREDICT.\n kwargs: Additional arguments for backwards compatibility.\n\n Raises:\n ValueError: If `steps_per_epoch` or `validation_steps` are not passed\n for data types that require them, or if unrecognized keyword\n arguments are passed.\n \"\"\"\n if not is_sequence and use_multiprocessing and workers > 1:\n logging.warning(\n UserWarning('Using a generator with `use_multiprocessing=True`'\n ' and multiple workers may duplicate your data.'\n ' Please consider using the `keras.utils.Sequence`'\n ' class.'))\n\n if steps_per_epoch is None and not is_dataset:\n arg_name = 'steps_per_epoch' if mode == ModeKeys.TRAIN else 'steps'\n raise ValueError('Please specify the number of steps via the '\n '`{}` argument.'.format(arg_name))\n\n val_gen = (\n data_utils.is_generator_or_sequence(validation_data) or\n isinstance(validation_data, iterator_ops.OwnedIterator))\n if (val_gen and not isinstance(validation_data, data_utils.Sequence) and\n not validation_steps):\n raise ValueError('Please specify the `validation_steps` argument.')\n\n if any(k != 'steps' for k in kwargs):\n raise ValueError('Invalid arguments passed: {}'.format(\n [k for k in kwargs if k != 'steps']))\n\n\ndef convert_to_generator_like(data,\n batch_size=None,\n steps_per_epoch=None,\n epochs=1,\n shuffle=False):\n \"\"\"Make a generator out of NumPy or EagerTensor inputs.\n\n Arguments:\n data: Either a generator or `keras.utils.data_utils.Sequence` object or\n `Dataset`, `Iterator`, or a {1,2,3}-tuple of NumPy arrays or EagerTensors.\n If a tuple, the elements represent `(x, y, sample_weights)` and may be\n `None` or `[None]`.\n batch_size: Used when creating a generator out of tuples of NumPy arrays or\n EagerTensors.\n steps_per_epoch: Steps of the generator to run each epoch. If `None` the\n number of steps will be read from the data (for\n `keras.utils.data_utils.Sequence` types).\n epochs: Total number of epochs to run.\n shuffle: Whether the data should be shuffled.\n\n Returns:\n - Generator, `keras.utils.data_utils.Sequence`, or `Iterator`.\n\n Raises:\n - ValueError: If `batch_size` is not provided for NumPy or EagerTensor\n inputs.\n \"\"\"\n if isinstance(data, tuple):\n # Scrub `Nones` that might have been passed for `targets`, `sample_weights`.\n data = tuple(\n ele for ele in data if not all(e is None for e in nest.flatten(ele)))\n\n if data_utils.is_generator_or_sequence(data) or isinstance(\n data, iterator_ops.OwnedIterator):\n if isinstance(data, data_utils.Sequence):\n if steps_per_epoch is None:\n steps_per_epoch = len(data)\n return data, steps_per_epoch\n if isinstance(data, dataset_ops.DatasetV2):\n return dataset_ops.make_one_shot_iterator(data), steps_per_epoch\n\n # Create generator from NumPy or EagerTensor Input.\n num_samples = int(nest.flatten(data)[0].shape[0])\n if batch_size is None:\n raise ValueError(\n 'When passing input data as arrays, do not specify '\n '`steps_per_epoch`/`steps` argument. Please use `batch_size` instead.')\n steps_per_epoch = int(math.ceil(num_samples / batch_size))\n\n def _gen(data):\n \"\"\"Makes a generator out of a structure of NumPy/EagerTensors.\"\"\"\n index_array = np.arange(num_samples)\n for _ in range(epochs):\n if shuffle:\n np.random.shuffle(index_array)\n batches = generic_utils.make_batches(num_samples, batch_size)\n for (batch_start, batch_end) in batches:\n batch_ids = index_array[batch_start:batch_end]\n flat_batch_data = training_utils.slice_arrays(\n nest.flatten(data), batch_ids, contiguous=(not shuffle))\n yield nest.pack_sequence_as(data, flat_batch_data)\n\n return _gen(data), steps_per_epoch\n\n\ndef _make_enqueued_generator(generator,\n workers=1,\n use_multiprocessing=False,\n max_queue_size=10,\n shuffle=False):\n \"\"\"Create a buffered queue of next elements of the generator.\"\"\"\n is_sequence = isinstance(generator, data_utils.Sequence)\n enqueuer = None\n if workers > 0:\n if is_sequence:\n enqueuer = data_utils.OrderedEnqueuer(\n generator, use_multiprocessing=use_multiprocessing, shuffle=shuffle)\n else:\n enqueuer = data_utils.GeneratorEnqueuer(\n generator, use_multiprocessing=use_multiprocessing)\n enqueuer.start(workers=workers, max_queue_size=max_queue_size)\n output_generator = enqueuer.get()\n else:\n if is_sequence:\n output_generator = data_utils.iter_sequence_infinite(generator)\n else:\n output_generator = generator\n return output_generator, enqueuer\n\n\ndef _make_execution_function(model, mode, class_weight=None):\n \"\"\"Makes function to run one step of model execution.\"\"\"\n if mode == ModeKeys.TRAIN:\n f = functools.partial(model.train_on_batch, class_weight=class_weight)\n elif mode == ModeKeys.TEST:\n f = model.test_on_batch\n else:\n # Match signature of other modes to allow\n # 1, 2, or 3-tuples from generator\n def predict_on_batch(x, y=None, sample_weights=None): # pylint: disable=unused-argument\n return model.predict_on_batch(x)\n\n f = predict_on_batch\n\n # Maintain stateful metrics across batch-level calls.\n if mode != ModeKeys.PREDICT:\n f = functools.partial(f, reset_metrics=False)\n\n return f\n\n\ndef _get_num_samples_or_steps(data, steps_per_epoch):\n \"\"\"Returns number of samples or steps, and whether to use steps count mode.\"\"\"\n flat_inputs = nest.flatten(data)\n if hasattr(flat_inputs[0], 'shape'):\n return int(flat_inputs[0].shape[0]), False\n return steps_per_epoch, True\n\n\nclass GeneratorOrSequenceTrainingLoop(training_utils.TrainingLoop):\n \"\"\"Generator-like.\n\n Input is Python generator, or Sequence object.\n\n The difference between this class and `GeneratorLikeTrainingFunction` is that\n this class only handles inputs that with x, y and sample_weight fused into one\n param.\n \"\"\"\n\n def fit(self,\n model,\n x=None,\n y=None,\n batch_size=None,\n epochs=1,\n verbose=1,\n callbacks=None,\n validation_split=0.,\n validation_data=None,\n shuffle=True,\n class_weight=None,\n sample_weight=None,\n initial_epoch=0,\n steps_per_epoch=None,\n validation_steps=None,\n validation_freq=1,\n max_queue_size=10,\n workers=1,\n use_multiprocessing=False):\n model._validate_or_infer_batch_size(batch_size, steps_per_epoch, x)\n training_utils.check_generator_arguments(\n y, sample_weight, validation_split=validation_split)\n return fit_generator(\n model,\n x,\n steps_per_epoch=steps_per_epoch,\n epochs=epochs,\n verbose=verbose,\n callbacks=callbacks,\n validation_data=validation_data,\n validation_steps=validation_steps,\n validation_freq=validation_freq,\n class_weight=class_weight,\n max_queue_size=max_queue_size,\n workers=workers,\n use_multiprocessing=use_multiprocessing,\n shuffle=shuffle,\n initial_epoch=initial_epoch,\n steps_name='steps_per_epoch')\n\n def evaluate(self,\n model,\n x=None,\n y=None,\n batch_size=None,\n verbose=1,\n sample_weight=None,\n steps=None,\n callbacks=None,\n max_queue_size=10,\n workers=1,\n use_multiprocessing=False):\n model._validate_or_infer_batch_size(batch_size, steps, x)\n training_utils.check_generator_arguments(y, sample_weight)\n return evaluate_generator(\n model,\n x,\n steps=steps,\n verbose=verbose,\n callbacks=callbacks,\n max_queue_size=max_queue_size,\n workers=workers,\n use_multiprocessing=use_multiprocessing)\n\n def predict(self,\n model,\n x,\n batch_size=None,\n verbose=0,\n steps=None,\n callbacks=None,\n max_queue_size=10,\n workers=1,\n use_multiprocessing=False):\n model._validate_or_infer_batch_size(batch_size, steps, x)\n return predict_generator(\n model,\n x,\n steps=steps,\n verbose=verbose,\n callbacks=callbacks,\n max_queue_size=max_queue_size,\n workers=workers,\n use_multiprocessing=use_multiprocessing)\n\n\nclass EagerDatasetOrIteratorTrainingLoop(training_utils.TrainingLoop):\n \"\"\"A non-distributed Dataset or iterator in eager execution.\"\"\"\n\n def fit(self,\n model,\n x=None,\n y=None,\n batch_size=None,\n epochs=1,\n verbose=1,\n callbacks=None,\n validation_split=0.,\n validation_data=None,\n shuffle=True,\n class_weight=None,\n sample_weight=None,\n initial_epoch=0,\n steps_per_epoch=None,\n validation_steps=None,\n validation_freq=1,\n **kwargs):\n model._validate_or_infer_batch_size(batch_size, steps_per_epoch, x)\n # Make sure that y, sample_weights, validation_split are not passed.\n training_utils.validate_dataset_input(x, y, sample_weight, validation_split)\n if (isinstance(x, (dataset_ops.DatasetV1, dataset_ops.DatasetV2)) and\n shuffle):\n training_utils.verify_dataset_shuffled(x)\n\n return fit_generator(\n model,\n x,\n steps_per_epoch=steps_per_epoch,\n epochs=epochs,\n verbose=verbose,\n callbacks=callbacks,\n validation_data=validation_data,\n validation_steps=validation_steps,\n validation_freq=validation_freq,\n class_weight=class_weight,\n workers=0,\n shuffle=shuffle,\n initial_epoch=initial_epoch,\n steps_name='steps_per_epoch')\n\n def evaluate(self,\n model,\n x=None,\n y=None,\n batch_size=None,\n verbose=1,\n sample_weight=None,\n steps=None,\n callbacks=None,\n **kwargs):\n model._validate_or_infer_batch_size(batch_size, steps, x)\n # Make sure that y, sample_weights, validation_split are not passed.\n training_utils.validate_dataset_input(x, y, sample_weight)\n return evaluate_generator(\n model, x, steps=steps, verbose=verbose, workers=0, callbacks=callbacks)\n\n def predict(self,\n model,\n x,\n batch_size=None,\n verbose=0,\n steps=None,\n callbacks=None,\n **kwargs):\n model._validate_or_infer_batch_size(batch_size, steps, x)\n return predict_generator(\n model, x, steps=steps, verbose=verbose, workers=0, callbacks=callbacks)\n\n\nclass GeneratorLikeTrainingLoop(training_utils.TrainingLoop):\n \"\"\"TrainingLoop that handle inputs like python generator.\n\n This is the default handler for most of the input data types, includes\n symbolic tensors or Numpy array-like, Datasets and iterators in graph mode\n (since they generate symbolic tensors). This Function is used to handle model\n with `run_eagerly` = True.\n \"\"\"\n\n def fit(self,\n model,\n x=None,\n y=None,\n batch_size=None,\n epochs=1,\n verbose=1,\n callbacks=None,\n validation_split=0.,\n validation_data=None,\n shuffle=True,\n class_weight=None,\n sample_weight=None,\n initial_epoch=0,\n steps_per_epoch=None,\n validation_steps=None,\n validation_freq=1,\n **kwargs):\n batch_size = model._validate_or_infer_batch_size(batch_size,\n steps_per_epoch, x)\n x, y, sample_weights = model._standardize_user_data(\n x,\n y,\n sample_weight=sample_weight,\n class_weight=class_weight,\n batch_size=batch_size,\n check_steps=True,\n steps_name='steps_per_epoch',\n steps=steps_per_epoch,\n validation_split=validation_split,\n shuffle=shuffle)\n\n if validation_data:\n validation_data = model._prepare_validation_data(validation_data,\n batch_size,\n validation_steps)\n elif validation_split and 0. < validation_split < 1.:\n (x, y, sample_weights, val_x, val_y,\n val_sample_weights) = training_utils.split_training_and_validation_data(\n x, y, sample_weights, validation_split)\n validation_data = (val_x, val_y, val_sample_weights)\n else:\n if validation_steps:\n raise ValueError('`validation_steps` should not be specified if '\n '`validation_data` is None.')\n\n return fit_generator(\n model, (x, y, sample_weights),\n steps_per_epoch=steps_per_epoch,\n batch_size=batch_size,\n epochs=epochs,\n verbose=verbose,\n callbacks=callbacks,\n validation_data=validation_data,\n validation_steps=validation_steps,\n validation_freq=validation_freq,\n workers=0,\n shuffle=shuffle,\n initial_epoch=initial_epoch,\n steps_name='steps_per_epoch')\n\n def evaluate(self,\n model,\n x=None,\n y=None,\n batch_size=None,\n verbose=1,\n sample_weight=None,\n steps=None,\n callbacks=None,\n **kwargs):\n batch_size = model._validate_or_infer_batch_size(batch_size, steps, x)\n x, y, sample_weights = model._standardize_user_data(\n x,\n y,\n sample_weight=sample_weight,\n batch_size=batch_size,\n check_steps=True,\n steps_name='steps',\n steps=steps)\n return evaluate_generator(\n model, (x, y, sample_weights),\n steps=steps,\n batch_size=batch_size,\n verbose=verbose,\n workers=0,\n callbacks=callbacks)\n\n def predict(self,\n model,\n x,\n batch_size=None,\n verbose=0,\n steps=None,\n callbacks=None,\n **kwargs):\n batch_size = model._validate_or_infer_batch_size(batch_size, steps, x)\n x, _, _ = model._standardize_user_data(\n x, check_steps=True, steps_name='steps', steps=steps)\n return predict_generator(\n model,\n x,\n steps=steps,\n batch_size=batch_size,\n verbose=verbose,\n workers=0,\n callbacks=callbacks)\n",
"file": "venv/lib/python3.6/site-packages/tensorflow/python/keras/engine/training_generator.py",
"file_size": 30736,
"file_write_time": 132508117590000000,
"settings":
{
"buffer_size": 30736,
"line_ending": "Unix"
}
},
{
"contents": "# Copyright 2018 The TensorFlow Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ==============================================================================\n\"\"\"Training-related utilities.\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nimport abc\nimport atexit\nimport collections\nfrom collections import OrderedDict\nimport functools\nimport multiprocessing.pool\nimport threading\nimport time\n\nimport numpy as np\nimport six\nfrom six.moves import zip # pylint: disable=redefined-builtin\n\nfrom tensorflow.python import tf2\nfrom tensorflow.python.data.experimental.ops import cardinality\nfrom tensorflow.python.data.experimental.ops.distribute_options import AutoShardPolicy\nfrom tensorflow.python.data.ops import dataset_ops\nfrom tensorflow.python.data.ops import iterator_ops\nfrom tensorflow.python.data.ops import readers\nfrom tensorflow.python.eager import context\nfrom tensorflow.python.framework import composite_tensor_utils\nfrom tensorflow.python.framework import dtypes\nfrom tensorflow.python.framework import errors\nfrom tensorflow.python.framework import ops\nfrom tensorflow.python.framework import smart_cond\nfrom tensorflow.python.framework import tensor_shape\nfrom tensorflow.python.framework import tensor_spec\nfrom tensorflow.python.framework import tensor_util\nfrom tensorflow.python.keras import backend as K\nfrom tensorflow.python.keras import callbacks as cbks\nfrom tensorflow.python.keras import losses\nfrom tensorflow.python.keras import metrics as metrics_module\nfrom tensorflow.python.keras.utils import data_utils\nfrom tensorflow.python.keras.utils import generic_utils\nfrom tensorflow.python.keras.utils import losses_utils\nfrom tensorflow.python.ops import array_ops\nfrom tensorflow.python.ops import gen_array_ops\nfrom tensorflow.python.ops import math_ops\nfrom tensorflow.python.ops.losses import util as tf_losses_utils\nfrom tensorflow.python.platform import tf_logging as logging\nfrom tensorflow.python.util import nest\nfrom tensorflow.python.util import tf_inspect\nfrom tensorflow.python.util.compat import collections_abc\n\n\n@six.add_metaclass(abc.ABCMeta)\nclass Aggregator(object):\n \"\"\"Abstract base class used to aggregate batch-level outputs of a loop.\n\n Attributes:\n use_steps: Whether the loop is using `step` or `batch_size`.\n num_samples: Total number of samples: `batch_size * num_batches`.\n steps: Total number of steps.\n batch_size: Batch size. It is used for validation checks between inputs and\n outputs.\n results: What to return at the end of the aggregation loop.\n \"\"\"\n\n def __init__(self, use_steps, num_samples=None, steps=None, batch_size=None):\n self.use_steps = use_steps\n self.num_samples = num_samples\n self.steps = steps\n self.batch_size = batch_size\n self.results = []\n\n @abc.abstractmethod\n def create(self, batch_outs):\n \"\"\"Creates the initial results from the first batch outputs.\n\n Arguments:\n batch_outs: A list of batch-level outputs.\n \"\"\"\n raise NotImplementedError('Must be implemented in subclasses.')\n\n @abc.abstractmethod\n def aggregate(self, batch_outs, batch_start=None, batch_end=None):\n \"\"\"Aggregates batch-level results into total results.\n\n Arguments:\n batch_outs: A list of batch-level outputs.\n batch_start: The start index of this batch. Always `None` if `use_steps`\n is `True`.\n batch_end: The end index of this batch. Always `None` if `use_steps` is\n `True`.\n \"\"\"\n raise NotImplementedError('Must be implemented in subclasses.')\n\n @abc.abstractmethod\n def finalize(self):\n \"\"\"Prepares the total results to be returned.\"\"\"\n raise NotImplementedError('Must be implemented in subclasses.')\n\n\nclass MetricsAggregator(Aggregator):\n \"\"\"Aggregator that calculates loss and metrics info.\n\n Attributes:\n use_steps: Whether the loop is using `step` or `batch_size`.\n num_samples: Total number of samples: `batch_size*num_batches`.\n steps: Total number of steps, ie number of times to iterate over a dataset\n to cover all samples.\n \"\"\"\n\n def __init__(self, use_steps, num_samples=None, steps=None):\n super(MetricsAggregator, self).__init__(\n use_steps=use_steps,\n num_samples=num_samples,\n steps=steps,\n batch_size=None)\n\n def create(self, batch_outs):\n self.results = [0.] * len(batch_outs)\n\n def aggregate(self, batch_outs, batch_start=None, batch_end=None):\n # Loss.\n if self.use_steps:\n self.results[0] += batch_outs[0]\n else:\n self.results[0] += batch_outs[0] * (batch_end - batch_start)\n # Metrics (always stateful, just grab current values.)\n self.results[1:] = batch_outs[1:]\n\n def finalize(self):\n if not self.results:\n raise ValueError('Empty training data.')\n self.results[0] /= (self.num_samples or self.steps)\n\n\nclass ConcatAggregator(Aggregator):\n \"\"\"Combine tensor-likes which cannot be merged on the fly.\n\n This class expects to aggregate a single tensor-like rather than a nested\n structure of tensor-likes.\n \"\"\"\n\n def __init__(self, batch_size):\n self.composite = None\n super(ConcatAggregator, self).__init__(\n use_steps=True, num_samples=None, steps=None, batch_size=batch_size)\n\n def create(self, batch_element):\n self.composite = composite_tensor_utils.is_composite_or_composite_value(\n batch_element)\n\n def aggregate(self, batch_element, batch_start=None, batch_end=None):\n\n # TODO(psv): Add num_samples check here to detect when output batch\n # #samples is < batch size and != input batch #samples.\n if self.batch_size and self.batch_size < batch_element.shape[0]:\n raise ValueError(\n 'Mismatch between expected batch size and model output batch size. '\n 'Output shape = {}, expected output shape = shape {}'.format(\n batch_element.shape,\n (self.batch_size,) + batch_element.shape[1:]))\n self.results.append(batch_element)\n\n def finalize(self):\n # Special case of single batch inference which skips a copy.\n if len(self.results) == 1:\n self.results = self.results[0]\n\n elif self.composite:\n # TODO(taylorrobie): efficiently concatenate.\n results = self.results[0]\n for r in self.results[1:]:\n results = composite_tensor_utils.append_composite_tensor(results, r)\n self.results = results\n\n else:\n self.results = np.concatenate(self.results, axis=0)\n\n if isinstance(self.results, ops.EagerTensor):\n self.results = self.results._numpy() # pylint: disable=protected-access\n\n\n_COPY_THREADS = 4\n_COPY_POOL = None\n\n\ndef get_copy_pool():\n \"\"\"Shared threadpool for copying arrays.\n\n Pool instantiation takes ~ 2ms, so a singleton pool is used rather than\n creating a pool per SliceAggregator.\n\n Returns:\n The global copy threadpool.\n \"\"\"\n global _COPY_POOL\n if _COPY_POOL is None:\n _COPY_POOL = multiprocessing.pool.ThreadPool(_COPY_THREADS)\n atexit.register(_COPY_POOL.close)\n return _COPY_POOL\n\n\nclass SliceAggregator(Aggregator):\n \"\"\"Combine arrays where the final size is known.\n\n This class expects to aggregate a single tensor-like rather than a nested\n structure of tensor-likes.\n\n NumPy copies are an operation that threads handle quite well because all of\n the heavy lifting is in c and does not need the GIL. Moreover, we can perform\n lock-free writes to the same buffer in multiple threads because the nature of\n result aggregation guarantees that either the indices are disjoint or the\n aggregator will throw an exception in finalize. Moreover, because aggregation\n is performed on the slowest varying dimension, assignments for a given batch\n will write to contiguous blocks of memory, further minimizing contention.\n\n There is, however, some scheduling and context switching overhead which will\n offset the gains from pipelining the slice assignment. Below a given threshold\n it is faster to simply assign in the main thread rather than enqueue the\n assignment in a side thread. The exact threshold will vary from system to\n system, but the time is not very sensitive to the exact transition so a value\n of 2 ** 14 was chosen which should be reasonable on most systems.\n \"\"\"\n\n _BINARY_SIZE_THRESHOLD = 2 ** 14\n _MAX_COPY_SECONDS = 300\n\n def __init__(self, num_samples, batch_size):\n self._async_copies = []\n self._pool = get_copy_pool()\n self._errors = []\n super(SliceAggregator, self).__init__(\n use_steps=False,\n num_samples=num_samples,\n steps=None,\n batch_size=batch_size)\n\n def create(self, batch_element):\n # This step does not need to be pipelined because NumPy empty array\n # initialization is effectively instantaneous.\n shape = (self.num_samples,) + batch_element.shape[1:]\n dtype = batch_element.dtype\n if isinstance(batch_element, ops.EagerTensor):\n dtype = dtype.as_numpy_dtype\n\n self.results = np.empty(shape=shape, dtype=dtype)\n\n def aggregate(self, batch_element, batch_start, batch_end):\n # Fail early.\n if self._errors:\n six.reraise(type(self._errors[0]), self._errors[0])\n\n # In the special case of single batch inference, no copy is needed.\n if batch_end - batch_start == self.num_samples:\n if self.num_samples != batch_element.shape[0]:\n raise ValueError(\n 'Mismatch between expected batch size and model output batch size. '\n 'Output shape = {}, expected output shape = shape {}'.format(\n batch_element.shape, self.results.shape))\n\n self.results = batch_element\n return\n\n # This is an approximate threshold, so we don't need to consider the number\n # of bytes per element.\n num_elements = np.prod(batch_element.shape)\n if num_elements < self._BINARY_SIZE_THRESHOLD:\n self.results[batch_start:batch_end] = batch_element\n else:\n is_finished = threading.Event()\n self._pool.apply_async(\n self._slice_assign,\n args=(batch_element, batch_start, batch_end, is_finished))\n self._async_copies.append(is_finished)\n\n def _slice_assign(self, batch_element, batch_start, batch_end, is_finished):\n try:\n self.results[batch_start:batch_end] = batch_element\n\n except Exception as e: # pylint: disable=broad-except\n # `_slice_assign` should only be called in threads and exceptions raised\n # in threads do not carry over to the main thread. So instead we perform a\n # a broad catch in the thread and then store the exception to be re-raised\n # in the main thread.\n self._errors.append(e)\n\n finally:\n is_finished.set()\n\n def finalize(self):\n start_time = time.time()\n for is_finished in self._async_copies:\n timeout = max([0., self._MAX_COPY_SECONDS - (time.time() - start_time)])\n if not is_finished.wait(timeout):\n raise ValueError('Timed out waiting for copy to complete.')\n\n if self._errors:\n six.reraise(self._errors[0].__class__, self._errors[0])\n\n\nclass OutputsAggregator(Aggregator):\n \"\"\"Aggregator that concatenates outputs.\"\"\"\n\n _structure = None\n\n def create(self, batch_outs):\n # SparseTensorValue is a named tuple which nest will flatten, so we need\n # to guard it to properly handle the structure.\n self._structure = nest.get_traverse_shallow_structure(\n lambda x: not composite_tensor_utils.is_composite_or_composite_value(x),\n batch_outs)\n batch_outs = nest.flatten_up_to(self._structure, batch_outs)\n\n for batch_element in batch_outs:\n if composite_tensor_utils.is_composite_or_composite_value(batch_element):\n # If the output is not a ndarray, it will be either a composite tensor\n # or a composite tensor's Value object. In either case, we can't\n # allocate an array to hold the object - we'll handle it later.\n self.results.append(ConcatAggregator(self.batch_size))\n elif isinstance(batch_element, (np.ndarray, ops.EagerTensor)):\n self.results.append(\n (ConcatAggregator(self.batch_size) if self.use_steps else\n SliceAggregator(self.num_samples, self.batch_size)))\n else:\n # This is not a ndarray, a CompositeTensor, or a CompositeTensorValue.\n # Fail fast rather than trying to concatenate it.\n raise RuntimeError('Attempted to aggregate unsupported object {}.'\n .format(batch_element))\n\n self.results[-1].create(batch_element)\n\n def aggregate(self, batch_outs, batch_start=None, batch_end=None):\n batch_outs = nest.flatten_up_to(self._structure, batch_outs)\n for batch_element, result in zip(batch_outs, self.results):\n result.aggregate(batch_element, batch_start, batch_end)\n\n def finalize(self):\n for result in self.results:\n result.finalize()\n self.results = [i.results for i in self.results]\n self.results = nest.pack_sequence_as(self._structure, self.results)\n\n\ndef get_progbar(model, count_mode, include_metrics=True):\n \"\"\"Get Progbar.\"\"\"\n if include_metrics:\n stateful_metric_names = getattr(model, 'metrics_names', None)\n if stateful_metric_names:\n stateful_metric_names = stateful_metric_names[1:] # Exclude `loss`\n else:\n stateful_metric_names = None\n return cbks.ProgbarLogger(count_mode, stateful_metrics=stateful_metric_names)\n\n\ndef slice_arrays(arrays, indices, contiguous=True):\n \"\"\"Slices batches out of provided arrays (workaround for eager tensors).\n\n Unfortunately eager tensors don't have the same slicing behavior as\n Numpy arrays (they follow the same slicing behavior as symbolic TF tensors),\n hence we cannot use `generic_utils.slice_arrays` directly\n and we have to implement this workaround based on `concat`. This has a\n performance cost.\n\n Arguments:\n arrays: Single array or list of arrays.\n indices: List of indices in the array that should be included in the output\n batch.\n contiguous: Boolean flag indicating whether the indices are contiguous.\n\n Returns:\n Slice of data (either single array or list of arrays).\n \"\"\"\n converted_to_list = False\n if not isinstance(arrays, list):\n converted_to_list = True\n arrays = [arrays]\n if any(tensor_util.is_tensor(x) for x in arrays):\n if not contiguous:\n entries = [[x[i:i + 1] for i in indices] for x in arrays]\n slices = [array_ops.concat(x, axis=0) for x in entries]\n else:\n slices = [x[indices[0]:indices[-1] + 1] for x in arrays]\n else:\n slices = generic_utils.slice_arrays(arrays, indices)\n\n if converted_to_list:\n slices = slices[0]\n return slices\n\n\ndef check_num_samples(ins, batch_size=None, steps=None, steps_name='steps'):\n \"\"\"Determine the number of samples provided for training and evaluation.\n\n The number of samples is not defined when running with `steps`,\n in which case the number of samples is set to `None`.\n\n Arguments:\n ins: List of tensors to be fed to the Keras function.\n batch_size: Integer batch size or `None` if not defined.\n steps: Total number of steps (batches of samples) before declaring\n `_predict_loop` finished. Ignored with the default value of `None`.\n steps_name: The public API's parameter name for `steps`.\n\n Raises:\n ValueError: when `steps` is `None` and the attribute `ins.shape`\n does not exist. Also raises ValueError when `steps` is not `None`\n and `batch_size` is not `None` because they are mutually\n exclusive.\n\n Returns:\n When steps is `None`, returns the number of samples to be\n processed based on the size of the first dimension of the\n first input numpy array. When steps is not `None` and\n `batch_size` is `None`, returns `None`.\n \"\"\"\n if steps is not None and batch_size is not None:\n raise ValueError('If ' + steps_name +\n ' is set, the `batch_size` must be None.')\n if check_steps_argument(ins, steps, steps_name):\n return None\n\n if hasattr(ins[0], 'shape'):\n return int(ins[0].shape[0])\n return None # Edge case where ins == [static_learning_phase]\n\n\ndef standardize_single_array(x, expected_shape=None):\n \"\"\"Expand data of shape (x,) to (x, 1), unless len(expected_shape)==1.\"\"\"\n if x is None:\n return None\n\n if composite_tensor_utils.is_composite_or_composite_value(x):\n return x\n\n if isinstance(x, int):\n raise ValueError(\n 'Expected an array data type but received an integer: {}'.format(x))\n\n if (x.shape is not None and len(x.shape) == 1 and\n (expected_shape is None or len(expected_shape) != 1)):\n if tensor_util.is_tensor(x):\n x = array_ops.expand_dims(x, axis=1)\n else:\n x = np.expand_dims(x, 1)\n return x\n\n\ndef standardize_input_data(data,\n names,\n shapes=None,\n check_batch_axis=True,\n exception_prefix=''):\n \"\"\"Normalizes inputs and targets provided by users.\n\n Users may pass data as a list of arrays, dictionary of arrays,\n or as a single array. We normalize this to an ordered list of\n arrays (same order as `names`), while checking that the provided\n arrays have shapes that match the network's expectations.\n\n Arguments:\n data: User-provided input data (polymorphic).\n names: List of expected array names.\n shapes: Optional list of expected array shapes.\n check_batch_axis: Boolean; whether to check that the batch axis of the\n arrays matches the expected value found in `shapes`.\n exception_prefix: String prefix used for exception formatting.\n\n Returns:\n List of standardized input arrays (one array per model input).\n\n Raises:\n ValueError: in case of improperly formatted user-provided data.\n \"\"\"\n try:\n data_len = len(data)\n except TypeError:\n # For instance if data is `None` or a symbolic Tensor.\n data_len = None\n\n if not names:\n if data_len and not isinstance(data, dict):\n raise ValueError(\n 'Error when checking model ' + exception_prefix + ': '\n 'expected no data, but got:', data)\n return []\n if data is None:\n return [None for _ in range(len(names))]\n\n if isinstance(data, dict):\n try:\n data = [\n data[x].values\n if data[x].__class__.__name__ == 'DataFrame' else data[x]\n for x in names\n ]\n except KeyError as e:\n raise ValueError('No data provided for \"' + e.args[0] + '\". Need data '\n 'for each key in: ' + str(names))\n elif isinstance(data, (list, tuple)):\n if isinstance(data[0], (list, tuple)):\n data = [np.asarray(d) for d in data]\n elif len(names) == 1 and isinstance(data[0], (float, int)):\n data = [np.asarray(data)]\n else:\n data = [\n x.values if x.__class__.__name__ == 'DataFrame' else x for x in data\n ]\n else:\n data = data.values if data.__class__.__name__ == 'DataFrame' else data\n data = [data]\n\n if shapes is not None:\n data = [\n standardize_single_array(x, shape) for (x, shape) in zip(data, shapes)\n ]\n else:\n data = [standardize_single_array(x) for x in data]\n\n if len(data) != len(names):\n if data and hasattr(data[0], 'shape'):\n raise ValueError('Error when checking model ' + exception_prefix +\n ': the list of Numpy arrays that you are passing to '\n 'your model is not the size the model expected. '\n 'Expected to see ' + str(len(names)) + ' array(s), ' +\n 'for inputs ' + str(names) + ' but instead got the '\n 'following list of ' + str(len(data)) + ' arrays: ' +\n str(data)[:200] + '...')\n elif len(names) > 1:\n raise ValueError('Error when checking model ' + exception_prefix +\n ': you are passing a list as input to your model, '\n 'but the model expects a list of ' + str(len(names)) +\n ' Numpy arrays instead. The list you passed was: ' +\n str(data)[:200])\n elif len(data) == 1 and not hasattr(data[0], 'shape'):\n raise TypeError('Error when checking model ' + exception_prefix +\n ': data should be a Numpy array, or list/dict of '\n 'Numpy arrays. Found: ' + str(data)[:200] + '...')\n elif len(names) == 1:\n data = [np.asarray(data)]\n\n # Check shapes compatibility.\n if shapes:\n for i in range(len(names)):\n if shapes[i] is not None:\n if tensor_util.is_tensor(data[i]):\n tensorshape = data[i].shape\n if not tensorshape:\n continue\n data_shape = tuple(tensorshape.as_list())\n elif composite_tensor_utils.is_composite_or_composite_value(data[i]):\n tensorshape = composite_tensor_utils.get_shape(data[i])\n data_shape = tuple(tensorshape.as_list())\n else:\n data_shape = data[i].shape\n\n shape = shapes[i]\n if len(data_shape) != len(shape):\n raise ValueError('Error when checking ' + exception_prefix +\n ': expected ' + names[i] + ' to have ' +\n str(len(shape)) + ' dimensions, but got array '\n 'with shape ' + str(data_shape))\n if not check_batch_axis:\n data_shape = data_shape[1:]\n shape = shape[1:]\n for dim, ref_dim in zip(data_shape, shape):\n if ref_dim != dim and ref_dim is not None and dim is not None:\n raise ValueError('Error when checking ' + exception_prefix +\n ': expected ' + names[i] + ' to have shape ' +\n str(shape) + ' but got array with shape ' +\n str(data_shape))\n return data\n\n\ndef standardize_sample_or_class_weights(x_weight, output_names, weight_type):\n \"\"\"Maps `sample_weight` or `class_weight` to model outputs.\n\n Arguments:\n x_weight: User-provided `sample_weight` or `class_weight` argument.\n output_names: List of output names (strings) in the model.\n weight_type: A string used purely for exception printing.\n\n Returns:\n A list of `sample_weight` or `class_weight` where there are exactly\n one element per model output.\n\n Raises:\n ValueError: In case of invalid user-provided argument.\n \"\"\"\n if x_weight is None or (isinstance(x_weight, (list, tuple)) and\n len(x_weight) == 0): # pylint: disable=g-explicit-length-test\n return [None for _ in output_names]\n if len(output_names) == 1:\n if isinstance(x_weight, (list, tuple)) and len(x_weight) == 1:\n return x_weight\n if isinstance(x_weight, dict) and output_names[0] in x_weight:\n return [x_weight[output_names[0]]]\n else:\n return [x_weight]\n if isinstance(x_weight, (list, tuple)):\n if len(x_weight) != len(output_names):\n raise ValueError('Provided `' + weight_type + '` was a list of ' +\n str(len(x_weight)) + ' elements, but the model has ' +\n str(len(output_names)) + ' outputs. '\n 'You should provide one `' + weight_type + '`'\n 'array per model output.')\n return x_weight\n if isinstance(x_weight, collections.Mapping):\n generic_utils.check_for_unexpected_keys(weight_type, x_weight, output_names)\n x_weights = []\n for name in output_names:\n x_weights.append(x_weight.get(name))\n return x_weights\n else:\n raise TypeError('The model has multiple outputs, so `' + weight_type + '` '\n 'should be either a list or a dict. '\n 'Provided `' + weight_type + '` type not understood: ' +\n str(x_weight))\n\n\ndef standardize_class_weights(class_weight, output_names):\n return standardize_sample_or_class_weights(class_weight, output_names,\n 'class_weight')\n\n\ndef standardize_sample_weights(sample_weight, output_names):\n return standardize_sample_or_class_weights(sample_weight, output_names,\n 'sample_weight')\n\n\ndef handle_partial_sample_weights(outputs, sample_weights, sample_weight_modes,\n check_all_flat=False):\n \"\"\"Adds 1.0 as sample weights for the outputs for which there is no weight.\n\n Args:\n outputs: List of model outputs.\n sample_weights: List of sample weight inputs.\n sample_weight_modes: List of sample weight modes or None.\n check_all_flat: Ensure that inputs are not nested structures. This is not\n a free check, so we may not want to run it eagerly every iteration.\n\n Returns:\n Tuple of sample weights, one sample weight for every output, and booleans\n describing the raw sample weights.\n \"\"\"\n any_sample_weight = sample_weights is not None and any(\n w is not None for w in sample_weights)\n partial_sample_weight = any_sample_weight and any(\n w is None for w in sample_weights)\n\n if not any_sample_weight:\n return None, any_sample_weight, partial_sample_weight\n\n if not partial_sample_weight:\n return sample_weights, any_sample_weight, partial_sample_weight\n\n if check_all_flat:\n nest.assert_same_structure(\n list_to_tuple(sample_weights),\n list_to_tuple(nest.flatten(sample_weights)))\n nest.assert_same_structure(\n list_to_tuple(outputs),\n list_to_tuple(nest.flatten(outputs)))\n if sample_weight_modes is not None:\n nest.assert_same_structure(\n sample_weight_modes, nest.flatten(sample_weight_modes))\n\n new_sample_weights = []\n for i, sw in enumerate(sample_weights):\n if sw is None:\n as_numpy = isinstance(outputs[i], np.ndarray)\n output = outputs[i]\n output_shape = output.shape if as_numpy else array_ops.shape(output)\n\n is_temporal = (\n sample_weight_modes is not None and\n sample_weight_modes[i] == 'temporal')\n sw_shape = (output_shape[0],\n output_shape[1]) if is_temporal else (output_shape[0],)\n\n new_sample_weights.append(\n np.ones(sw_shape) if as_numpy else array_ops.ones(sw_shape))\n\n else:\n new_sample_weights.append(sw)\n return (list_to_tuple(new_sample_weights),\n any_sample_weight, partial_sample_weight)\n\n\ndef check_array_lengths(inputs, targets, weights=None):\n \"\"\"Does user input validation for numpy arrays.\n\n Arguments:\n inputs: list of Numpy arrays of inputs.\n targets: list of Numpy arrays of targets.\n weights: list of Numpy arrays of sample weights.\n\n Raises:\n ValueError: in case of incorrectly formatted data.\n \"\"\"\n\n def is_tensor_or_composite_tensor(x):\n return tensor_util.is_tensor(\n x) or composite_tensor_utils.is_composite_or_composite_value(x)\n\n def set_of_lengths(x):\n # Returns a set with the variation between\n # different shapes, with None => 0\n if x is None:\n return {}\n else:\n return set([\n y.shape[0]\n for y in x\n if y is not None and not is_tensor_or_composite_tensor(y)\n ])\n\n set_x = set_of_lengths(inputs)\n set_y = set_of_lengths(targets)\n set_w = set_of_lengths(weights)\n if len(set_x) > 1:\n raise ValueError('All input arrays (x) should have '\n 'the same number of samples. Got array shapes: ' +\n str([x.shape for x in inputs]))\n if len(set_y) > 1:\n raise ValueError('All target arrays (y) should have '\n 'the same number of samples. Got array shapes: ' +\n str([y.shape for y in targets]))\n if set_x and set_y and list(set_x)[0] != list(set_y)[0]:\n raise ValueError('Input arrays should have '\n 'the same number of samples as target arrays. '\n 'Found ' + str(list(set_x)[0]) + ' input samples '\n 'and ' + str(list(set_y)[0]) + ' target samples.')\n if len(set_w) > 1:\n raise ValueError('All sample_weight arrays should have '\n 'the same number of samples. Got array shapes: ' +\n str([w.shape for w in weights]))\n if set_y and set_w and list(set_y)[0] != list(set_w)[0]:\n raise ValueError('Sample_weight arrays should have '\n 'the same number of samples as target arrays. Got ' +\n str(list(set_y)[0]) + ' input samples and ' +\n str(list(set_w)[0]) + ' target samples.')\n\n\ndef check_loss_and_target_compatibility(targets, loss_fns, output_shapes):\n \"\"\"Does validation on the compatibility of targets and loss functions.\n\n This helps prevent users from using loss functions incorrectly. This check\n is purely for UX purposes.\n\n Arguments:\n targets: list of Numpy arrays of targets.\n loss_fns: list of loss functions.\n output_shapes: list of shapes of model outputs.\n\n Raises:\n ValueError: if a loss function or target array\n is incompatible with an output.\n \"\"\"\n key_loss_fns = {\n losses.mean_squared_error, losses.binary_crossentropy,\n losses.categorical_crossentropy\n }\n key_loss_classes = (losses.MeanSquaredError, losses.BinaryCrossentropy,\n losses.CategoricalCrossentropy)\n for y, loss, shape in zip(targets, loss_fns, output_shapes):\n if y is None or loss is None or tensor_util.is_tensor(y):\n continue\n if losses.is_categorical_crossentropy(loss):\n if y.shape[-1] == 1:\n raise ValueError('You are passing a target array of shape ' +\n str(y.shape) +\n ' while using as loss `categorical_crossentropy`. '\n '`categorical_crossentropy` expects '\n 'targets to be binary matrices (1s and 0s) '\n 'of shape (samples, classes). '\n 'If your targets are integer classes, '\n 'you can convert them to the expected format via:\\n'\n '```\\n'\n 'from keras.utils import to_categorical\\n'\n 'y_binary = to_categorical(y_int)\\n'\n '```\\n'\n '\\n'\n 'Alternatively, you can use the loss function '\n '`sparse_categorical_crossentropy` instead, '\n 'which does expect integer targets.')\n\n is_loss_wrapper = isinstance(loss, losses.LossFunctionWrapper)\n if (isinstance(loss, key_loss_classes) or (is_loss_wrapper and\n (loss.fn in key_loss_fns))):\n for target_dim, out_dim in zip(y.shape[1:], shape[1:]):\n if out_dim is not None and target_dim != out_dim:\n loss_name = loss.name\n if loss_name is None:\n loss_type = loss.fn if is_loss_wrapper else type(loss)\n loss_name = loss_type.__name__\n raise ValueError('A target array with shape ' + str(y.shape) +\n ' was passed for an output of shape ' + str(shape) +\n ' while using as loss `' + loss_name + '`. '\n 'This loss expects targets to have the same shape '\n 'as the output.')\n\n\ndef collect_per_output_metric_info(metrics,\n output_names,\n output_shapes,\n loss_fns,\n is_weighted=False):\n \"\"\"Maps metric names and functions to model outputs.\n\n Arguments:\n metrics: a list or a list of lists or a dict of metric functions.\n output_names: a list of the names (strings) of model outputs.\n output_shapes: a list of the shapes (strings) of model outputs.\n loss_fns: a list of the loss functions corresponding to the model outputs.\n is_weighted: Boolean indicating whether the given metrics are weighted.\n\n Returns:\n A list (one entry per model output) of dicts.\n For instance, if the model has 2 outputs, and for the first output\n we want to compute \"binary_accuracy\" and \"binary_crossentropy\",\n and just \"binary_accuracy\" for the second output,\n the list would look like: `[{\n 'acc': binary_accuracy(),\n 'ce': binary_crossentropy(),\n }, {\n 'acc': binary_accuracy(),\n }]`\n\n Raises:\n TypeError: if an incorrect type is passed for the `metrics` argument.\n \"\"\"\n if not metrics:\n return [{} for _ in output_names]\n\n if isinstance(metrics, list):\n any_sub_list = any(isinstance(m, list) for m in metrics)\n if any_sub_list:\n if len(metrics) != len(output_names):\n raise ValueError('When passing a list of lists as `metrics`, '\n 'it should have one entry per model output. '\n 'The model has ' + str(len(output_names)) +\n ' outputs, but you passed metrics=' + str(metrics))\n # User has provided a list of len = len(outputs).\n nested_metrics = [generic_utils.to_list(m) for m in metrics]\n else:\n # If it is a single list we then apply all metrics to all outputs.\n if len(output_names) > 1:\n nested_metrics = []\n for _ in output_names:\n nested_metrics.append(\n [metrics_module.clone_metric(m) for m in metrics])\n else:\n nested_metrics = [metrics]\n elif isinstance(metrics, collections.Mapping):\n generic_utils.check_for_unexpected_keys('metrics', metrics, output_names)\n nested_metrics = []\n for name in output_names:\n output_metrics = generic_utils.to_list(metrics.get(name, []))\n nested_metrics.append(output_metrics)\n else:\n raise TypeError('Type of `metrics` argument not understood. '\n 'Expected a list or dictionary, found: ' + str(metrics))\n\n per_output_metrics = []\n for i, metrics in enumerate(nested_metrics):\n metrics_dict = OrderedDict()\n for metric in metrics:\n metric_name = get_metric_name(metric, is_weighted)\n metric_fn = get_metric_function(\n metric, output_shape=output_shapes[i], loss_fn=loss_fns[i])\n\n # If the metric function is not stateful, we create a stateful version.\n if not isinstance(metric_fn, metrics_module.Metric):\n metric_fn = metrics_module.MeanMetricWrapper(\n metric_fn, name=metric_name)\n metrics_dict[metric_name] = metric_fn\n per_output_metrics.append(metrics_dict)\n\n return per_output_metrics\n\n\ndef batch_shuffle(index_array, batch_size):\n \"\"\"Shuffles an array in a batch-wise fashion.\n\n Useful for shuffling HDF5 arrays\n (where one cannot access arbitrary indices).\n\n Arguments:\n index_array: array of indices to be shuffled.\n batch_size: integer.\n\n Returns:\n The `index_array` array, shuffled in a batch-wise fashion.\n \"\"\"\n batch_count = int(len(index_array) / batch_size)\n # to reshape we need to be cleanly divisible by batch size\n # we stash extra items and reappend them after shuffling\n last_batch = index_array[batch_count * batch_size:]\n index_array = index_array[:batch_count * batch_size]\n index_array = index_array.reshape((batch_count, batch_size))\n np.random.shuffle(index_array)\n index_array = index_array.flatten()\n return np.append(index_array, last_batch)\n\n\ndef standardize_weights(y,\n sample_weight=None,\n class_weight=None,\n sample_weight_mode=None):\n \"\"\"Performs sample weight validation and standardization.\n\n Everything gets normalized to a single sample-wise (or timestep-wise)\n weight array. If both `sample_weight` and `class_weight` are provided,\n the weights are multiplied.\n\n Arguments:\n y: Numpy array or Tensor of model targets to be weighted.\n sample_weight: User-provided `sample_weight` argument.\n class_weight: User-provided `class_weight` argument.\n sample_weight_mode: One of `None` or `\"temporal\"`. `\"temporal\"` indicated\n that we expect 2D weight data that will be applied to the last 2\n dimensions of the targets (i.e. we are weighting timesteps, not\n samples).\n\n Returns:\n A numpy array of target weights, one entry per sample to weight.\n\n Raises:\n ValueError: In case of invalid user-provided arguments.\n \"\"\"\n # Iterator may return sample_weight as 1-tuple\n if isinstance(sample_weight, tuple):\n sample_weight = sample_weight[0]\n if sample_weight_mode is not None and sample_weight_mode != 'samplewise':\n if sample_weight_mode != 'temporal':\n raise ValueError('\"sample_weight_mode '\n 'should be None or \"temporal\". '\n 'Found: ' + str(sample_weight_mode))\n if len(y.shape) < 3:\n raise ValueError('Found a sample_weight array for '\n 'an input with shape ' + str(y.shape) + '. '\n 'Timestep-wise sample weighting (use of '\n 'sample_weight_mode=\"temporal\") is restricted to '\n 'outputs that are at least 3D, i.e. that have '\n 'a time dimension.')\n if sample_weight is not None and len(sample_weight.shape) != 2:\n raise ValueError('Found a sample_weight array with shape ' +\n str(sample_weight.shape) + '. '\n 'In order to use timestep-wise sample weighting, '\n 'you should pass a 2D sample_weight array.')\n else:\n if sample_weight is not None and len(sample_weight.shape) != 1:\n raise ValueError('Found a sample_weight array with shape {}. In order to '\n 'use timestep-wise sample weights, you should specify '\n 'sample_weight_mode=\"temporal\" in compile(); found \"{}\" '\n 'instead. If you just mean to use sample-wise weights, '\n 'make sure your sample_weight array is 1D.'\n .format(sample_weight.shape, sample_weight_mode))\n\n if sample_weight is not None:\n if len(sample_weight.shape) > len(y.shape):\n raise ValueError('Found a sample_weight with shape' +\n str(sample_weight.shape) + '.'\n 'Expected sample_weight with rank '\n 'less than or equal to ' + str(len(y.shape)))\n\n if (not tensor_util.is_tensor(sample_weight) and\n y.shape[:sample_weight.ndim] != sample_weight.shape):\n raise ValueError('Found a sample_weight array with shape ' +\n str(sample_weight.shape) + ' for an input with shape ' +\n str(y.shape) + '. '\n 'sample_weight cannot be broadcast.')\n\n # Class weights applied per-sample.\n class_sample_weight = None\n if isinstance(class_weight, dict):\n if len(y.shape) > 2:\n raise ValueError('`class_weight` not supported for '\n '3+ dimensional targets.')\n\n if tensor_util.is_tensor(y):\n # Few classes are expected, so densifying is reasonable.\n keys = np.array(sorted(class_weight.keys()))\n values = np.array([class_weight[i] for i in keys])\n weight_vector = np.zeros(np.max(keys) + 1)\n weight_vector[:] = np.nan\n weight_vector[keys] = values\n\n y_classes = smart_cond.smart_cond(\n len(y.shape.as_list()) == 2 and K.shape(y)[1] > 1,\n lambda: K.argmax(y, axis=1),\n lambda: math_ops.cast(K.reshape(y, (-1,)), dtypes.int64)\n )\n class_sample_weight = array_ops.gather(weight_vector, y_classes)\n gen_array_ops.check_numerics(\n class_sample_weight,\n 'Invalid classes or class weights detected. NaN values indicate that '\n 'an appropriate class weight could not be determined.')\n class_sample_weight = math_ops.cast(class_sample_weight, K.floatx())\n if sample_weight is not None:\n sample_weight = math_ops.cast(\n ops.convert_to_tensor_v2(sample_weight), K.floatx())\n else:\n y_classes = y\n if len(y.shape) == 2:\n if y.shape[1] > 1:\n y_classes = np.argmax(y, axis=1)\n elif y.shape[1] == 1:\n y_classes = np.reshape(y, y.shape[0])\n\n class_sample_weight = np.asarray(\n [class_weight[cls] for cls in y_classes if cls in class_weight])\n\n if len(class_sample_weight) != len(y_classes):\n # subtract the sets to pick all missing classes\n existing_classes = set(y_classes)\n existing_class_weight = set(class_weight.keys())\n raise ValueError(\n '`class_weight` must contain all classes in the data.'\n ' The classes %s exist in the data but not in '\n '`class_weight`.' % (existing_classes - existing_class_weight))\n\n if class_sample_weight is not None and sample_weight is not None:\n # Multiply weights if both are provided.\n return class_sample_weight * sample_weight\n if sample_weight is not None:\n return sample_weight\n if class_sample_weight is not None:\n return class_sample_weight\n return None\n\n\ndef has_symbolic_tensors(ls):\n if context.executing_eagerly():\n return False\n return has_tensors(ls)\n\n\ndef has_tensors(ls):\n if isinstance(ls, (list, tuple)):\n return any(tensor_util.is_tensor(v) for v in ls)\n if isinstance(ls, dict):\n return any(tensor_util.is_tensor(v) for _, v in six.iteritems(ls))\n return tensor_util.is_tensor(ls)\n\n\ndef get_metric_name(metric, weighted=False):\n \"\"\"Returns the name corresponding to the given metric input.\n\n Arguments:\n metric: Metric function name or reference.\n weighted: Boolean indicating if the given metric is weighted.\n\n Returns:\n The metric name.\n \"\"\"\n if tf2.enabled():\n # We keep the string that the user has set in compile as the metric name.\n if isinstance(metric, six.string_types):\n return metric\n\n metric = metrics_module.get(metric)\n return metric.name if hasattr(metric, 'name') else metric.__name__\n else:\n metric_name_prefix = 'weighted_' if weighted else ''\n if metric in ('accuracy', 'acc', 'crossentropy', 'ce'):\n if metric in ('accuracy', 'acc'):\n suffix = 'acc'\n elif metric in ('crossentropy', 'ce'):\n suffix = 'ce'\n else:\n metric_fn = metrics_module.get(metric)\n # Get metric name as string\n if hasattr(metric_fn, 'name'):\n suffix = metric_fn.name\n else:\n suffix = metric_fn.__name__\n metric_name = metric_name_prefix + suffix\n return metric_name\n\n\ndef get_metric_function(metric, output_shape=None, loss_fn=None):\n \"\"\"Returns the metric function corresponding to the given metric input.\n\n Arguments:\n metric: Metric function name or reference.\n output_shape: The shape of the output that this metric will be calculated\n for.\n loss_fn: The loss function used.\n\n Returns:\n The metric function.\n \"\"\"\n if metric not in ['accuracy', 'acc', 'crossentropy', 'ce']:\n return metrics_module.get(metric)\n\n is_sparse_categorical_crossentropy = (\n isinstance(loss_fn, losses.SparseCategoricalCrossentropy) or\n (isinstance(loss_fn, losses.LossFunctionWrapper) and\n loss_fn.fn == losses.sparse_categorical_crossentropy))\n\n is_binary_crossentropy = (\n isinstance(loss_fn, losses.BinaryCrossentropy) or\n (isinstance(loss_fn, losses.LossFunctionWrapper) and\n loss_fn.fn == losses.binary_crossentropy))\n\n if metric in ['accuracy', 'acc']:\n if output_shape[-1] == 1 or is_binary_crossentropy:\n return metrics_module.binary_accuracy\n elif is_sparse_categorical_crossentropy:\n return metrics_module.sparse_categorical_accuracy\n # If the output_shape[-1] is not 1, then we know output is `categorical`.\n # We assume it is sparse categorical only if loss is explicitly given\n # as sparse categorical crossentropy loss.\n return metrics_module.categorical_accuracy\n else:\n if output_shape[-1] == 1 or is_binary_crossentropy:\n return metrics_module.binary_crossentropy\n elif is_sparse_categorical_crossentropy:\n return metrics_module.sparse_categorical_crossentropy\n return metrics_module.categorical_crossentropy\n\n\ndef call_metric_function(metric_fn,\n y_true,\n y_pred=None,\n weights=None,\n mask=None):\n \"\"\"Invokes metric function and returns the metric result tensor.\"\"\"\n if mask is not None:\n mask = math_ops.cast(mask, y_pred.dtype)\n if weights is None:\n # Use mask as sample weight.\n weights = mask\n else:\n # Update dimensions of weights to match with mask.\n weights = math_ops.cast(weights, dtype=y_pred.dtype)\n mask, _, weights = tf_losses_utils.squeeze_or_expand_dimensions(\n mask, sample_weight=weights)\n weights *= mask\n\n if y_pred is not None:\n return metric_fn(y_true, y_pred, sample_weight=weights)\n # `Mean` metric only takes a single value.\n return metric_fn(y_true, sample_weight=weights)\n\n\ndef get_loss_function(loss):\n \"\"\"Returns the loss corresponding to the loss input in `compile` API.\"\"\"\n if loss is None or isinstance(loss, losses.Loss):\n return loss\n\n if tf_inspect.isclass(loss) and issubclass(loss, losses.Loss):\n # It is not safe to assume that the loss takes no constructor arguments.\n raise ValueError(\n 'Received uninstantiated Loss class: {}\\nPlease call loss \"\"classes '\n 'before passing them to Model.compile.'.format(loss))\n\n # Deserialize loss configuration, if needed.\n if isinstance(loss, collections_abc.Mapping):\n loss = losses.get(loss)\n\n # Custom callable class.\n if callable(loss) and not hasattr(loss, '__name__'):\n return loss\n\n # Wrap loss function with signature `(y_true, y_pred, **kwargs)`\n # in `LossFunctionWrapper` class.\n loss_fn = losses.get(loss)\n\n # For losses which are given as strings/functions in the compile API,\n # we always set the loss reduction type to be `SUM_OVER_BATCH_SIZE`\n # (both in distribution strategy context and otherwise).\n return losses.LossFunctionWrapper(\n loss_fn,\n name=loss_fn.__name__,\n reduction=losses_utils.ReductionV2.SUM_OVER_BATCH_SIZE)\n\n\nclass RespectCompiledTrainableState(object):\n \"\"\"Set and restore trainable state if it has changed since compile.\n\n The keras API guarantees that the value of each Layer's `trainable` property\n at `Model.compile` time will be used when training that model. In order to\n respect this requirement, it may be necessary to set the trainable value of\n layers to their compile time values before beginning a training endpoint and\n restore the values before returing from said endpoint. This scope checks if\n any layer's trainable state has changed since Model compile, and performs this\n set and un-set bookkeeping.\n\n However, the trainable state of a layer changes quite infrequently, if ever,\n for many kinds of workflows. Moreover, updating every layer in a model is an\n expensive operation. As a result, we will only explicitly set and unset the\n trainable state of a model if a trainable value has changed since compile.\n \"\"\"\n\n def __init__(self, model):\n self._model = model\n self._current_trainable_state = None\n self._compiled_trainable_state = None\n self._should_set_trainable = False\n\n def __enter__(self):\n self._current_trainable_state = self._model._get_trainable_state() # pylint: disable=protected-access\n self._compiled_trainable_state = self._model._compiled_trainable_state # pylint: disable=protected-access\n\n # Check to see if any layer's trainable state has changed since `compile`.\n for layer, trainable in self._compiled_trainable_state.items():\n if (layer in self._current_trainable_state and\n trainable != self._current_trainable_state[layer]):\n self._should_set_trainable = True\n break\n\n # If so, restore the model to its compiled state.\n if self._should_set_trainable:\n self._model._set_trainable_state(self._compiled_trainable_state) # pylint: disable=protected-access\n\n def __exit__(self, type_arg, value_arg, traceback_arg):\n # If we set the values to their compiled state in __enter__, we need to\n # restore the original values before leaving the scope.\n if self._should_set_trainable:\n self._model._set_trainable_state(self._current_trainable_state) # pylint: disable=protected-access\n return False # False values do not suppress exceptions\n\n\ndef validate_dataset_input(x, y, sample_weight, validation_split=None):\n \"\"\"Validates user input arguments when a dataset iterator is passed.\n\n Arguments:\n x: Input data. A `tf.data` dataset or iterator.\n y: Target data. It could be either Numpy array(s) or TensorFlow tensor(s).\n Expected to be `None` when `x` is a dataset iterator.\n sample_weight: An optional sample-weight array passed by the user to weight\n the importance of each sample in `x`. Expected to be `None` when `x` is a\n dataset iterator\n validation_split: Float between 0 and 1. Fraction of the training data to be\n used as validation data. Expected to be `None` when `x` is a dataset\n iterator.\n\n Raises:\n ValueError: if argument `y` or `sample_weight` or `validation_split` are\n provided by user.\n \"\"\"\n if y is not None:\n raise ValueError('You passed a dataset or dataset iterator (%s) as '\n 'input `x` to your model. In that case, you should '\n 'not specify a target (`y`) argument, since the dataset '\n 'or dataset iterator generates both input data and '\n 'target data. '\n 'Received: %s' % (x, y))\n if sample_weight is not None:\n raise ValueError('`sample_weight` argument is not supported when input '\n '`x` is a dataset or a dataset iterator. Instead, you'\n 'can provide sample_weight as the third element of your'\n 'dataset, i.e. (inputs, targets, sample_weight). '\n 'Received: x=%s, sample_weight=%s' % (x, sample_weight))\n if validation_split is not None and validation_split != 0.0:\n raise ValueError(\n '`validation_split` argument is not supported when '\n 'input `x` is a dataset or a dataset iterator. '\n 'Received: x=%s, validation_split=%f' % (x, validation_split))\n\n\ndef validate_input_types(inp, orig_inp, allow_dict=True, field_name='inputs'):\n \"\"\"Helper function to validate either inputs or targets.\"\"\"\n if isinstance(inp, (list, tuple)):\n if not all(isinstance(v, np.ndarray) or\n tensor_util.is_tensor(v) for v in inp):\n raise ValueError(\n 'Please provide as model inputs either a single array or a list of '\n 'arrays. You passed: {}={}'.format(field_name, str(orig_inp)))\n elif isinstance(inp, dict):\n if not allow_dict:\n raise ValueError(\n 'You cannot pass a dictionary as model {}.'.format(field_name))\n elif not isinstance(inp, np.ndarray) and not tensor_util.is_tensor(inp):\n raise ValueError(\n 'Please provide as model inputs either a single array or a list of '\n 'arrays. You passed: {}={}'.format(field_name, orig_inp))\n\n\ndef check_generator_arguments(y=None, sample_weight=None,\n validation_split=None):\n \"\"\"Validates arguments passed when using a generator.\"\"\"\n if y is not None:\n raise ValueError('`y` argument is not supported when data is'\n 'a generator or Sequence instance. Instead pass targets'\n ' as the second element of the generator.')\n if sample_weight is not None:\n raise ValueError('`sample_weight` argument is not supported when data is'\n 'a generator or Sequence instance. Instead pass sample'\n ' weights as the third element of the generator.')\n if validation_split:\n raise ValueError('If your data is in the form of a Python generator, '\n 'you cannot use `validation_split`.')\n\n\ndef check_steps_argument(input_data, steps, steps_name):\n \"\"\"Validates `steps` argument based on input data's type.\n\n The cases when `steps` value must be provided are when\n 1. input data passed is an iterator.\n 2. model was built on top of symbolic tensors, input data is not\n required and is `None`.\n 3. input data passed is a symbolic tensor.\n\n Arguments:\n input_data: Input data. Can be Numpy array(s) or TensorFlow tensor(s) or\n tf.data.Dataset iterator or `None`.\n steps: Integer or `None`. Total number of steps (batches of samples) to\n execute.\n steps_name: The public API's parameter name for `steps`.\n\n Returns:\n boolean, True if `steps` argument is required, else False.\n\n Raises:\n ValueError: if `steps` argument is required for given input data type\n but not provided.\n \"\"\"\n is_x_iterator = isinstance(\n input_data, (iterator_ops.Iterator, iterator_ops.OwnedIterator))\n if (input_data is None or is_x_iterator or has_symbolic_tensors(input_data) or\n (isinstance(input_data, list) and not input_data)):\n if steps is None:\n input_type_str = 'a Dataset iterator' if is_x_iterator else 'data tensors'\n raise ValueError('When using {input_type} as input to a model, you should'\n ' specify the `{steps_name}` argument.'.format(\n input_type=input_type_str, steps_name=steps_name))\n return True\n\n if isinstance(input_data, (dataset_ops.DatasetV1, dataset_ops.DatasetV2)):\n return True\n\n if steps is not None:\n list_types = (np.ndarray, list, tuple)\n if (isinstance(input_data, list_types) or\n (isinstance(input_data, dict) and\n any(isinstance(v, list_types) for v in input_data.values()))):\n logging.warning('When passing input data as arrays, do not specify '\n '`steps_per_epoch`/`steps` argument. '\n 'Please use `batch_size` instead.')\n return False\n\n\ndef cast_single_tensor(x, dtype=None):\n if isinstance(x, np.ndarray):\n x = ops.convert_to_tensor_v2(x)\n dtype = dtype or K.floatx()\n if x.dtype.is_floating:\n return math_ops.cast(x, dtype=dtype)\n return x\n\n\ndef cast_if_floating_dtype_and_mismatch(targets, outputs):\n \"\"\"Returns target data tensors using correct datatype.\n\n Checks that each target and output pair are the same datatype. If not, casts\n the target to the output's datatype.\n\n Args:\n targets: tensor or list of targets.\n outputs: tensor or list of outputs.\n\n Returns:\n Targets in appropriate datatype.\n \"\"\"\n if tensor_util.is_tensor(targets):\n # There is one target, so output[0] should be the only output.\n return cast_single_tensor(targets, dtype=outputs[0].dtype)\n new_targets = []\n for target, out in zip(targets, outputs):\n if isinstance(target, np.ndarray):\n target = ops.convert_to_tensor_v2(target)\n if target.dtype != out.dtype:\n new_targets.append(cast_single_tensor(target, dtype=out.dtype))\n else:\n new_targets.append(target)\n return new_targets\n\n\ndef cast_if_floating_dtype(x, dtype=None):\n \"\"\"Casts the given data tensors to the default floating point type.\n\n Casts only if the input is already a floating point type.\n Args:\n x: tensor or list/tuple of tensors.\n dtype: The dtype to which Tensors should be cast.\n\n Returns:\n Converted input.\n \"\"\"\n return nest.map_structure(functools.partial(cast_single_tensor, dtype=dtype),\n x)\n\n\ndef cast_to_model_input_dtypes(x, model):\n \"\"\"Casts the given data tensors to the dtypes of the model inputs.\n\n Args:\n x: tensor or list/tuple of tensors.\n model: The model.\n\n Returns:\n Converted input. Each tensor is casted to the corresponding input in\n `model.inputs`.\n \"\"\"\n input_dtypes = nest.map_structure(lambda t: t.dtype, model.inputs)\n return nest.map_structure(math_ops.cast, x, input_dtypes)\n\n\ndef prepare_sample_weight_modes(training_endpoints, sample_weight_mode):\n \"\"\"Prepares sample weight modes for the model.\n\n Args:\n training_endpoints: List of model _TrainingEndpoints.\n sample_weight_mode: sample weight mode user input passed from compile API.\n\n Raises:\n ValueError: In case of invalid `sample_weight_mode` input.\n \"\"\"\n\n if isinstance(sample_weight_mode, collections.Mapping):\n generic_utils.check_for_unexpected_keys(\n 'sample_weight_mode', sample_weight_mode,\n [e.output_name for e in training_endpoints])\n\n for end_point in training_endpoints:\n if not end_point.should_skip_target_weights():\n if end_point.output_name not in sample_weight_mode:\n raise ValueError('Output ' + end_point.output_name +\n 'missing from `_sample_weight_modes` dictionary')\n else:\n end_point.sample_weight_mode = sample_weight_mode.get(\n end_point.output_name)\n elif isinstance(sample_weight_mode, (list, tuple)):\n if len(sample_weight_mode) != len(training_endpoints):\n raise ValueError('When passing a list as sample_weight_mode, '\n 'it should have one entry per model output. '\n 'The model has ' + str(len(training_endpoints)) +\n ' outputs, but you passed ' +\n str(len(sample_weight_mode)) + '_sample_weight_modes.')\n for mode, endpoint in zip(sample_weight_mode, training_endpoints):\n if not endpoint.should_skip_target_weights():\n endpoint.sample_weight_mode = mode\n else:\n for endpoint in training_endpoints:\n if not endpoint.should_skip_target_weights():\n endpoint.sample_weight_mode = sample_weight_mode\n\n\ndef prepare_loss_functions(loss, output_names):\n \"\"\"Converts loss to a list of loss functions.\n\n Arguments:\n loss: String (name of objective function), objective function or\n `tf.losses.Loss` instance. See `tf.losses`. If the model has multiple\n outputs, you can use a different loss on each output by passing a\n dictionary or a list of losses. The loss value that will be minimized by\n the model will then be the sum of all individual losses.\n output_names: List of model output names.\n\n Returns:\n A list of loss objective functions.\n\n Raises:\n ValueError: If loss is a dict with keys not in model output names,\n or if loss is a list with len not equal to model outputs.\n \"\"\"\n if isinstance(loss, collections_abc.Mapping):\n generic_utils.check_for_unexpected_keys('loss', loss, output_names)\n loss_functions = []\n for name in output_names:\n if name not in loss:\n logging.warning(\n 'Output {0} missing from loss dictionary. We assume '\n 'this was done on purpose. The fit and evaluate APIs will not be '\n 'expecting any data to be passed to {0}.'.format(name))\n loss_functions.append(get_loss_function(loss.get(name, None)))\n elif isinstance(loss, six.string_types):\n loss_functions = [get_loss_function(loss) for _ in output_names]\n elif isinstance(loss, collections_abc.Sequence):\n if len(loss) != len(output_names):\n raise ValueError('When passing a list as loss, it should have one entry '\n 'per model outputs. The model has {} outputs, but you '\n 'passed loss={}'.format(len(output_names), loss))\n loss_functions = nest.map_structure(get_loss_function, loss)\n else:\n loss_functions = [get_loss_function(loss) for _ in range(len(output_names))]\n\n return loss_functions\n\n\ndef prepare_loss_weights(training_endpoints, loss_weights=None):\n \"\"\"Converts loss weights to a list of loss weights.\n\n The result loss weights will be populated on the training endpoint.\n\n Arguments:\n training_endpoints: List of model training endpoints.\n loss_weights: Optional list or dictionary specifying scalar coefficients\n (Python floats) to weight the loss contributions of different model\n outputs. The loss value that will be minimized by the model will then be\n the *weighted sum* of all individual losses, weighted by the\n `loss_weights` coefficients. If a list, it is expected to have a 1:1\n mapping to the model's outputs. If a dict, it is expected to map\n output names (strings) to scalar coefficients.\n\n Raises:\n ValueError: If loss weight is a dict with key not in model output names,\n or if loss is a list with len not equal to model outputs.\n \"\"\"\n if loss_weights is None:\n for e in training_endpoints:\n e.loss_weight = 1.\n elif isinstance(loss_weights, collections.Mapping):\n generic_utils.check_for_unexpected_keys(\n 'loss_weights', loss_weights,\n [e.output_name for e in training_endpoints])\n for e in training_endpoints:\n e.loss_weight = loss_weights.get(e.output_name, 1.)\n elif isinstance(loss_weights, list):\n if len(loss_weights) != len(training_endpoints):\n raise ValueError('When passing a list as loss_weights, '\n 'it should have one entry per model output. '\n 'The model has ' + str(len(training_endpoints)) +\n ' outputs, but you passed loss_weights=' +\n str(loss_weights))\n for w, e in zip(loss_weights, training_endpoints):\n e.loss_weight = w\n else:\n raise TypeError('Could not interpret loss_weights argument: ' +\n str(loss_weights) + ' - expected a list of dicts.')\n\n\n# TODO(rohanj): This is a hack to get around not depending on feature_column and\n# create a cyclical dependency. Figure out a cleaner solution\ndef is_feature_layer(layer):\n \"\"\"Returns whether `layer` is a FeatureLayer or not.\"\"\"\n return getattr(layer, '_is_feature_layer', False)\n\n\ndef is_eager_dataset_or_iterator(data):\n return context.executing_eagerly() and isinstance(\n data, (dataset_ops.DatasetV1, dataset_ops.DatasetV2,\n iterator_ops.OwnedIterator))\n\n\n# pylint: disable=protected-access\ndef assert_not_batched(dataset):\n \"\"\"Asserts that `dataset` is not batched.\n\n The algorithm used by this method is sound but not complete. In other words,\n if the method fails to establish the assertion, it does not mean the dataset\n is batched.\n\n Example usage:\n ```python\n try:\n assert_not_batched(dataset)\n # safe to assume `dataset` it not batched here\n expect ValueError:\n # make no assumptions about `dataset`\n ```\n\n Args:\n dataset: The dataset to analyze.\n\n Raises:\n ValueError: If the method cannot establish the assertion.\n \"\"\"\n if isinstance(dataset, dataset_ops.DatasetV1Adapter):\n return assert_not_batched(dataset._dataset)\n else:\n whitelisted_types = [\n dataset_ops._OptionsDataset,\n dataset_ops.ConcatenateDataset,\n dataset_ops.CacheDataset,\n dataset_ops.FilterDataset,\n dataset_ops.MapDataset,\n dataset_ops.ParallelMapDataset,\n dataset_ops.PrefetchDataset,\n dataset_ops.RangeDataset,\n dataset_ops.RepeatDataset,\n dataset_ops.ShuffleDataset,\n dataset_ops.SkipDataset,\n dataset_ops.SparseTensorSliceDataset,\n dataset_ops.TakeDataset,\n dataset_ops.TensorDataset,\n dataset_ops.TensorSliceDataset,\n dataset_ops.ZipDataset,\n readers.FixedLengthRecordDatasetV2,\n readers.TextLineDatasetV2,\n readers.TFRecordDatasetV2,\n ]\n for ty in whitelisted_types:\n if isinstance(dataset, ty):\n for input_dataset in dataset._inputs():\n assert_not_batched(input_dataset)\n return\n raise ValueError('Could not assert that dataset is not batched.')\n\n\n# pylint: disable=protected-access\ndef assert_not_shuffled(dataset):\n \"\"\"Asserts that `dataset` is not shuffled.\n\n The algorithm used by this method is sound but not complete. In other words,\n if the method fails to establish the assertion, it does not mean the dataset\n is shuffled.\n\n Example usage:\n ```python\n try:\n assert_not_shuffled(dataset)\n # safe to assume `dataset` it not shuffled here\n expect ValueError:\n # make no assumptions about `dataset`\n ```\n\n Args:\n dataset: The dataset to analyze.\n\n Raises:\n ValueError: If the method cannot establish the assertion.\n \"\"\"\n if isinstance(dataset, dataset_ops.DatasetV1Adapter):\n return assert_not_shuffled(dataset._dataset)\n else:\n whitelisted_types = [\n dataset_ops._OptionsDataset,\n dataset_ops.BatchDataset,\n dataset_ops.ConcatenateDataset,\n dataset_ops.CacheDataset,\n dataset_ops.FilterDataset,\n dataset_ops.MapDataset,\n dataset_ops.PaddedBatchDataset,\n dataset_ops.ParallelMapDataset,\n dataset_ops.PrefetchDataset,\n dataset_ops.RangeDataset,\n dataset_ops.RepeatDataset,\n dataset_ops.SkipDataset,\n dataset_ops.SparseTensorSliceDataset,\n dataset_ops.TakeDataset,\n dataset_ops.TensorDataset,\n dataset_ops.TensorSliceDataset,\n dataset_ops.WindowDataset,\n dataset_ops.ZipDataset,\n readers.FixedLengthRecordDatasetV2,\n readers.TextLineDatasetV2,\n readers.TFRecordDatasetV2,\n ]\n for ty in whitelisted_types:\n if isinstance(dataset, ty):\n for input_dataset in dataset._inputs():\n assert_not_shuffled(input_dataset)\n return\n raise ValueError('Could not assert that dataset is not shuffled.')\n\n\ndef verify_dataset_shuffled(x):\n \"\"\"Verifies that the dataset is shuffled.\n\n Args:\n x: Dataset passed as an input to the model.\n\n Raises:\n ValueError: if the dataset is not already shuffled.\n \"\"\"\n assert isinstance(x, dataset_ops.DatasetV2)\n try:\n assert_not_shuffled(x)\n except ValueError:\n # Dataset may or may not be shuffled.\n return\n else:\n logging.warning('Expected a shuffled dataset but input dataset `x` is '\n 'not shuffled. Please invoke `shuffle()` on input dataset.')\n\n\ndef is_dataset_or_iterator(data):\n return isinstance(data, (dataset_ops.DatasetV1, dataset_ops.DatasetV2,\n iterator_ops.Iterator, iterator_ops.OwnedIterator))\n\n\ndef get_iterator(dataset):\n \"\"\"Create and initialize an iterator from a dataset.\"\"\"\n if context.executing_eagerly():\n iterator = dataset_ops.make_one_shot_iterator(dataset)\n else:\n iterator = dataset_ops.make_initializable_iterator(dataset)\n initialize_iterator(iterator)\n return iterator\n\n\ndef initialize_iterator(iterator):\n if not context.executing_eagerly():\n init_op = iterator.initializer\n K.get_session((init_op,)).run(init_op)\n\n\ndef extract_tensors_from_dataset(dataset):\n \"\"\"Extract a tuple of tensors `inputs, targets, sample_weight` from a dataset.\n\n Arguments:\n dataset: Dataset instance.\n\n Returns:\n Tuple of tensors `x, y, weights`. `y` and `weights` entry may be None.\n \"\"\"\n iterator = get_iterator(dataset)\n inputs, targets, sample_weight = unpack_iterator_input(iterator)\n return inputs, targets, sample_weight\n\n\ndef unpack_iterator_input(iterator):\n \"\"\"Convert a dataset iterator to a tuple of tensors `x, y, sample_weights`.\n\n Arguments:\n iterator: Instance of a dataset iterator.\n\n Returns:\n Tuple of tensors `x, y, weights`. `y` and `weights` entry may be None.\n \"\"\"\n try:\n next_element = iterator.get_next()\n except errors.OutOfRangeError:\n raise RuntimeError('Your dataset iterator ran out of data; '\n 'Make sure that your dataset can generate '\n 'required number of samples.')\n\n if isinstance(next_element, (list, tuple)):\n if len(next_element) not in [2, 3]:\n raise ValueError(\n 'Please provide model inputs as a list or tuple of 2 or 3 '\n 'elements: (input, target) or (input, target, sample_weights) '\n 'Received %s' % next_element)\n if len(next_element) == 2:\n x, y = next_element\n weights = None\n else:\n x, y, weights = next_element\n else:\n x = next_element\n y = None\n weights = None\n return x, y, weights\n\n\ndef infer_steps_for_dataset(model,\n dataset,\n steps,\n epochs=1,\n steps_name='steps'):\n \"\"\"Infers steps_per_epoch needed to loop through a dataset.\n\n Arguments:\n model: Keras model instance.\n dataset: Input data of type tf.data.Dataset.\n steps: Number of steps to draw from the dataset (may be None if unknown).\n epochs: Number of times to iterate over the dataset.\n steps_name: The string name of the steps argument, either `steps`,\n `validation_steps`, or `steps_per_epoch`. Only used for error message\n formatting.\n\n Returns:\n Integer or `None`. Inferred number of steps to loop through the dataset.\n `None` is returned if 1) the size of the dataset is unknown and `steps` was\n not specified, or 2) this is multi-worker training and auto sharding is\n enabled.\n\n Raises:\n ValueError: In case of invalid argument values.\n \"\"\"\n assert isinstance(dataset, dataset_ops.DatasetV2)\n if (model._in_multi_worker_mode() and\n (dataset.options().experimental_distribute.auto_shard_policy !=\n AutoShardPolicy.OFF)):\n # If the dataset would be auto-sharded, we should not infer a local\n # steps_per_epoch due to the possible inbalanced sharding between workers.\n return None\n\n size = K.get_value(cardinality.cardinality(dataset))\n if size == cardinality.INFINITE and steps is None:\n raise ValueError('When passing an infinitely repeating dataset, you '\n 'must specify the `%s` argument.' % (steps_name,))\n if size >= 0:\n if steps is not None and steps * epochs > size:\n if epochs > 1:\n raise ValueError('The dataset you passed contains %s batches, but you '\n 'passed `epochs=%s` and `%s=%s`, which is a total of '\n '%s steps. We cannot draw that many steps from this '\n 'dataset. We suggest to set `%s=%s`.' %\n (size, epochs, steps_name, steps, steps * epochs,\n steps_name, size // epochs))\n else:\n raise ValueError('The dataset you passed contains %s batches, but you '\n 'passed `%s=%s`. We cannot draw that many steps from '\n 'this dataset. We suggest to set `%s=%s`.' %\n (size, steps_name, steps, steps_name, size))\n if steps is None:\n if size >= 0:\n return size\n return None\n return steps\n\n\nclass ModelInputs(object):\n \"\"\"Encapsulates model inputs.\n\n Allows for transforming model inputs while keeping the same structure.\n \"\"\"\n\n def __init__(self, inputs):\n self._inputs = inputs\n self._is_dict = isinstance(self._inputs, dict)\n self._is_single_input = not isinstance(self._inputs, (list, tuple, dict))\n\n self._flattened_inputs = []\n self._input_names = []\n\n if self._is_dict:\n for k in sorted(self._inputs.keys()):\n self._flattened_inputs.append(self._inputs[k])\n self._input_names.append(k)\n else:\n self._flattened_inputs = nest.flatten(self._inputs)\n self._input_names = [\n 'input_%d' % (i + 1) for i in range(len(self._flattened_inputs))\n ]\n\n def get_input_names(self):\n \"\"\"Returns keys to name inputs by.\n\n In case inputs provided were a list, tuple or single entry, we make up a\n key 'input_%d'. For dictionary case, we return a sorted list of keys.\n \"\"\"\n return self._input_names\n\n def get_symbolic_inputs(self, return_single_as_list=False):\n \"\"\"Returns inputs to be set as self.inputs for a model.\"\"\"\n # TODO(karmel): There is a side-effect here where what you get\n # with as_list and as_dict depends on whether you have called this\n # method first, since it modifies in place.\n for i, (k, v) in enumerate(zip(self._input_names, self._flattened_inputs)):\n if isinstance(v, (list, float, int)):\n v = np.asarray(v)\n if v.ndim == 1:\n v = np.expand_dims(v, 1)\n\n if isinstance(v, (np.ndarray, ops.EagerTensor)):\n # We fix the placeholder shape except the batch size.\n # This is suboptimal, but it is the best we can do with the info\n # we have. The user should call `model._set_inputs(placeholders)`\n # to specify custom placeholders if the need arises.\n shape = (None,) + tuple(v.shape[1:])\n if shape == (None,):\n shape = (None, 1)\n dtype = dtypes.as_dtype(v.dtype)\n if dtype.is_floating:\n dtype = K.floatx()\n v = K.placeholder(shape=shape, name=k, dtype=dtype)\n elif isinstance(v, tensor_spec.TensorSpec):\n shape = (None,) + tuple(v.shape.as_list()[1:])\n if shape == (None,):\n shape = (None, 1)\n v = K.placeholder(shape=shape, name=k, dtype=v.dtype)\n\n self._flattened_inputs[i] = v\n\n if self._is_dict:\n return dict(zip(self._input_names, self._flattened_inputs))\n if self._is_single_input and not return_single_as_list:\n return self._flattened_inputs[0]\n return self._flattened_inputs\n\n def as_dict(self):\n \"\"\"An iterable over a dictionary version of inputs.\"\"\"\n for k, v in zip(self._input_names, self._flattened_inputs):\n yield k, v\n\n def as_list(self):\n \"\"\"Returning the inputs as a list.\"\"\"\n return self._flattened_inputs\n\n\n# Allow use of methods not exposed to the user.\n# pylint: disable=protected-access\ndef get_input_shape_and_dtype(layer):\n \"\"\"Retrieves input shape and input dtype of layer if applicable.\n\n Args:\n layer: Layer (or model) instance.\n\n Returns:\n Tuple (input_shape, input_dtype). Both could be None if the layer\n does not have a defined input shape.\n\n Raises:\n ValueError: in case an empty Sequential or Functional model is passed.\n \"\"\"\n\n def _is_graph_model(layer):\n return ((hasattr(layer, '_is_graph_network') and layer._is_graph_network) or\n layer.__class__.__name__ == 'Sequential')\n\n # In case of nested models: recover the first layer\n # of the deepest model to infer input shape and dtype.\n # Subclassed Models may not have been built so can't be checked.\n while _is_graph_model(layer):\n if not layer.layers:\n raise ValueError('An empty Model cannot be used as a Layer.')\n layer = layer.layers[0]\n\n if hasattr(layer, '_batch_input_shape'):\n return layer._batch_input_shape, layer.dtype\n return None, None\n\n\n# pylint: enable=protected-access\n\n\ndef get_static_batch_size(layer):\n \"\"\"Gets the static batch size of a Layer.\n\n Arguments:\n layer: a `Layer` instance.\n\n Returns:\n The static batch size of a Layer.\n \"\"\"\n batch_input_shape, _ = get_input_shape_and_dtype(layer)\n if batch_input_shape is not None:\n return tensor_shape.as_dimension(batch_input_shape[0]).value\n return None\n\n\ndef generic_output_names(outputs_list):\n return ['output_%d' % (i + 1) for i in range(len(outputs_list))]\n\n\ndef convert_eager_tensors_to_numpy(structure):\n \"\"\"Convert every EagerTensor in `structure` to NumPy.\n\n Arguments:\n structure: An arbitrary structure of elements to be converted to NumPy\n arrays.\n\n Returns:\n An identical structure with EagerTensors converted to NumPy arrays.\n \"\"\"\n\n def _convert(element):\n if isinstance(element, ops.EagerTensor):\n return element.numpy()\n return element\n\n return nest.map_structure(_convert, structure)\n\n\ndef list_to_tuple(maybe_list):\n \"\"\"Datasets will stack the list of tensor, so switch them to tuples.\"\"\"\n if isinstance(maybe_list, list):\n return tuple(maybe_list)\n return maybe_list\n\n\ndef should_run_validation(validation_freq, epoch):\n \"\"\"Checks if validation should be run this epoch.\n\n Arguments:\n validation_freq: Integer or list. If an integer, specifies how many training\n epochs to run before a new validation run is performed. If a list,\n specifies the epochs on which to run validation.\n epoch: Integer, the number of the training epoch just completed.\n\n Returns:\n Bool, True if validation should be run.\n\n Raises:\n ValueError: if `validation_freq` is an Integer and less than 1, or if\n it is neither an Integer nor a Sequence.\n \"\"\"\n # `epoch` is 0-indexed internally but 1-indexed in the public API.\n one_indexed_epoch = epoch + 1\n\n if isinstance(validation_freq, int):\n if validation_freq < 1:\n raise ValueError('`validation_freq` can not be less than 1.')\n return one_indexed_epoch % validation_freq == 0\n\n if not isinstance(validation_freq, collections_abc.Container):\n raise ValueError('`validation_freq` must be an Integer or '\n '`collections_abc.Container` (e.g. list, tuple, etc.)')\n return one_indexed_epoch in validation_freq\n\n\ndef split_training_and_validation_data(x, y, sample_weights, validation_split):\n \"\"\"Split input data into train/eval section based on validation_split.\"\"\"\n if has_symbolic_tensors(x):\n raise ValueError('If your data is in the form of symbolic tensors, '\n 'you cannot use `validation_split`.')\n if hasattr(x[0], 'shape'):\n split_at = int(x[0].shape[0] * (1. - validation_split))\n else:\n split_at = int(len(x[0]) * (1. - validation_split))\n x, val_x = (generic_utils.slice_arrays(x, 0, split_at),\n generic_utils.slice_arrays(x, split_at))\n y, val_y = (generic_utils.slice_arrays(y, 0, split_at),\n generic_utils.slice_arrays(y, split_at))\n if sample_weights:\n sample_weights, val_sample_weights = (\n generic_utils.slice_arrays(sample_weights, 0, split_at),\n generic_utils.slice_arrays(sample_weights, split_at),\n )\n else:\n val_sample_weights = None\n return x, y, sample_weights, val_x, val_y, val_sample_weights\n\n\ndef unpack_validation_data(validation_data, raise_if_ambiguous=True):\n \"\"\"Unpack validation data based input type.\n\n The validation data is not touched if its dataset or dataset iterator.\n For other type of input (Numpy or tensor), it will be unpacked into tuple of\n 3 which is x, y and sample weights.\n\n Args:\n validation_data: dataset, dataset iterator, or numpy, tensor tuple.\n raise_if_ambiguous: boolean on whether to fail if validation_data cannot be\n parsed. Otherwise simply return validation_data, None, None and defer the\n decision to the caller.\n\n Returns:\n tuple of 3, (x, y, sample_weights) for numpy and tensor input.\n \"\"\"\n if (isinstance(validation_data, (iterator_ops.Iterator,\n iterator_ops.OwnedIterator,\n dataset_ops.DatasetV2,\n data_utils.Sequence))\n or not hasattr(validation_data, '__len__')):\n val_x = validation_data\n val_y = None\n val_sample_weight = None\n elif len(validation_data) == 2:\n try:\n val_x, val_y = validation_data # pylint: disable=unpacking-non-sequence\n val_sample_weight = None\n except ValueError:\n val_x, val_y, val_sample_weight = validation_data, None, None\n elif len(validation_data) == 3:\n try:\n val_x, val_y, val_sample_weight = validation_data # pylint: disable=unpacking-non-sequence\n except ValueError:\n val_x, val_y, val_sample_weight = validation_data, None, None\n else:\n if raise_if_ambiguous:\n raise ValueError(\n 'When passing a `validation_data` argument, '\n 'it must contain either 2 items (x_val, y_val), '\n 'or 3 items (x_val, y_val, val_sample_weights), '\n 'or alternatively it could be a dataset or a '\n 'dataset or a dataset iterator. '\n 'However we received `validation_data=%s`' % validation_data)\n val_x, val_y, val_sample_weight = validation_data, None, None\n return val_x, val_y, val_sample_weight\n\n\nclass TrainingLoop(object):\n \"\"\"TrainingLoop is a wrapper class around the training logic.\n\n This class is trying to encapsulate the different logic of fit/eval/predict\n with regard to different data input and model condition.\n\n Note that TrainingLoop is stateless, which means it doesn't contain any\n internal field and can be reused with different model and inputs.\n \"\"\"\n\n def fit(self,\n model,\n x=None,\n y=None,\n batch_size=None,\n epochs=1,\n verbose=1,\n callbacks=None,\n validation_split=0.,\n validation_data=None,\n shuffle=True,\n class_weight=None,\n sample_weight=None,\n initial_epoch=0,\n steps_per_epoch=None,\n validation_steps=None,\n validation_freq=1,\n **kwargs):\n \"\"\"Train the model with the inputs and targets.\"\"\"\n raise NotImplementedError()\n\n def evaluate(self,\n model,\n x=None,\n y=None,\n batch_size=None,\n verbose=1,\n sample_weight=None,\n steps=None,\n callbacks=None,\n **kwargs):\n \"\"\"Returns the loss value & metrics values for the model in test mode.\"\"\"\n raise NotImplementedError()\n\n def predict(self,\n model,\n x,\n batch_size=None,\n verbose=0,\n steps=None,\n callbacks=None,\n **kwargs):\n raise NotImplementedError()\n",
"file": "venv/lib/python3.6/site-packages/tensorflow/python/keras/engine/training_utils.py",
"file_size": 81689,
"file_write_time": 132394892070000000,
"settings":
{
"buffer_size": 81689,
"line_ending": "Unix"
}
},
{
"contents": "import numpy as np\nimport sarewt.data_reader as dare\nimport pofah.util.utility_fun as utfu\n\n\n\n\ndef mask_training_cuts(constituents, features):\n ''' get mask for training cuts requiring a jet-pt > 200'''\n jetPt_cut = 200.\n idx_j1Pt, idx_j2Pt = 1, 6\n mask_j1 = features[:, idx_j1Pt] > jetPt_cut\n mask_j2 = features[:, idx_j2Pt] > jetPt_cut\n return mask_j1, mask_j2\n\ndef constituents_to_input_samples(constituents, mask_j1, mask_j2): # -> np.ndarray\n const_j1 = constituents[:,0,:,:][mask_j1]\n const_j2 = constituents[:,1,:,:][mask_j2]\n samples = np.vstack([const_j1, const_j2])\n np.random.shuffle(samples)\n return samples \n\ndef events_to_input_samples(constituents, features):\n mask_j1, mask_j2 = mask_training_cuts(constituents, features)\n return constituents_to_input_samples(constituents, mask_j1, mask_j2)\n\n\nclass DataGenerator():\n\n def __init__(self, path, sample_part_n=1e4, sample_max_n=None, **cuts):\n ''' \n sample_part_n ... number of events(!) read as chunk from file-data-generator (TODO: change to event_part_n)\n sample_max_n ... number of single jet samples as input into VAE (unpacked dijets)\n '''\n self.path = path\n self.sample_part_n = int(sample_part_n) # sample_part_n events from file parts\n self.sample_max_n = int(sample_max_n) if sample_max_n else None\n self.cuts = cuts\n\n\n def __call__(self): # -> generator object yielding np.ndarray, np.ndarray\n '''\n generate single(!) data-sample (batching done in tf.Dataset)\n '''\n \n # create new file data-reader, each time data-generator is called (otherwise file-data-reader generation not reset)\n generator = dare.DataReader(self.path).generate_event_parts_from_dir(parts_n=self.sample_part_n, **self.cuts)\n\n samples_read_n = 0\n # loop through whole dataset, reading sample_part_n events at a time\n for constituents, features in generator:\n samples = events_to_input_samples(constituents, features)\n indices = list(range(len(samples)))\n samples_read_n += len(samples)\n while indices:\n index = indices.pop(0)\n next_sample = samples[index] #.copy() \n yield next_sample\n if self.sample_max_n is not None and (samples_read_n >= self.sample_max_n):\n break\n \n print('[DataGenerator]: __call__() yielded {} samples'.format(samples_read_n))\n generator.close()\n\n\n def get_mean_and_stdev(self): # -> nd.array [num-features], nd.array [num-features]\n '''\n get mean and standard deviation of input samples constituents (first 1 million events) for each feature\n '''\n data_reader = dare.DataReader(self.path)\n\n constituents = data_reader.read_constituents_from_dir(read_n=int(1e6))\n constituents_j1j2 = np.vstack([constituents[:,0,:,:], constituents[:,1,:,:]])\n return utfu.get_mean_and_stdev(constituents_j1j2)\n\n\nclass DataGeneratorMixedBgSig():\n\n def __init__(self, path_bg, path_sig, sample_bg_part_n, sample_sig_part_n, sample_bg_total_n=None, sample_sig_total_n=None):\n self.path_bg = path_bg\n self.path_sig = path_sig\n self.sample_bg_part_n = int(sample_bg_part_n)\n self.sample_sig_part_n = int(sample_sig_part_n)\n self.sample_bg_total_n = int(sample_bg_total_n) if sample_bg_total_n else None\n self.sample_sig_total_n = int(sample_sig_total_n) if sample_sig_total_n else None\n\n\n def __call__(self): # -> generator object yielding (np.ndarray, np.ndarray)\n\n # make background and signal sample generators\n generator_bg = dare.DataReader(self.path_bg).generate_constituents_parts_from_dir(parts_n=self.sample_bg_part_n) \n generator_sig = dare.DataReader(self.path_sig).generate_constituents_parts_from_dir(parts_n=self.sample_sig_part_n)\n\n sig_every_n_bg_samples = sample_bg_total_n//sample_sig_total_n\n \n samples_read_bg_n, samples_read_sig_n = 0\n\n while True:\n bg_constituents = constituents_to_input_samples(next(generator_bg))\n sig_constituents = constituents_to_input_samples(next(generator_sig))\n",
"file": "util/data_generator.py",
"file_size": 4258,
"file_write_time": 132560643210000000,
"settings":
{
"buffer_size": 4258,
"encoding": "UTF-8",
"line_ending": "Unix"
}
},
{
"contents": "import tensorflow as tf\n\n@tf.function\ndef bar(vv):\n\tprint(vv)\n\treturn vv\n\t\n\ndef foo(v):\n\tfor vv in v:\n\t\tprint(vv.numpy())\n\nv = tf.random.uniform([4, 10], minval=1, maxval=10, dtype=tf.int32)\ndataset = tf.data.Dataset.from_tensor_slices(v)\ndataset.map(bar)\nfoo(dataset)\n",
"file": "playground/tf_test.py",
"file_size": 269,
"file_write_time": 132545248260000000,
"settings":
{
"buffer_size": 269,
"line_ending": "Unix"
}
}
],
"build_system": "Packages/User/python3.sublime-build",
"build_system_choices":
[
[
[
[
"Packages/Python/Python.sublime-build",
""
],
[
"Packages/Python/Python.sublime-build",
"Syntax Check"
],
[
"Packages/User/python3.sublime-build",
""
],
[
"Packages/User/python37.sublime-build",
""
]
],
[
"Packages/User/python3.sublime-build",
""
]
]
],
"build_varint": "",
"command_palette":
{
"height": 0.0,
"last_filter": "",
"selected_items":
[
[
"inden",
"Indentation: Reindent Lines"
],
[
"indent",
"Indentation: Reindent Lines"
],
[
"ins",
"Package Control: Install Package"
],
[
"remov",
"Package Control: Remove Package"
],
[
"install",
"Package Control: Install Package"
],
[
"pack",
"Package Control: Install Package"
],
[
"side",
"View: Toggle Open Files in Side Bar"
]
],
"width": 0.0
},
"console":
{
"height": 0.0,
"history":
[
]
},
"distraction_free":
{
"menu_visible": true,
"show_minimap": false,
"show_open_files": false,
"show_tabs": false,
"side_bar_visible": false,
"status_bar_visible": false
},
"expanded_folders":
[
"/home/kinga/mnt/vande",
"/home/kinga/mnt/vande/vae"
],
"file_history":
[
"/home/kinga/mnt/playground/test_tf_dataset.py",
"/home/kinga/mnt/analysis/analysis_losses.py",
"/home/kinga/mnt/main_analysis_model_comparison.py",
"/home/kinga/mnt/main_train.py",
"/home/kinga/mnt/venv/lib/python3.6/site-packages/tensorflow/python/data/ops/dataset_ops.py",
"/home/kinga/mnt/main_train_3d_vae.py",
"/home/kinga/mnt/analysis_main/main_analysis_roc.py",
"/home/kinga/mnt/analysis_main/main_analysis_losses.py",
"/home/kinga/mnt/vae/vae_model.py",
"/home/kinga/mnt/main_predict_3d_vae.py",
"/home/kinga/mnt/venv/lib/python3.6/site-packages/tensorflow/python/ops/gen_dataset_ops.py",
"/home/kinga/mnt/util/event_sample.py",
"/home/kinga/mnt/analysis/analysis_roc.py",
"/home/kinga/mnt/config/config.py",
"/home/kinga/mnt/util/plotting.py",
"/home/kinga/mnt/tf_dataset_test.py",
"/home/kinga/mnt/util/utility_fun.py",
"/home/kinga/mnt/inout/event_to_image_converter.py",
"/home/kinga/mnt/main.py",
"/home/kinga/mnt/main_3d_vae.py",
"/home/kinga/mnt/analysis_main/main_analysis_jet_features.py",
"/home/kinga/mnt/playground/test_sample_path_factory.py",
"/home/kinga/mnt/tests/test_event_sample_dump.py",
"/home/kinga/mnt/venv/lib/python3.6/site-packages/tensorboard/backend/application.py",
"/home/kinga/mnt/venv/lib/python3.6/site-packages/tensorboard/plugins/audio/audio_plugin.py",
"/home/kinga/mnt/venv/lib/python3.6/site-packages/tensorboard/plugins/core/core_plugin.py",
"/home/kinga/mnt/venv/lib/python3.6/site-packages/tensorboard/plugins/custom_scalar/custom_scalars_plugin.py",
"/home/kinga/mnt/main_analysis_jet_features.py",
"/home/kinga/mnt/main_analysis.py",
"/home/kinga/mnt/main_predict.py",
"/home/kinga/mnt/vae/vae_prediction.py",
"/home/kinga/mnt/venv/lib/python3.6/site-packages/tensorboard/plugins/text/text_plugin.py",
"/home/kinga/mnt/venv/lib/python3.6/site-packages/tensorboard/plugins/scalar/scalars_plugin.py",
"/home/kinga/mnt/venv/lib/python3.6/site-packages/tensorboard/plugins/pr_curve/pr_curves_plugin.py",
"/home/kinga/mnt/venv/lib/python3.6/site-packages/tensorboard/plugins/image/images_plugin.py",
"/home/kinga/mnt/venv/lib/python3.6/site-packages/tensorboard/plugins/hparams/list_session_groups.py",
"/home/kinga/mnt/venv/lib/python3.6/site-packages/tensorboard/plugins/hparams/hparams_plugin.py",
"/home/kinga/mnt/venv/lib/python3.6/site-packages/tensorboard/plugins/hparams/get_experiment.py",
"/home/kinga/mnt/venv/lib/python3.6/site-packages/tensorboard/plugins/hparams/backend_context.py",
"/home/kinga/mnt/venv/lib/python3.6/site-packages/tensorboard/plugins/histogram/histograms_plugin.py",
"/home/kinga/mnt/venv/lib/python3.6/site-packages/tensorboard/plugins/graph/graphs_plugin.py",
"/home/kinga/mnt/venv/lib/python3.6/site-packages/tensorboard/plugins/distribution/distributions_plugin.py",
"/home/kinga/mnt/venv/lib/python3.6/site-packages/tensorboard/plugins/debugger_v2/debugger_v2_plugin.py",
"/home/kinga/mnt/inout/sample_factory.py"
],
"find":
{
"height": 39.0
},
"find_in_files":
{
"height": 101.0,
"where_history":
[
"*.py",
"~/mnt/main(.*)",
"~/mnt/main*",
"~/mnt/.*/.*.py",
"~/mnt/*/.*.py",
"~/mnt/*/*.py",
"~/mnt/main.*",
"~/mnt/main*",
"~/mnt/*main*",
"~/mnt/*main*.py",
"~/mnt/.*.py",
"~/mnt",
"~/mnt/.*.py",
"~/mnt/*.py",
"~/mnt/.*.py",
"~/mnt/.*/.*.py",
"~/mnt/*/*.py",
"~/mnt/*.py",
"~/mnt/*/*.py",
"~/mnt/*.py",
"~/mnt/analysis",
"~/mnt/vae",
"~/mnt",
"~/mnt/inout",
""
]
},
"find_state":
{
"case_sensitive": false,
"find_history":
[
"train_evts",
"paths",
"file_path.numpy().decode('utf-8').split(os.sep)[-1]",
"file_path",
"from",
"from_",
"POfAH",
"util.experiment",
"inout.input_data_reader",
"inout.sample_factory",
"util.jet_sample",
"config.sample_dict"
],
"highlight": true,
"in_selection": false,
"preserve_case": false,
"regex": true,
"replace_history":
[
"pofah",
"POfAH.util.experiment",
"POfAH.util.input_data_reader",
"POfAH.util.sample_factory",
"POfAH.jet_sample",
"POfAH.sample_dict"
],
"reverse": false,
"show_context": true,
"use_buffer2": true,
"whole_word": false,
"wrap": true
},
"groups":
[
{
"selected": 2,
"sheets":
[
{
"buffer": 0,
"file": "main_analysis_jet_features.py",
"semi_transient": false,
"settings":
{
"buffer_size": 3835,
"regions":
{
},
"selection":
[
[
929,
929
]
],
"settings":
{
"auto_complete": false,
"git_gutter_is_enabled": true,
"syntax": "Packages/Python/Python.sublime-syntax",
"tabs_extra_last_activated": 1605536838.82,
"tabs_extra_last_activated_sheet_index": 1
},
"translation.x": 0.0,
"translation.y": 499.0,
"zoom_level": 1.0
},
"stack_index": 5,
"type": "text"
},
{
"buffer": 1,
"file": "main_predict.py",
"semi_transient": false,
"settings":
{
"buffer_size": 2651,
"regions":
{
},
"selection":
[
[
448,
448
]
],
"settings":
{
"auto_complete": false,
"git_gutter_is_enabled": true,
"syntax": "Packages/Python/Python.sublime-syntax",
"tab_size": 4,
"tabs_extra_last_activated": 1605527359.31,
"tabs_extra_last_activated_sheet_index": 2,
"tabs_extra_spawned": true,
"translate_tabs_to_spaces": true
},
"translation.x": 0.0,
"translation.y": 408.0,
"zoom_level": 1.0
},
"stack_index": 10,
"type": "text"
},
{
"buffer": 2,
"file": "main_train_particle_vae.py",
"semi_transient": false,
"settings":
{
"buffer_size": 4018,
"regions":
{
},
"selection":
[
[
997,
997
]
],
"settings":
{
"auto_complete": false,
"git_gutter_is_enabled": true,
"show_definitions": false,
"syntax": "Packages/Python/Python.sublime-syntax",
"tabs_extra_last_activated": 1614700162.2,
"tabs_extra_last_activated_sheet_index": 2
},
"translation.x": 0.0,
"translation.y": 0.0,
"zoom_level": 1.0
},
"stack_index": 0,
"type": "text"
},
{
"buffer": 3,
"file": "tests/test_data_generator.py",
"semi_transient": false,
"settings":
{
"buffer_size": 1603,
"regions":
{
},
"selection":
[
[
171,
171
]
],
"settings":
{
"auto_complete": false,
"git_gutter_is_enabled": false,
"open_with_edit": true,
"show_definitions": false,
"syntax": "Packages/Python/Python.sublime-syntax",
"tabs_extra_last_activated": 1614198551.02,
"tabs_extra_last_activated_sheet_index": 3
},
"translation.x": 0.0,
"translation.y": 0.0,
"zoom_level": 1.0
},
"stack_index": 3,
"type": "text"
},
{
"buffer": 4,
"file": "vae/vae_particle.py",
"semi_transient": false,
"settings":
{
"buffer_size": 5233,
"regions":
{
},
"selection":
[
[
1052,
1052
]
],
"settings":
{
"auto_complete": false,
"git_gutter_is_enabled": true,
"show_definitions": false,
"syntax": "Packages/Python/Python.sublime-syntax",
"tabs_extra_last_activated": 1614698059.7,
"tabs_extra_last_activated_sheet_index": 4,
"translate_tabs_to_spaces": false
},
"translation.x": 0.0,
"translation.y": 306.0,
"zoom_level": 1.0
},
"stack_index": 1,
"type": "text"
},
{
"buffer": 5,
"file": "vae/vae_base.py",
"semi_transient": true,
"settings":
{
"buffer_size": 3726,
"regions":
{
},
"selection":
[
[
3531,
3531
]
],
"settings":
{
"git_gutter_is_enabled": true,
"show_definitions": false,
"syntax": "Packages/Python/Python.sublime-syntax",
"tab_size": 4,
"tabs_extra_last_activated": 1614264143.32,
"tabs_extra_last_activated_sheet_index": 5,
"translate_tabs_to_spaces": true
},
"translation.x": 0.0,
"translation.y": 612.0,
"zoom_level": 1.0
},
"stack_index": 2,
"type": "text"
},
{
"buffer": 6,
"file": "venv/lib/python3.6/site-packages/tensorflow/python/keras/engine/training_v1.py",
"semi_transient": false,
"settings":
{
"buffer_size": 137170,
"regions":
{
},
"selection":
[
[
60346,
60346
]
],
"settings":
{
"auto_complete": false,
"git_gutter_is_enabled": true,
"syntax": "Packages/Python/Python.sublime-syntax",
"tab_size": 2,
"tabs_extra_last_activated": 1605610992.47,
"tabs_extra_last_activated_sheet_index": 5,
"translate_tabs_to_spaces": true
},
"translation.x": 0.0,
"translation.y": 12983.0,
"zoom_level": 1.0
},
"stack_index": 9,
"type": "text"
},
{
"buffer": 7,
"file": "venv/lib/python3.6/site-packages/tensorflow/python/keras/engine/training_generator.py",
"semi_transient": false,
"settings":
{
"buffer_size": 30736,
"regions":
{
},
"selection":
[
[
28734,
28734
]
],
"settings":
{
"auto_complete": false,
"git_gutter_is_enabled": true,
"syntax": "Packages/Python/Python.sublime-syntax",
"tab_size": 2,
"tabs_extra_last_activated": 1605610997.0,
"tabs_extra_last_activated_sheet_index": 6,
"translate_tabs_to_spaces": true
},
"translation.x": 0.0,
"translation.y": 10229.0,
"zoom_level": 1.0
},
"stack_index": 8,
"type": "text"
},
{
"buffer": 8,
"file": "venv/lib/python3.6/site-packages/tensorflow/python/keras/engine/training_utils.py",
"semi_transient": false,
"settings":
{
"buffer_size": 81689,
"regions":
{
},
"selection":
[
[
76890,
76890
]
],
"settings":
{
"auto_complete": false,
"git_gutter_is_enabled": true,
"syntax": "Packages/Python/Python.sublime-syntax",
"tab_size": 2,
"tabs_extra_last_activated": 1605614549.75,
"tabs_extra_last_activated_sheet_index": 7,
"translate_tabs_to_spaces": true
},
"translation.x": 0.0,
"translation.y": 25614.0,
"zoom_level": 1.0
},
"stack_index": 7,
"type": "text"
},
{
"buffer": 9,
"file": "util/data_generator.py",
"semi_transient": false,
"settings":
{
"buffer_size": 4258,
"regions":
{
},
"selection":
[
[
729,
729
]
],
"settings":
{
"auto_complete": false,
"git_gutter_is_enabled": false,
"open_with_edit": true,
"syntax": "Packages/Python/Python.sublime-syntax",
"tabs_extra_last_activated": 1605614601.09,
"tabs_extra_last_activated_sheet_index": 8,
"translate_tabs_to_spaces": false
},
"translation.x": 0.0,
"translation.y": 0.0,
"zoom_level": 1.0
},
"stack_index": 4,
"type": "text"
},
{
"buffer": 10,
"file": "playground/tf_test.py",
"semi_transient": false,
"settings":
{
"buffer_size": 269,
"regions":
{
},
"selection":
[
[
256,
256
]
],
"settings":
{
"auto_complete": false,
"git_gutter_is_enabled": true,
"open_with_edit": true,
"syntax": "Packages/Python/Python.sublime-syntax",
"tabs_extra_last_activated": 1598293344.24,
"tabs_extra_last_activated_sheet_index": 11
},
"translation.x": 0.0,
"translation.y": 0.0,
"zoom_level": 1.0
},
"stack_index": 6,
"type": "text"
}
]
}
],
"incremental_find":
{
"height": 26.0
},
"input":
{
"height": 38.0
},
"layout":
{
"cells":
[
[
0,
0,
1,
1
]
],
"cols":
[
0.0,
1.0
],
"rows":
[
0.0,
1.0
]
},
"menu_visible": true,
"output.SublimeLinter":
{
"height": 0.0
},
"output.exec":
{
"height": 320.0
},
"output.find_results":
{
"height": 120.0
},
"output.mdpopups":
{
"height": 0.0
},
"pinned_build_system": "Packages/User/python3.sublime-build",
"project": "vae.sublime-project",
"replace":
{
"height": 70.0
},
"save_all_on_build": true,
"select_file":
{
"height": 0.0,
"last_filter": "",
"selected_items":
[
],
"width": 0.0
},
"select_project":
{
"height": 0.0,
"last_filter": "",
"selected_items":
[
],
"width": 0.0
},
"select_symbol":
{
"height": 0.0,
"last_filter": "",
"selected_items":
[
],
"width": 0.0
},
"selected_group": 0,
"settings":
{
},
"show_minimap": true,
"show_open_files": true,
"show_tabs": true,
"side_bar_visible": true,
"side_bar_width": 229.0,
"status_bar_visible": true,
"template_settings":
{
}
}