Instructions to use thu-sail-lab/Time-RCD with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use thu-sail-lab/Time-RCD with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("feature-extraction", model="thu-sail-lab/Time-RCD", trust_remote_code=True)# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("thu-sail-lab/Time-RCD", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
File size: 6,088 Bytes
0880420 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | """User-facing zero-shot inference API for Time-RCD."""
from __future__ import annotations
from copy import deepcopy
from pathlib import Path
from typing import Literal, Optional, Tuple, Union
import numpy as np
HF_REPO_ID = "thu-sail-lab/Time-RCD"
CHECKPOINT_FILES = {
"uni": "best_model/pretrain_checkpoint_best_uni.pth",
"multi": "best_model/pretrain_checkpoint_best_multi.pth",
}
DEFAULT_WIN_SIZE = 5000
DEFAULT_BATCH_SIZE = {"uni": 64, "multi": 1}
class TimeRCDDetector:
"""Zero-shot time series anomaly detector powered by Time-RCD.
Parameters
----------
checkpoint_path:
Path to a local ``.pth`` checkpoint.
variant:
``"uni"`` for univariate series, ``"multi"`` for multivariate series.
win_size:
Sliding window length. Sequences shorter than this value use the full
sequence length instead.
batch_size:
Inference batch size. Defaults to 64 (uni) or 1 (multi).
device:
PyTorch device string, e.g. ``"cuda"`` or ``"cpu"``. Auto-detected when
omitted.
Notes
-----
The model is initialized on the first call to :meth:`predict`, when the
number of input features is known.
"""
def __init__(
self,
checkpoint_path: str,
variant: Literal["uni", "multi"] = "uni",
win_size: int = DEFAULT_WIN_SIZE,
batch_size: Optional[int] = None,
device: Optional[str] = None,
) -> None:
if variant not in CHECKPOINT_FILES:
raise ValueError(f"variant must be one of {list(CHECKPOINT_FILES)}, got {variant!r}")
self.variant = variant
self.win_size = win_size
self.batch_size = batch_size if batch_size is not None else DEFAULT_BATCH_SIZE[variant]
self.checkpoint_path = str(checkpoint_path)
self.device = device
self._tester = None
self._num_features: Optional[int] = None
def _ensure_tester(self, num_features: int) -> None:
"""Initialize a model compatible with ``num_features`` when needed."""
if self._tester is not None and self._num_features == num_features:
return
from ._core.time_rcd_config import default_config
from ._inference import TimeRCDPretrainTester
# ``default_config`` is a module-level template. Each detector must own
# its configuration so its runtime options cannot affect other instances.
config = deepcopy(default_config)
config.ts_config.patch_size = 16
config.win_size = self.win_size
config.batch_size = self.batch_size
config.ts_config.num_features = num_features
self._tester = TimeRCDPretrainTester(self.checkpoint_path, config)
self._num_features = num_features
if self.device is not None:
import torch
self._tester.device = torch.device(self.device)
self._tester.model.to(self._tester.device)
@classmethod
def from_pretrained(
cls,
repo_id: str = HF_REPO_ID,
variant: Literal["uni", "multi"] = "uni",
cache_dir: Optional[str] = None,
local_files_only: bool = False,
**kwargs,
) -> "TimeRCDDetector":
"""Load a checkpoint from Hugging Face Hub (cached locally after first use)."""
from huggingface_hub import hf_hub_download
checkpoint_path = hf_hub_download(
repo_id=repo_id,
filename=CHECKPOINT_FILES[variant],
cache_dir=cache_dir,
local_files_only=local_files_only,
)
return cls(checkpoint_path=checkpoint_path, variant=variant, **kwargs)
@classmethod
def from_local(
cls,
checkpoint_path: Union[str, Path],
variant: Literal["uni", "multi"] = "uni",
**kwargs,
) -> "TimeRCDDetector":
"""Load a checkpoint from a local path."""
path = Path(checkpoint_path)
if not path.is_file():
raise FileNotFoundError(f"Checkpoint not found: {path}")
return cls(checkpoint_path=str(path), variant=variant, **kwargs)
def predict(
self,
data: Union[np.ndarray, list],
return_logits: bool = False,
) -> Union[np.ndarray, Tuple[np.ndarray, np.ndarray]]:
"""Run zero-shot anomaly scoring on a single time series.
Parameters
----------
data:
Array of shape ``(T,)`` or ``(T, C)`` where ``T`` is time steps and
``C`` is the number of channels.
return_logits:
When ``True``, also return raw anomaly logits.
Returns
-------
scores:
Anomaly scores in ``[0, 1]``, one value per time step.
logits:
Returned only when ``return_logits=True``.
"""
data = np.asarray(data, dtype=np.float64)
if data.ndim == 1:
data = data.reshape(-1, 1)
elif data.ndim != 2:
raise ValueError(f"data must be 1D or 2D, got shape {data.shape}")
if self.variant == "uni" and data.shape[1] != 1:
raise ValueError(
"variant='uni' expects a univariate series with shape (T,) or (T, 1). "
f"Got {data.shape[1]} channels; use variant='multi' instead."
)
if self.variant == "multi" and data.shape[1] < 2:
raise ValueError(
"variant='multi' expects at least two channels with shape (T, C), where C > 1. "
"Use variant='uni' for a univariate series."
)
original_length = data.shape[0]
self._ensure_tester(data.shape[1])
assert self._tester is not None
score_chunks, logit_chunks = self._tester.zero_shot(data)
scores = np.concatenate([np.asarray(chunk).reshape(-1) for chunk in score_chunks], axis=0)
logits = np.concatenate([np.asarray(chunk).reshape(-1) for chunk in logit_chunks], axis=0)
scores = scores[:original_length]
logits = logits[:original_length]
if return_logits:
return scores, logits
return scores
|