NW.UnivariateForecasting
4.2.1
dotnet add package NW.UnivariateForecasting --version 4.2.1
NuGet\Install-Package NW.UnivariateForecasting -Version 4.2.1
<PackageReference Include="NW.UnivariateForecasting" Version="4.2.1" />
<PackageVersion Include="NW.UnivariateForecasting" Version="4.2.1" />
<PackageReference Include="NW.UnivariateForecasting" />
paket add NW.UnivariateForecasting --version 4.2.1
#r "nuget: NW.UnivariateForecasting, 4.2.1"
#:package NW.UnivariateForecasting@4.2.1
#addin nuget:?package=NW.UnivariateForecasting&version=4.2.1
#tool nuget:?package=NW.UnivariateForecasting&version=4.2.1
NW.UnivariateForecasting
NW.UnivariateForecasting is a library to perform univariate forecasting tasks on the values you provide.
Getting Started
If /home/nw.univariateforecasting is the folder in which the .nupkg file is located, you can install it using this command:
dotnet add package NW.UnivariateForecasting --source /home/nw.univariateforecasting
How Time Series Forecasting Works
Time Series Forecasting is a machine learning technique that aims to predict the next values in a time series when a subset of subsequent timestamped values is provided ("sliding window"). There is no other information available than the timestamp and the value itself.
For example, given the last six months of "Total Monthly Sales USD" of your company, you would like the machine to predict the amounts for the next x months.
Time Series Forecasting is divided in univariate and multivariate.
The first one can predict only one step ahead, while the second one can predict multiple steps ahead. As its name states, this library implements the univariate approach.
A good definition of univariate could be: "[...] univariate refers to an expression, equation, function or polynomial of only one variable [...] which consists of observations on only a single characteristic or attribute."
Univariate Forecasting In Action
In order to use the library, the first thing we need to do is to create a ForecastingInit object containing the initialization data and then pass it to the Forecast method of the a UnivariateForecaster object, as shown in the following example:
using System;
using System.Collections.Generic;
using NW.UnivariateForecasting;
using NW.UnivariateForecasting.Forecasts;
...
ForecastingInit init
= new ForecastingInit(
values: new List<double>() { 58.5, 615.26 },
steps: 1
observationName: null,
coefficient: null,
error: null
);
IUnivariateForecaster forecaster = new UnivariateForecaster();
ForecastingSession session = forecaster.Forecast(init);
...
Highlights:
valuesmust contains at least two items of a time serie of whatever kind;stepsrefers to the number ofsteps(how many values you want to forecast) and it must be at least one (obviously);- if provided,
coefficientanderrorwill overwrite the ones calculated by the library; observationNameis a (optional) label about whatvaluesrefer to
The output of the forecasting task will be a ForecastingSession object, which would look like the example below if instantiated manually:
ForecastingSession session
= new ForecastingSession(
init: new ForecastingInit(
values: new List<double>() { 58.5, 615.26 },
steps: 1
observationName: null,
coefficient: null,
error: null
),
observations: new List<Observation>() {
new Observation(
coefficient: 0.095081754055196,
error: 0,
nextValue: 58.49999999999989
)};
version: "4.0.0.0"
);
By default, the amounts calculated by the library (coefficient, error, ...) are rounded to the 15th decimal digit (the maximum amount of digits for the double amounts), but you might want to customize this aspect to improve readibility.
If so, you can inject a custom SettingBag object into the UnivariateForecaster object, as shown in the following example:
using System;
using System.Collections.Generic;
using NW.UnivariateForecasting;
using NW.UnivariateForecasting.Bags;
using NW.UnivariateForecasting.Forecasts;
...
ForecastingInit init
= new ForecastingInit(
values: new List<double>() { 58.5, 615.26 },
steps: 1
observationName: null,
coefficient: null,
error: null
);
SettingBag settingBag = new SettingBag(
forecastingDenominator: SettingBag.DefaultForecastingDenominator,
folderPath: SettingBag.DefaultFolderPath,
roundingDigits: 2
);
IUnivariateForecaster forecaster = new UnivariateForecaster(
componentBag: new ComponentBag(),
settingBag: settingBag
);
ForecastingSession session = forecaster.Forecast(init);
...
This code will output the following ForecastingSession object:
ForecastingSession session
= new ForecastingSession(
init: new ForecastingInit(
values: new List<double>() { 58.5, 615.26 },
steps: 1
observationName: null,
coefficient: null,
error: null
),
observations: new List<Observation>() {
new Observation(
coefficient: 0.1,
error: 0,
nextValue: 61.53
)};
version: "4.0.0.0"
);
The user will only interact with ForecastingInit and ForecastingSession objects, but the library will use a data structure known as SlidingWindow to internally organize and transfer data:
SlidingWindow slidingWindow = new SlidingWindow(
items: new List<SlidingWindowItem>() {
new SlidingWindowItem(id: 1, X_Actual: 58.5, Y_Forecasted: 615.26),
new SlidingWindowItem(id: 2, X_Actual: 615.26, Y_Forecasted: 659.84),
new SlidingWindowItem(id: 3, X_Actual: 659.84, Y_Forecasted: 635.69),
new SlidingWindowItem(id: 4, X_Actual: 635.69, Y_Forecasted: 612.27),
new SlidingWindowItem(id: 5, X_Actual: 612.27, Y_Forecasted: 632.94),
new SlidingWindowItem(id: 6, X_Actual: 632.94, Y_Forecasted: null)
});
The SlidingWindow object above corresponds to the following list of values:
List<double> values
= new[] { 58.50, 615.26, 659.84, 635.69, 612.27, 632.94 }.ToList();
Each SlidingWindowItem object has the following properties:
Idis a sequential identifier (a number works fine in this case)X_Actualis the current amountY_Forecastedis the next amount in the time series
The Y_Forecasted for the last *Item is [NULL] and it's the value we want to predict.
Once the SlidingWindow object is set, we are ready to perform the prediction itself, which will return an Observation object:
Observation observation
= new Observation(coefficient: 0.82, error: 0.22, nextValue: 519.23);
The original time series was: { 58.50, 615.26, 659.84, 635.69, 612.27, 632.94 }.
According to the univariate forecasting, the next value of the series will be: 519.23.
Side note: we could use Forecast to recursively add each Observation to the SlidingWindow and perform the forecast more than one step ahead, but obviously the predictions will be quite on the pessimistic side.
The Algorithm
Let's explain the algorithm on which the library is based by using an example.
This is our trusty SlidingWindow:
| Id | X_Actual | Y_Forecasted |
|---|---|---|
| 1 | 58,5 | 615,26 |
| 2 | 615,26 | 659,84 |
| 3 | 659,84 | 635,69 |
| 4 | 635,69 | 612,27 |
| 5 | 612,27 | 632,94 |
| 6 | 632,94 | [NULL] |
The first thing we do is to divide each X_Actual for the corresponding Y_Forecasted:
| Id | XByY |
|---|---|
| 1 | 0,1 |
| 2 | 0,93 |
| 3 | 1,04 |
| 4 | 1,04 |
| 5 | 0,97 |
Then, we do calculate C by averaging all the values in the XByY column:
| C |
|---|
| 0,82 |
At this point, we do substract C from each values in XByY:
| Id | (XByY)-C |
|---|---|
| 1 | -0,72 |
| 2 | 0,11 |
| 3 | 0,22 |
| 4 | 0,22 |
| 5 | 0,15 |
Calculating the MODE of (XByY)-C will return the error E:
| E |
|---|
| 0,22 |
The function to forecast the next value in the series is Y=F(X)+E, which can be expressed as Y=CX+E, where X is the actual value. Now that we have both C and E, it's just a matter of replacing them in the equation to obtain the Y_Forecasted value we are looking for:
| Y_Forecasted |
|---|
| 519,23 |
The library offers the possibility to skip all the calculations above and provide the C and E coefficients by yourself.
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- nw.shared.files (>= 1.0.0)
- nw.shared.serialization (>= 1.0.0)
- nw.shared.validation (>= 1.0.0)
- System.Text.Json (>= 8.0.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.