Skip to content
This repository was archived by the owner on Nov 16, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/DotNetBridge/Bridge.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
using Microsoft.ML.Trainers.FastTree;
using Microsoft.ML.Trainers.LightGbm;
using Microsoft.ML.Transforms;
using Microsoft.ML.TimeSeries;
using Microsoft.ML.Transforms.TimeSeries;

namespace Microsoft.MachineLearning.DotNetBridge
{
Expand Down Expand Up @@ -329,7 +329,7 @@ private static unsafe int GenericExec(EnvironmentBlock* penv, sbyte* psz, int cd
//env.ComponentCatalog.RegisterAssembly(typeof(SaveOnnxCommand).Assembly);
//env.ComponentCatalog.RegisterAssembly(typeof(TimeSeriesProcessingEntryPoints).Assembly);
//env.ComponentCatalog.RegisterAssembly(typeof(ParquetLoader).Assembly);
env.ComponentCatalog.RegisterAssembly(typeof(ForecastExtensions).Assembly);
env.ComponentCatalog.RegisterAssembly(typeof(SsaChangePointDetector).Assembly);

using (var ch = host.Start("Executing"))
{
Expand Down
6 changes: 6 additions & 0 deletions src/python/nimbusml.pyproj
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
<Compile Include="nimbusml\examples\examples_from_dataframe\GlobalContrastRowScaler_df.py" />
<Compile Include="nimbusml\examples\examples_from_dataframe\Handler_df.py" />
<Compile Include="nimbusml\examples\examples_from_dataframe\IidChangePointDetector_df.py" />
<Compile Include="nimbusml\examples\examples_from_dataframe\SsaForecaster_df.py" />
<Compile Include="nimbusml\examples\examples_from_dataframe\SsaChangePointDetector_df.py" />
<Compile Include="nimbusml\examples\examples_from_dataframe\SsaSpikeDetector_df.py" />
<Compile Include="nimbusml\examples\examples_from_dataframe\Image_df.py" />
Expand Down Expand Up @@ -139,6 +140,7 @@
<Compile Include="nimbusml\examples\Handler.py" />
<Compile Include="nimbusml\examples\Hinge.py" />
<Compile Include="nimbusml\examples\IidChangePointDetector.py" />
<Compile Include="nimbusml\examples\SsaForecaster.py" />
<Compile Include="nimbusml\examples\SsaChangePointDetector.py" />
<Compile Include="nimbusml\examples\SsaSpikeDetector.py" />
<Compile Include="nimbusml\examples\Image.py" />
Expand Down Expand Up @@ -235,6 +237,7 @@
<Compile Include="nimbusml\internal\core\timeseries\iidchangepointdetector.py" />
<Compile Include="nimbusml\internal\core\timeseries\iidspikedetector.py" />
<Compile Include="nimbusml\internal\core\timeseries\ssachangepointdetector.py" />
<Compile Include="nimbusml\internal\core\timeseries\ssaforecaster.py" />
<Compile Include="nimbusml\internal\core\timeseries\ssaspikedetector.py" />
<Compile Include="nimbusml\internal\core\timeseries\__init__.py" />
<Compile Include="nimbusml\internal\entrypoints\data_customtextloader.py" />
Expand Down Expand Up @@ -277,6 +280,7 @@
<Compile Include="nimbusml\internal\entrypoints\timeseriesprocessingentrypoints_pvaluetransform.py" />
<Compile Include="nimbusml\internal\entrypoints\timeseriesprocessingentrypoints_slidingwindowtransform.py" />
<Compile Include="nimbusml\internal\entrypoints\timeseriesprocessingentrypoints_ssachangepointdetector.py" />
<Compile Include="nimbusml\internal\entrypoints\timeseriesprocessingentrypoints_ssaforecasting.py" />
<Compile Include="nimbusml\internal\entrypoints\timeseriesprocessingentrypoints_ssaspikedetector.py" />
<Compile Include="nimbusml\internal\entrypoints\trainers_averagedperceptronbinaryclassifier.py" />
<Compile Include="nimbusml\internal\entrypoints\trainers_fastforestbinaryclassifier.py" />
Expand Down Expand Up @@ -586,13 +590,15 @@
<Compile Include="nimbusml\tests\pipeline\test_pipeline_subclassing.py" />
<Compile Include="nimbusml\tests\preprocessing\normalization\test_meanvariancescaler.py" />
<Compile Include="nimbusml\tests\timeseries\test_iidchangepointdetector.py" />
<Compile Include="nimbusml\tests\timeseries\test_ssaforecaster.py" />
<Compile Include="nimbusml\tests\timeseries\test_ssachangepointdetector.py" />
<Compile Include="nimbusml\tests\timeseries\test_ssaspikedetector.py" />
<Compile Include="nimbusml\tests\timeseries\test_iidspikedetector.py" />
<Compile Include="nimbusml\tests\timeseries\__init__.py" />
<Compile Include="nimbusml\timeseries\iidchangepointdetector.py" />
<Compile Include="nimbusml\timeseries\iidspikedetector.py" />
<Compile Include="nimbusml\timeseries\ssachangepointdetector.py" />
<Compile Include="nimbusml\timeseries\ssaforecaster.py" />
<Compile Include="nimbusml\timeseries\ssaspikedetector.py" />
<Compile Include="nimbusml\timeseries\__init__.py" />
<Compile Include="tests\test_estimator_checks.py" />
Expand Down
47 changes: 47 additions & 0 deletions src/python/nimbusml/examples/SsaForecaster.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
###############################################################################
# SsaForecaster
import pandas as pd
from nimbusml import Pipeline, FileDataStream
from nimbusml.datasets import get_dataset
from nimbusml.timeseries import SsaForecaster

# data input (as a FileDataStream)
path = get_dataset('timeseries').as_filepath()

data = FileDataStream.read_csv(path)
print(data.head())
# t1 t2 t3
# 0 0.01 0.01 0.0100
# 1 0.02 0.02 0.0200
# 2 0.03 0.03 0.0200
# 3 0.03 0.03 0.0250
# 4 0.03 0.03 0.0005

# define the training pipeline
pipeline = Pipeline([
SsaForecaster(series_length=6,
train_size=8,
window_size=3,
horizon=2,
columns={'t2_fc': 't2'})
])

result = pipeline.fit_transform(data)

pd.set_option('display.float_format', lambda x: '%.2f' % x)
print(result)

# Output
#
# t1 t2 t3 t2_fc.0 t2_fc.1
# 0 0.01 0.01 0.01 0.10 0.12
# 1 0.02 0.02 0.02 0.06 0.08
# 2 0.03 0.03 0.02 0.04 0.05
# 3 0.03 0.03 0.03 0.05 0.06
# 4 0.03 0.03 0.00 0.05 0.07
# 5 0.03 0.05 0.01 0.06 0.08
# 6 0.05 0.07 0.05 0.09 0.12
# 7 0.07 0.09 0.09 0.12 0.16
# 8 0.09 99.00 99.00 57.92 82.88
# 9 1.10 0.10 0.10 60.50 77.18

Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
###############################################################################
# SsaForecaster
import numpy as np
import pandas as pd
from nimbusml.timeseries import SsaForecaster

# This example creates a time series (list of data with the
# i-th element corresponding to the i-th time slot).

# Generate sample series data with a recurring pattern
seasonality_size = 5
seasonal_data = np.arange(seasonality_size)

data = np.tile(seasonal_data, 3)
X_train = pd.Series(data, name="ts")

# X_train looks like this
# 0 0
# 1 1
# 2 2
# 3 3
# 4 4
# 5 0
# 6 1
# 7 2
# 8 3
# 9 4
# 10 0
# 11 1
# 12 2
# 13 3
# 14 4

x_test = X_train.copy()
x_test[-3:] = [100, 110, 120]

# x_test looks like this
# 0 0
# 1 1
# 2 2
# 3 3
# 4 4
# 5 0
# 6 1
# 7 2
# 8 3
# 9 4
# 10 0
# 11 1
# 12 100
# 13 110
# 14 120

training_seasons = 3
training_size = seasonality_size * training_seasons

forecaster = SsaForecaster(series_length=8,
train_size=training_size,
window_size=seasonality_size + 1,
horizon=4) << {'fc': 'ts'}

forecaster.fit(X_train, verbose=1)
data = forecaster.transform(x_test)

pd.set_option('display.float_format', lambda x: '%.2f' % x)
print(data)

# The fc.x columns are the forecasts
# given the input in the ts column.
#
# ts fc.0 fc.1 fc.2 fc.3
# 0 0 1.00 2.00 3.00 4.00
# 1 1 2.00 3.00 4.00 -0.00
# 2 2 3.00 4.00 -0.00 1.00
# 3 3 4.00 -0.00 1.00 2.00
# 4 4 -0.00 1.00 2.00 3.00
# 5 0 1.00 2.00 3.00 4.00
# 6 1 2.00 3.00 4.00 -0.00
# 7 2 3.00 4.00 -0.00 1.00
# 8 3 4.00 -0.00 1.00 2.00
# 9 4 -0.00 1.00 2.00 3.00
# 10 0 1.00 2.00 3.00 4.00
# 11 1 2.00 3.00 4.00 -0.00
# 12 100 3.00 4.00 0.00 1.00
# 13 110 4.00 -0.00 1.00 75.50
# 14 120 -0.00 1.00 83.67 83.25
141 changes: 141 additions & 0 deletions src/python/nimbusml/internal/core/timeseries/ssaforecaster.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
# --------------------------------------------------------------------------------------------
# - Generated by tools/entrypoint_compiler.py: do not edit by hand
"""
SsaForecaster
"""

__all__ = ["SsaForecaster"]


from ...entrypoints.timeseriesprocessingentrypoints_ssaforecasting import \
timeseriesprocessingentrypoints_ssaforecasting
from ...utils.utils import trace
from ..base_pipeline_item import BasePipelineItem, DefaultSignature


class SsaForecaster(BasePipelineItem, DefaultSignature):
"""
**Description**
This transform forecasts using Singular Spectrum Analysis (SSA).

:param window_size: The length of the window on the series for building the
trajectory matrix (parameter L).

:param series_length: The length of series that is kept in buffer for
modeling (parameter N).

:param train_size: The length of series from the begining used for
training.

:param horizon: The number of values to forecast.

:param confidence_level: The confidence level in [0, 1) for forecasting.

:param variable_horizon: Set this to true horizon will change at prediction
time.

:param confidence_lower_bound_column: The name of the confidence interval
lower bound column.

:param confidence_upper_bound_column: The name of the confidence interval
upper bound column.

:param rank_selection_method: The rank selection method.

:param rank: The desired rank of the subspace used for SSA projection
(parameter r). This parameter should be in the range in [1,
windowSize]. If set to null, the rank is automatically determined based
on prediction error minimization.

:param max_rank: The maximum rank considered during the rank selection
process. If not provided (i.e. set to null), it is set to windowSize -
1.

:param should_stabilize: The flag determining whether the model should be
stabilized.

:param should_maintain_info: The flag determining whether the meta
information for the model needs to be maintained.

:param max_growth: The maximum growth on the exponential trend.

:param discount_factor: The discount factor in [0,1] used for online
updates.

:param is_adaptive: The flag determing whether the model is adaptive.

:param params: Additional arguments sent to compute engine.

"""

@trace
def __init__(
self,
window_size=0,
series_length=0,
train_size=0,
horizon=0,
confidence_level=0.95,
variable_horizon=False,
confidence_lower_bound_column=None,
confidence_upper_bound_column=None,
rank_selection_method='Exact',
rank=None,
max_rank=None,
should_stabilize=True,
should_maintain_info=False,
max_growth=None,
discount_factor=1.0,
is_adaptive=False,
**params):
BasePipelineItem.__init__(
self, type='transform', **params)

self.window_size = window_size
self.series_length = series_length
self.train_size = train_size
self.horizon = horizon
self.confidence_level = confidence_level
self.variable_horizon = variable_horizon
self.confidence_lower_bound_column = confidence_lower_bound_column
self.confidence_upper_bound_column = confidence_upper_bound_column
self.rank_selection_method = rank_selection_method
self.rank = rank
self.max_rank = max_rank
self.should_stabilize = should_stabilize
self.should_maintain_info = should_maintain_info
self.max_growth = max_growth
self.discount_factor = discount_factor
self.is_adaptive = is_adaptive

@property
def _entrypoint(self):
return timeseriesprocessingentrypoints_ssaforecasting

@trace
def _get_node(self, **all_args):
algo_args = dict(
source=self.source,
name=self._name_or_source,
window_size=self.window_size,
series_length=self.series_length,
train_size=self.train_size,
horizon=self.horizon,
confidence_level=self.confidence_level,
variable_horizon=self.variable_horizon,
confidence_lower_bound_column=self.confidence_lower_bound_column,
confidence_upper_bound_column=self.confidence_upper_bound_column,
rank_selection_method=self.rank_selection_method,
rank=self.rank,
max_rank=self.max_rank,
should_stabilize=self.should_stabilize,
should_maintain_info=self.should_maintain_info,
max_growth=self.max_growth,
discount_factor=self.discount_factor,
is_adaptive=self.is_adaptive)

all_args.update(algo_args)
return self._entrypoint(**all_args)
Loading