#include "stdafx.h" #include #include "Method.h" #include "Dsa.h" #include "Aic.h" #include "AicWeights.h" #include "Normalization.h" #include "Mape.h" #include "SMape.h" #include "Vovk.h" #include "NoTrendNoSeasonality.h" #include "NoTrendAddSeasonality.h" #include "NoTrendMultSeasonality.h" #include "AddTrendNoSeasonality.h" #include "AddTrendAddSeasonality.h" #include "AddTrendMultSeasonality.h" #include "MultTrendNoSeasonality.h" #include "MultTrendAddSeasonality.h" #include "MultTrendMultSeasonality.h" #include "DATrendNoSeasonality.h" #include "DATrendAddSeasonality.h" #include "DATrendMultSeasonality.h" #include "DMTrendNoSeasonality.h" #include "DMTrendAddSeasonality.h" #include "DMTrendMultSeasonality.h" #include "Tsaur.h" #include "A.h" #include "Fuzzy.h" #include "FuzzyWithSets.h" #include "File.h" #include #include "Param.h" #include #include #include #include #include #include "Transformation.h" #include "nlopt.hpp" #include "nlopt.h" #include "BIC.h" int iMethod; // номер текущего метода const int n = 29; // количество методов, чтоб лишнего памяти не жрать int numberParam; // число параметров у метода Method** m = new Method*[n]; Estimation* est1 = new SMape(); int ii; // счетчик итераций double round (double value) { return floor(value + 0.5); } double myRound(double num) { double n = ((double)round(num * 1000)) / 1000; return n; } void printTs(vector ts) { for (unsigned int i = 0; i < ts.size(); i++) { cout << ts[i]; cout << " "; } } double getEstimation(const std::vector &x, std::vector &grad, void *f_data) { ii++; // счетчик итераций int radix = 10; //система счисления char sbuffer[10]; //результат for (int iiParam = 0; iiParam < numberParam; iiParam++) { m[iMethod]->setParam(itoa(iiParam, sbuffer, radix), myRound(x[iiParam])); } m[iMethod]->createModelForEstimation(); double smapeValue = myRound(est1->getValue(m[iMethod]->x, m[iMethod]->getForecast())); return smapeValue; } int main(int argc, char* argv[]) { Param* bestParams = new Param(); double bestSmape = DBL_MAX; double bestAic = DBL_MAX; int bestMethodIndex = 0; setlocale(LC_ALL, "Russian"); string path; string fileName; string s; if (argc < 1) { cout << "set ts file like 'project_template.exe 1.csv count_forecast period!!!"; return 0; } else { stringstream ss; ss << argv[1]; ss >> s; int found = 0; int offset =0; do { found = s.find("\\", found +1); if (found > 0) { offset = found; cout << found << "\n"; } } while (found!=std::string::npos); if (offset ==0) { fileName = s.substr(offset, s.length()); } else { fileName = s.substr(offset+1, s.length()); } path = s.substr(0, offset); } // объект для работы с файлами: загрузить и сохранить ВР vector timeSeries = File::readFile(argv[1]); Transformation *transform = new Transformation(timeSeries); transform->seasonalPeriod = atof(argv[3]); // timeSeries = transform->Normalization(); //transform->setTimeSeries(tsTransform); transform->lambdaEstimation(); timeSeries = transform->ModifiedBoxCox(); Normalization * norm = new Normalization(); //timeSeries = norm->normalizeTimeSeria(timeSeries); // сколько точек будем прогнозировать int pointForecast = 18; if (strcmp(argv[2], "") != 0) { pointForecast = atof(argv[2]); } int p = 12; if (strcmp(argv[3], "") != 0) { p = atof(argv[3]); } double alpha = 0.1; double delta = 0.2; double gamma = 0.4; double phi = 0.1; int countRulesIn = 1; int countFuzzyParts = 2; // далее задаем параметры, специфичные для методов //... // так как использовать будем все методы (или объединять в коллективы) нужно // все их проинициализировать и загнать в массив m[0] = new NoTrendNoSeasonality(timeSeries, pointForecast); m[1] = new NoTrendAddSeasonality(timeSeries, pointForecast); m[2] = new NoTrendMultSeasonality(timeSeries, pointForecast); m[3] = new AddTrendNoSeasonality(timeSeries, pointForecast); m[4] = new MultTrendNoSeasonality(timeSeries, pointForecast); m[5] = new DATrendNoSeasonality(timeSeries, pointForecast); m[6] = new DMTrendNoSeasonality(timeSeries, pointForecast); m[7] = new AddTrendAddSeasonality(timeSeries, pointForecast); m[8] = new MultTrendAddSeasonality(timeSeries, pointForecast); m[9] = new DATrendAddSeasonality(timeSeries, pointForecast); m[10] = new DMTrendAddSeasonality(timeSeries, pointForecast); m[11] = new AddTrendMultSeasonality(timeSeries, pointForecast); m[12] = new MultTrendMultSeasonality(timeSeries, pointForecast); m[13] = new DATrendMultSeasonality(timeSeries, pointForecast); m[14] = new DMTrendMultSeasonality(timeSeries, pointForecast); m[15] = new Dsa(timeSeries, pointForecast); m[16] = new Fuzzy("None", "None", timeSeries, pointForecast); m[17] = new Fuzzy("Add", "None", timeSeries, pointForecast); m[18] = new Fuzzy("None", "Add", timeSeries, pointForecast); m[19] = new Fuzzy("Add", "Add", timeSeries, pointForecast); m[20] = new FuzzyWithSets("None", "None", timeSeries, pointForecast); m[21] = new FuzzyWithSets("None", "Add", timeSeries, pointForecast); m[22] = new FuzzyWithSets("None", "Mult", timeSeries, pointForecast); m[23] = new FuzzyWithSets("Add", "None", timeSeries, pointForecast); m[24] = new FuzzyWithSets("Add", "Add", timeSeries, pointForecast); m[25] = new FuzzyWithSets("Add", "Mult", timeSeries, pointForecast); m[26] = new FuzzyWithSets("Mult", "None", timeSeries, pointForecast); m[27] = new FuzzyWithSets("Mult", "Add", timeSeries, pointForecast); m[28] = new FuzzyWithSets("Mult", "Mult", timeSeries, pointForecast); //m[29] = new Tsaur(timeSeries, pointForecast); AicWeights *aicWeights = new AicWeights(); vector aicValues; vector> modelsResults; vector optimal; string smapeResults = ""; for (int i = 15; i < n; i++) { iMethod = i; m[i]->setParam("p", p); // вызовем метод оптимизации одного параметра //Estimation *est1 = new SMape(); Estimation *est1 = new Bic(algoritm::RMSE, m[i]->getNamberParam()); //optimal.push_back(m[i]->optimize(est1)); numberParam = m[i]->getNamberParam(); if (numberParam == 1) // для одного параметра проще перебор по сетке { optimal.push_back(m[i]->optimize(est1)); m[i]->setParam("alpha", optimal[optimal.size()-1]->alpha); } else { // вектора для начальных, минимальных и максимальных значений параметров std::vector x(numberParam); std::vector lb(numberParam); std::vector ub(numberParam); // устанавливаем параметры for (int iParam = 0; iParam < numberParam; iParam++) { lb[iParam] = 0.01; // минимальное значение параметра ub[iParam] = 0.99; // максимальное значение переметра x[iParam] = 0.3; // начальное значение параметра } // создаем основной метод оптимизации nlopt::opt opt(nlopt::AUGLAG, numberParam); // создаем вспомагательный метод оптимизации nlopt::opt subOpt(nlopt::GN_ORIG_DIRECT_L, numberParam); subOpt.set_lower_bounds(lb); subOpt.set_upper_bounds(ub); // устанавливаем параметры основного метода оптимизации opt.set_lower_bounds(lb); opt.set_upper_bounds(ub); opt.set_local_optimizer(subOpt); // в зависимости от числа параметров, устанавливаем количество итераций оптимизации if (numberParam == 2) { subOpt.set_maxeval(10000); opt.set_maxeval(10000); } else if (numberParam == 3) { subOpt.set_maxeval(50000); opt.set_maxeval(50000); } else { subOpt.set_maxeval(100000); opt.set_maxeval(100000); } // запускаем оптимизацию // getEstimation - метод в самом вверху, котрый возвращает ошибку на каждой итерации double minf; opt.set_min_objective(getEstimation, NULL); nlopt::result subResult = opt.optimize(x, minf); cout << minf << endl; // попытаемся улучшить параметры nlopt::opt ssubOpt(nlopt::LN_NELDERMEAD, numberParam); ssubOpt.set_lower_bounds(lb); ssubOpt.set_upper_bounds(ub); ssubOpt.set_maxeval(500); ssubOpt.set_min_objective(getEstimation, NULL); nlopt::result Result = ssubOpt.optimize(x, minf); cout << minf << endl; if (m[i]->getNamberParam() > 1) { optimal.push_back(new Param()); } optimal[optimal.size()-1]->countFuzzyParts = x[0] * 100; optimal[optimal.size()-1]->countRulesIn = x[1] * 5; if (i == 15) { optimal[optimal.size()-1]->sizeLabels = x[2] * 100; } else { optimal[optimal.size()-1]->gamma = x[2]; } if (m[i]->getNamberParam() > 3) { optimal[optimal.size()-1]->delta = x[3]; if (m[i]->getNamberParam() > 4) { optimal[optimal.size()-1]->alpha = x[4]; } } // в векторе x найденные параметры, в min - smape } // создаем модель для тестирования при помощи выбранного метода // задаем параметры m[i]->setParam("alpha", optimal[optimal.size()-1]->alpha); m[i]->setParam("gamma", optimal[optimal.size()-1]->gamma); m[i]->setParam("delta", optimal[optimal.size()-1]->delta); m[i]->setParam("phi", optimal[optimal.size()-1]->phi); m[i]->setParam("countRulesIn", optimal[optimal.size()-1]->countRulesIn); m[i]->setParam("countFuzzyParts", optimal[optimal.size()-1]->countFuzzyParts); m[i]->setParam("lb1", optimal[optimal.size()-1]->lb1); m[i]->setParam("rb1", optimal[optimal.size()-1]->rb1); m[i]->setParam("lb2", optimal[optimal.size()-1]->lb2); m[i]->setParam("rb2", optimal[optimal.size()-1]->rb2); m[i]->setParam("sizeLabels", optimal[optimal.size()-1]->sizeLabels); // создаем модель m[i]->createModelForEstimation(); // вычисляем ошибку //aicValues.push_back(aic->getValue(4, m[i]->getXEstimation(), m[i]->getForecast())); //aicValues.push_back(aic->getAiccValue(4, m[i]->getXEstimation(), m[i]->getForecast())); //aicValues.push_back(aic->getBicValue(4, m[i]->getXEstimation(), m[i]->getForecast())); //modelsResults.push_back(m[i]->getForecast()); SMape* smape = new SMape(); stringstream ss1; ss1 << i; string str1 = ss1.str(); stringstream ss2; double sm = smape->getValue(m[i]->x, m[i]->getForecast()); double ai = optimal[optimal.size()-1]->estim; ss2 << sm; // определяем, являются ли данные параметры лучшими if (ai < bestAic) { bestAic = ai; bestParams = optimal[optimal.size()-1]; bestMethodIndex = i; } string str2 = ss2.str(); smapeResults = smapeResults + "Smape for " + str1 + " method: " + str2 + " "; smapeResults = smapeResults + optimal[optimal.size()-1]->toString() + "\n"; // создаем модель при помощи выбранного метода // получим и сохраним прогноз string target = path +"\\"+ fileName+"result"; _mkdir(target.c_str()); string fileNameOut = target + "\\"; char suff[3]; itoa(i, suff, 10); fileNameOut.append(suff); fileNameOut.append("out"); m[i]->createModel(); //File::writeFile(fileNameOut, norm->deNormalizeTimeSeria(m[i]->getForecast())); //transform->setTimeSeries(m[i]->getForecast()); //transform->setTimeSeries(transform->invModifiedBoxCox()); transform->setTimeSeries(m[i]->getForecast()); File::writeFile(fileNameOut, transform->invModifiedBoxCox()); } Method* bestMethod = m[bestMethodIndex]; // после того, как отработали все модели // задаем лучшие параметры bestMethod->setParam("alpha", bestParams->alpha); bestMethod->setParam("gamma", bestParams->gamma); bestMethod->setParam("delta", bestParams->delta); bestMethod->setParam("phi", bestParams->phi); bestMethod->setParam("countRulesIn", bestParams->countRulesIn); bestMethod->setParam("countFuzzyParts", bestParams->countFuzzyParts); bestMethod->setParam("lb1", bestParams->lb1); bestMethod->setParam("rb1", bestParams->rb1); bestMethod->setParam("lb2", bestParams->lb2); bestMethod->setParam("rb2", bestParams->rb2); bestMethod->setParam("sizeLabels", bestParams->sizeLabels); bestMethod->createModel(); string target = path +"\\"+ fileName+"result"; string fileNameOut = target + "\\"; fileNameOut.append("best"); char _s[3]; itoa(bestMethodIndex, _s, 10); fileNameOut.append(_s); //File::writeFile(fileNameOut, norm->deNormalizeTimeSeria(bestMethod->getForecast())); transform->setTimeSeries(bestMethod->getForecast()); File::writeFile(fileNameOut, transform->invModifiedBoxCox()); string smapeFileName = path +"\\"+ fileName+"result\\smape"; FILE * file = fopen(smapeFileName.c_str(), "w"); if (file) // если есть доступ к файлу, { bool result = fputs(smapeResults.c_str(), file); // и записываем ее в файл if (!result) // если запись произошла успешно cout << "Строка в файл успешно записана!"; // выводим сообщение fclose(file); } return 0; Vovk *vovk = new Vovk(timeSeries, pointForecast, m); vector res; res.push_back(vovk->getForecast()); for (int i = 0; i < pointForecast - 1; i++){ //cout << i + 1 << " " << vovk->getForecast() << endl; vovk->updateTS(res[res.size() - 1]); res.push_back(vovk->getForecast()); } res = norm->deNormalizeTimeSeria(res); for (int i = 0; i < pointForecast - 1; i++){ cout << i + 1 << " " << res[i] << endl; } SMape *smape = new SMape(); cout << "Smape for Vovk " << " method: " << smape->getValue(norm->deNormalizeTimeSeria(m[0]->getXEstimation()), res) << "\n"; vector weights = aicWeights->calculateWeights(aicValues); vector fuzzyAdoptiveWeights = aicWeights->calculateFuzzyAdaptiveWeights(timeSeries, modelsResults); cout << "Smape for etalon forecast " << " method: " << smape->getValue(m[21]->getXEstimation(), m[21]->getXEstimation()) << "\n"; delete(m); return 0; }