Feature Extraction
Transformers
Joblib
Safetensors
English
comodo
imu
wearable-sensing
human-activity-recognition
time-series
cross-modal-distillation
svm
custom_code
Instructions to use CRUISEResearchGroup/COMODO-AnyMo-Bench with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use CRUISEResearchGroup/COMODO-AnyMo-Bench with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("feature-extraction", model="CRUISEResearchGroup/COMODO-AnyMo-Bench", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("CRUISEResearchGroup/COMODO-AnyMo-Bench", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Download processing_comodo.py from CRUISEResearchGroup/COMODO-AnyMo-Bench: direct link, hf CLI and curl.
- Browser
- Download file 5.35 kB
-
https://huggingface.co/CRUISEResearchGroup/COMODO-AnyMo-Bench/resolve/main/processing_comodo.py
- Command line
-
hf download hf://CRUISEResearchGroup/COMODO-AnyMo-Bench/processing_comodo.py
-
curl -L -o processing_comodo.py https://huggingface.co/CRUISEResearchGroup/COMODO-AnyMo-Bench/resolve/main/processing_comodo.py
5.35 kB
| # SPDX-License-Identifier: MIT | |
| # Copyright (c) 2026 Baiyu Chen and the COMODO-AnyMo-Bench contributors | |
| """Preprocessing that matches the original Nymeria COMODO loader and collate.""" | |
| import json | |
| from pathlib import Path | |
| import numpy as np | |
| import torch | |
| from torch.nn import functional as F | |
| from transformers import BatchFeature, ProcessorMixin | |
| from transformers.utils.hub import cached_file | |
| class ComodoProcessor(ProcessorMixin): | |
| attributes = [] | |
| model_input_names = ["imu_values"] | |
| def __init__(self, mean, std, sampling_rate=60, sequence_length=512): | |
| super().__init__() | |
| self.mean = np.asarray(mean, dtype=np.float32) | |
| self.std = np.asarray(std, dtype=np.float32) | |
| if self.mean.shape != (18,) or self.std.shape != (18,): | |
| raise ValueError("COMODO requires normalization statistics for 18 channels") | |
| self.std = np.where(self.std < 1e-6, 1.0, self.std).astype(np.float32) | |
| self.sampling_rate = sampling_rate | |
| self.sequence_length = sequence_length | |
| def from_pretrained(cls, pretrained_model_name_or_path, **kwargs): | |
| variant = kwargs.pop("variant", None) | |
| hub_kwargs = {key: kwargs[key] for key in | |
| ("subfolder", "revision", "token", "cache_dir", "local_files_only", | |
| "force_download") if key in kwargs} | |
| if variant is not None: | |
| if variant not in ("core50", "fine150"): | |
| raise ValueError("variant must be 'core50' or 'fine150'") | |
| if hub_kwargs.get("subfolder") not in (None, "", variant): | |
| raise ValueError("variant conflicts with subfolder") | |
| hub_kwargs["subfolder"] = variant | |
| elif not hub_kwargs.get("subfolder"): | |
| metadata_path = cached_file(str(pretrained_model_name_or_path), "config.json", | |
| _raise_exceptions_for_missing_entries=False, **hub_kwargs) | |
| metadata = json.loads(Path(metadata_path).read_text()) if metadata_path else {} | |
| if metadata.get("is_variant_bundle", False): | |
| hub_kwargs["subfolder"] = metadata.get("variant", "core50") | |
| config = json.loads(Path(cached_file(str(pretrained_model_name_or_path), | |
| "processor_config.json", **hub_kwargs)).read_text()) | |
| stats = json.loads(Path(cached_file(str(pretrained_model_name_or_path), | |
| "normalization_stats.json", **hub_kwargs)).read_text()) | |
| return cls(stats["mean"], stats["std"], config["sampling_rate"], config["sequence_length"]) | |
| def save_pretrained(self, save_directory, **kwargs): | |
| target = Path(save_directory) | |
| target.mkdir(parents=True, exist_ok=True) | |
| config = {"processor_class": "ComodoProcessor", "sampling_rate": self.sampling_rate, | |
| "sequence_length": self.sequence_length, | |
| "auto_map": {"AutoProcessor": "processing_comodo.ComodoProcessor"}} | |
| (target / "processor_config.json").write_text(json.dumps(config, indent=2) + "\n") | |
| (target / "normalization_stats.json").write_text(json.dumps({ | |
| "mean": self.mean.tolist(), "std": self.std.tolist()}, indent=2) + "\n") | |
| source = Path(__file__) | |
| if source.resolve() != (target / source.name).resolve(): | |
| (target / source.name).write_text(source.read_text()) | |
| return [str(target / "processor_config.json")] | |
| def __call__(self, imu, sampling_rate=60, return_tensors="pt", **kwargs): | |
| if kwargs: | |
| raise TypeError(f"Unknown preprocessing arguments: {sorted(kwargs)}") | |
| if sampling_rate != self.sampling_rate: | |
| raise ValueError(f"Provide {self.sampling_rate} Hz IMU windows; got {sampling_rate} Hz") | |
| if return_tensors != "pt": | |
| raise ValueError("Only return_tensors='pt' is supported") | |
| if isinstance(imu, torch.Tensor): | |
| imu = imu.detach().cpu().numpy() | |
| try: | |
| values = np.asarray(imu, dtype=np.float32) | |
| except ValueError: | |
| values = None # A batch of windows with different lengths. | |
| if values is not None and values.ndim == 2: | |
| windows = [values] | |
| elif values is not None and values.ndim == 3: | |
| windows = list(values) | |
| elif values is None and isinstance(imu, (list, tuple)): | |
| windows = [np.asarray(row, dtype=np.float32) for row in imu] | |
| else: | |
| raise ValueError("Expected [T, 18], [B, T, 18], or a list of [T, 18] windows") | |
| resized = [] | |
| for window in windows: | |
| if window.ndim != 2 or window.shape[1] != 18 or window.shape[0] == 0: | |
| raise ValueError("Each IMU window must have shape [T, 18] with T > 0") | |
| window = np.nan_to_num(window, copy=True) | |
| window = (window - self.mean.reshape(1, -1)) / self.std.reshape(1, -1) | |
| tensor = torch.from_numpy(np.ascontiguousarray(window.T)).unsqueeze(0) | |
| resized.append(F.interpolate(tensor, size=self.sequence_length, mode="linear", | |
| align_corners=False).squeeze(0)) | |
| if not resized: | |
| raise ValueError("The input batch must contain at least one window") | |
| return BatchFeature({"imu_values": torch.stack(resized)}) | |