code: @Override
      public INDArray computeScoreArray(INDArray labels, INDArray preOutput, IActivation activationFn, INDArray mask) {
          labels = labels.castTo(preOutput.dataType());   //No-op if already correct dtype
          INDArray output = activationFn.getActivation(preOutput.dup(), false);
          MixtureDensityComponents mdc = extractComponents(output);
          INDArray scoreArr = negativeLogLikelihood(labels, mdc.alpha, mdc.mu, mdc.sigma);
  
          if (mask != null) {
              LossUtil.applyMask(scoreArr, mask);
          }
  
          return scoreArr;
      }
docs: This method returns the score for each of the given outputs against the
  given set of labels.  For a mixture density network, this is done by
  extracting the "alpha", "mu", and "sigma" components of each gaussian
  and computing the negative log likelihood that the labels fall within
  a linear combination of these gaussian distributions.  The smaller
  the negative log likelihood, the higher the probability that the given
  labels actually would fall within the distribution.  Therefore by
  minimizing the negative log likelihood, we get to a position of highest
  probability that the gaussian mixture explains the phenomenon.
  
  @param labels Labels give the sample output that the network should
  be trying to converge on.
  @param preOutput The output of the last layer (before applying the activation function).
  @param activationFn The activation function of the current layer.
  @param mask Mask to apply to score evaluation (not supported for this cost function).
  @return