class_docstr: This class is responsible for analyzing the results and outputting various types of analysis to the results folder.
class_docstr_tok: ["This","class","is","responsible","for","analyzing","the","results","and","outputting","various","types","of","analysis","to","the","results","folder","."]
docstr: This computes the loss matrix between two hyper-parameters. The loss matrix
  helps you to visualize what are the best areas of the hyper parameter space
  by plotting them on a grid and coloring them.
docstr_tok: ["This","computes","the","loss","matrix","between","two","hyper-parameters",".","The","loss","matrix","helps","you","to","visualize","what","are","the","best","areas","of","the","hyper","parameter","space","by","plotting","them","on","a","grid","and","coloring","them","."]
code: def computeLossMatrix(
      self,
      results,
      parameter1,
      parameter2,
      valueKey="loss",
      cutoff=1.0,
      reduction="min",
  ):
      """
      This computes the loss matrix between two hyper-parameters. The loss matrix
      helps you to visualize what are the best areas of the hyper parameter space
      by plotting them on a grid and coloring them.
      """
      losses = [
          numpy.min(v[valueKey])
          for v in results
          if v[valueKey] is not None
      ]
      threshhold = numpy.percentile(losses, cutoff * 100)
      filteredResults = [
          result
          for result in results
          if result[valueKey] is not None
          and result[valueKey] < threshhold
      ]
  
      # Divide the range up into 100 parts
      numBuckets = 10
      parameter1Buckets = self.computeBucketsForParameter(
          filteredResults, parameter1, numBuckets
      )
      parameter2Buckets = self.computeBucketsForParameter(
          filteredResults, parameter2, numBuckets
      )
  
      # Create a grid for each of the values
      resultGrid = []
      for value in parameter1Buckets[1:]:
          row = []
          for value in parameter2Buckets[1:]:
              row.append([])
          resultGrid.append(row)
  
      # Go through each of the results, and put them into one of the buckets (or exclude them if these hyper-parameters were not active
      for result in results:
          if result[valueKey] is None:
              continue
          parameter1Key = parameter1.root[5:]
          parameter2Key = parameter2.root[5:]
  
          if (
              isinstance(result[parameter1Key], float)
              or isinstance(result[parameter1Key], int)
              or isinstance(result[parameter1Key], bool)
          ):
              if (
                  isinstance(result[parameter2Key], float)
                  or isinstance(result[parameter2Key], int)
                  or isinstance(result[parameter2Key], bool)
              ):
                  parameter1Value = float(result[parameter1Key])
                  parameter2Value = float(result[parameter2Key])
  
                  parameter1Index = None
                  for index1, value1 in enumerate(
                      parameter1Buckets[1:]
                  ):
                      if parameter1Value <= value1:
                          parameter1Index = index1
                          break
                  parameter2Index = None
                  for index2, value2 in enumerate(
                      parameter2Buckets[1:]
                  ):
                      if parameter2Value <= value2:
                          parameter2Index = index2
                          break
                  if (
                      parameter1Index is not None
                      and parameter2Index is not None
                  ):
                      resultGrid[parameter1Index][
                          parameter2Index
                      ].append(result)
  
      # Now go through each entry in the grid and compute the average score
      scoreGrid = []
      for row in resultGrid:
          scoreRow = []
          for column in row:
              if len(column) > 0:
                  if reduction == "min":
                      scoreRow.append(
                          numpy.min(
                              [
                                  result[valueKey]
                                  for result in column
                                  if result[valueKey] is not None
                              ]
                          )
                      )
                  elif reduction == "mean":
                      scoreRow.append(
                          numpy.mean(
                              [
                                  result[valueKey]
                                  for result in column
                                  if result[valueKey] is not None
                              ]
                          )
                      )
                  elif reduction == "median":
                      scoreRow.append(
                          numpy.median(
                              [
                                  result[valueKey]
                                  for result in column
                                  if result[valueKey] is not None
                              ]
                          )
                      )
              else:
                  scoreRow.append(None)
          scoreGrid.append(scoreRow)
  
      newScoreGrid = []
      for value in parameter1Buckets[1:]:
          row = []
          for value in parameter2Buckets[1:]:
              row.append(0)
          newScoreGrid.append(row)
  
      # Now for any parts of the grid which don't have a score, we find the nearest neighbor on the grid and just take its score. If theres multiple, we take the average of them.
      for rowIndex, row in enumerate(scoreGrid):
          for columnIndex, column in enumerate(row):
              if column is None:
                  closest = None
                  closestValues = []
                  # Find the nearest location on the score grid which has a value
                  for possibleRowIndex, possibleRow in enumerate(
                      scoreGrid
                  ):
                      for (
                          possibleColumnIndex,
                          possibleColumn,
                      ) in enumerate(possibleRow):
                          if possibleColumn is not None:
                              dist = (rowIndex - possibleRowIndex) * (
                                  rowIndex - possibleRowIndex
                              ) + (
                                  columnIndex - possibleColumnIndex
                              ) * (
                                  columnIndex - possibleColumnIndex
                              )
                              if closest is None or dist < closest:
                                  closest = dist
                                  closestValues = [possibleColumn]
                              elif dist == closest:
                                  closestValues.append(possibleColumn)
                  if len(closestValues) > 0:
                      # Take the mean of the closest values and use that for this location on the score grid
                      newScoreGrid[rowIndex][columnIndex] = numpy.mean(
                          closestValues
                      )
                  else:
                      newScoreGrid[rowIndex][columnIndex] = 0
              else:
                  newScoreGrid[rowIndex][columnIndex] = scoreGrid[
                      rowIndex
                  ][columnIndex]
  
      # Round all of the values in the final score grid. This makes them more pleasant to look at for display purposes.
      for rowIndex, row in enumerate(newScoreGrid):
          for columnIndex, column in enumerate(row):
              newScoreGrid[rowIndex][columnIndex] = roundPrecision(
                  newScoreGrid[rowIndex][columnIndex]
              )
  
      # Transpose the score grid, so that parameter1 is on the horizontal
      newScoreGrid = numpy.transpose(numpy.array(newScoreGrid))
      newScoreGrid = numpy.flip(newScoreGrid, axis=0)
  
      parameter2Buckets.reverse()
  
      return newScoreGrid, parameter1Buckets, parameter2Buckets
  
imports: import jsonschema
  import os
  import os.path
  import math
  import csv
  from hypermax.hyperparameter import Hyperparameter
  import sklearn.covariance
  import numpy
  from hypermax.utils import roundPrecision
  import matplotlib
  import matplotlib.cm
  import matplotlib.style
  import matplotlib.pyplot
  from pprint import pprint
  import concurrent.futures
  import colors
  import traceback
  import functools
  import warnings
  import scipy.optimize
  import random
  import json
  import atexit
  import matplotlib.ticker
  import traceback
  import copy
label_desc: Use image node_id 17 for calling the ResultsAnalyzer obj's underlying member method code with example usage: obj.computeLossMatrix(results, parameter1, parameter2, valueKey, cutoff, reduction) and returns: newScoreGrid,  parameter1Buckets,  parameter2Buckets