#2 -- fix forecasting
This commit is contained in:
parent
be9a761f0f
commit
85c4b3cad8
35
src/main/java/ru/ulstu/TimeSeriesUtils.java
Normal file
35
src/main/java/ru/ulstu/TimeSeriesUtils.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package ru.ulstu;
|
||||||
|
|
||||||
|
import ru.ulstu.models.TimeSeries;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
|
||||||
|
public class TimeSeriesUtils {
|
||||||
|
/**
|
||||||
|
* Вычисляет среднее значение между датами временного ряда
|
||||||
|
*
|
||||||
|
* @param timeSeries объект, содержащий временной ряд
|
||||||
|
* @return средняя разница между датами исходного временного ряда в миллисекундах
|
||||||
|
*/
|
||||||
|
public static long getTimeDifferenceInMilliseconds(TimeSeries timeSeries) {
|
||||||
|
long diffMilliseconds = 0;
|
||||||
|
for (int i = 1; i < timeSeries.getLength(); i++) {
|
||||||
|
diffMilliseconds += timeSeries.getValues().get(i - 1).getDate()
|
||||||
|
.until(timeSeries.getValues().get(i).getDate(), ChronoUnit.MILLIS);
|
||||||
|
}
|
||||||
|
return diffMilliseconds / (timeSeries.getLength() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TimeSeries fillDates(TimeSeries timeSeries, long milliseconds) {
|
||||||
|
timeSeries.getLastValue().setDate(LocalDateTime.now());
|
||||||
|
for (int i = timeSeries.getLength() - 2; i >= 0; i--) {
|
||||||
|
timeSeries.getValues().get(i).setDate(timeSeries.getValues().get(i + 1).getDate().minus(milliseconds, ChronoUnit.MILLIS));
|
||||||
|
}
|
||||||
|
return timeSeries;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TimeSeries fillDates(TimeSeries timeSeries) {
|
||||||
|
return fillDates(timeSeries, 1000 * 60 * 60 * 24);
|
||||||
|
}
|
||||||
|
}
|
@ -38,6 +38,18 @@ public class TimeSeriesController {
|
|||||||
return new ResponseEntity<>(timeSeriesService.getRandomTimeSeries(length), HttpStatus.OK);
|
return new ResponseEntity<>(timeSeriesService.getRandomTimeSeries(length), HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("getFromString")
|
||||||
|
@ApiOperation("Преобразовать строку с разделителями во временной ряд")
|
||||||
|
public ResponseEntity<TimeSeries> getTimeSeriesFromString(@RequestParam("tsString") String tsString) {
|
||||||
|
return new ResponseEntity<>(timeSeriesService.getTimeSeriesFromString(tsString), HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("timeSeriesToString")
|
||||||
|
@ApiOperation("Преобразовать временной ряд в строку с разделителями")
|
||||||
|
public ResponseEntity<String> getTimeSeriesToString(@RequestBody TimeSeries timeSeries) {
|
||||||
|
return new ResponseEntity<>(timeSeriesService.getTimeSeriesToString(timeSeries), HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("getForecast")
|
@PostMapping("getForecast")
|
||||||
@ApiOperation("Получить прогноз временного ряда")
|
@ApiOperation("Получить прогноз временного ряда")
|
||||||
public ResponseEntity<Forecast> getForecastTimeSeries(@RequestBody ForecastParams forecastParams) throws ModelingException {
|
public ResponseEntity<Forecast> getForecastTimeSeries(@RequestBody ForecastParams forecastParams) throws ModelingException {
|
||||||
|
@ -24,6 +24,10 @@ public class TimeSeries {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TimeSeries(List<TimeSeriesValue> values) {
|
||||||
|
this.values = values;
|
||||||
|
}
|
||||||
|
|
||||||
public List<TimeSeriesValue> getValues() {
|
public List<TimeSeriesValue> getValues() {
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,10 @@ public class TimeSeriesValue {
|
|||||||
this.date = date;
|
this.date = date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TimeSeriesValue(Double value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
public LocalDateTime getDate() {
|
public LocalDateTime getDate() {
|
||||||
return date;
|
return date;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package ru.ulstu.services;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import ru.ulstu.TimeSeriesUtils;
|
||||||
import ru.ulstu.models.Forecast;
|
import ru.ulstu.models.Forecast;
|
||||||
import ru.ulstu.models.TimeSeries;
|
import ru.ulstu.models.TimeSeries;
|
||||||
import ru.ulstu.models.TimeSeriesValue;
|
import ru.ulstu.models.TimeSeriesValue;
|
||||||
@ -10,6 +11,9 @@ import ru.ulstu.models.exceptions.ModelingException;
|
|||||||
import ru.ulstu.tsMethods.exponential.NoTrendNoSeason;
|
import ru.ulstu.tsMethods.exponential.NoTrendNoSeason;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@ -27,7 +31,34 @@ public class TimeSeriesService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Forecast getForecast(TimeSeries timeSeries, int countPoints) throws ModelingException {
|
public Forecast getForecast(TimeSeries timeSeries, int countPoints) throws ModelingException {
|
||||||
NoTrendNoSeason nn = new NoTrendNoSeason(0.1);
|
NoTrendNoSeason nn = new NoTrendNoSeason(0.8);
|
||||||
return nn.getForecast(timeSeries, countPoints);
|
return nn.getForecast(timeSeries, countPoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TimeSeries getTimeSeriesFromString(String tsString) {
|
||||||
|
List<TimeSeriesValue> tsValues = Arrays.stream(tsString.split("\n"))
|
||||||
|
.flatMap(v -> Arrays.stream(v.split(";")))
|
||||||
|
.flatMap(v -> Arrays.stream(v.split(",")))
|
||||||
|
.flatMap(v -> Arrays.stream(v.split("<br>")))
|
||||||
|
.filter(v -> {
|
||||||
|
try {
|
||||||
|
Double.parseDouble(v);
|
||||||
|
return true;
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map(Double::parseDouble)
|
||||||
|
.map(TimeSeriesValue::new)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
return TimeSeriesUtils.fillDates(new TimeSeries(tsValues));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTimeSeriesToString(TimeSeries timeSeries) {
|
||||||
|
return timeSeries
|
||||||
|
.getValues()
|
||||||
|
.stream()
|
||||||
|
.map(v -> v.getValue().toString().replaceAll("\\.", ","))
|
||||||
|
.collect(Collectors.joining(";"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package ru.ulstu.tsMethods;
|
package ru.ulstu.tsMethods;
|
||||||
|
|
||||||
|
import ru.ulstu.TimeSeriesUtils;
|
||||||
import ru.ulstu.models.Forecast;
|
import ru.ulstu.models.Forecast;
|
||||||
import ru.ulstu.models.Model;
|
import ru.ulstu.models.Model;
|
||||||
import ru.ulstu.models.TimeSeries;
|
import ru.ulstu.models.TimeSeries;
|
||||||
@ -8,8 +9,6 @@ import ru.ulstu.models.exceptions.ForecastValidateException;
|
|||||||
import ru.ulstu.models.exceptions.ModelingException;
|
import ru.ulstu.models.exceptions.ModelingException;
|
||||||
import ru.ulstu.models.exceptions.TimeSeriesValidateException;
|
import ru.ulstu.models.exceptions.TimeSeriesValidateException;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.time.ZoneId;
|
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,7 +57,7 @@ public abstract class TimeSeriesMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Выполняет построение прогноза ждя уже сгенерированных будущих точек временного ряда.
|
* Выполняет построение прогноза для уже сгенерированных будущих точек временного ряда.
|
||||||
*
|
*
|
||||||
* @param forecast Заготовка прогноза временного ряда с пустыми значениями
|
* @param forecast Заготовка прогноза временного ряда с пустыми значениями
|
||||||
* @return
|
* @return
|
||||||
@ -66,14 +65,7 @@ public abstract class TimeSeriesMethod {
|
|||||||
protected abstract Forecast makeForecast(Forecast forecast);
|
protected abstract Forecast makeForecast(Forecast forecast);
|
||||||
|
|
||||||
protected Forecast generateEmptyForecastPoints(Forecast forecast, int countPointForecast) {
|
protected Forecast generateEmptyForecastPoints(Forecast forecast, int countPointForecast) {
|
||||||
long diffMilliseconds = getTimeDifferenceInMilliseconds(forecast);
|
long diffMilliseconds = TimeSeriesUtils.getTimeDifferenceInMilliseconds(forecast.getModel().getOriginalTimeSeries());
|
||||||
LocalDateTime lastTimeSeriesDateTime = forecast
|
|
||||||
.getModel()
|
|
||||||
.getOriginalTimeSeries()
|
|
||||||
.getLastValue()
|
|
||||||
.getDate()
|
|
||||||
.atZone(ZoneId.systemDefault())
|
|
||||||
.toLocalDateTime();
|
|
||||||
forecast.getForecastTimeSeries()
|
forecast.getForecastTimeSeries()
|
||||||
.addValue(new TimeSeriesValue(forecast.getModel().getModelTimeSeries().getLastValue().getDate()));
|
.addValue(new TimeSeriesValue(forecast.getModel().getModelTimeSeries().getLastValue().getDate()));
|
||||||
for (int i = 1; i < countPointForecast + 1; i++) {
|
for (int i = 1; i < countPointForecast + 1; i++) {
|
||||||
@ -83,21 +75,6 @@ public abstract class TimeSeriesMethod {
|
|||||||
return forecast;
|
return forecast;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Вычисляет среднее значение между датами исходного временного ряда
|
|
||||||
*
|
|
||||||
* @param forecast объект, содержащий результат прогнозирования
|
|
||||||
* @return средняя разница между датами исходного временного ряда в миллисекундах
|
|
||||||
*/
|
|
||||||
protected long getTimeDifferenceInMilliseconds(Forecast forecast) {
|
|
||||||
long diffMilliseconds = 0;
|
|
||||||
for (int i = 1; i < forecast.getModel().getOriginalTimeSeries().getLength(); i++) {
|
|
||||||
diffMilliseconds += forecast.getModel().getOriginalTimeSeries().getValues().get(i - 1).getDate()
|
|
||||||
.until(forecast.getModel().getOriginalTimeSeries().getValues().get(i).getDate(), ChronoUnit.MILLIS);
|
|
||||||
}
|
|
||||||
return diffMilliseconds / (forecast.getModel().getOriginalTimeSeries().getLength() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Выполняет построение модели и прогноза временного ряда. Даты спрогнозированных точек будут сгенерированы
|
* Выполняет построение модели и прогноза временного ряда. Даты спрогнозированных точек будут сгенерированы
|
||||||
* по модельным точкам.
|
* по модельным точкам.
|
||||||
|
@ -34,7 +34,7 @@ public class NoTrendNoSeason extends TimeSeriesMethod {
|
|||||||
forecast.getForecastTimeSeries()
|
forecast.getForecastTimeSeries()
|
||||||
.getValues()
|
.getValues()
|
||||||
.get(t)
|
.get(t)
|
||||||
.setValue(alpha * forecast.getForecastTimeSeries().getValues().get(t - 1).getValue());
|
.setValue(forecast.getForecastTimeSeries().getValues().get(t - 1).getValue());
|
||||||
}
|
}
|
||||||
return forecast;
|
return forecast;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user