code: def wer_details_by_speaker(details_by_utterance, utt2spk):
      """Compute word error rate and another salient info grouping by speakers.
  
      Arguments
      ---------
      details_by_utterance : list
          See the output of wer_details_by_utterance
      utt2spk : dict
          Map from utterance id to speaker id
  
  
      Returns
      -------
      dict
          Maps speaker id to a dictionary of the statistics, with keys:
  
          * "speaker": Speaker id,
          * "num_edits": (int) Number of edits in total by this speaker.
          * "insertions": (int) Number insertions by this speaker.
          * "dels": (int) Number of deletions by this speaker.
          * "subs": (int) Number of substitutions by this speaker.
          * "num_scored_tokens": (int) Number of scored reference
            tokens by this speaker (a missing hypothesis might still
            have been scored with 'all' scoring mode).
          * "num_scored_sents": (int) number of scored utterances
            by this speaker.
          * "num_erraneous_sents": (int) number of utterance with at least
            one error, by this speaker.
          * "num_absent_sents": (int) number of utterances for which no
            hypotheses was found, by this speaker.
          * "num_ref_sents": (int) number of utterances by this speaker
            in total.
      """
      # Build the speakerwise details:
      details_by_speaker = {}
      for dets in details_by_utterance:
          speaker = utt2spk[dets["key"]]
          spk_dets = details_by_speaker.setdefault(
              speaker,
              collections.Counter(
                  {
                      "speaker": speaker,
                      "insertions": 0,
                      "dels": 0,
                      "subs": 0,
                      "num_scored_tokens": 0,
                      "num_scored_sents": 0,
                      "num_edits": 0,
                      "num_erraneous_sents": 0,
                      "num_absent_sents": 0,
                      "num_ref_sents": 0,
                  }
              ),
          )
          utt_stats = collections.Counter()
          if dets["hyp_absent"]:
              utt_stats.update({"num_absent_sents": 1})
          if dets["scored"]:
              utt_stats.update(
                  {
                      "num_scored_sents": 1,
                      "num_scored_tokens": dets["num_ref_tokens"],
                      "insertions": dets["insertions"],
                      "dels": dets["deletions"],
                      "subs": dets["substitutions"],
                      "num_edits": dets["num_edits"],
                  }
              )
              if dets["num_edits"] > 0:
                  utt_stats.update({"num_erraneous_sents": 1})
          spk_dets.update(utt_stats)
      # We will in the end return a list of normal dicts
      # We want the output to be sortable
      details_by_speaker_dicts = []
      # Now compute speakerwise summary details
      for speaker, spk_dets in details_by_speaker.items():
          spk_dets["speaker"] = speaker
          if spk_dets["num_scored_sents"] > 0:
              spk_dets["WER"] = (
                  100.0
                  * spk_dets["num_edits"]
                  / spk_dets["num_scored_tokens"]
              )
              spk_dets["SER"] = (
                  100.0
                  * spk_dets["num_erraneous_sents"]
                  / spk_dets["num_scored_sents"]
              )
          else:
              spk_dets["WER"] = None
              spk_dets["SER"] = None
          details_by_speaker_dicts.append(spk_dets)
      return details_by_speaker_dicts
  
file_path: speechbrain/speechbrain/utils/edit_distance.py
imports: import collections
label_desc: Use image node_id 10 for calling a global function with example usage: wer_details_by_speaker(details_by_utterance, utt2spk) and returns: details_by_speaker_dicts