/// <summary>
        /// Check that the model is able to fit the classification data
        /// </summary>
        private void check_predictions(LogisticRegression<int> clf, Matrix<double> X, int[] y)
        {
            int nSamples = y.Length;
            int[] classes = y.Distinct().OrderBy(v => v).ToArray();
            int nClasses = classes.Length;

            clf.Fit(X, y);
            var predicted = clf.Predict(X);
            Assert.IsTrue(classes.SequenceEqual(clf.Classes));

            Assert.AreEqual(nSamples, predicted.Length);
            Assert.IsTrue(y.SequenceEqual(predicted));
                
            Matrix<double> probabilities = clf.PredictProba(X);
            Assert.AreEqual(Tuple.Create(nSamples, nClasses), probabilities.Shape());
            Assert.IsTrue(probabilities.SumOfEveryRow().AlmostEquals(DenseVector.Create(probabilities.RowCount, i => 1.0)));
            Assert.IsTrue(y.SequenceEqual(probabilities.ArgmaxColumns()));
        }
        /// <summary>
        /// Check that the model is able to fit the classification data
        /// </summary>
        private void check_predictions(LogisticRegression <int> clf, Matrix <double> X, int[] y)
        {
            int nSamples = y.Length;

            int[] classes  = y.Distinct().OrderBy(v => v).ToArray();
            int   nClasses = classes.Length;

            clf.Fit(X, y);
            var predicted = clf.Predict(X);

            Assert.IsTrue(classes.SequenceEqual(clf.Classes));

            Assert.AreEqual(nSamples, predicted.Length);
            Assert.IsTrue(y.SequenceEqual(predicted));

            Matrix <double> probabilities = clf.PredictProba(X);

            Assert.AreEqual(Tuple.Create(nSamples, nClasses), probabilities.Shape());
            Assert.IsTrue(probabilities.SumOfEveryRow().AlmostEquals(DenseVector.Create(probabilities.RowCount, i => 1.0)));
            Assert.IsTrue(y.SequenceEqual(probabilities.ArgmaxColumns()));
        }
        public void TestPredictIris()
        {
            int nSamples = iris.Data.RowCount;

            string[] target = iris.Target.Select(v => iris.TargetNames[v]).ToArray();
            var      clf    = new LogisticRegression <string>(c: iris.Data.RowCount);

            clf.Fit(iris.Data, target);
            Assert.IsTrue(target.Distinct().OrderBy(t => t).SequenceEqual(clf.Classes));

            var pred      = clf.Predict(iris.Data);
            var matchingN = pred.Zip(target, Tuple.Create).Where(t => t.Item1 == t.Item2).Count();

            Assert.IsTrue(1.0 * matchingN / pred.Length > 0.95);

            var probabilities = clf.PredictProba(iris.Data);

            Assert.IsTrue(probabilities.SumOfEveryRow().AlmostEquals(DenseVector.Create(nSamples, i => 1.0)));

            pred      = probabilities.RowEnumerator().Select(r => iris.TargetNames[r.Item2.MaximumIndex()]).ToArray();
            matchingN = pred.Zip(target, Tuple.Create).Where(t => t.Item1 == t.Item2).Count();
            Assert.IsTrue(1.0 * matchingN / pred.Length > 0.95);
        }
        public void TestPredictIris()
        {
            int nSamples = iris.Data.RowCount;

            string[] target = iris.Target.Select(v => iris.TargetNames[v]).ToArray();
            var clf = new LogisticRegression<string>(c: iris.Data.RowCount);
            clf.Fit(iris.Data, target);
            Assert.IsTrue(target.Distinct().OrderBy(t => t).SequenceEqual(clf.Classes));

            var pred = clf.Predict(iris.Data);
            var matchingN = pred.Zip(target, Tuple.Create).Where(t => t.Item1 == t.Item2).Count();
            Assert.IsTrue(1.0*matchingN/pred.Length > 0.95);

            var probabilities = clf.PredictProba(iris.Data);
            Assert.IsTrue(probabilities.SumOfEveryRow().AlmostEquals(DenseVector.Create(nSamples, i => 1.0)));

            pred = probabilities.RowEnumerator().Select(r => iris.TargetNames[r.Item2.MaximumIndex()]).ToArray();
            matchingN = pred.Zip(target, Tuple.Create).Where(t => t.Item1 == t.Item2).Count();
            Assert.IsTrue(1.0 * matchingN / pred.Length > 0.95);
        }