File: Evaluators\Metrics\MulticlassClassificationMetrics.cs
Web Access
Project: src\src\Microsoft.ML.Data\Microsoft.ML.Data.csproj (Microsoft.ML.Data)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.ML.Runtime;
 
namespace Microsoft.ML.Data
{
    /// <summary>
    /// Evaluation results for multi-class classification trainers.
    /// </summary>
    public sealed class MulticlassClassificationMetrics
    {
        /// <summary>
        /// Gets the average log-loss of the classifier. Log-loss measures the performance of a classifier
        /// with respect to how much the predicted probabilities diverge from the true class label. Lower
        /// log-loss indicates a better model. A perfect model, which predicts a probability of 1 for the
        /// true class, will have a log-loss of 0.
        /// </summary>
        /// <remarks>
        /// <format type="text/markdown"><![CDATA[
        /// The log-loss metric is computed as follows:
        /// $LogLoss = - \frac{1}{m} \sum_{i = 1}^m log(p_i)$,
        /// where $m$ is the number of instances in the test set and
        /// $p_i$ is the probability returned by the classifier
        /// of the instance belonging to the true class.
        /// ]]>
        /// </format>
        /// </remarks>
        public double LogLoss { get; }
 
        /// <summary>
        /// Gets the log-loss reduction (also known as relative log-loss, or reduction in information gain - RIG)
        /// of the classifier. It gives a measure of how much a model improves on a model that gives random predictions.
        /// Log-loss reduction closer to 1 indicates a better model.
        /// </summary>
        /// <remarks>
        /// <format type="text/markdown"><![CDATA[
        /// The log-loss reduction is scaled relative to a classifier that predicts the prior for every example:
        /// $LogLossReduction = \frac{LogLoss(prior) - LogLoss(classifier)}{LogLoss(prior)}$
        /// This metric can be interpreted as the advantage of the classifier over a random prediction.
        /// For example, if the RIG equals 0.2, it can be interpreted as "the probability of a correct prediction is
        /// 20% better than random guessing".
        /// ]]>
        /// </format>
        /// </remarks>
        public double LogLossReduction { get; private set; }
 
        /// <summary>
        /// Gets the macro-average accuracy of the model.
        /// </summary>
        /// <remarks>
        /// The macro-average is the average accuracy at the class level. The accuracy for each class is computed
        /// and the macro-accuracy is the average of these accuracies.
        ///
        /// The macro-average metric gives the same weight to each class, no matter how many instances from
        /// that class the dataset contains.
        /// </remarks>
        public double MacroAccuracy { get; }
 
        /// <summary>
        /// Gets the micro-average accuracy of the model.
        /// </summary>
        /// <remarks>
        /// The micro-average is the fraction of instances predicted correctly across all classes. Micro-average can
        /// be a more useful metric than macro-average if class imbalance is suspected (i.e. one class has many more
        /// instances than the rest).
        /// </remarks>
        public double MicroAccuracy { get; }
 
        /// <summary>
        /// Convenience method for "TopKAccuracyForAllK[TopKPredictionCount - 1]". If <see cref="TopKPredictionCount"/> is positive,
        /// this is the relative number of examples where
        /// the true label is one of the top K predicted labels by the predictor.
        /// </summary>
        public double TopKAccuracy => TopKAccuracyForAllK?.LastOrDefault() ?? 0;
 
        /// <summary>
        /// If positive, this indicates the K in <see cref="TopKAccuracy"/> and <see cref="TopKAccuracyForAllK"/>.
        /// </summary>
        public int TopKPredictionCount { get; }
 
        /// <summary>
        /// Returns the top K accuracy for all K from 1 to the value of TopKPredictionCount.
        /// </summary>
        public IReadOnlyList<double> TopKAccuracyForAllK { get; }
 
        /// <summary>
        /// Gets the log-loss of the classifier for each class. Log-loss measures the performance of a classifier
        /// with respect to how much the predicted probabilities diverge from the true class label. Lower
        /// log-loss indicates a better model. A perfect model, which predicts a probability of 1 for the
        /// true class, will have a log-loss of 0.
        /// </summary>
        /// <remarks>
        /// The log-loss metric is computed as $-\frac{1}{m} \sum_{i=1}^m \log(p_i)$,
        /// where $m$ is the number of instances in the test set.
        /// $p_i$ is the probability returned by the classifier if the instance belongs to the class,
        /// and 1 minus the probability returned by the classifier if the instance does not belong to the class.
        /// </remarks>
        /// <example>
        /// <format type="text/markdown">
        /// <![CDATA[
        ///  [!code-csharp[LogLoss](~/../docs/samples/docs/samples/Microsoft.ML.Samples/Dynamic/Trainers/MulticlassClassification/LogLossPerClass.cs)]
        /// ]]></format>
        /// </example>
        public IReadOnlyList<double> PerClassLogLoss { get; }
 
        /// <summary>
        /// The <a href="https://en.wikipedia.org/wiki/Confusion_matrix">confusion matrix</a> giving the counts of the
        /// predicted classes versus the actual classes.
        /// </summary>
        public ConfusionMatrix ConfusionMatrix { get; }
 
        internal MulticlassClassificationMetrics(IHost host, DataViewRow overallResult, int topKPredictionCount, IDataView confusionMatrix)
        {
            double FetchDouble(string name) => RowCursorUtils.Fetch<double>(host, overallResult, name);
            MicroAccuracy = FetchDouble(MulticlassClassificationEvaluator.AccuracyMicro);
            MacroAccuracy = FetchDouble(MulticlassClassificationEvaluator.AccuracyMacro);
            LogLoss = FetchDouble(MulticlassClassificationEvaluator.LogLoss);
            LogLossReduction = FetchDouble(MulticlassClassificationEvaluator.LogLossReduction);
            TopKPredictionCount = topKPredictionCount;
 
            if (topKPredictionCount > 0)
                TopKAccuracyForAllK = RowCursorUtils.Fetch<VBuffer<double>>(host, overallResult, MulticlassClassificationEvaluator.AllTopKAccuracy).DenseValues().ToImmutableArray();
 
            var perClassLogLoss = RowCursorUtils.Fetch<VBuffer<double>>(host, overallResult, MulticlassClassificationEvaluator.PerClassLogLoss);
            PerClassLogLoss = perClassLogLoss.DenseValues().ToImmutableArray();
            ConfusionMatrix = MetricWriter.GetConfusionMatrix(host, confusionMatrix, binary: false, perClassLogLoss.Length);
        }
 
        internal MulticlassClassificationMetrics(double accuracyMicro, double accuracyMacro, double logLoss, double logLossReduction,
            int topKPredictionCount, double[] topKAccuracies, double[] perClassLogLoss)
        {
            MicroAccuracy = accuracyMicro;
            MacroAccuracy = accuracyMacro;
            LogLoss = logLoss;
            LogLossReduction = logLossReduction;
            TopKPredictionCount = topKPredictionCount;
            TopKAccuracyForAllK = topKAccuracies;
            PerClassLogLoss = perClassLogLoss.ToImmutableArray();
        }
 
        internal MulticlassClassificationMetrics(double accuracyMicro, double accuracyMacro, double logLoss, double logLossReduction,
            int topKPredictionCount, double[] topKAccuracies, double[] perClassLogLoss, ConfusionMatrix confusionMatrix)
            : this(accuracyMicro, accuracyMacro, logLoss, logLossReduction, topKPredictionCount, topKAccuracies, perClassLogLoss)
        {
            ConfusionMatrix = confusionMatrix;
        }
    }
}