code: def parse_progress_logs_for_param_diff(exp_dir, pattern):
      """Parse progress logs for per-component parameter differences.
  
      e.g. for a line that is parsed from progress.*.log:
      exp/chain/cwrnn_trial2_ld5_sp/log/progress.245.log:LOG
      (nnet3-show-progress:main():nnet3-show-progress.cc:144) Relative parameter
      differences per layer are [ Cwrnn1_T3_W_r:0.0171537
      Cwrnn1_T3_W_x:1.33338e-07 Cwrnn1_T2_W_r:0.048075 Cwrnn1_T2_W_x:1.34088e-07
      Cwrnn1_T1_W_r:0.0157277 Cwrnn1_T1_W_x:0.0212704 Final_affine:0.0321521
      Cwrnn2_T3_W_r:0.0212082 Cwrnn2_T3_W_x:1.33691e-07 Cwrnn2_T2_W_r:0.0212978
      Cwrnn2_T2_W_x:1.33401e-07 Cwrnn2_T1_W_r:0.014976 Cwrnn2_T1_W_x:0.0233588
      Cwrnn3_T3_W_r:0.0237165 Cwrnn3_T3_W_x:1.33184e-07 Cwrnn3_T2_W_r:0.0239754
      Cwrnn3_T2_W_x:1.3296e-07 Cwrnn3_T1_W_r:0.0194809 Cwrnn3_T1_W_x:0.0271934 ]
      """
  
      if pattern not in set(
          ["Relative parameter differences", "Parameter differences"]
      ):
          raise Exception(
              "Unknown value for pattern : {0}".format(pattern)
          )
  
      progress_log_files = "%s/log/progress.*.log" % (exp_dir)
      progress_per_iter = {}
      component_names = set([])
      progress_log_lines = common_lib.get_command_stdout(
          'grep -e "{0}" {1}'.format(pattern, progress_log_files)
      )
      parse_regex = re.compile(
          ".*progress\.([0-9]+)\.log:"
          "LOG.*{0}.*\[(.*)\]".format(pattern)
      )
      for line in progress_log_lines.split("\n"):
          mat_obj = parse_regex.search(line)
          if mat_obj is None:
              continue
          groups = mat_obj.groups()
          iteration = groups[0]
          differences = parse_difference_string(groups[1])
          component_names = component_names.union(
              list(differences.keys())
          )
          progress_per_iter[int(iteration)] = differences
  
      component_names = list(component_names)
      component_names.sort()
      # rearranging the parameter differences available per iter
      # into parameter differences per component
      progress_per_component = {}
      for cn in component_names:
          progress_per_component[cn] = {}
  
      max_iter = max(progress_per_iter.keys())
      total_missing_iterations = 0
      gave_user_warning = False
      for iter in range(max_iter + 1):
          try:
              component_dict = progress_per_iter[iter]
          except KeyError:
              continue
  
          for component_name in component_names:
              try:
                  progress_per_component[component_name][
                      iter
                  ] = component_dict[component_name]
              except KeyError:
                  total_missing_iterations += 1
                  # the component was not found this iteration, may be because of
                  # layerwise discriminative training
                  pass
          if (
              total_missing_iterations / len(component_names) > 20
              and not gave_user_warning
              and logger is not None
          ):
              logger.warning(
                  "There are more than {0} missing iterations per "
                  "component. Something might be wrong.".format(
                      total_missing_iterations / len(component_names)
                  )
              )
              gave_user_warning = True
  
      return {
          "progress_per_component": progress_per_component,
          "component_names": component_names,
          "max_iter": max_iter,
      }
  
imports: from __future__ import division
  from __future__ import print_function
  import traceback
  import datetime
  import logging
  import re
  import libs.common
label_desc: Use image node_id 5 for calling a global function with example usage: parse_progress_logs_for_param_diff(exp_dir, pattern) and returns: dict