public void SaveCore(ModelSaveContext ctx)
        {
            _host.CheckValue(ctx, "ctx");
            // We save the labels. The rest is already saved.
            ctx.Writer.Write(_labelWeights.Count);

            var conv = new TypedConverters <TLabel>();

            foreach (var pair in _labelWeights)
            {
                ctx.Writer.Write(pair.Key);
                conv.Save(ctx, pair.Value.Item1);
                ctx.Writer.Write(pair.Value.Item2);
            }
        }
        ValueMapper <TIn, TOut> GetMapperBinaryPrediction <TIn, TOut>(NearestNeighborsTrees trees, int k,
                                                                      NearestNeighborsAlgorithm algo, NearestNeighborsWeights weight)
        {
            var    conv          = new TypedConverters <TLabel>();
            TLabel positiveClass = default(TLabel);

            if (typeof(TLabel) == typeof(bool))
            {
                var convMap = conv.GetMapperFrom <bool>();
                var b       = true;
                convMap(in b, ref positiveClass);
            }
            else if (typeof(TLabel) == typeof(float))
            {
                var convMap = conv.GetMapperFrom <float>();
                var b       = 1f;
                convMap(in b, ref positiveClass);
            }
            else if (typeof(TLabel) == typeof(uint))
            {
                var  convMap = conv.GetMapperFrom <uint>();
                uint b       = 1;
                convMap(in b, ref positiveClass);
            }
            else
            {
                _host.ExceptNotImpl("Not implemented for type {0}", typeof(TLabel));
            }

            Dictionary <TLabel, float> hist = null;

            if (weight == NearestNeighborsWeights.uniform)
            {
                ValueMapper <VBuffer <float>, float> mapper = (in VBuffer <float> input, ref float output) =>
                {
                    GetMapperUniformBinaryPrediction(trees, k, in input, ref output, positiveClass, ref hist);
                };
                return(mapper as ValueMapper <TIn, TOut>);
            }
            else
            {
                throw _host.ExceptNotImpl("Not implemented for {0}", weight);
            }
        }
        protected void ReadCore(ModelLoadContext ctx)
        {
            // We load the labels. The rest is already saved.
            var conv = new TypedConverters <TLabel>();
            int nb   = ctx.Reader.ReadInt32();

            _labelWeights = new Dictionary <long, Tuple <TLabel, float> >();

            long   key;
            TLabel lab = default(TLabel);
            float  weight;

            for (int i = 0; i < nb; ++i)
            {
                key = ctx.Reader.ReadInt64();
                conv.Read(ctx, ref lab);
                weight             = ctx.Reader.ReadFloat();
                _labelWeights[key] = new Tuple <TLabel, float>(lab, weight);
            }
        }
        public int ComputeNbClass(PredictionKind kind)
        {
            _host.AssertValue(_labelWeights);
            KeyValuePair <long, Tuple <TLabel, float> > first = new KeyValuePair <long, Tuple <TLabel, float> >(0, new Tuple <TLabel, float>(default(TLabel), 0));

            foreach (var pair in _labelWeights)
            {
                first = pair;
                break;
            }

            TLabel mini = first.Value.Item1, maxi = first.Value.Item1;

            foreach (var pair in _labelWeights)
            {
                if (mini.CompareTo(pair.Value.Item1) > 0)
                {
                    mini = pair.Value.Item1;
                }
                if (maxi.CompareTo(pair.Value.Item1) < 0)
                {
                    maxi = pair.Value.Item1;
                }
            }

            var conv = new TypedConverters <TLabel>(DataKind.Int32);

            int imini = 0, imaxi = 0;
            var convMapper = conv.GetMapper <int>();

            if (convMapper == null)
            {
                throw _host.Except("No conversion from {0} to {1}", typeof(TLabel), typeof(int));
            }
            switch (kind)
            {
            case PredictionKind.BinaryClassification:
                if (mini.CompareTo(maxi) == 0)
                {
                    throw _host.Except("Only one class, two are expected.");
                }
                convMapper(in mini, ref imini);
                convMapper(in maxi, ref imaxi);
                if (imaxi - imini != 1)
                {
                    throw _host.Except("More than two classes: min(labels)={0} max(labels)={1}", imini, imaxi);
                }
                return(2);

            case PredictionKind.MulticlassClassification:
                if (mini.CompareTo(maxi) == 0)
                {
                    throw _host.Except("Only one class, more are expected.");
                }
                convMapper(in mini, ref imini);
                convMapper(in maxi, ref imaxi);
                return(imini == 0 ? imaxi + 1 : imini);

            default:
                throw _host.ExceptNotSupp("Not suported for predictor {0}", kind);
            }
        }