From 2ddc5b4b05048cfb5a90b895cab3655a3bbae396 Mon Sep 17 00:00:00 2001 From: Wenjie Du Date: Fri, 5 May 2023 20:42:22 +0800 Subject: [PATCH 1/6] docs: update docs; --- docs/index.rst | 12 +++--------- docs/install.rst | 9 ++++----- docs/pypots.classification.rst | 3 --- docs/pypots.clustering.rst | 3 --- docs/pypots.data.rst | 30 ------------------------------ docs/pypots.forecasting.rst | 3 --- docs/pypots.imputation.rst | 3 --- docs/pypots.rst | 1 + docs/pypots.utils.rst | 12 +++++++++--- 9 files changed, 17 insertions(+), 59 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 2fd6fa0a..b5997255 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -71,6 +71,7 @@ Welcome to PyPOTS docs! ----------------- + ⦿ `Motivation`: Due to all kinds of reasons like failure of collection sensors, communication error, and unexpected malfunction, missing values are common to see in time series from the real-world environment. This makes partially-observed time series (POTS) a pervasive problem in open-world modeling and prevents advanced data analysis. Although this problem is important, the area of data mining on POTS still lacks a dedicated toolkit. PyPOTS is created to fill in this blank. ⦿ `Mission`: PyPOTS is born to become a handy toolbox that is going to make data mining on POTS easy rather than tedious, to help engineers and researchers focus more on the core problems in their hands rather than on how to deal with the missing parts in their data. PyPOTS will keep integrating classical and the latest state-of-the-art data mining algorithms for partially-observed multivariate time series. For sure, besides various algorithms, PyPOTS is going to have unified APIs together with detailed documentation and interactive examples across algorithms as tutorials. @@ -96,17 +97,10 @@ The rest of this readme file is organized as follows: ❖ Installation ^^^^^^^^^^^^^^^ -PyPOTS now is available on `Anaconda `_ ❗️ - -Install it with ``conda install pypots``, you may need to specify the channel with option ``-c conda-forge`` - -Install the latest release from PyPI: - - pip install pypots +PyPOTS is available on both `PyPI `_ and `Anaconda `_ ❗️ -or install from the source code with the latest features not officially released in a version: +Refer to the page `Installation `_ to see how to install PyPOTS. - pip install https://github.com/WenjieDu/PyPOTS/archive/main.zip ❖ Usage ^^^^^^^^ diff --git a/docs/install.rst b/docs/install.rst index fa638016..9f8324b0 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -12,20 +12,19 @@ It is recommended to use **pip** or **conda** for PyPOTS installation as shown b # by pip pip install pypots # the first time installation - pip install --upgrade pypots # update pypots if needed + pip install --upgrade pypots # update pypots to the latest version .. code-block:: bash # by conda - conda install -c conda-forge pypots + conda install -c conda-forge pypots # the first time installation + conda update -c conda-forge pypots # update pypots to the latest version Alternatively, you can install from the latest source code which may be not officially released yet: .. code-block:: bash - git clone https://github.com/WenjieDu/PyPOTS PyPOTS_latest --depth 1 - cd PyPOTS_latest - pip install . + pip install https://github.com/WenjieDu/PyPOTS/archive/main.zip Required Dependencies """"""""""""""""""""" diff --git a/docs/pypots.classification.rst b/docs/pypots.classification.rst index e0443e2f..741d5828 100644 --- a/docs/pypots.classification.rst +++ b/docs/pypots.classification.rst @@ -1,9 +1,6 @@ pypots.classification package ============================= -Submodules ----------- - pypots.classification.base module --------------------------------- diff --git a/docs/pypots.clustering.rst b/docs/pypots.clustering.rst index 3569bbde..4ea71a7c 100644 --- a/docs/pypots.clustering.rst +++ b/docs/pypots.clustering.rst @@ -1,9 +1,6 @@ pypots.clustering package ========================= -Submodules ----------- - pypots.clustering.base module ----------------------------- diff --git a/docs/pypots.data.rst b/docs/pypots.data.rst index a2a88346..e7bc7d9d 100644 --- a/docs/pypots.data.rst +++ b/docs/pypots.data.rst @@ -1,9 +1,6 @@ pypots.data package =================== -Submodules ----------- - pypots.data.base module ----------------------- @@ -13,33 +10,6 @@ pypots.data.base module :show-inheritance: :inherited-members: -pypots.data.dataset\_for\_brits module --------------------------------------- - -.. automodule:: pypots.data.dataset_for_brits - :members: - :undoc-members: - :show-inheritance: - :inherited-members: - -pypots.data.dataset\_for\_grud module -------------------------------------- - -.. automodule:: pypots.data.dataset_for_grud - :members: - :undoc-members: - :show-inheritance: - :inherited-members: - -pypots.data.dataset\_for\_mit module ------------------------------------- - -.. automodule:: pypots.data.dataset_for_mit - :members: - :undoc-members: - :show-inheritance: - :inherited-members: - pypots.data.generating module ----------------------------- diff --git a/docs/pypots.forecasting.rst b/docs/pypots.forecasting.rst index 3e7299f6..51d2296e 100644 --- a/docs/pypots.forecasting.rst +++ b/docs/pypots.forecasting.rst @@ -1,9 +1,6 @@ pypots.forecasting package ========================== -Submodules ----------- - pypots.forecasting.base module ------------------------------ diff --git a/docs/pypots.imputation.rst b/docs/pypots.imputation.rst index 71f3525d..a43fea0d 100644 --- a/docs/pypots.imputation.rst +++ b/docs/pypots.imputation.rst @@ -1,9 +1,6 @@ pypots.imputation package ========================= -Submodules ----------- - pypots.imputation.base module ----------------------------- diff --git a/docs/pypots.rst b/docs/pypots.rst index ff430d0d..8b71dfee 100644 --- a/docs/pypots.rst +++ b/docs/pypots.rst @@ -8,6 +8,7 @@ Subpackages :maxdepth: 4 pypots.classification + pypots.cli pypots.clustering pypots.data pypots.forecasting diff --git a/docs/pypots.utils.rst b/docs/pypots.utils.rst index 2331064f..69190c91 100644 --- a/docs/pypots.utils.rst +++ b/docs/pypots.utils.rst @@ -1,9 +1,6 @@ pypots.utils package ==================== -Submodules ----------- - pypots.utils.files module ------------------------- @@ -31,6 +28,15 @@ pypots.utils.metrics module :show-inheritance: :inherited-members: +pypots.utils.random module +-------------------------- + +.. automodule:: pypots.utils.random + :members: + :undoc-members: + :show-inheritance: + :inherited-members: + Module contents --------------- From 9ee11487727911f659e6ae79d9722c516b9d4c2f Mon Sep 17 00:00:00 2001 From: Wenjie Du Date: Fri, 5 May 2023 21:12:02 +0800 Subject: [PATCH 2/6] refactor: rename some internal functions, and rename `module.py` to `modules.py`; --- docs/pypots.cli.rst | 56 +++++++++++++++++++ pypots/base.py | 18 ++---- pypots/classification/base.py | 6 +- pypots/classification/brits/model.py | 24 +------- pypots/classification/brits/modules.py | 35 ++++++++++++ pypots/classification/grud/model.py | 4 +- pypots/classification/raindrop/model.py | 4 +- .../raindrop/{module.py => modules.py} | 0 pypots/clustering/crli/model.py | 10 ++-- .../clustering/crli/{module.py => modules.py} | 2 +- pypots/clustering/vader/model.py | 14 +++-- .../vader/{module.py => modules.py} | 0 pypots/data/base.py | 4 +- pypots/forecasting/base.py | 4 +- pypots/forecasting/bttf/__init__.py | 2 +- pypots/forecasting/bttf/model.py | 2 +- .../bttf/{module.py => modules.py} | 0 pypots/imputation/base.py | 6 +- pypots/imputation/brits/model.py | 4 +- .../brits/{module.py => modules.py} | 0 pypots/imputation/locf/model.py | 2 +- pypots/imputation/saits/model.py | 4 +- pypots/imputation/transformer/model.py | 4 +- .../transformer/{module.py => modules.py} | 0 24 files changed, 136 insertions(+), 69 deletions(-) create mode 100644 docs/pypots.cli.rst create mode 100644 pypots/classification/brits/modules.py rename pypots/classification/raindrop/{module.py => modules.py} (100%) rename pypots/clustering/crli/{module.py => modules.py} (99%) rename pypots/clustering/vader/{module.py => modules.py} (100%) rename pypots/forecasting/bttf/{module.py => modules.py} (100%) rename pypots/imputation/brits/{module.py => modules.py} (100%) rename pypots/imputation/transformer/{module.py => modules.py} (100%) diff --git a/docs/pypots.cli.rst b/docs/pypots.cli.rst new file mode 100644 index 00000000..72789211 --- /dev/null +++ b/docs/pypots.cli.rst @@ -0,0 +1,56 @@ +pypots.cli package +================== + +pypots.cli.base module +---------------------- + +.. automodule:: pypots.cli.base + :members: + :undoc-members: + :show-inheritance: + :inherited-members: + +pypots.cli.dev module +--------------------- + +.. automodule:: pypots.cli.dev + :members: + :undoc-members: + :show-inheritance: + :inherited-members: + +pypots.cli.doc module +--------------------- + +.. automodule:: pypots.cli.doc + :members: + :undoc-members: + :show-inheritance: + :inherited-members: + +pypots.cli.env module +--------------------- + +.. automodule:: pypots.cli.env + :members: + :undoc-members: + :show-inheritance: + :inherited-members: + +pypots.cli.pypots\_cli module +----------------------------- + +.. automodule:: pypots.cli.pypots_cli + :members: + :undoc-members: + :show-inheritance: + :inherited-members: + +Module contents +--------------- + +.. automodule:: pypots.cli + :members: + :undoc-members: + :show-inheritance: + :inherited-members: diff --git a/pypots/base.py b/pypots/base.py index fd983cf9..e3e91ddc 100644 --- a/pypots/base.py +++ b/pypots/base.py @@ -54,22 +54,16 @@ class BaseModel(ABC): """ - # leverage typing to show type hints in IDEs - # SAVING_STRATEGY = Literal["best", "better"] - SAVING_STRATEGY = [None, "best", "better"] - def __init__( self, device: Optional[Union[str, torch.device]] = None, saving_path: str = None, model_saving_strategy: Optional[str] = "best", ): - - assert model_saving_strategy in [ - None, - "best", - "better", - ], f"saving_strategy must be one of {self.SAVING_STRATEGY}, but got f{model_saving_strategy}." + saving_strategies = [None, "best", "better"] + assert ( + model_saving_strategy in saving_strategies + ), f"saving_strategy must be one of {saving_strategies}, but got f{model_saving_strategy}." self.device = None self.saving_path = saving_path @@ -121,7 +115,7 @@ def __init__( f"the tensorboard file will be saved to {tb_saving_path}" ) - def save_log_into_tb_file(self, step: int, stage: str, loss_dict: dict) -> None: + def _save_log_into_tb_file(self, step: int, stage: str, loss_dict: dict) -> None: """Saving training logs into the tensorboard file specified by the given path `tb_file_saving_path`. Parameters @@ -190,7 +184,7 @@ def save_model( f'Failed to save the model to "{saving_path}" because of the below error! \n{e}' ) - def auto_save_model_if_necessary( + def _auto_save_model_if_necessary( self, training_finished: bool = True, saving_name: str = None, diff --git a/pypots/classification/base.py b/pypots/classification/base.py index cb099147..35592b49 100644 --- a/pypots/classification/base.py +++ b/pypots/classification/base.py @@ -211,7 +211,7 @@ def _train_model( # save training loss logs into the tensorboard file for every step if in need if self.summary_writer is not None: - self.save_log_into_tb_file(training_step, "training", results) + self._save_log_into_tb_file(training_step, "training", results) # mean training loss of the current epoch mean_train_loss = np.mean(epoch_train_loss_collector) @@ -232,7 +232,7 @@ def _train_model( val_loss_dict = { "classification_loss": mean_val_loss, } - self.save_log_into_tb_file(epoch, "validating", val_loss_dict) + self._save_log_into_tb_file(epoch, "validating", val_loss_dict) logger.info( f"epoch {epoch}: " @@ -249,7 +249,7 @@ def _train_model( self.best_model_dict = self.model.state_dict() self.patience = self.original_patience # save the model if necessary - self.auto_save_model_if_necessary( + self._auto_save_model_if_necessary( training_finished=False, saving_name=f"{self.__class__.__name__}_epoch{epoch}_loss{mean_loss}", ) diff --git a/pypots/classification/brits/model.py b/pypots/classification/brits/model.py index 0a9c5100..c68851ee 100644 --- a/pypots/classification/brits/model.py +++ b/pypots/classification/brits/model.py @@ -14,32 +14,12 @@ from pypots.classification.base import BaseNNClassifier from pypots.classification.brits.dataset import DatasetForBRITS +from pypots.classification.brits.modules import RITS from pypots.imputation.brits.model import ( - RITS as imputation_RITS, _BRITS as imputation_BRITS, ) -class RITS(imputation_RITS): - def __init__( - self, - n_steps: int, - n_features: int, - rnn_hidden_size: int, - n_classes: int, - device: Union[str, torch.device], - ): - super().__init__(n_steps, n_features, rnn_hidden_size, device) - self.dropout = nn.Dropout(p=0.25) - self.classifier = nn.Linear(self.rnn_hidden_size, n_classes) - - def forward(self, inputs: dict, direction: str = "forward") -> dict: - ret_dict = super().forward(inputs, direction) - logits = self.classifier(ret_dict["final_hidden_state"]) - ret_dict["prediction"] = torch.softmax(logits, dim=1) - return ret_dict - - class _BRITS(imputation_BRITS, nn.Module): def __init__( self, @@ -361,7 +341,7 @@ def fit( self.model.eval() # set the model as eval status to freeze it. # Step 3: save the model if necessary - self.auto_save_model_if_necessary(training_finished=True) + self._auto_save_model_if_necessary(training_finished=True) def classify(self, X: Union[dict, str], file_type: str = "h5py"): """Classify the input data with the trained model. diff --git a/pypots/classification/brits/modules.py b/pypots/classification/brits/modules.py new file mode 100644 index 00000000..81e9d6a1 --- /dev/null +++ b/pypots/classification/brits/modules.py @@ -0,0 +1,35 @@ +""" +PyTorch BRITS model for both the time-series imputation task and the classification task. +""" + +# Created by Wenjie Du +# License: GPL-v3 + +from typing import Union + +import torch +import torch.nn as nn + +from pypots.imputation.brits.model import ( + RITS as imputation_RITS, +) + + +class RITS(imputation_RITS): + def __init__( + self, + n_steps: int, + n_features: int, + rnn_hidden_size: int, + n_classes: int, + device: Union[str, torch.device], + ): + super().__init__(n_steps, n_features, rnn_hidden_size, device) + self.dropout = nn.Dropout(p=0.25) + self.classifier = nn.Linear(self.rnn_hidden_size, n_classes) + + def forward(self, inputs: dict, direction: str = "forward") -> dict: + ret_dict = super().forward(inputs, direction) + logits = self.classifier(ret_dict["final_hidden_state"]) + ret_dict["prediction"] = torch.softmax(logits, dim=1) + return ret_dict diff --git a/pypots/classification/grud/model.py b/pypots/classification/grud/model.py index 36a5473d..2456aedb 100644 --- a/pypots/classification/grud/model.py +++ b/pypots/classification/grud/model.py @@ -16,7 +16,7 @@ from pypots.classification.base import BaseNNClassifier from pypots.classification.grud.dataset import DatasetForGRUD -from pypots.imputation.brits.module import TemporalDecay +from pypots.imputation.brits.modules import TemporalDecay class _GRUD(nn.Module): @@ -311,7 +311,7 @@ def fit( self.model.eval() # set the model as eval status to freeze it. # Step 3: save the model if necessary - self.auto_save_model_if_necessary(training_finished=True) + self._auto_save_model_if_necessary(training_finished=True) def classify(self, X: Union[dict, str], file_type: str = "h5py") -> np.ndarray: """Classify the input data with the trained model. diff --git a/pypots/classification/raindrop/model.py b/pypots/classification/raindrop/model.py index 31a44819..51f479d4 100644 --- a/pypots/classification/raindrop/model.py +++ b/pypots/classification/raindrop/model.py @@ -25,7 +25,7 @@ from pypots.classification.base import BaseNNClassifier from pypots.classification.grud.dataset import DatasetForGRUD -from pypots.classification.raindrop.module import ( +from pypots.classification.raindrop.modules import ( PositionalEncoding, ObservationPropagation, ) @@ -517,7 +517,7 @@ def fit( self.model.eval() # set the model as eval status to freeze it. # Step 3: save the model if necessary - self.auto_save_model_if_necessary(training_finished=True) + self._auto_save_model_if_necessary(training_finished=True) def classify(self, X: Union[dict, str], file_type: str = "h5py") -> np.ndarray: """Classify the input data with the trained model. diff --git a/pypots/classification/raindrop/module.py b/pypots/classification/raindrop/modules.py similarity index 100% rename from pypots/classification/raindrop/module.py rename to pypots/classification/raindrop/modules.py diff --git a/pypots/clustering/crli/model.py b/pypots/clustering/crli/model.py index 0846340d..0997cb8f 100644 --- a/pypots/clustering/crli/model.py +++ b/pypots/clustering/crli/model.py @@ -1,7 +1,7 @@ """ Torch implementation of CRLI (Clustering Representation Learning on Incomplete time-series data). -Please refer to :cite:``ma2021CRLI``. +Please refer to :cite:`ma2021CRLI`. """ # Created by Wenjie Du @@ -18,7 +18,7 @@ from pypots.clustering.base import BaseNNClusterer from pypots.clustering.crli.dataset import DatasetForCRLI -from pypots.clustering.crli.module import Generator, Decoder, Discriminator +from pypots.clustering.crli.modules import Generator, Decoder, Discriminator from pypots.utils.logging import logger from pypots.utils.metrics import cal_mse @@ -292,7 +292,7 @@ def _train_model( "generation_loss": mean_step_train_G_loss, "discrimination_loss": mean_step_train_D_loss, } - self.save_log_into_tb_file( + self._save_log_into_tb_file( training_step, "training", loss_results ) mean_epoch_train_D_loss = np.mean(epoch_train_loss_D_collector) @@ -309,7 +309,7 @@ def _train_model( self.best_model_dict = self.model.state_dict() self.patience = self.original_patience # save the model if necessary - self.auto_save_model_if_necessary( + self._auto_save_model_if_necessary( training_finished=False, saving_name=f"{self.__class__.__name__}_epoch{epoch}_loss{mean_loss}", ) @@ -376,7 +376,7 @@ def fit( self.model.eval() # set the model as eval status to freeze it. # Step 3: save the model if necessary - self.auto_save_model_if_necessary(training_finished=True) + self._auto_save_model_if_necessary(training_finished=True) def cluster( self, diff --git a/pypots/clustering/crli/module.py b/pypots/clustering/crli/modules.py similarity index 99% rename from pypots/clustering/crli/module.py rename to pypots/clustering/crli/modules.py index 414c7b99..d99a7045 100644 --- a/pypots/clustering/crli/module.py +++ b/pypots/clustering/crli/modules.py @@ -1,7 +1,7 @@ """ Torch implementation of CRLI (Clustering Representation Learning on Incomplete time-series data). -Please refer to :cite:``ma2021CRLI``. +Please refer to :cite:`ma2021CRLI` for details. """ # Created by Wenjie Du diff --git a/pypots/clustering/vader/model.py b/pypots/clustering/vader/model.py index f7bab566..60b80c28 100644 --- a/pypots/clustering/vader/model.py +++ b/pypots/clustering/vader/model.py @@ -19,7 +19,7 @@ from torch.utils.data import DataLoader from pypots.clustering.base import BaseNNClusterer -from pypots.clustering.vader.module import ( +from pypots.clustering.vader.modules import ( GMMLayer, PeepholeLSTMCell, ImplicitImputation, @@ -412,7 +412,9 @@ def _train_model( # save pre-training loss logs into the tensorboard file for every step if in need if self.summary_writer is not None: - self.save_log_into_tb_file(pretraining_step, "pretraining", results) + self._save_log_into_tb_file( + pretraining_step, "pretraining", results + ) with torch.no_grad(): sample_collector = [] @@ -485,7 +487,7 @@ def _train_model( # save training loss logs into the tensorboard file for every step if in need if self.summary_writer is not None: - self.save_log_into_tb_file(training_step, "training", results) + self._save_log_into_tb_file(training_step, "training", results) # mean training loss of the current epoch mean_train_loss = np.mean(epoch_train_loss_collector) @@ -506,7 +508,7 @@ def _train_model( val_loss_dict = { "loss": mean_val_loss, } - self.save_log_into_tb_file(epoch, "validating", val_loss_dict) + self._save_log_into_tb_file(epoch, "validating", val_loss_dict) logger.info( f"epoch {epoch}: " @@ -523,7 +525,7 @@ def _train_model( self.best_model_dict = self.model.state_dict() self.patience = self.original_patience # save the model if necessary - self.auto_save_model_if_necessary( + self._auto_save_model_if_necessary( training_finished=False, saving_name=f"{self.__class__.__name__}_epoch{epoch}_loss{mean_loss}", ) @@ -594,7 +596,7 @@ def fit( self.model.eval() # set the model as eval status to freeze it. # Step 3: save the model if necessary - self.auto_save_model_if_necessary(training_finished=True) + self._auto_save_model_if_necessary(training_finished=True) def cluster(self, X: Union[dict, str], file_type: str = "h5py") -> np.ndarray: """Cluster the input with the trained model. diff --git a/pypots/clustering/vader/module.py b/pypots/clustering/vader/modules.py similarity index 100% rename from pypots/clustering/vader/module.py rename to pypots/clustering/vader/modules.py diff --git a/pypots/data/base.py b/pypots/data/base.py index 77179b52..46839b25 100644 --- a/pypots/data/base.py +++ b/pypots/data/base.py @@ -72,7 +72,7 @@ def __init__( else: # data from array X = data["X"] y = None if "y" not in data.keys() else data["y"] - self.X, self.y = self.check_input(X, y) + self.X, self.y = self._check_input(X, y) self.sample_num = self._get_sample_num() @@ -103,7 +103,7 @@ def __len__(self) -> int: return self.sample_num @staticmethod - def check_input( + def _check_input( X: Union[np.ndarray, torch.Tensor, list], y: Optional[Union[np.ndarray, torch.Tensor, list]] = None, out_dtype: str = "tensor", diff --git a/pypots/forecasting/base.py b/pypots/forecasting/base.py index dba5b4c0..9eba9f19 100644 --- a/pypots/forecasting/base.py +++ b/pypots/forecasting/base.py @@ -198,7 +198,7 @@ def _train_model( # save training loss logs into the tensorboard file for every step if in need if self.summary_writer is not None: - self.save_log_into_tb_file(training_step, "training", results) + self._save_log_into_tb_file(training_step, "training", results) # mean training loss of the current epoch mean_train_loss = np.mean(epoch_train_loss_collector) @@ -219,7 +219,7 @@ def _train_model( val_loss_dict = { "imputation_loss": mean_val_loss, } - self.save_log_into_tb_file(epoch, "validating", val_loss_dict) + self._save_log_into_tb_file(epoch, "validating", val_loss_dict) logger.info( f"epoch {epoch}: " diff --git a/pypots/forecasting/bttf/__init__.py b/pypots/forecasting/bttf/__init__.py index d2c05519..67c07aa6 100644 --- a/pypots/forecasting/bttf/__init__.py +++ b/pypots/forecasting/bttf/__init__.py @@ -1,5 +1,5 @@ """ - +The package for BTTF model . """ # Created by Wenjie Du diff --git a/pypots/forecasting/bttf/model.py b/pypots/forecasting/bttf/model.py index 166360de..222f368d 100644 --- a/pypots/forecasting/bttf/model.py +++ b/pypots/forecasting/bttf/model.py @@ -17,7 +17,7 @@ from scipy.linalg import khatri_rao as kr_prod from pypots.forecasting.base import BaseForecaster -from pypots.forecasting.bttf.module import ( +from pypots.forecasting.bttf.modules import ( mvnrnd_pre, ten2mat, sample_factor_u, diff --git a/pypots/forecasting/bttf/module.py b/pypots/forecasting/bttf/modules.py similarity index 100% rename from pypots/forecasting/bttf/module.py rename to pypots/forecasting/bttf/modules.py diff --git a/pypots/imputation/base.py b/pypots/imputation/base.py index 1a690fe7..65155303 100644 --- a/pypots/imputation/base.py +++ b/pypots/imputation/base.py @@ -250,7 +250,7 @@ def _train_model( # save training loss logs into the tensorboard file for every step if in need if self.summary_writer is not None: - self.save_log_into_tb_file(training_step, "training", results) + self._save_log_into_tb_file(training_step, "training", results) # mean training loss of the current epoch mean_train_loss = np.mean(epoch_train_loss_collector) @@ -279,7 +279,7 @@ def _train_model( val_loss_dict = { "imputation_loss": mean_val_loss, } - self.save_log_into_tb_file(epoch, "validating", val_loss_dict) + self._save_log_into_tb_file(epoch, "validating", val_loss_dict) logger.info( f"epoch {epoch}: " @@ -296,7 +296,7 @@ def _train_model( self.best_model_dict = self.model.state_dict() self.patience = self.original_patience # save the model if necessary - self.auto_save_model_if_necessary( + self._auto_save_model_if_necessary( training_finished=False, saving_name=f"{self.__class__.__name__}_epoch{epoch}_loss{mean_loss}", ) diff --git a/pypots/imputation/brits/model.py b/pypots/imputation/brits/model.py index 34623933..41c40880 100644 --- a/pypots/imputation/brits/model.py +++ b/pypots/imputation/brits/model.py @@ -19,7 +19,7 @@ from pypots.imputation.base import BaseNNImputer from pypots.imputation.brits.dataset import DatasetForBRITS -from pypots.imputation.brits.module import TemporalDecay, FeatureRegression +from pypots.imputation.brits.modules import TemporalDecay, FeatureRegression from pypots.utils.metrics import cal_mae @@ -581,7 +581,7 @@ def fit( self.model.eval() # set the model as eval status to freeze it. # Step 3: save the model if necessary - self.auto_save_model_if_necessary(training_finished=True) + self._auto_save_model_if_necessary(training_finished=True) def impute( self, diff --git a/pypots/imputation/brits/module.py b/pypots/imputation/brits/modules.py similarity index 100% rename from pypots/imputation/brits/module.py rename to pypots/imputation/brits/modules.py diff --git a/pypots/imputation/locf/model.py b/pypots/imputation/locf/model.py index bd718ee2..88c3ff8f 100644 --- a/pypots/imputation/locf/model.py +++ b/pypots/imputation/locf/model.py @@ -17,7 +17,7 @@ class LOCF(BaseImputer): """LOCF (Last Observed Carried Forward) imputation method. - Attributes + Parameters ---------- nan : int/float Value used to impute data missing at the beginning of the sequence. diff --git a/pypots/imputation/saits/model.py b/pypots/imputation/saits/model.py index 9ec902ff..fd738e9a 100644 --- a/pypots/imputation/saits/model.py +++ b/pypots/imputation/saits/model.py @@ -21,7 +21,7 @@ from pypots.data.base import BaseDataset from pypots.imputation.base import BaseNNImputer from pypots.imputation.saits.dataset import DatasetForSAITS -from pypots.imputation.transformer.module import EncoderLayer, PositionalEncoding +from pypots.imputation.transformer.modules import EncoderLayer, PositionalEncoding from pypots.utils.metrics import cal_mae @@ -411,7 +411,7 @@ def fit( self.model.eval() # set the model as eval status to freeze it. # Step 3: save the model if necessary - self.auto_save_model_if_necessary(training_finished=True) + self._auto_save_model_if_necessary(training_finished=True) def impute( self, diff --git a/pypots/imputation/transformer/model.py b/pypots/imputation/transformer/model.py index 23e4e8f2..7cadef0f 100644 --- a/pypots/imputation/transformer/model.py +++ b/pypots/imputation/transformer/model.py @@ -20,7 +20,7 @@ from pypots.data.base import BaseDataset from pypots.imputation.base import BaseNNImputer from pypots.imputation.transformer.dataset import DatasetForSAITS -from pypots.imputation.transformer.module import EncoderLayer, PositionalEncoding +from pypots.imputation.transformer.modules import EncoderLayer, PositionalEncoding from pypots.utils.metrics import cal_mae @@ -314,7 +314,7 @@ def fit( self.model.eval() # set the model as eval status to freeze it. # Step 3: save the model if necessary - self.auto_save_model_if_necessary(training_finished=True) + self._auto_save_model_if_necessary(training_finished=True) def impute(self, X: Union[dict, str], file_type: str = "h5py") -> np.ndarray: """Impute missing values in the given data with the trained model. diff --git a/pypots/imputation/transformer/module.py b/pypots/imputation/transformer/modules.py similarity index 100% rename from pypots/imputation/transformer/module.py rename to pypots/imputation/transformer/modules.py From 1bf49fb99e5293663376694f9561585788009155 Mon Sep 17 00:00:00 2001 From: Wenjie Du Date: Fri, 5 May 2023 23:09:48 +0800 Subject: [PATCH 3/6] feat: allow tests for CLI to fail; --- pypots/tests/test_cli.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pypots/tests/test_cli.py b/pypots/tests/test_cli.py index b6605000..0e58aa8d 100644 --- a/pypots/tests/test_cli.py +++ b/pypots/tests/test_cli.py @@ -42,6 +42,7 @@ def wrapper(*args, **kwargs): return decorator +@pytest.mark.xfail(reason="Allow tests for CLI to fail") class TestPyPOTSCLIDev(unittest.TestCase): # set up the default arguments default_arguments = { @@ -91,6 +92,7 @@ def test_3_cleanup(self): dev_command_factory(args).run() +@pytest.mark.xfail(reason="Allow tests for CLI to fail") class TestPyPOTSCLIDoc(unittest.TestCase): # set up the default arguments default_arguments = { @@ -151,6 +153,7 @@ def test_3_cleanup(self): doc_command_factory(args).run() +@pytest.mark.xfail(reason="Allow tests for CLI to fail") class TestPyPOTSCLIEnv(unittest.TestCase): # set up the default arguments default_arguments = { From 7671164df9ea1bf4a0d673442d999ed80604bc9e Mon Sep 17 00:00:00 2001 From: Wenjie Du Date: Fri, 5 May 2023 23:22:11 +0800 Subject: [PATCH 4/6] fix: error caused by missing dependencies during building docs; --- .readthedocs.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 18252e2e..40946c82 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -21,6 +21,6 @@ build: pre_install: - python -m pip install --upgrade pip - pip install torch==1.13.1 -f https://download.pytorch.org/whl/cpu - - pip install -e ".[optional]" -f "https://data.pyg.org/whl/torch-1.13.1+cpu.html" - - pip install -e ".[basic]" + - pip install torch-geometric torch-scatter torch-sparse -f "https://data.pyg.org/whl/torch-1.13.1+cpu.html" + - pip install pypots - pip install sphinx==6.2.1 docutils==0.19 sphinxcontrib-bibtex furo From 7f55b9135699423d0ff9a315e89acdb66ebaae34 Mon Sep 17 00:00:00 2001 From: Wenjie Du Date: Fri, 5 May 2023 23:23:46 +0800 Subject: [PATCH 5/6] docs: remove cli that we don't need it be shown in our docs; --- docs/pypots.cli.rst | 56 --------------------------------------------- docs/pypots.rst | 1 - 2 files changed, 57 deletions(-) delete mode 100644 docs/pypots.cli.rst diff --git a/docs/pypots.cli.rst b/docs/pypots.cli.rst deleted file mode 100644 index 72789211..00000000 --- a/docs/pypots.cli.rst +++ /dev/null @@ -1,56 +0,0 @@ -pypots.cli package -================== - -pypots.cli.base module ----------------------- - -.. automodule:: pypots.cli.base - :members: - :undoc-members: - :show-inheritance: - :inherited-members: - -pypots.cli.dev module ---------------------- - -.. automodule:: pypots.cli.dev - :members: - :undoc-members: - :show-inheritance: - :inherited-members: - -pypots.cli.doc module ---------------------- - -.. automodule:: pypots.cli.doc - :members: - :undoc-members: - :show-inheritance: - :inherited-members: - -pypots.cli.env module ---------------------- - -.. automodule:: pypots.cli.env - :members: - :undoc-members: - :show-inheritance: - :inherited-members: - -pypots.cli.pypots\_cli module ------------------------------ - -.. automodule:: pypots.cli.pypots_cli - :members: - :undoc-members: - :show-inheritance: - :inherited-members: - -Module contents ---------------- - -.. automodule:: pypots.cli - :members: - :undoc-members: - :show-inheritance: - :inherited-members: diff --git a/docs/pypots.rst b/docs/pypots.rst index 8b71dfee..ff430d0d 100644 --- a/docs/pypots.rst +++ b/docs/pypots.rst @@ -8,7 +8,6 @@ Subpackages :maxdepth: 4 pypots.classification - pypots.cli pypots.clustering pypots.data pypots.forecasting From f440a6ed386309343941c0f9931ff2d4841d85b4 Mon Sep 17 00:00:00 2001 From: Wenjie Du Date: Fri, 5 May 2023 23:36:50 +0800 Subject: [PATCH 6/6] docs: update docs and enable to use `html_favicon` in `conf.py`; --- docs/conf.py | 2 ++ docs/pypots.imputation.rst | 20 ++++++++++---------- docs/pypots.rst | 7 ++----- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index bc4a8e9d..6bb61507 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -76,6 +76,8 @@ "last_updated": f"{date_now.year}/{date_now.month}/{date_now.day}", } +html_favicon = "_static/figs/PyPOTS_logo.svg" + html_sidebars = { "**": [ "sidebar/scroll-start.html", diff --git a/docs/pypots.imputation.rst b/docs/pypots.imputation.rst index a43fea0d..66faae8e 100644 --- a/docs/pypots.imputation.rst +++ b/docs/pypots.imputation.rst @@ -10,37 +10,37 @@ pypots.imputation.base module :show-inheritance: :inherited-members: -pypots.imputation.brits module +pypots.imputation.saits module ------------------------------ -.. automodule:: pypots.imputation.brits +.. automodule:: pypots.imputation.saits :members: :undoc-members: :show-inheritance: :inherited-members: -pypots.imputation.locf module ------------------------------ +pypots.imputation.transformer module +------------------------------------ -.. automodule:: pypots.imputation.locf +.. automodule:: pypots.imputation.transformer :members: :undoc-members: :show-inheritance: :inherited-members: -pypots.imputation.saits module +pypots.imputation.brits module ------------------------------ -.. automodule:: pypots.imputation.saits +.. automodule:: pypots.imputation.brits :members: :undoc-members: :show-inheritance: :inherited-members: -pypots.imputation.transformer module ------------------------------------- +pypots.imputation.locf module +----------------------------- -.. automodule:: pypots.imputation.transformer +.. automodule:: pypots.imputation.locf :members: :undoc-members: :show-inheritance: diff --git a/docs/pypots.rst b/docs/pypots.rst index ff430d0d..bf6718f8 100644 --- a/docs/pypots.rst +++ b/docs/pypots.rst @@ -7,16 +7,13 @@ Subpackages .. toctree:: :maxdepth: 4 + pypots.imputation pypots.classification pypots.clustering - pypots.data pypots.forecasting - pypots.imputation + pypots.data pypots.utils -Submodules ----------- - pypots.base module ------------------