Esempio n. 1
0
        /// <summary>
        /// Перестройка индексов для определения объектов, которые плохо классифицтрованы
        /// </summary>
        private void RefreshIndexes()
        {
            int rowsCnt = _trainResult.Count;

            // находим разницы между реальными значениями и прогнозными в train-set
            _errors = new Dictionary<string, double>();
            var rlist = new RocItem[rowsCnt]; // массив для оценки результата

            double sumdiff = 0;
            int i = 0;
            foreach (var k in _trainResult.Keys)
            {
                double tprob = _trainProbAvg[k];
                int targ = _trainResult[k];
                double diff = Math.Abs(tprob - targ);
                sumdiff += diff;

                _errors.Add(k, diff);

                rlist[i] = new RocItem();
                rlist[i].Prob = tprob;
                rlist[i].Target = targ;
                rlist[i].Predicted = tprob > 0.5 ? 1 : 0;

                i++;
            }

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

            Logger.Log("cl auc=" + clres.AUC.ToString("F10") + "; loss=" + clres.LogLoss.ToString("F10") + "; sumdiff=" + sumdiff);

            // сортируем индексы
            KeyValuePair<string, double>[] sarr = null;
            if (IndexSortOrder==null || (IndexSortOrder.ToLower()!="desc" && IndexSortOrder.ToLower()!="asc"))
            {
                sarr = new KeyValuePair<string, double>[rowsCnt];
                for (int l=0;l<sarr.Length;l++)
                    sarr[l] = new KeyValuePair<string, double>(l.ToString(), l);
            }
            else
            {
                if (IndexSortOrder.ToLower() == "desc")
                {
                    sarr = _errors.OrderByDescending(t => t.Value).ToArray();

                    int outliersCnt = (int)(sarr.Length * OutliersPrct);
                    for (int s = 0; s < outliersCnt; s++)
                        sarr[s] = new KeyValuePair<string, FType>(sarr[s].Key, -1);

                    sarr = sarr.OrderByDescending(t => t.Value).ToArray();
                }
                if (IndexSortOrder.ToLower() == "asc")
                    sarr = _errors.OrderBy(t => t.Value).ToArray();
            }

            _indexes = new int[rowsCnt];
            i = 0;
            if (sarr == null)
            {
                Logger.Log("sarr is null");
                return;
            }
            foreach (var kvp in sarr)
                _indexes[i++] = Convert.ToInt32(double.Parse(kvp.Key));
        }
Esempio n. 2
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;
        }
Esempio n. 3
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);
        }
Esempio n. 4
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 *= (1 - clsRes.AUC);

                        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;
        }
Esempio n. 5
0
        public override ClassifierResult Build()
        {
            //For this example (and indeed, many scenarios), the default
            //parameters will suffice.
            Parameter parameters = new Parameter();
            double C;
            double Gamma;

            //This will do a grid optimization to find the best parameters
            //and store them in C and Gamma, outputting the entire
            //search to params.txt.

            ParameterSelection.Grid(_trainProblem, parameters, "params.txt", out C, out Gamma);
            parameters.C = C;
            parameters.Gamma = Gamma;

            //Train the model using the optimal parameters.

            _model = Training.Train(_trainProblem, parameters);

            // пробегаем по всем клиентски данным и сохраняем результат
            var probDictList = new Dictionary<string, Dictionary<int, double>>();
            foreach (string id in _testDataDict.Keys)
            {
                if (!probDictList.ContainsKey(id))
                    probDictList.Add(id, new Dictionary<int, double>());

                foreach (var sarr in _testDataDict[id])
                {
                    var y = PredictProba(sarr);

                    double prob = y.Probs[1];
                    int kmax = probDictList[id].Keys.Count == 0 ? 0 : probDictList[id].Keys.Max() + 1;
                    probDictList[id].Add(kmax, prob);
                }
            }

            // вероятность дефолта определяется как среднее по записям для клиента
            var probDict = new Dictionary<string, double>();
            foreach (var id in probDictList.Keys)
            {
                int cnt = probDictList[id].Keys.Count();
                double prob = 0;
                foreach (var d in probDictList[id].Keys)
                {
                    prob += probDictList[id][d];
                }

                if (!probDict.ContainsKey(id))
                    probDict.Add(id, prob / cnt);
            }

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

                rlist[idx].Prob = probDict[id]; // среднее по наблюдениям
                rlist[idx].Target = _resultDict[id];
                rlist[idx].Predicted = 0;

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

            var clsRes = new ClassifierResult();
            clsRes.BestResult = cres;
            clsRes.LastResult = cres;
            clsRes.ResDict.Add(0, cres);

            return clsRes;
        }