public double? Forecast(TimeSeries source, int horizon, ForecastSettings settings) { var i = source.timeseries.Count - 1; //это означает, что хотим получить прогноз для последнего значения в ряду var counter = i % timestampNumber; List<double> inputVector = createInputVector(i, source, settings, maxValues[counter], minValues[counter], timestampNumber); if (inputVector == null) return null; //не получилось if (networkSet.Count <= counter) return null; networkSet[counter].propagate(inputVector); var output = networkSet[counter].Outputs.First(); output = output*(maxValues[counter] - minValues[counter]) + minValues[counter]; return output; }
public onNeuralPredictionFilter(FilterParameters parameters, DateTime trainTill, DataExchange exchange = null) { this.exchange = exchange; this.waitUntil = trainTill; this.timeSeries = new TimeSeries(0); settings = new ForecastSettings(); for (int i = 0; i < 5; i++) { settings.energyLags.Add(i + 1); } model = new MultipleNeuralNetworksModel(); this.parameters = parameters; parameters.Values["model"] = model; }
public offPredictionFittingFilter(FilterParameters parameters, DateTime trainTill, Dictionary<string, int> time, DataExchange exchange = null) { this.exchange = exchange; this.time = time; this.waitUntil = trainTill; this.parameters = parameters; settings = new ForecastSettings(); for (int i = 0; i < 5; i++) { settings.energyLags.Add(i + 1); } for (int i = 0; i < PACKAGE_SIZE; i++) { timeSeriesEnsemble.Add(new TimeSeries(0)); } }
/// <summary> /// Тренировка модели. /// </summary> /// <param name="source">Подготовленный список значений для тренировки. /// "Подготовленность" заключается в том, что каждое значение списка содержит все значения в соответствующее время суток. /// Например, source[0] содержит все значения энергопотребления в 00:00, source[1] - в 00:15, и так далее. В данном примере длина списка будет равна 96.</param> /// <param name="settings">Настройки прогнозирования.</param> /// <param name="additionalTraining">Производится ли дообучение модели.</param> public void Train(List<TimeSeries> source, ForecastSettings settings, bool additionalTraining) { var trainSet = new List<StructuredDataSet>(); var cvSet = new List<StructuredDataSet>(); for (int i = 0; i < timestampNumber; i++) { trainSet.Add(new StructuredDataSet()); cvSet.Add(new StructuredDataSet()); double valueMax = 0; double valueMin = double.MaxValue; for (int day = 0; day < source[i].timeseries.Count; day++) { var value = source[i].timeseries[day]; valueMax = Math.Max(value, valueMax); valueMin = Math.Min(value, valueMin); } maxValues[i] = valueMax; minValues[i] = valueMin; trainSet[i].Pairs = new List<DataPair>(); //преобразуем то, что нужно в выборки данных. //формируем trainingset for (int time = settings.energyLags.Max(); time < source[i].timeseries.Count(); time++) { DataPair trainingPair = new DataPair(); trainingPair.InputVector = createInputVector(time, source[i], settings, maxValues[i], minValues[i], 1); trainingPair.OutputVector = createOutputVector(time, source[i], maxValues[i], minValues[i]); if(trainingPair.InputVector != null) trainSet[i].Pairs.Add(trainingPair); } if (trainSet[i].Pairs.Any()) { var neuralNetwork = new MultiLayersNN( trainSet[i].Pairs[0].InputVector.Count, trainSet[i].Pairs[0].OutputVector.Count, 4, new[] { trainSet[i].Pairs[0].InputVector.Count, 8, 8, trainSet[i].Pairs[0].OutputVector.Count }); neuralNetwork.trainNetwork(trainSet[i], 1000, 0.1, true); for (int e = 0; e < neuralNetwork.absoluteErrors.Count; e++) { //денормализация neuralNetwork.absoluteErrors[e] = (neuralNetwork.absoluteErrors[e] * (maxValues[i] - minValues[i]) + minValues[i]); } if (networkSet.Count <= i) networkSet.Add(neuralNetwork); else networkSet[i] = neuralNetwork; } } }
/// <summary> /// Извлечь входной вектор для обучения /// </summary> /// <param name="counter">Порядковый номер значения во временном ряду, которое будет прогнозироваться.</param> /// <param name="source">Временной ряд, из которого брать значения.</param> /// <param name="settings">Настройки прогнозирования.</param> /// <param name="_maxValue">Максимальное значение для данного времени суток.</param> /// <param name="_minValue">Минимальное значение для данного времени суток.</param> /// <param name="timestampNumber">Количество отсчетов в день.</param> /// <returns></returns> private List<double> createInputVector(int counter, TimeSeries source, ForecastSettings settings, double _maxValue, double _minValue, int timestampNumber) { //вычисляем нижнюю границу, т.е. минимальное количество ретроспективных значений, //необходимое для осуществления прогноза var minLength = settings.energyLags.Max() * timestampNumber; //если доступно значений меньше, чем нужно, то ничего не получится if (counter < minLength) return null; List<double> InputVector = new List<double>(); InputVector.Add(1.0); //это вот точно здесь нужно? зачем? for (int j = 0; j < settings.energyLags.Count; j++) { var energyValue = source.timeseries[counter - (settings.energyLags[j] * timestampNumber)]; var normalizedValue = _maxValue != _minValue ? (energyValue - _minValue)/(_maxValue - _minValue) : 0.5; InputVector.Add(normalizedValue); } return InputVector; }