/// <summary>
 /// Writes class classification statistics.
 /// </summary>
 /// <param name="writer">A stream to write the report to.</param>
 /// <param name="summary">Classification results for the class.</param>
 /// <param name="classNameLength">The number of characters in the class name column.</param>
 private static void WriteClassStatistics(TextWriter writer, ClassSummary <T> summary, int classNameLength)
 {
     writer.Write(string.Format(CultureInfo.InvariantCulture, "{{0,-{0}}},", classNameLength), summary.Label);
     WriteShortStatistics(writer, summary.Statistics.All);
     WriteLongStatistics(writer, summary.Statistics.WithTruth);
     writer.WriteLine();
 }
Beispiel #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ClassificationReport{T}"/> class.
        /// </summary>
        /// <param name="results">The classification results.</param>
        public ClassificationReport(IEnumerable <ClassificationResult <T> > results)
        {
            if (results == null)
            {
                throw new ArgumentNullException(nameof(results));
            }

            Dictionary <T, ClassSummary <T> > summaries = new Dictionary <T, ClassSummary <T> >();

            foreach (ClassificationResult <T> result in results)
            {
                this.results.Add(result);

                T expected = result.Expected;
                if (!summaries.TryGetValue(expected, out ClassSummary <T> summary))
                {
                    summaries[expected] = summary = new ClassSummary <T>(expected);
                    this.classes.Add(summary);
                }

                summary.Add(result);

                this.AllClasses.Add(result);
                this.ConfusionMatrix.Add(result.Predicted, expected);
            }

            this.results.TrimExcess();
            this.classes.TrimExcess();
        }
        /// <summary>
        /// Writes class errors.
        /// </summary>
        /// <param name="writer">A stream to write the report to.</param>
        /// <param name="summary">Classification results for the class.</param>
        private static void WriteClassificationErrors(TextWriter writer, ClassSummary <T> summary)
        {
            int acceptedErrors = summary.Errors.Count();

            if (acceptedErrors > 0)
            {
                writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0} ({1})", summary.Label, acceptedErrors));
                writer.WriteLine();
                ClassificationResult <T> .Write(writer, summary.Errors);

                writer.WriteLine("-----------------------------------------------------------------------------");
                writer.WriteLine();
            }
        }
        /// <summary>
        /// Writes class reject curve.
        /// </summary>
        /// <param name="writer">A stream to write the report to.</param>
        /// <param name="summary">Classification results for the class.</param>
        private static void WriteClassRejectCurve(TextWriter writer, ClassSummary <T> summary)
        {
            float[] errorRates = { 0.001f, 0.005f, 0.01f, 0.02f, 0.03f, 0.04f, 0.05f, 0.06f, 0.07f, 0.08f, 0.09f, 0.10f, 0.11f };

            writer.WriteLine(summary.Label);
            writer.WriteLine();

            writer.WriteLine(
                "{0,-10}{1,-10}{2,-10}{3,-10}",
                "Target",
                "Error",
                "Accept",
                "Threshold");

            RejectCurveTarget[] targets = summary.Statistics.RejectCurveTruth.GetTargets(errorRates);
            foreach (RejectCurveTarget target in targets)
            {
                if (target.Point.HasValue)
                {
                    writer.WriteLine(
                        "{0,-10:P2}{1,-10:P2}{2,-10:P2}{3,-10:N0}",
                        target.Target,
                        target.Point.Value.ErrorRate,
                        target.Point.Value.AcceptRate,
                        target.Point.Value.Threshold);
                }
                else
                {
                    writer.WriteLine(
                        "{0,-10:P2}{1,-10}{1,-10}{1,-10}",
                        target.Target,
                        "N/A");
                }
            }

            writer.WriteLine();

            // write area
            float average = summary.Statistics.RejectCurveTruth.GetArea(0.0f, errorRates.Last(), 100);

            writer.WriteLine(
                "Area: {0:P2}",
                average);

            writer.WriteLine("-----------------------------------------------------------------------------");
            writer.WriteLine();
        }
        /// <summary>
        /// Writes all reject curves.
        /// </summary>
        /// <param name="writer">A stream to write the report to.</param>
        /// <param name="all">Classification results for all classes.</param>
        /// <param name="classes">Classification results for each class.</param>
        private static void WriteRejectCurves(TextWriter writer, ClassSummary <T> all, IList <ClassSummary <T> > classes)
        {
            float[] errorRates = { 0.001f, 0.005f, 0.01f, 0.02f, 0.03f, 0.04f, 0.05f, 0.06f, 0.07f, 0.08f, 0.09f, 0.10f, 0.11f };

            List <ClassSummary <T> > combined = new List <ClassSummary <T> >()
            {
                all
            };

            combined.AddRange(classes);

            string separator = new string('-', 10 + (30 * combined.Count));

            // write class names
            writer.Write("{0,-10}", string.Empty);
            foreach (ClassSummary <T> cls in combined)
            {
                writer.Write("{0,-30}", cls.Label);
            }

            writer.WriteLine();
            writer.WriteLine(separator);

            // write header
            writer.Write("{0,-10}", "Target");
            for (int i = 0, ii = combined.Count; i < ii; i++)
            {
                writer.Write("{0,-10}{1,-10}{2,-10}", "Error", "Accept", "Thresh");
            }

            writer.WriteLine();

            // write targets
            foreach (float errorRate in errorRates)
            {
                writer.Write("{0,-10:P2}", errorRate);

                foreach (ClassSummary <T> cls in combined)
                {
                    RejectCurveTarget target = cls.Statistics.RejectCurveTruth.GetTarget(errorRate);
                    if (target.Point.HasValue)
                    {
                        writer.Write(
                            "{0,-10:P2}{1,-10:P2}{2,-10:N0}",
                            target.Point.Value.ErrorRate,
                            target.Point.Value.AcceptRate,
                            target.Point.Value.Threshold);
                    }
                    else
                    {
                        writer.Write(
                            "{0,-10}{0,-10}{0,-10}",
                            "N/A");
                    }
                }

                writer.WriteLine();
            }

            writer.WriteLine(separator);

            // write area
            writer.Write("{0,-10}", "Area:");
            foreach (ClassSummary <T> cls in combined)
            {
                float average = cls.Statistics.RejectCurveTruth.GetArea(0.0f, errorRates.Last(), 100);
                writer.Write("{0,-30:P2}", average);
            }

            writer.WriteLine();
        }