Exemple #1
0
        /// <summary>
        /// Creates one classifier (batch of trees)
        /// </summary>
        /// <returns></returns>
        public static DecisionBatch CreateBatch(double[,] xy, int treesInBatch, int nclasses, double rfcoeff,
                                                double varscoeff, int[] idx, bool parallel, bool useLogit)
        {
            var batch = new DecisionBatch();


            IEnumerable <int>   source = Enumerable.Range(1, treesInBatch);
            List <DecisionTree> treeList;

            if (parallel)
            {
                treeList = (from n in source.AsParallel()
                            select DecisionTree.CreateTree(idx, xy, nclasses, rfcoeff, varscoeff)
                            ).ToList();
            }
            else
            {
                treeList = (from n in source
                            select DecisionTree.CreateTree(idx, xy, nclasses, rfcoeff, varscoeff)
                            ).ToList();
            }

            treeList.ForEach(batch.AddTree);
            CalcOutOfTheBagMetrics(treeList, xy, batch, useLogit);

            return(batch);
        }
Exemple #2
0
        /// <summary>
        /// Load trees from dump files
        /// </summary>
        public override int LoadClassifier()
        {
            string treesRoot  = ConfigReader.Read("TreesRoot");
            int    bucketSize = int.Parse(ConfigReader.Read("BucketSize"));

            string treesDir = treesRoot ?? (Environment.CurrentDirectory + "\\batches");

            if (!Directory.Exists(treesDir))
            {
                Logger.Log("directory " + treesDir + " doesn't exists");
                return(0);
            }
            var dinfo = new DirectoryInfo(treesDir);

            _classifiers.Clear();

            var files = dinfo.GetFiles("*.dmp").OrderBy(f => f.Name).ToArray();

            if (bucketSize > 0)
            {
                files = files.Skip(bucketSize * _bucketNum).Take(bucketSize).ToArray();
                _bucketNum++;
            }
            int clid = 0;

            foreach (var finfo in files)
            {
                var cls = DecisionBatch.Load(finfo.FullName);
                _classifiers.Add(clid++, cls);
                Logger.Log(finfo.Name + " loaded;");
            }
            Logger.Log("all trees loaded;");
            return(clid);
        }
Exemple #3
0
        /// <summary>
        /// Расчет классификации по тестовому обучающему на одном классификаторе
        /// </summary>
        /// <param name="batch"></param>
        /// <returns>Количество деревьев, проголосовавших за каждый класс</returns>
        private Dictionary <string, double> GetTrainClassificationCounts(DecisionBatch batch)
        {
            var probDict = new Dictionary <string, double>();

            int lines = _trainLoader.TotalDataLines;
            int vars  = _trainLoader.NVars;

            // пробегаем по всем клиентски данным и сохраняем результат
            for (int i = 0; i < lines; i++)
            {
                var cdata = new double[vars];
                for (int j = 0; j < vars; j++)
                {
                    cdata[j] = _trainLoader.LearnRows[i, j];
                }

                //var y = batch.PredictCounts(cdata);
                var    y  = batch.PredictProba(cdata);
                string id = i.ToString();
                if (!probDict.ContainsKey(id))
                {
                    probDict.Add(id, y[1]);
                }
            }

            return(probDict);
        }
Exemple #4
0
        private FinalFuncResult GetMetricsAccumulated(DecisionBatch cls,
                                                      Dictionary <string, double> probSum,
                                                      Dictionary <string, double> probAvg,
                                                      Dictionary <string, int> resultDict,
                                                      int nbcount,
                                                      Func <DecisionBatch, Dictionary <string, double> > getResult
                                                      )
        {
            // получаем результат по одному классификатору
            var result = getResult(cls);

            // сохраняем общую сумму голостов по идентификатору
            // т.е. добавляем результат голосований от очередного классификатора cls
            foreach (string id in result.Keys)
            {
                if (!probSum.ContainsKey(id))
                {
                    probSum.Add(id, 0);
                }

                probSum[id] += result[id];
            }

            // находим вероятности, деля количество голосов на количеств деревьев во всех классификаторах
            foreach (var id in probSum.Keys)
            {
                if (!probAvg.ContainsKey(id))
                {
                    probAvg.Add(id, 0);
                }
                probAvg[id] = probSum[id] / nbcount;
            }

            var rlist = new RocItem[resultDict.Count]; // массив для оценки результата
            // находим статистики классификации
            int idx = 0;

            foreach (string id in result.Keys)
            {
                if (rlist[idx] == null)
                {
                    rlist[idx] = new RocItem();
                }

                rlist[idx].Prob      = probAvg[id]; // среднее по наблюдениям
                rlist[idx].Target    = resultDict[id];
                rlist[idx].Predicted = probAvg[id] > 0.5 ? 1 : 0;

                idx++;
            }
            Array.Sort(rlist, (o1, o2) => (1 - o1.Prob).CompareTo(1 - o2.Prob));
            var clsRes = ResultCalc.GetResult(rlist, 0.05);

            return(clsRes);
        }
Exemple #5
0
        /// <summary>
        /// Расчет классификации по тестовому множеству на одном классификаторе
        /// ипользуется в GetTestSetMetrics
        /// </summary>
        /// <param name="batch"></param>
        /// <returns>Количество деревьев, проголосовавших за каждый класс</returns>
        private Dictionary <string, double> GetTestClassificationCounts(DecisionBatch batch)
        {
            var probDict = new Dictionary <string, double>();

            // пробегаем по всем клиентски данным и сохраняем результат
            foreach (string id in _testDataDict.Keys)
            {
                //var y = batch.PredictCounts(_testDataDict[id]);
                var y = batch.PredictProba(_testDataDict[id]);
                if (!probDict.ContainsKey(id))
                {
                    probDict.Add(id, y[1]);
                }
            }

            return(probDict);
        }
Exemple #6
0
        /// <summary>
        /// Creates one classifier (batch of trees)
        /// </summary>
        /// <returns></returns>
        public static DecisionBatch CreateBatch(double[,] xy, int treesInBatch, int nclasses, double rfcoeff,
            double varscoeff, int[] idx, bool parallel, bool useLogit)
        {
            var batch = new DecisionBatch();

            IEnumerable<int> source = Enumerable.Range(1, treesInBatch);
            List<DecisionTree> treeList;

            if (parallel)
                treeList = (from n in source.AsParallel()
                            select DecisionTree.CreateTree(idx, xy, nclasses, rfcoeff, varscoeff)
                        ).ToList();
            else
                treeList = (from n in source
                            select DecisionTree.CreateTree(idx, xy, nclasses, rfcoeff, varscoeff)
                        ).ToList();

            treeList.ForEach(batch.AddTree);
            CalcOutOfTheBagMetrics(treeList, xy, batch, useLogit);

            return batch;
        }
Exemple #7
0
        public static DecisionBatch Load(string path)
        {
            DecisionBatch cls = null;
            FileStream    fs  = null;

            try
            {
                fs = new FileStream(path, FileMode.Open, FileAccess.Read);
                var formatter = new BinaryFormatter();
                cls    = (DecisionBatch)formatter.Deserialize(fs);
                cls.Id = NCls++;
            }
            catch (Exception e)
            {
                Logger.Log(e);
            }
            finally
            {
                fs?.Close();
            }

            return(cls);
        }
Exemple #8
0
        private static void CalcOutOfTheBagMetrics(List <DecisionTree> treeList, double[,] xy, DecisionBatch batch, bool useLogit)
        {
            var rdict = new Dictionary <int, int>();

            foreach (var tree in treeList)
            {
                foreach (int id in tree.RowIndexes)
                {
                    if (!rdict.ContainsKey(id))
                    {
                        rdict.Add(id, 0);
                    }
                    rdict[id]++;
                }
            }

            int npoints  = xy.GetLength(0);
            int nvars    = xy.GetLength(1) - 1;
            int tnpoints = npoints - rdict.Count;

            var    rlist    = new RocItem[tnpoints];                             // массив для оценки результата
            var    ntrain   = new double[tnpoints, batch.CountTreesInBatch + 1]; // массив для оценки результата
            double accCoeff = rdict.Count / (double)npoints;

            for (int i = 0, k = 0; i < npoints; i++)
            {
                if (rdict.ContainsKey(i))
                {
                    continue;
                }

                var tobj = new double[nvars];
                for (int j = 0; j < nvars; j++)
                {
                    tobj[j] = xy[i, j];
                }

                rlist[k] = new RocItem();
                double[] tprob = batch.PredictProba(tobj);
                rlist[k].Prob      = tprob[1];
                rlist[k].Predicted = tprob[1] > 0.5?1:0;
                rlist[k].Target    = Convert.ToInt32(xy[i, nvars]);

                double[] bytree = batch.PredictByTree(tobj);
                for (int j = 0; j < batch.CountTreesInBatch; j++)
                {
                    ntrain[k, j] = bytree[j];
                }
                ntrain[k, batch.CountTreesInBatch] = xy[i, nvars];

                k++;
            }

            Array.Sort(rlist, (o1, o2) => (1 - o1.Prob).CompareTo(1 - o2.Prob));
            batch.OutBagEstimations = ResultCalc.GetResult(rlist, 0.05);

            if (useLogit)
            {
                int info;
                alglib.mnlreport rep;
                alglib.mnltrainh(ntrain, tnpoints, batch.CountTreesInBatch, 2, out info, out batch._logitModel, out rep);

                for (int i = 0, k = 0; i < npoints; i++)
                {
                    if (rdict.ContainsKey(i))
                    {
                        continue;
                    }

                    var tobj = new double[nvars];
                    for (int j = 0; j < nvars; j++)
                    {
                        tobj[j] = xy[i, j];
                    }

                    rlist[k] = new RocItem();
                    double[] tprob = batch.PredictProba(tobj);
                    rlist[k].Prob      = tprob[1];
                    rlist[k].Predicted = tprob[1] > 0.5 ? 1 : 0;
                    rlist[k].Target    = Convert.ToInt32(xy[i, nvars]);

                    k++;
                }

                Array.Sort(rlist, (o1, o2) => (1 - o1.Prob).CompareTo(1 - o2.Prob));
                batch.OutBagEstimationsLogit = ResultCalc.GetResult(rlist, 0.05);
            }

            Logger.Log("train used: " + accCoeff + "; out_of_bag:" + batch.OutBagEstimations.AUC + "; out_of_bag_logit:" + batch.OutBagEstimationsLogit?.AUC);
        }
Exemple #9
0
 /// <summary>
 /// Полный расчет метрик качества классификации на тестовом множестве
 /// c учетом очередного классификатора
 /// </summary>
 /// <returns>Результат классификации</returns>
 private FinalFuncResult GetTrainMetricsAccumulated(DecisionBatch cls)
 {
     _nbTrain += UseBatchLogit ? 1 : cls.CountTreesInBatch; // обновляем общее кол-во деревьев
     return GetMetricsAccumulated(cls, _trainProbSum, _trainProbAvg, _trainResult, _nbTrain, GetTrainClassificationCounts);
 }
Exemple #10
0
        /// <summary>
        /// Расчет классификации по тестовому обучающему на одном классификаторе
        /// </summary>
        /// <param name="batch"></param>
        /// <returns>Количество деревьев, проголосовавших за каждый класс</returns>
        private Dictionary<string, double> GetTrainClassificationCounts(DecisionBatch batch)
        {
            var probDict = new Dictionary<string, double>();

            int lines = _trainLoader.TotalDataLines;
            int vars = _trainLoader.NVars;

            // пробегаем по всем клиентски данным и сохраняем результат
            for (int i = 0; i < lines; i++)
            {
                var cdata = new double[vars];
                for (int j = 0; j < vars; j++)
                    cdata[j] = _trainLoader.LearnRows[i, j];

                //var y = batch.PredictCounts(cdata);
                var y = batch.PredictProba(cdata);
                string id = i.ToString();
                if (!probDict.ContainsKey(id))
                    probDict.Add(id, y[1]);
            }

            return probDict;
        }
Exemple #11
0
        /// <summary>
        /// Расчет классификации по тестовому множеству на одном классификаторе
        /// ипользуется в GetTestSetMetrics
        /// </summary>
        /// <param name="batch"></param>
        /// <returns>Количество деревьев, проголосовавших за каждый класс</returns>
        private Dictionary<string, double> GetTestClassificationCounts(DecisionBatch batch)
        {
            var probDict = new Dictionary<string, double>();

            // пробегаем по всем клиентски данным и сохраняем результат
            foreach (string id in _testDataDict.Keys)
            {
                //var y = batch.PredictCounts(_testDataDict[id]);
                var y = batch.PredictProba(_testDataDict[id]);
                if (!probDict.ContainsKey(id))
                    probDict.Add(id, y[1]);
            }

            return probDict;
        }
Exemple #12
0
        private FinalFuncResult GetMetricsAccumulated(DecisionBatch cls,
                Dictionary<string, double> probSum,
                Dictionary<string, double> probAvg,
                Dictionary<string, int> resultDict,
                int nbcount,
                Func<DecisionBatch, Dictionary<string, double>> getResult
            )
        {
            // получаем результат по одному классификатору
            var result = getResult(cls);

            // сохраняем общую сумму голостов по идентификатору
            // т.е. добавляем результат голосований от очередного классификатора cls
            foreach (string id in result.Keys)
            {
                if (!probSum.ContainsKey(id))
                    probSum.Add(id, 0);

                probSum[id] += result[id];
            }

            // находим вероятности, деля количество голосов на количеств деревьев во всех классификаторах
            foreach (var id in probSum.Keys)
            {
                if (!probAvg.ContainsKey(id))
                    probAvg.Add(id, 0);
                probAvg[id] = probSum[id] / nbcount;
            }

            var rlist = new RocItem[resultDict.Count]; // массив для оценки результата
            // находим статистики классификации
            int idx = 0;
            foreach (string id in result.Keys)
            {
                if (rlist[idx] == null) rlist[idx] = new RocItem();

                rlist[idx].Prob = probAvg[id]; // среднее по наблюдениям
                rlist[idx].Target = resultDict[id];
                rlist[idx].Predicted = probAvg[id] > 0.5 ? 1 : 0;

                idx++;
            }
            Array.Sort(rlist, (o1, o2) => (1 - o1.Prob).CompareTo(1 - o2.Prob));
            var clsRes = ResultCalc.GetResult(rlist, 0.05);
            return clsRes;
        }
Exemple #13
0
        private static void CalcOutOfTheBagMetrics(List<DecisionTree> treeList, double[,] xy, DecisionBatch batch, bool useLogit)
        {
            var rdict = new Dictionary<int, int>();
            foreach (var tree in treeList)
            {
                foreach (int id in tree.RowIndexes)
                {
                    if (!rdict.ContainsKey(id))
                        rdict.Add(id, 0);
                    rdict[id]++;
                }
            }

            int npoints = xy.GetLength(0);
            int nvars = xy.GetLength(1) - 1;
            int tnpoints = npoints - rdict.Count;

            var rlist = new RocItem[tnpoints]; // массив для оценки результата
            var ntrain = new double[tnpoints, batch.CountTreesInBatch+1]; // массив для оценки результата
            double accCoeff = rdict.Count / (double)npoints;

            for (int i=0, k=0; i < npoints; i++)
            {
                if (rdict.ContainsKey(i)) continue;

                var tobj = new double[nvars];
                for (int j = 0; j < nvars; j++)
                    tobj[j] = xy[i, j];

                rlist[k] = new RocItem();
                double[] tprob = batch.PredictProba(tobj);
                rlist[k].Prob = tprob[1];
                rlist[k].Predicted = tprob[1]>0.5?1:0;
                rlist[k].Target = Convert.ToInt32(xy[i, nvars]);

                double[] bytree = batch.PredictByTree(tobj);
                for (int j = 0; j < batch.CountTreesInBatch; j++)
                    ntrain[k, j] = bytree[j];
                ntrain[k, batch.CountTreesInBatch] = xy[i, nvars];

                k++;
            }

            Array.Sort(rlist, (o1, o2) => (1 - o1.Prob).CompareTo(1 - o2.Prob));
            batch.OutBagEstimations = ResultCalc.GetResult(rlist, 0.05);

            if (useLogit)
            {
                int info;
                alglib.mnlreport rep;
                alglib.mnltrainh(ntrain, tnpoints, batch.CountTreesInBatch, 2, out info, out batch._logitModel, out rep);

                for (int i = 0, k = 0; i < npoints; i++)
                {
                    if (rdict.ContainsKey(i)) continue;

                    var tobj = new double[nvars];
                    for (int j = 0; j < nvars; j++)
                        tobj[j] = xy[i, j];

                    rlist[k] = new RocItem();
                    double[] tprob = batch.PredictProba(tobj);
                    rlist[k].Prob = tprob[1];
                    rlist[k].Predicted = tprob[1] > 0.5 ? 1 : 0;
                    rlist[k].Target = Convert.ToInt32(xy[i, nvars]);

                    k++;
                }

                Array.Sort(rlist, (o1, o2) => (1 - o1.Prob).CompareTo(1 - o2.Prob));
                batch.OutBagEstimationsLogit = ResultCalc.GetResult(rlist, 0.05);
            }

            Logger.Log("accCoeff: " + accCoeff + "; bag:" + batch.OutBagEstimations.AUC + "; logit:" + batch.OutBagEstimationsLogit?.AUC);
        }
Exemple #14
0
 /// <summary>
 /// Полный расчет метрик качества классификации на тестовом множестве
 /// c учетом очередного классификатора
 /// </summary>
 /// <returns>Результат классификации</returns>
 private FinalFuncResult GetTrainMetricsAccumulated(DecisionBatch cls)
 {
     _nbTrain += UseBatchLogit ? 1 : cls.CountTreesInBatch; // обновляем общее кол-во деревьев
     return(GetMetricsAccumulated(cls, _trainProbSum, _trainProbAvg, _trainResult, _nbTrain, GetTrainClassificationCounts));
 }
Exemple #15
0
        /// <summary>
        /// build and test classifier
        /// </summary>
        public override ClassifierResult Build()
        {
            if (_trainLoader?.LearnRows == null)
            {
                throw new InvalidOperationException("train set is empty");
            }

            Clear();
            var ret = new ClassifierResult();

            using (var sw = new StreamWriter(new FileStream("auchist.csv", FileMode.Create, FileAccess.Write)))
            {
                sw.WriteLine("time;n;train auc;test auc;stype");

                // создаем первые классификаторы (first step)
                for (int i = 0; i < BatchesInFirstStep; i++)
                {
                    DecisionBatch cls;
                    if (IsLoadFirstStepBatches)
                    {
                        cls = DecisionBatch.Load(Environment.CurrentDirectory + "\\batches\\" + "batch_" + $"{i:0000.#}" + ".dmp");
                        if (cls == null)
                        {
                            cls = DecisionBatch.CreateBatch(_trainLoader.LearnRows, TreesInBatch, _nclasses, RfCoeff,
                                                            VarsCoeff, null, IsParallel, UseBatchLogit);
                            if (IsSaveTrees)
                            {
                                cls.Save();
                            }
                        }
                    }
                    else
                    {
                        cls = DecisionBatch.CreateBatch(_trainLoader.LearnRows, TreesInBatch, _nclasses, RfCoeff,
                                                        VarsCoeff, null, IsParallel, UseBatchLogit);
                        if (IsSaveTrees)
                        {
                            cls.Save();
                        }
                    }

                    // расчитываем метрики для тестового и обучающего множества (накопленные)
                    var testRes  = GetTestMetricsAccumulated(cls);
                    var trainRes = GetTrainMetricsAccumulated(cls);

                    Logger.Log("batch=" + i + " ok; train AUC=" + trainRes.AUC.ToString("F10") + " test AUC = " + testRes.AUC.ToString("F10"));
                    sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ";" + i + ";" + trainRes.AUC + ";" + testRes.AUC + ";none");
                    sw.Flush();

                    ret.AddStepResult(testRes, i);
                }

                // далее создаем классификаторы с учетом ошибки предыдущих (second step)
                int totalBatches = BatchesInFirstStep + BatchesInSecondStep;
                for (int i = BatchesInFirstStep; i < totalBatches; i++)
                {
                    DecisionBatch bestBatch = null;

                    // перестраиваем индексы плохо классифицированных объектов (плохие сначала)
                    RefreshIndexes();

                    double bestMetric = double.MaxValue;

                    // строим классификаторы и выбираем лучший
                    for (int k = 0; k < BatchesInBruteForce; k++)
                    {
                        var scls = DecisionBatch.CreateBatch(_trainLoader.LearnRows, TreesInBatch, _nclasses, RfCoeff,
                                                             VarsCoeff, _indexes, IsParallel, UseBatchLogit);

                        // расчитываем метрики для тестового множества
                        var trainCntRes = GetTrainClassificationCounts(scls);
                        int cnt         = UseBatchLogit ? 1 : scls.CountTreesInBatch;

                        var rlist = new RocItem[_trainResult.Count]; // массив для оценки результата
                                                                     // находим статистики классификации
                        int    idx    = 0;
                        double accerr = 0.0;
                        foreach (string id in _trainResult.Keys)
                        {
                            if (rlist[idx] == null)
                            {
                                rlist[idx] = new RocItem();
                            }

                            rlist[idx].Prob      = trainCntRes[id] / cnt; // среднее по наблюдениям
                            rlist[idx].Target    = _trainResult[id];
                            rlist[idx].Predicted = rlist[idx].Prob > 0.5 ? 1 : 0;

                            //accerr += Math.Pow(rlist[idx].Prob - rlist[idx].Target, 2);

                            idx++;
                        }

                        Array.Sort(rlist, (o1, o2) => (1 - o1.Prob).CompareTo(1 - o2.Prob));
                        var clsRes = ResultCalc.GetResult(rlist, 0.05);

                        accerr = clsRes.LogLoss;

                        Logger.Log("sub cls #" + k + " auc=" + clsRes.AUC.ToString("F10") + " eps=" + accerr + (accerr < bestMetric ? " [best]" : ""));

                        if (accerr < bestMetric)
                        {
                            bestMetric = accerr;
                            bestBatch  = scls;
                        }
                    }


                    var testRes  = GetTestMetricsAccumulated(bestBatch);
                    var trainRes = GetTrainMetricsAccumulated(bestBatch);
                    if (IsSaveTrees)
                    {
                        if (bestBatch != null)
                        {
                            bestBatch.Save();
                        }
                        else
                        {
                            Logger.Log("best Batch is null");
                        }
                    }

                    ret.AddStepResult(testRes, i);
                    Logger.Log("batch=" + i + " ok; train AUC=" + trainRes.AUC.ToString("F10") + "; test AUC = " + testRes.AUC.ToString("F10"));
                    sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ";" + i + ";" + trainRes.AUC + ";" + testRes.AUC + ";" + IndexSortOrder);
                    sw.Flush();
                }

                sw.Close();
            }

            return(ret);
        }