From 051cda961da769df6e421b42831bdbb0f9e91e04 Mon Sep 17 00:00:00 2001 From: troyyyyy Date: Tue, 2 Jan 2024 14:20:45 +0800 Subject: [PATCH] [FIX] fix optional in docstring --- abl/bridge/simple_bridge.py | 10 +- abl/learning/basic_nn.py | 31 +++- abl/learning/readme.md | 136 ------------------ .../torch_dataset/classification_dataset.py | 4 +- .../torch_dataset/prediction_dataset.py | 4 +- abl/reasoning/kb.py | 31 ++-- abl/utils/logger.py | 16 ++- abl/utils/utils.py | 14 +- 8 files changed, 70 insertions(+), 176 deletions(-) delete mode 100644 abl/learning/readme.md diff --git a/abl/bridge/simple_bridge.py b/abl/bridge/simple_bridge.py index 44a41e9..9fb22d4 100644 --- a/abl/bridge/simple_bridge.py +++ b/abl/bridge/simple_bridge.py @@ -170,7 +170,7 @@ class SimpleBridge(BaseBridge): ---------- unlabel_data_examples : ListData Unlabeled data examples to concatenate. - label_data_examples : Optional[ListData] + label_data_examples : ListData, optional Labeled data examples to concatenate, if available. Returns @@ -215,11 +215,11 @@ class SimpleBridge(BaseBridge): - ``gt_pseudo_label`` is only used to evaluate the performance of the ``ABLModel`` but not to train. ``gt_pseudo_label`` can be ``None``. - ``Y`` is a list representing the ground truth reasoning result for each sublist in ``X``. - label_data : Optional[Union[ListData, Tuple[List[List[Any]], List[List[Any]], List[Any]]]] + label_data : Union[ListData, Tuple[List[List[Any]], List[List[Any]], List[Any]]], optional Labeled data should be in the same format as ``train_data``. The only difference is that the ``gt_pseudo_label`` in ``label_data`` should not be ``None`` and will be utilized to train the model. Defaults to None. - val_data : Optional[Union[ListData, Tuple[List[List[Any]], Optional[List[List[Any]]], Optional[List[Any]]]]] + val_data : Union[ListData, Tuple[List[List[Any]], Optional[List[List[Any]]], Optional[List[Any]]]], optional Validation data should be in the same format as ``train_data``. Both ``gt_pseudo_label`` and ``Y`` can be either None or not, which depends on the evaluation metircs in ``self.metric_list``. If ``val_data`` is None, ``train_data`` will be used to validate the @@ -233,10 +233,10 @@ class SimpleBridge(BaseBridge): eval_interval : int The model will be evaluated every ``eval_interval`` loops during training, by default 1. - save_interval : Optional[int] + save_interval : int, optional The model will be saved every ``eval_interval`` loops during training, by default None. - save_dir : Optional[str] + save_dir : str, optional Directory to save the model, by default None. """ data_examples = self.data_preprocess("train", train_data) diff --git a/abl/learning/basic_nn.py b/abl/learning/basic_nn.py index 017960c..4d28728 100644 --- a/abl/learning/basic_nn.py +++ b/abl/learning/basic_nn.py @@ -163,7 +163,10 @@ class BasicNN: return self def fit( - self, data_loader: DataLoader = None, X: List[Any] = None, y: List[int] = None + self, + data_loader: Optional[DataLoader] = None, + X: Optional[List[Any]] = None, + y: Optional[List[int]] = None, ) -> BasicNN: """ Train the model for self.num_epochs times or until the average loss on one epoch @@ -267,7 +270,11 @@ class BasicNN: return torch.cat(results, axis=0) - def predict(self, data_loader: DataLoader = None, X: List[Any] = None) -> numpy.ndarray: + def predict( + self, + data_loader: Optional[DataLoader] = None, + X: Optional[List[Any]] = None, + ) -> numpy.ndarray: """ Predict the class of the input data. This method supports prediction with either a DataLoader object (data_loader) or a list of input data (X). If both data_loader @@ -304,7 +311,11 @@ class BasicNN: ) return self._predict(data_loader).argmax(axis=1).cpu().numpy() - def predict_proba(self, data_loader: DataLoader = None, X: List[Any] = None) -> numpy.ndarray: + def predict_proba( + self, + data_loader: Optional[DataLoader] = None, + X: Optional[List[Any]] = None, + ) -> numpy.ndarray: """ Predict the probability of each class for the input data. This method supports prediction with either a DataLoader object (data_loader) or a list of input data (X). @@ -392,7 +403,10 @@ class BasicNN: return mean_loss, accuracy def score( - self, data_loader: DataLoader = None, X: List[Any] = None, y: List[int] = None + self, + data_loader: Optional[DataLoader] = None, + X: Optional[List[Any]] = None, + y: Optional[List[int]] = None, ) -> float: """ Validate the model. It supports validation with either a DataLoader object (data_loader) @@ -431,7 +445,12 @@ class BasicNN: print_log(f"mean loss: {mean_loss:.3f}, accuray: {accuracy:.3f}", logger="current") return accuracy - def _data_loader(self, X: List[Any], y: List[int] = None, shuffle: bool = True) -> DataLoader: + def _data_loader( + self, + X: Optional[List[Any]], + y: Optional[List[int]] = None, + shuffle: Optional[bool] = True, + ) -> DataLoader: """ Generate a DataLoader for user-provided input data and target labels. @@ -467,7 +486,7 @@ class BasicNN: ) return data_loader - def save(self, epoch_id: int = 0, save_path: str = None) -> None: + def save(self, epoch_id: int = 0, save_path: Optional[str] = None) -> None: """ Save the model and the optimizer. User can either provide a save_path or specify the epoch_id at which the model and optimizer is saved. if both save_path and diff --git a/abl/learning/readme.md b/abl/learning/readme.md deleted file mode 100644 index d556b55..0000000 --- a/abl/learning/readme.md +++ /dev/null @@ -1,136 +0,0 @@ -# `basic_model.py` - -可以使用`basic_model.py`中实现的`BasicModel`类将`pytorch`神经网络模型包装成`sklearn`模型的形式. - -## BasicModel 类提供的接口 - -| 方法 | 功能 | -| ---- | ---- | -| fit(X, y) | 训练神经网络 | -| predict(X) | 预测 X 的类别 | -| predict_proba(X) | 预测 X 的类别概率 | -| score(X, y) | 计算模型在测试数据上的准确率 | -| save() | 保存模型 | -| load() | 加载模型 | - - -## BasicModel 类的参数 - -**model : torch.nn.Module** -+ The PyTorch model to be trained or used for prediction. - -**batch_size : int** -+ The batch size used for training. - -**num_epochs : int** -+ The number of epochs used for training. - -**stop_loss : Optional[float]** -+ The loss value at which to stop training. - -**num_workers : int** -+ The number of workers used for loading data. - -**loss_fn : torch.nn.Module** -+ The loss function used for training. - -**optimizer : torch.nn.Module** -+ The optimizer used for training. - -**transform : Callable[..., Any]** -+ The transformation function used for data augmentation. - -**device : torch.device** -+ The device on which the model will be trained or used for prediction. - -**recorder : Any** -+ The recorder used to record training progress. - -**save_interval : Optional[int]** -+ The interval at which to save the model during training. - -**save_dir : Optional[str]** -+ The directory in which to save the model during training. - -**collate_fn : Callable[[List[T]], Any]** -+ The function used to collate data. - -## 例子 -> -> ```python -> # Three necessary component -> cls = LeNet5() -> loss_fn = nn.CrossEntropyLoss() -> optimizer = torch.optim.Adam(cls.parameters()) -> -> # Initialize base_model -> base_model = BasicModel( -> cls, -> loss_fn, -> optimizer, -> torch.device("cuda:0"), -> batch_size=32, -> num_epochs=10, -> ) -> -> # Prepare data -> train_X, train_y = get_train_data() -> test_X, test_y = get_test_data() -> -> # Train model -> base_model.fit(train_X, train_y) -> -> # Predict -> base_model.predict(test_X) -> -> # Validation -> base_model.score(test_X, test_y) -> ``` - -# `wabl_models.py` - -`wabl_models.py`中实现的`WABLBasicModel`能够序列化数据并为不同的机器学习模型提供统一的接口. - -## WABLBasicModel 类提供的接口 - -| 方法 | 功能 | -| ---- | ---- | -| train(X, Y) | 利用训练数据训练机器学习模型(不涉及反绎) | -| predict(X) | 预测 X 的类别和概率 | -| valid(X, Y) | 计算模型在测试数据上的准确率 | - -## WABLBasicModel 类的参数 -**base_model : Machine Learning Model** -+ The base model to use for training and prediction. - -**pseudo_label_list : List[Any]** -+ A list of pseudo-labels to use for training. - -## 序列化数据 -考虑到训练数据可能多种组织形式,比如:\ -`X: List[List[img]], Y: List[List[label]]`\ -`X: List[List[img]], Y: List[label]`\ -`X: List[img], Y: List[label]` -... \ -不便于训练. 因此先将形式统一为:`X: List[img], Y: List[label]`,也就是所谓的序列化数据. - -## 例子 -> -> ```python -> # Three necessary component -> # 'ml_model' is no longer limited to NN models -> model = WABLBasicModel(ml_model, kb.pseudo_label_list) -> -> # Prepare data -> train_X, train_y = get_train_data() -> test_X, test_y = get_test_data() -> -> # Train model -> model.train(train_X, train_y) -> -> # Predict -> model.predict(test_X) -> -> # Validation -> model.valid(test_X, test_y) -> ``` \ No newline at end of file diff --git a/abl/learning/torch_dataset/classification_dataset.py b/abl/learning/torch_dataset/classification_dataset.py index 2efb8f6..a45acd3 100644 --- a/abl/learning/torch_dataset/classification_dataset.py +++ b/abl/learning/torch_dataset/classification_dataset.py @@ -1,4 +1,4 @@ -from typing import Any, Callable, List, Tuple +from typing import Any, Callable, List, Tuple, Optional import torch from torch.utils.data import Dataset @@ -19,7 +19,7 @@ class ClassificationDataset(Dataset): Defaults to None. """ - def __init__(self, X: List[Any], Y: List[int], transform: Callable[..., Any] = None): + def __init__(self, X: List[Any], Y: List[int], transform: Optional[Callable[..., Any]] = None): if (not isinstance(X, list)) or (not isinstance(Y, list)): raise ValueError("X and Y should be of type list.") if len(X) != len(Y): diff --git a/abl/learning/torch_dataset/prediction_dataset.py b/abl/learning/torch_dataset/prediction_dataset.py index 6776988..1abf12e 100644 --- a/abl/learning/torch_dataset/prediction_dataset.py +++ b/abl/learning/torch_dataset/prediction_dataset.py @@ -1,4 +1,4 @@ -from typing import Any, Callable, List, Tuple +from typing import Any, Callable, List, Tuple, Optional import torch from torch.utils.data import Dataset @@ -17,7 +17,7 @@ class PredictionDataset(Dataset): Defaults to None. """ - def __init__(self, X: List[Any], transform: Callable[..., Any] = None): + def __init__(self, X: List[Any], transform: Optional[Callable[..., Any]] = None): if not isinstance(X, list): raise ValueError("X should be of type list.") diff --git a/abl/reasoning/kb.py b/abl/reasoning/kb.py index df54b28..a60a257 100644 --- a/abl/reasoning/kb.py +++ b/abl/reasoning/kb.py @@ -21,7 +21,7 @@ class KBBase(ABC): Parameters ---------- - pseudo_label_list : list + pseudo_label_list : List[Any] List of possible pseudo-labels. It's recommended to arrange the pseudo-labels in this list so that each aligns with its corresponding index in the base model: the first with the 0th index, the second with the 1st, and so forth. @@ -51,11 +51,11 @@ class KBBase(ABC): def __init__( self, - pseudo_label_list: list, - max_err: float = 1e-10, - use_cache: bool = True, - key_func: Callable = to_hashable, - cache_size: int = 4096, + pseudo_label_list: List[Any], + max_err: Optional[float] = 1e-10, + use_cache: Optional[bool] = True, + key_func: Optional[Callable] = to_hashable, + cache_size: Optional[int] = 4096, ): if not isinstance(pseudo_label_list, list): raise TypeError(f"pseudo_label_list should be list, got {type(pseudo_label_list)}") @@ -88,7 +88,7 @@ class KBBase(ABC): ---------- pseudo_label : List[Any] Pseudo-labels of an example. - x : Optional[List[Any]] + x : List[Any], optional The example. If deductive logical reasoning does not require any information from the example, the overridden function provided by the user can omit this parameter. @@ -288,9 +288,9 @@ class GroundKB(KBBase): Parameters ---------- - pseudo_label_list : list + pseudo_label_list : List[Any] Refer to class ``KBBase``. - GKB_len_list : list + GKB_len_list : List[int] List of possible lengths for pseudo-labels of an example. max_err : float, optional Refer to class ``KBBase``. @@ -304,7 +304,12 @@ class GroundKB(KBBase): abductive reasoning) will be automatically set up. """ - def __init__(self, pseudo_label_list, GKB_len_list, max_err=1e-10): + def __init__( + self, + pseudo_label_list: List[Any], + GKB_len_list: List[int], + max_err: Optional[float] = 1e-10, + ): super().__init__(pseudo_label_list, max_err) if not isinstance(GKB_len_list, list): raise TypeError("GKB_len_list should be list, but got {type(GKB_len_list)}") @@ -445,12 +450,10 @@ class PrologKB(KBBase): Parameters ---------- - pseudo_label_list : list + pseudo_label_list : List[Any] Refer to class ``KBBase``. - pl_file : + pl_file : str Prolog file containing the KB. - max_err : float, optional - Refer to class ``KBBase``. Notes ----- diff --git a/abl/utils/logger.py b/abl/utils/logger.py index 3a89469..dcc079c 100644 --- a/abl/utils/logger.py +++ b/abl/utils/logger.py @@ -24,7 +24,7 @@ class FilterDuplicateWarning(logging.Filter): The name of the filter, by default "abl". """ - def __init__(self, name: str = "abl"): + def __init__(self, name: Optional[str] = "abl"): super().__init__(name) self.seen: set = set() @@ -85,7 +85,7 @@ class ABLFormatter(logging.Formatter): self.info_format = f"%(asctime)s - %(name)s - {info_prefix} - %(" "message)s" self.debug_format = f"%(asctime)s - %(name)s - {debug_prefix} - %(" "message)s" - def _get_prefix(self, level: str, color: bool, blink=False) -> str: + def _get_prefix(self, level: str, color: bool, blink: Optional[bool] = False) -> str: """ Get the prefix of the target log level. @@ -192,8 +192,8 @@ class ABLLogger(Logger, ManagerMixin): name: str, logger_name="abl", log_file: Optional[str] = None, - log_level: Union[int, str] = "INFO", - file_mode: str = "w", + log_level: Optional[Union[int, str]] = "INFO", + file_mode: Optional[str] = "w", ): Logger.__init__(self, logger_name) ManagerMixin.__init__(self, name) @@ -286,7 +286,11 @@ class ABLLogger(Logger, ManagerMixin): _release_lock() -def print_log(msg, logger: Optional[Union[Logger, str]] = None, level=logging.INFO) -> None: +def print_log( + msg, + logger: Optional[Union[Logger, str]] = None, + level: Optional[int] = logging.INFO, +) -> None: """ Print a log message using the specified logger or a default method. @@ -297,7 +301,7 @@ def print_log(msg, logger: Optional[Union[Logger, str]] = None, level=logging.IN ---------- msg : str The message to be logged. - logger : Optional[Union[Logger, str]], optional + logger : Union[Logger, str], optional The logger to use for logging the message. It can be a `logging.Logger` instance, a string specifying the logger name, 'silent', 'current', or None. If None, the `print` method is used. diff --git a/abl/utils/utils.py b/abl/utils/utils.py index 4fceec9..72535dd 100644 --- a/abl/utils/utils.py +++ b/abl/utils/utils.py @@ -1,4 +1,4 @@ -from typing import List, Any, Union, Tuple +from typing import List, Any, Union, Tuple, Optional import numpy as np @@ -62,7 +62,7 @@ def reform_list( return reformed_list -def hamming_dist(pred_pseudo_label, candidates): +def hamming_dist(pred_pseudo_label: List[Any], candidates: List[List[Any]]) -> np.ndarray: """ Compute the Hamming distance between two arrays. @@ -87,7 +87,7 @@ def hamming_dist(pred_pseudo_label, candidates): return np.sum(pred_pseudo_label != candidates, axis=1) -def confidence_dist(pred_prob, candidates_idxs): +def confidence_dist(pred_prob: List[np.ndarray], candidates_idxs: List[List[Any]]) -> np.ndarray: """ Compute the confidence distance between prediction probabilities and candidates. @@ -109,7 +109,7 @@ def confidence_dist(pred_prob, candidates_idxs): return 1 - np.prod(pred_prob[cols, candidates_idxs], axis=1) -def to_hashable(x): +def to_hashable(x: Union[List[Any], Any]) -> Union[Tuple[Any, ...], Any]: """ Convert a nested list to a nested tuple so it is hashable. @@ -148,7 +148,11 @@ def restore_from_hashable(x): return [restore_from_hashable(item) for item in x] return x -def tab_data_to_tuple(X, y, reasoning_result = 0): +def tab_data_to_tuple( + X: Union[List[Any], Any], + y: Union[List[Any], Any], + reasoning_result: Optional[Any] = 0 +) -> Tuple[List[List[Any]], List[List[Any]], List[Any]]: ''' Convert a tabular data to a tuple by adding a dimension to each element of X and y. The tuple contains three elements: data, label, and reasoning result.