Skip to content

Commit

Permalink
move ssa to rsvd
Browse files Browse the repository at this point in the history
  • Loading branch information
valer1435 committed Aug 21, 2023
1 parent 5e76abc commit 210ff64
Show file tree
Hide file tree
Showing 12 changed files with 712 additions and 610 deletions.
2 changes: 1 addition & 1 deletion examples/anomaly_detection/detection_classification.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def generate_colors(num_colors):
industrial = FedotIndustrial(task='ts_classification',
dataset='custom_dataset',
strategy='fedot_preset',
branch_nodes=['fourier_basis'],
branch_nodes=['data_driven_basis'],
use_cache=False,
timeout=1,
n_jobs=2,
Expand Down
6 changes: 1 addition & 5 deletions examples/ts_forecasting/with_decomposition.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,8 @@ def get_ts_data(dataset='australia', horizon: int = 30, validation_blocks=None):
train_data, test_data = get_ts_data('m4_weekly', 13)

with IndustrialModels():
# n, _ = WindowSizeSelection(time_series=train_data.features,
# wss_algorithm='dominant_fourier_frequency').get_window_size()
# print(n)
# n = 30
pipeline = PipelineBuilder().add_node('data_driven_basis_for_forecasting',
params={'n_components': 3, 'window_size': 20,
params={'window_size': 20,
'seasonality': 20
},
).build()
Expand Down
2 changes: 1 addition & 1 deletion fedot_ind/api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def __init_solver(self):
# solver = TaskEnum[self.config_dict['task']].value['nn']
else:
solver = TaskEnum[self.config_dict['task']].value['default']
if self.config_dict['task'] == 'ts_forecasting':
elif self.config_dict['task'] == 'ts_forecasting':
if self.config_dict['strategy'] == 'decomposition':
solver = TaskEnum[self.config_dict['task']].value['fedot_preset']

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
from fedot.core.repository.tasks import Task, TaskTypesEnum
from golem.core.tuning.simultaneous import SimultaneousTuner

from fedot_ind.core.architecture.postprocessing.Analyzer import PerformanceAnalyzer
from fedot_ind.core.architecture.utils.utils import default_path_to_save_results
from fedot_ind.api.utils.path_lib import default_path_to_save_results
from fedot_ind.core.metrics.evaluation import PerformanceAnalyzer
from fedot_ind.core.repository.initializer_industrial_models import IndustrialModels

np.random.seed(0)
Expand Down
5 changes: 3 additions & 2 deletions fedot_ind/core/architecture/settings/pipeline_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
from fedot_ind.core.models.recurrence.RecurrenceExtractor import RecurrenceExtractor
from fedot_ind.core.models.signal.SignalExtractor import SignalExtractor
from fedot_ind.core.models.topological.TopologicalExtractor import TopologicalExtractor
from fedot_ind.core.operation.implementation.basis.fourier import FourierBasisImplementation
from fedot_ind.core.operation.implementation.basis.wavelet import WaveletBasisImplementation
from fedot_ind.core.operation.transformation.basis.data_driven import DataDrivenBasisImplementation
from fedot_ind.core.operation.transformation.basis.fourier import FourierBasisImplementation
from fedot_ind.core.operation.transformation.basis.wavelet import WaveletBasisImplementation



class BasisTransformations(Enum):
Expand Down
5 changes: 1 addition & 4 deletions fedot_ind/core/operation/IndustrialCachableOperation.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,5 @@ def transform(self, input_data: InputData, use_cache: bool = False) -> OutputDat
predict = self._convert_to_output(input_data, predict, data_type=self.data_type)
return predict

def _transform(self, input_data) -> np.array:
"""
Method for feature generation for all series
"""
def _transform(self, input_data):
pass
68 changes: 33 additions & 35 deletions fedot_ind/core/operation/decomposition/SpectrumDecomposition.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
# -*- coding: utf-8 -*-
from typing import Optional

import numpy as np
import pandas as pd
import tensorly as tl
from pymonad.list import ListMonad
from tensorly.decomposition import parafac

from fedot_ind.core.operation.decomposition.matrix_decomposition.fast_svd import RSVDDecomposition
from fedot_ind.core.operation.transformation.data.eigen import combine_eigenvectors
from fedot_ind.core.operation.transformation.regularization.spectrum import singular_value_hard_threshold, \
reconstruct_basis
from fedot_ind.core.operation.transformation.regularization.spectrum import reconstruct_basis, \
singular_value_hard_threshold

supported_types = (pd.Series, np.ndarray, list)

Expand All @@ -24,45 +26,41 @@ class SpectrumDecomposer:
"""

def __init__(self, data, n_components, ts_length):
def __init__(self, data, ts_length, threshold: Optional[int] = None):
if type(data) == list:
rank = round(data[0].shape[0] / 10)
beta = data[0].shape[0] / data[0].shape[1]

window_size = data.shape[0]
self.svd_estimator = RSVDDecomposition()
self.low_rank_approximation = True

self.svd = lambda x: ListMonad(np.linalg.svd(x))
self.threshold = lambda Monoid: ListMonad([Monoid[0],
singular_value_hard_threshold(singular_values=Monoid[1],
beta=data.shape[0] / data.shape[1],
threshold=None),
Monoid[2]]) if n_components is None else ListMonad(
[Monoid[0][:, :n_components],
Monoid[1][
:n_components],
Monoid[2][:n_components, :]])
self.data_driven_basis = lambda Monoid: ListMonad(reconstruct_basis(Monoid[0],
Monoid[1],
Monoid[2],
ts_length=ts_length))
self.svd = lambda x: ListMonad(self.svd_estimator.rsvd(tensor=x,
approximation=self.low_rank_approximation,
regularized_rank=threshold))

self.tensor_decomposition = lambda x: ListMonad(parafac(tl.tensor(x), rank=rank).factors)
multi_threshold = lambda x: singular_value_hard_threshold(singular_values=x,
beta=beta,
threshold=None)
self.threshold = lambda Monoid: ListMonad([Monoid[0],
Monoid[1][:threshold],
Monoid[2]])

self.multi_threshold = lambda Monoid: ListMonad([Monoid[1],
list(map(multi_threshold, Monoid[0])),
Monoid[2].T]) if n_components is None else ListMonad(
[Monoid[1][
:,
:n_components],
Monoid[0][
:,
:n_components],
Monoid[2][
:,
:n_components].T])
list(map(lambda x: singular_value_hard_threshold(
singular_values=x,
beta=beta,
threshold=None), Monoid[0])),
Monoid[2].T]) if threshold is None else ListMonad([Monoid[1][
:,
:threshold],
Monoid[0][
:,
:threshold],
Monoid[2][
:,
:threshold].T])

self.data_driven_basis = lambda x: ListMonad(reconstruct_basis(x[0],
x[1],
x[2],
ts_length=ts_length))

self.tensor_decomposition = lambda x: ListMonad(parafac(tl.tensor(x), rank=rank).factors)

self.combine_components = lambda Monoid: ListMonad(
combine_eigenvectors(Monoid, window_length=window_size, correlation_level=0.6))
52 changes: 0 additions & 52 deletions fedot_ind/core/operation/implementation/basis/data_driven.py
Original file line number Diff line number Diff line change
@@ -1,52 +0,0 @@
from typing import Tuple, TypeVar, Optional

import numpy as np
from fedot.core.operations.operation_parameters import OperationParameters
from pymonad.either import Either

from fedot_ind.core.operation.decomposition.SpectrumDecomposition import SpectrumDecomposer
from fedot_ind.core.operation.implementation.basis.abstract_basis import BasisDecompositionImplementation
from fedot_ind.core.operation.transformation.data.hankel import HankelMatrix

class_type = TypeVar("T", bound="DataDrivenBasis")


class DataDrivenBasisImplementation(BasisDecompositionImplementation):
"""DataDriven basis
Example:
ts1 = np.random.rand(200)
ts2 = np.random.rand(200)
ts = [ts1, ts2]
bss = DataDrivenBasisImplementation({'n_components': 3, 'window_size': 30})
basis_multi = bss._transform(ts)
basis_1d = bss._transform(ts1)
"""

def __init__(self, params: Optional[OperationParameters] = None):
super().__init__(params)
self.n_components = params.get('n_components')
self.window_size = params.get('window_size')

self.decomposer = None
self.basis = None

def _transform_one_sample(self, series: np.array):
trajectory_transformer = HankelMatrix(time_series=series, window_size=self.window_size)
data = trajectory_transformer.trajectory_matrix
self.ts_length = trajectory_transformer.ts_length
self.decomposer = SpectrumDecomposer(data, self.n_components, self.ts_length)
return self._get_basis(data)

def _get_1d_basis(self, data):
basis = Either.insert(data).then(self.decomposer.svd).then(self.decomposer.threshold).then(
self.decomposer.data_driven_basis).value[0]

return np.swapaxes(basis, 1, 0)

def _get_multidim_basis(self, data):
basis = np.array(
Either.insert(data).then(self.decomposer.tensor_decomposition).then(self.decomposer.multi_threshold).then(
self.decomposer.data_driven_basis).value[0])
basis = basis.reshape(basis.shape[1], -1)
return basis

Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
from fedot_ind.core.models.quantile.quantile_extractor import QuantileExtractor
from fedot_ind.core.models.topological.TopologicalExtractor import TopologicalExtractor
from fedot_ind.core.operation.dummy.dummy_operation import DummyOperation
from fedot_ind.core.operation.implementation.basis.data_driven import DataDrivenBasisImplementation

from fedot_ind.core.operation.implementation.basis.fourier import FourierBasisImplementation
from fedot_ind.core.operation.implementation.basis.wavelet import WaveletBasisImplementation
from fedot_ind.core.operation.transformation.basis.data_driven import DataDrivenBasisImplementation

from fedot_ind.core.repository.IndustrialOperationParameters import IndustrialOperationParameters

Expand Down
Loading

0 comments on commit 210ff64

Please sign in to comment.