ecker commited on
Commit
7f2da0f
·
1 Parent(s): df0edac

rewrote how AIVC gets training metrics (need to clean up later)

Browse files
Files changed (3) hide show
  1. src/train.py +2 -1
  2. src/utils.py +87 -112
  3. src/webui.py +4 -8
src/train.py CHANGED
@@ -18,6 +18,7 @@ if __name__ == "__main__":
18
  parser = argparse.ArgumentParser()
19
  parser.add_argument('-opt', type=str, help='Path to option YAML file.', default='../options/train_vit_latent.yml', nargs='+') # ugh
20
  parser.add_argument('--launcher', choices=['none', 'pytorch'], default='none', help='job launcher')
 
21
  args = parser.parse_args()
22
  args.opt = " ".join(args.opt) # absolutely disgusting
23
 
@@ -77,7 +78,7 @@ def train(yaml, launcher='none'):
77
  trainer.rank = torch.distributed.get_rank()
78
  torch.cuda.set_device(torch.distributed.get_rank())
79
 
80
- trainer.init(yaml, opt, launcher)
81
  trainer.do_training()
82
 
83
  if __name__ == "__main__":
 
18
  parser = argparse.ArgumentParser()
19
  parser.add_argument('-opt', type=str, help='Path to option YAML file.', default='../options/train_vit_latent.yml', nargs='+') # ugh
20
  parser.add_argument('--launcher', choices=['none', 'pytorch'], default='none', help='job launcher')
21
+ parser.add_argument('--mode', type=str, default='none', help='mode')
22
  args = parser.parse_args()
23
  args.opt = " ".join(args.opt) # absolutely disgusting
24
 
 
78
  trainer.rank = torch.distributed.get_rank()
79
  torch.cuda.set_device(torch.distributed.get_rank())
80
 
81
+ trainer.init(yaml, opt, launcher, '')
82
  trainer.do_training()
83
 
84
  if __name__ == "__main__":
src/utils.py CHANGED
@@ -594,6 +594,9 @@ class TrainingState():
594
 
595
  self.it = 0
596
  self.its = self.config['train']['niter']
 
 
 
597
 
598
  self.epoch = 0
599
  self.epochs = int(self.its*self.batch_size/self.dataset_size)
@@ -653,13 +656,8 @@ class TrainingState():
653
  self.process = subprocess.Popen(self.cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
654
 
655
  def load_statistics(self, update=False):
656
- if not os.path.isdir(f'{self.dataset_dir}/tb_logger/'):
657
  return
658
- try:
659
- from tensorboard.backend.event_processing import event_accumulator
660
- use_tensorboard = True
661
- except Exception as e:
662
- use_tensorboard = False
663
 
664
  keys = ['loss_text_ce', 'loss_mel_ce', 'loss_gpt_total', 'val_loss_text_ce', 'val_loss_mel_ce', 'learning_rate_gpt_0']
665
  infos = {}
@@ -669,32 +667,44 @@ class TrainingState():
669
  self.statistics['loss'] = []
670
  self.statistics['lr'] = []
671
 
672
- logs = sorted([f'{self.dataset_dir}/tb_logger/{d}' for d in os.listdir(f'{self.dataset_dir}/tb_logger/') if d[:6] == "events" ])
673
  if update:
674
  logs = [logs[-1]]
675
 
676
  for log in logs:
677
- ea = event_accumulator.EventAccumulator(log, size_guidance={event_accumulator.SCALARS: 0})
678
- ea.Reload()
679
 
680
- scalars = ea.Tags()['scalars']
 
 
 
681
 
682
- for key in keys:
683
- if key not in scalars:
684
  continue
685
 
686
- try:
687
- scalar = ea.Scalars(key)
688
- for s in scalar:
689
- if update and s.step <= self.last_info_check_at:
690
- continue
691
- highest_step = max( highest_step, s.step )
692
- target = 'lr' if key == "learning_rate_gpt_0" else 'loss'
693
- self.statistics[target].append( { "step": s.step, "value": s.value, "type": key } )
694
- if key == 'loss_gpt_total':
695
- self.losses.append( { "step": s.step, "value": s.value, "type": key } )
696
- except Exception as e:
697
- pass
 
 
 
 
 
 
 
 
 
698
 
699
  self.last_info_check_at = highest_step
700
 
@@ -707,9 +717,8 @@ class TrainingState():
707
 
708
  models = sorted([ int(d[:-8]) for d in os.listdir(f'{self.dataset_dir}/models/') if d[-8:] == "_gpt.pth" ])
709
  states = sorted([ int(d[:-6]) for d in os.listdir(f'{self.dataset_dir}/training_state/') if d[-6:] == ".state" ])
710
-
711
- remove_models = models[:-keep]
712
- remove_states = states[:-keep]
713
 
714
  for d in remove_models:
715
  path = f'{self.dataset_dir}/models/{d}_gpt.pth'
@@ -727,8 +736,10 @@ class TrainingState():
727
  percent = 0
728
  message = None
729
 
 
 
730
  # rip out iteration info
731
- if not self.training_started:
732
  if line.find('Start training from epoch') >= 0:
733
  self.it_time_start = time.time()
734
  self.epoch_time_start = time.time()
@@ -745,83 +756,57 @@ class TrainingState():
745
  self.checkpoints = int((self.its - self.it) / self.config['logger']['save_checkpoint_freq'])
746
  else:
747
  lapsed = False
748
-
749
  message = None
750
- if line.find('INFO: [epoch:') >= 0:
751
- info_line = line.split("INFO:")[-1]
752
- # to-do, actually validate this works, and probably kill training when it's found, the model's dead by this point
753
- if ': nan' in info_line and not self.nan_detected:
754
- self.nan_detected = self.it
755
-
756
- # easily rip out our stats...
757
- match = re.findall(r'\b([a-z_0-9]+?)\b: *?([0-9]\.[0-9]+?e[+-]\d+|[\d,]+)\b', info_line)
758
- if match and len(match) > 0:
759
- for k, v in match:
760
- self.info[k] = float(v.replace(",", ""))
761
 
762
- self.load_statistics(update=True)
763
- should_return = True
 
 
764
 
765
  if 'epoch' in self.info:
766
  self.epoch = int(self.info['epoch'])
767
- if 'iter' in self.info:
768
- self.it = int(self.info['iter'])
769
-
770
- elif line.find('Saving models and training states') >= 0:
771
- self.checkpoint = self.checkpoint + 1
772
-
773
- percent = self.checkpoint / float(self.checkpoints)
774
- message = f'[{self.checkpoint}/{self.checkpoints}] Saving checkpoint...'
775
- if progress is not None:
776
- progress(percent, message)
 
 
 
 
 
 
 
 
 
 
 
 
 
777
 
778
- print(f'{"{:.3f}".format(percent*100)}% {message}')
779
- self.buffer.append(f'{"{:.3f}".format(percent*100)}% {message}')
 
 
 
 
780
 
781
- self.cleanup_old(keep=keep_x_past_checkpoints)
 
 
782
 
783
- if line.find('%|') > 0:
784
- match = re.findall(r'(\d+)%\|(.+?)\| (\d+|\?)\/(\d+|\?) \[(.+?)<(.+?), +(.+?)\]', line)
785
- if match and len(match) > 0:
786
- match = match[0]
787
- per_cent = int(match[0])/100.0
788
- progressbar = match[1]
789
- step = int(match[2])
790
- steps = int(match[3])
791
- elapsed = match[4]
792
- until = match[5]
793
- rate = match[6]
794
-
795
- last_step = self.last_step
796
- self.last_step = step
797
- if last_step < step:
798
- self.it = self.it + (step - last_step)
799
-
800
- if last_step == step and step == steps:
801
- lapsed = True
802
-
803
- self.it_time_end = time.time()
804
- self.it_time_delta = self.it_time_end-self.it_time_start
805
- self.it_time_start = time.time()
806
- self.it_taken = self.it_taken + 1
807
- if self.it_time_delta:
808
- try:
809
- rate = f'{"{:.3f}".format(self.it_time_delta)}s/it' if self.it_time_delta >= 1 or self.it_time_delta == 0 else f'{"{:.3f}".format(1/self.it_time_delta)}it/s'
810
- self.it_rate = rate
811
- except Exception as e:
812
- pass
813
-
814
- self.metrics['step'] = [f"{self.epoch}/{self.epochs}"]
815
- if self.epochs != self.its:
816
- self.metrics['step'].append(f"{self.it}/{self.its}")
817
- if steps > 1:
818
- self.metrics['step'].append(f"{step}/{steps}")
819
- self.metrics['step'] = ", ".join(self.metrics['step'])
820
 
821
  if lapsed:
822
- self.epoch = self.epoch + 1
823
- self.it = int(self.epoch * (self.dataset_size / self.batch_size))
824
-
825
  self.epoch_time_end = time.time()
826
  self.epoch_time_delta = self.epoch_time_end-self.epoch_time_start
827
  self.epoch_time_start = time.time()
@@ -850,24 +835,16 @@ class TrainingState():
850
  eta_hhmmss = "?"
851
  if self.eta_hhmmss:
852
  eta_hhmmss = self.eta_hhmmss
853
- else:
854
- try:
855
- eta = (self.its - self.it) * (self.it_time_deltas / self.it_taken)
856
- eta = str(timedelta(seconds=int(eta)))
857
- eta_hhmmss = eta
858
- except Exception as e:
859
- pass
860
 
861
  self.metrics['loss'] = []
862
 
863
- if 'learning_rate_gpt_0' in self.info:
864
- self.metrics['loss'].append(f'LR: {"{:.3e}".format(self.info["learning_rate_gpt_0"])}')
865
 
866
  if len(self.losses) > 0:
867
  self.metrics['loss'].append(f'Loss: {"{:.3f}".format(self.losses[-1]["value"])}')
868
 
869
  if len(self.losses) >= 2:
870
- # """riemann sum""" but not really as this is for derivatives and not integrals
871
  deriv = 0
872
  accum_length = len(self.losses)//2 # i *guess* this is fine when you think about it
873
  loss_value = self.losses[-1]["value"]
@@ -1296,10 +1273,6 @@ def optimize_training_settings( **kwargs ):
1296
 
1297
  iterations = calc_iterations(epochs=settings['epochs'], lines=lines, batch_size=settings['batch_size'])
1298
 
1299
- if settings['epochs'] < settings['print_rate']:
1300
- settings['print_rate'] = settings['epochs']
1301
- messages.append(f"Print rate is too small for the given iteration step, clamping print rate to: {settings['print_rate']}")
1302
-
1303
  if settings['epochs'] < settings['save_rate']:
1304
  settings['save_rate'] = settings['epochs']
1305
  messages.append(f"Save rate is too small for the given iteration step, clamping save rate to: {settings['save_rate']}")
@@ -1355,14 +1328,11 @@ def save_training_settings( **kwargs ):
1355
 
1356
  iterations_per_epoch = settings['iterations'] / settings['epochs']
1357
 
1358
- settings['print_rate'] = int(settings['print_rate'] * iterations_per_epoch)
1359
  settings['save_rate'] = int(settings['save_rate'] * iterations_per_epoch)
1360
  settings['validation_rate'] = int(settings['validation_rate'] * iterations_per_epoch)
1361
 
1362
  iterations_per_epoch = int(iterations_per_epoch)
1363
 
1364
- if settings['print_rate'] < 1:
1365
- settings['print_rate'] = 1
1366
  if settings['save_rate'] < 1:
1367
  settings['save_rate'] = 1
1368
  if settings['validation_rate'] < 1:
@@ -1858,6 +1828,11 @@ def import_generate_settings(file="./config/generate.json"):
1858
  res.update(settings)
1859
  return res
1860
 
 
 
 
 
 
1861
  def read_generate_settings(file, read_latents=True):
1862
  j = None
1863
  latents = None
 
594
 
595
  self.it = 0
596
  self.its = self.config['train']['niter']
597
+
598
+ self.step = 0
599
+ self.steps = 1
600
 
601
  self.epoch = 0
602
  self.epochs = int(self.its*self.batch_size/self.dataset_size)
 
656
  self.process = subprocess.Popen(self.cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
657
 
658
  def load_statistics(self, update=False):
659
+ if not os.path.isdir(f'{self.dataset_dir}/'):
660
  return
 
 
 
 
 
661
 
662
  keys = ['loss_text_ce', 'loss_mel_ce', 'loss_gpt_total', 'val_loss_text_ce', 'val_loss_mel_ce', 'learning_rate_gpt_0']
663
  infos = {}
 
667
  self.statistics['loss'] = []
668
  self.statistics['lr'] = []
669
 
670
+ logs = sorted([f'{self.dataset_dir}/{d}' for d in os.listdir(self.dataset_dir) if d[-4:] == ".log" ])
671
  if update:
672
  logs = [logs[-1]]
673
 
674
  for log in logs:
675
+ with open(log, 'r', encoding="utf-8") as f:
676
+ lines = f.readlines()
677
 
678
+ for line in lines:
679
+ if line.find('INFO: Training Metrics:') >= 0:
680
+ data = line.split("INFO: Training Metrics:")[-1]
681
+ info = json.loads(data)
682
 
683
+ step = info['it']
684
+ if update and step <= self.last_info_check_at:
685
  continue
686
 
687
+ if 'lr' in info:
688
+ self.statistics['lr'].append({'step': step, 'value': info['lr'], 'type': 'learning_rate_gpt_0'})
689
+ if 'loss_text_ce' in info:
690
+ self.statistics['loss'].append({'step': step, 'value': info['loss_text_ce'], 'type': 'loss_text_ce'})
691
+ if 'loss_mel_ce' in info:
692
+ self.statistics['loss'].append({'step': step, 'value': info['loss_mel_ce'], 'type': 'loss_mel_ce'})
693
+ if 'loss_gpt_total' in info:
694
+ self.statistics['loss'].append({'step': step, 'value': info['loss_gpt_total'], 'type': 'loss_gpt_total'})
695
+ self.losses.append( self.statistics['loss'][-1] )
696
+
697
+ elif line.find('INFO: Validation Metrics:') >= 0:
698
+ data = line.split("INFO: Validation Metrics:")[-1]
699
+
700
+ step = info['it']
701
+ if update and step <= self.last_info_check_at:
702
+ continue
703
+
704
+ if 'loss_text_ce' in info:
705
+ self.statistics['loss'].append({'step': step, 'value': info['loss_gpt_total'], 'type': 'val_loss_text_ce'})
706
+ if 'loss_mel_ce' in info:
707
+ self.statistics['loss'].append({'step': step, 'value': info['loss_gpt_total'], 'type': 'val_loss_mel_ce'})
708
 
709
  self.last_info_check_at = highest_step
710
 
 
717
 
718
  models = sorted([ int(d[:-8]) for d in os.listdir(f'{self.dataset_dir}/models/') if d[-8:] == "_gpt.pth" ])
719
  states = sorted([ int(d[:-6]) for d in os.listdir(f'{self.dataset_dir}/training_state/') if d[-6:] == ".state" ])
720
+ remove_models = models[:-2]
721
+ remove_states = states[:-2]
 
722
 
723
  for d in remove_models:
724
  path = f'{self.dataset_dir}/models/{d}_gpt.pth'
 
736
  percent = 0
737
  message = None
738
 
739
+ if line.find('Finished training') >= 0:
740
+ self.killed = True
741
  # rip out iteration info
742
+ elif not self.training_started:
743
  if line.find('Start training from epoch') >= 0:
744
  self.it_time_start = time.time()
745
  self.epoch_time_start = time.time()
 
756
  self.checkpoints = int((self.its - self.it) / self.config['logger']['save_checkpoint_freq'])
757
  else:
758
  lapsed = False
 
759
  message = None
 
 
 
 
 
 
 
 
 
 
 
760
 
761
+ # INFO: Training Metrics: {"loss_text_ce": 4.308311939239502, "loss_mel_ce": 2.1610655784606934, "loss_gpt_total": 2.204148769378662, "lr": 0.0001, "it": 2, "step": 1, "steps": 1, "epoch": 1, "iteration_rate": 0.10700102965037028}
762
+ if line.find('INFO: Training Metrics:') >= 0:
763
+ data = line.split("INFO: Training Metrics:")[-1]
764
+ self.info = json.loads(data)
765
 
766
  if 'epoch' in self.info:
767
  self.epoch = int(self.info['epoch'])
768
+ if 'it' in self.info:
769
+ self.it = int(self.info['it'])
770
+ if 'step' in self.info:
771
+ self.step = int(self.info['step'])
772
+ if 'steps' in self.info:
773
+ self.steps = int(self.info['steps'])
774
+
775
+ if self.step == self.steps:
776
+ lapsed = True
777
+
778
+ if 'lr' in self.info:
779
+ self.statistics['lr'].append({'step': self.it, 'value': self.info['lr'], 'type': 'learning_rate_gpt_0'})
780
+ if 'loss_text_ce' in self.info:
781
+ self.statistics['loss'].append({'step': self.it, 'value': self.info['loss_text_ce'], 'type': 'loss_text_ce'})
782
+ if 'loss_mel_ce' in self.info:
783
+ self.statistics['loss'].append({'step': self.it, 'value': self.info['loss_mel_ce'], 'type': 'loss_mel_ce'})
784
+ if 'loss_gpt_total' in self.info:
785
+ self.statistics['loss'].append({'step': self.it, 'value': self.info['loss_gpt_total'], 'type': 'loss_gpt_total'})
786
+ self.losses.append( self.statistics['loss'][-1] )
787
+
788
+ if 'iteration_rate' in self.info:
789
+ it_rate = self.info['iteration_rate']
790
+ self.it_rate = f'{"{:.3f}".format(it_rate)}s/it' if it_rate >= 1 or it_rate == 0 else f'{"{:.3f}".format(1/it_rate)}it/s'
791
 
792
+ self.metrics['step'] = [f"{self.epoch}/{self.epochs}"]
793
+ if self.epochs != self.its:
794
+ self.metrics['step'].append(f"{self.it}/{self.its}")
795
+ if self.steps > 1:
796
+ self.metrics['step'].append(f"{self.step}/{self.steps}")
797
+ self.metrics['step'] = ", ".join(self.metrics['step'])
798
 
799
+ should_return = True
800
+ elif line.find('INFO: Validation Metrics:') >= 0:
801
+ data = line.split("INFO: Validation Metrics:")[-1]
802
 
803
+ if 'loss_text_ce' in self.info:
804
+ self.statistics['loss'].append({'step': self.it, 'value': self.info['loss_gpt_total'], 'type': 'val_loss_text_ce'})
805
+ if 'loss_mel_ce' in self.info:
806
+ self.statistics['loss'].append({'step': self.it, 'value': self.info['loss_gpt_total'], 'type': 'val_loss_mel_ce'})
807
+ should_return = True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
808
 
809
  if lapsed:
 
 
 
810
  self.epoch_time_end = time.time()
811
  self.epoch_time_delta = self.epoch_time_end-self.epoch_time_start
812
  self.epoch_time_start = time.time()
 
835
  eta_hhmmss = "?"
836
  if self.eta_hhmmss:
837
  eta_hhmmss = self.eta_hhmmss
 
 
 
 
 
 
 
838
 
839
  self.metrics['loss'] = []
840
 
841
+ if 'lr' in self.info:
842
+ self.metrics['loss'].append(f'LR: {"{:.3e}".format(self.info["lr"])}')
843
 
844
  if len(self.losses) > 0:
845
  self.metrics['loss'].append(f'Loss: {"{:.3f}".format(self.losses[-1]["value"])}')
846
 
847
  if len(self.losses) >= 2:
 
848
  deriv = 0
849
  accum_length = len(self.losses)//2 # i *guess* this is fine when you think about it
850
  loss_value = self.losses[-1]["value"]
 
1273
 
1274
  iterations = calc_iterations(epochs=settings['epochs'], lines=lines, batch_size=settings['batch_size'])
1275
 
 
 
 
 
1276
  if settings['epochs'] < settings['save_rate']:
1277
  settings['save_rate'] = settings['epochs']
1278
  messages.append(f"Save rate is too small for the given iteration step, clamping save rate to: {settings['save_rate']}")
 
1328
 
1329
  iterations_per_epoch = settings['iterations'] / settings['epochs']
1330
 
 
1331
  settings['save_rate'] = int(settings['save_rate'] * iterations_per_epoch)
1332
  settings['validation_rate'] = int(settings['validation_rate'] * iterations_per_epoch)
1333
 
1334
  iterations_per_epoch = int(iterations_per_epoch)
1335
 
 
 
1336
  if settings['save_rate'] < 1:
1337
  settings['save_rate'] = 1
1338
  if settings['validation_rate'] < 1:
 
1828
  res.update(settings)
1829
  return res
1830
 
1831
+ def reset_generation_settings():
1832
+ with open(f'./config/generate.json', 'w', encoding="utf-8") as f:
1833
+ f.write(json.dumps({}, indent='\t') )
1834
+ return import_generate_settings()
1835
+
1836
  def read_generate_settings(file, read_latents=True):
1837
  j = None
1838
  latents = None
src/webui.py CHANGED
@@ -152,14 +152,11 @@ def import_generate_settings_proxy( file=None ):
152
  res = []
153
  for k in GENERATE_SETTINGS_ARGS:
154
  res.append(settings[k] if k in settings else None)
155
-
 
 
156
  return tuple(res)
157
 
158
- def reset_generation_settings_proxy():
159
- with open(f'./config/generate.json', 'w', encoding="utf-8") as f:
160
- f.write(json.dumps({}, indent='\t') )
161
- return import_generate_settings_proxy()
162
-
163
  def compute_latents_proxy(voice, voice_latents_chunks, progress=gr.Progress(track_tqdm=True)):
164
  compute_latents( voice=voice, voice_latents_chunks=voice_latents_chunks, progress=progress )
165
  return voice
@@ -442,7 +439,6 @@ def setup_gradio():
442
  TRAINING_SETTINGS["batch_size"] = gr.Number(label="Batch Size", value=128, precision=0)
443
  TRAINING_SETTINGS["gradient_accumulation_size"] = gr.Number(label="Gradient Accumulation Size", value=4, precision=0)
444
  with gr.Row():
445
- TRAINING_SETTINGS["print_rate"] = gr.Number(label="Print Frequency (in epochs)", value=5, precision=0)
446
  TRAINING_SETTINGS["save_rate"] = gr.Number(label="Save Frequency (in epochs)", value=5, precision=0)
447
  TRAINING_SETTINGS["validation_rate"] = gr.Number(label="Validation Frequency (in epochs)", value=5, precision=0)
448
 
@@ -665,7 +661,7 @@ def setup_gradio():
665
  )
666
 
667
  reset_generation_settings_button.click(
668
- fn=reset_generation_settings_proxy,
669
  inputs=None,
670
  outputs=generate_settings
671
  )
 
152
  res = []
153
  for k in GENERATE_SETTINGS_ARGS:
154
  res.append(settings[k] if k in settings else None)
155
+ print(GENERATE_SETTINGS_ARGS)
156
+ print(settings)
157
+ print(res)
158
  return tuple(res)
159
 
 
 
 
 
 
160
  def compute_latents_proxy(voice, voice_latents_chunks, progress=gr.Progress(track_tqdm=True)):
161
  compute_latents( voice=voice, voice_latents_chunks=voice_latents_chunks, progress=progress )
162
  return voice
 
439
  TRAINING_SETTINGS["batch_size"] = gr.Number(label="Batch Size", value=128, precision=0)
440
  TRAINING_SETTINGS["gradient_accumulation_size"] = gr.Number(label="Gradient Accumulation Size", value=4, precision=0)
441
  with gr.Row():
 
442
  TRAINING_SETTINGS["save_rate"] = gr.Number(label="Save Frequency (in epochs)", value=5, precision=0)
443
  TRAINING_SETTINGS["validation_rate"] = gr.Number(label="Validation Frequency (in epochs)", value=5, precision=0)
444
 
 
661
  )
662
 
663
  reset_generation_settings_button.click(
664
+ fn=reset_generation_settings,
665
  inputs=None,
666
  outputs=generate_settings
667
  )