Instructions to use Zipeng365/WISP with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Scikit-learn
How to use Zipeng365/WISP with Scikit-learn:
from huggingface_hub import hf_hub_download import joblib model = joblib.load( hf_hub_download("Zipeng365/WISP", "sklearn_model.joblib") ) # only load pickle files from sources you trust # read more about it here https://skops.readthedocs.io/en/stable/persistence.html - Notebooks
- Google Colab
- Kaggle
Download src/wisp/search/operator_program.py from Zipeng365/WISP: direct link, hf CLI and curl.
- Browser
- Download file 9.25 kB
-
https://huggingface.co/Zipeng365/WISP/resolve/main/src/wisp/search/operator_program.py
- Command line
-
hf download hf://Zipeng365/WISP/src/wisp/search/operator_program.py
-
curl -L -o operator_program.py https://huggingface.co/Zipeng365/WISP/resolve/main/src/wisp/search/operator_program.py
9.25 kB
| # Paper-scoped implementation; see SOURCE_PROVENANCE.json. | |
| from __future__ import annotations | |
| from dataclasses import asdict, dataclass, field | |
| from typing import Any | |
| import numpy as np | |
| from wisp.search.grammar import CandidateSpec | |
| from wisp.search.motifs import canonicalize_tags, family_motif_match | |
| class OperatorNode: | |
| name: str | |
| family: str | |
| information: float = 0.0 | |
| invariance: float = 0.0 | |
| dynamics: float = 0.0 | |
| reconstructability: float = 0.0 | |
| cost: float = 1.0 | |
| tags: tuple[str, ...] = () | |
| def to_dict(self) -> dict[str, Any]: | |
| d = asdict(self) | |
| d['tags'] = list(self.tags) | |
| return d | |
| OPERATOR_LIBRARY: dict[str, OperatorNode] = {'identity': OperatorNode('identity', 'preprocess', information=1.0, reconstructability=1.0, cost=0.1, tags=('lossless',)), 'zscore': OperatorNode('zscore', 'preprocess', information=0.5, invariance=0.8, reconstructability=0.0, cost=0.2, tags=('shift_scale_invariant',)), 'magnitude': OperatorNode('magnitude', 'derive', information=0.5, invariance=0.8, cost=0.3, tags=('orientation_invariance',)), 'jerk': OperatorNode('jerk', 'derive', information=0.6, dynamics=0.8, cost=0.3, tags=('micro_burst',)), 'gram_eig': OperatorNode('gram_eig', 'derive', information=0.45, invariance=0.8, cost=0.4, tags=('device_shift', 'orientation_invariance')), 'intrinsic_timescale': OperatorNode('intrinsic_timescale', 'derive', information=0.45, dynamics=0.7, cost=0.4, tags=('state_persistence',)), 'multiscale_stats': OperatorNode('multiscale_stats', 'aggregate', information=0.65, dynamics=0.55, cost=1.0, tags=('local_shape',)), 'multiscale_interval_stats': OperatorNode('multiscale_interval_stats', 'aggregate', information=0.65, dynamics=0.55, cost=1.0, tags=('local_shape',)), 'dyadic_intervals': OperatorNode('dyadic_intervals', 'segment', information=0.6, dynamics=0.5, cost=0.8, tags=('interval_distribution',)), 'quantile_distribution': OperatorNode('quantile_distribution', 'aggregate', information=0.55, invariance=0.3, dynamics=0.4, cost=0.8, tags=('distribution_shape',)), 'random_shapelet': OperatorNode('random_shapelet', 'aggregate', information=0.7, invariance=0.2, dynamics=0.75, cost=1.4, tags=('local_shape', 'micro_burst')), 'aggregate_stats': OperatorNode('aggregate_stats', 'aggregate', information=0.55, cost=0.7, tags=('summary',)), 'segment': OperatorNode('segment', 'segment', information=0.7, cost=0.4, tags=('localization',)), 'fft_bands': OperatorNode('fft_bands', 'spectral', information=0.55, invariance=0.35, dynamics=0.55, cost=0.5, tags=('periodic_locomotion',)), 'autocorr': OperatorNode('autocorr', 'spectral', information=0.55, invariance=0.35, dynamics=0.75, cost=0.5, tags=('periodic_locomotion', 'state_persistence')), 'random_conv': OperatorNode('random_conv', 'random_conv', information=0.7, dynamics=0.65, cost=1.3, tags=('phase_tolerant_local_shape',)), 'ppv_pool': OperatorNode('ppv_pool', 'random_conv', information=0.45, invariance=0.5, cost=0.3, tags=('phase_tolerant_local_shape',)), 'ppv_max_mean_std': OperatorNode('ppv_max_mean_std', 'random_conv', information=0.55, invariance=0.5, cost=0.4, tags=('phase_tolerant_local_shape',)), 'symbolic_transition': OperatorNode('symbolic_transition', 'symbolic', information=0.35, invariance=0.5, dynamics=0.85, cost=0.9, tags=('state_dynamics', 'micro_pattern')), 'transition_histogram': OperatorNode('transition_histogram', 'symbolic', information=0.35, invariance=0.5, dynamics=0.8, cost=0.8, tags=('state_dynamics',)), 'quantize': OperatorNode('quantize', 'symbolic', information=0.25, invariance=0.4, cost=0.3, tags=('symbolic',)), 'symbolic': OperatorNode('symbolic', 'symbolic', information=0.35, dynamics=0.7, cost=0.8, tags=('state_dynamics',)), 'extratrees': OperatorNode('extratrees', 'classifier_cpu', information=0.4, cost=1.1, tags=('nonlinear_cpu',)), 'rf': OperatorNode('rf', 'classifier_cpu', information=0.4, cost=1.1, tags=('nonlinear_cpu',)), 'ridge': OperatorNode('ridge', 'classifier_cpu', information=0.3, cost=0.4, tags=('fast_cpu',)), 'logreg': OperatorNode('logreg', 'classifier_cpu', information=0.3, cost=0.6, tags=('calibrated_cpu',)), 'probability_ensemble': OperatorNode('probability_ensemble', 'classifier_cpu', information=0.55, cost=1.3, tags=('multi_view_cpu',)), 'posterior_weighting': OperatorNode('posterior_weighting', 'posterior', information=0.45, cost=0.5, tags=('posterior_over_motifs',)), 'invariant_physics': OperatorNode('invariant_physics', 'derive', information=0.55, invariance=0.8, cost=1.0, tags=('device_shift',)), 'feature_union': OperatorNode('feature_union', 'fusion', information=0.65, cost=1.2, tags=('multi_view_cpu',)), 'hmm': OperatorNode('hmm', 'postprocess', information=0.25, dynamics=0.9, cost=0.4, tags=('transition_smoothing', 'free_living_noise')), 'argmax': OperatorNode('argmax', 'postprocess', information=0.1, cost=0.1, tags=('window_only',))} | |
| class TemporalProgram: | |
| name: str | |
| route: str | |
| nodes: list[OperatorNode] | |
| params: dict[str, Any] = field(default_factory=dict) | |
| parent_id: str | None = None | |
| mutation: str | None = None | |
| def from_candidate(cls, spec: CandidateSpec) -> 'TemporalProgram': | |
| nodes = [OPERATOR_LIBRARY.get(op, OperatorNode(op, 'unknown', cost=1.0)) for op in spec.operators] | |
| return cls(name=spec.name, route=spec.route, nodes=nodes, params=dict(spec.params), parent_id=spec.parent_id, mutation=spec.mutation) | |
| def to_candidate(self) -> CandidateSpec: | |
| return CandidateSpec(name=self.name, route=self.route, params=dict(self.params), operators=[node.name for node in self.nodes], parent_id=self.parent_id, mutation=self.mutation) | |
| def operators(self) -> list[str]: | |
| return [node.name for node in self.nodes] | |
| def families(self) -> list[str]: | |
| return [node.family for node in self.nodes] | |
| def certificate(self) -> dict[str, Any]: | |
| if not self.nodes: | |
| return {} | |
| arr = np.asarray([[n.information, n.invariance, n.dynamics, n.reconstructability, n.cost] for n in self.nodes], dtype=np.float64) | |
| tags: set[str] = set() | |
| for node in self.nodes: | |
| tags.update(node.tags) | |
| canonical = canonicalize_tags(tags) | |
| return {'name': self.name, 'route': self.route, 'n_operators': len(self.nodes), 'operator_trace': self.operators, 'family_trace': self.families, 'mean_information': float(np.mean(arr[:, 0])), 'mean_invariance': float(np.mean(arr[:, 1])), 'mean_dynamics': float(np.mean(arr[:, 2])), 'mean_reconstructability': float(np.mean(arr[:, 3])), 'estimated_cost': float(np.sum(arr[:, 4])), 'tags': sorted(tags), 'canonical_motifs': sorted(canonical), 'task_representation_congruence': self.task_congruence()} | |
| def motif_match(self, motif_weights: dict[str, float]) -> dict[str, Any]: | |
| match = family_motif_match(self.name, motif_weights) | |
| return {'family': match.family, 'score': match.score, 'contributions': match.contributions} | |
| def task_congruence(self) -> dict[str, float]: | |
| tags = set() | |
| for node in self.nodes: | |
| tags.update(node.tags) | |
| score = {'Capture24_free_living': 0.0, 'WISDM_micro_actions': 0.0, 'HHAR_device_shift': 0.0, 'PAMAP2_multisensor': 0.0, 'MHEALTH_small_scripted': 0.0} | |
| score['Capture24_free_living'] += 0.35 if 'free_living_noise' in tags else 0.0 | |
| score['Capture24_free_living'] += 0.25 if 'transition_smoothing' in tags else 0.0 | |
| score['Capture24_free_living'] += 0.2 if 'periodic_locomotion' in tags else 0.0 | |
| score['Capture24_free_living'] += 0.2 if 'orientation_invariance' in tags else 0.0 | |
| score['WISDM_micro_actions'] += 0.35 if 'micro_burst' in tags or 'micro_pattern' in tags else 0.0 | |
| score['WISDM_micro_actions'] += 0.25 if 'local_shape' in tags else 0.0 | |
| score['WISDM_micro_actions'] += 0.2 if 'state_dynamics' in tags else 0.0 | |
| score['WISDM_micro_actions'] += 0.2 if 'phase_tolerant_local_shape' in tags else 0.0 | |
| score['HHAR_device_shift'] += 0.45 if 'device_shift' in tags else 0.0 | |
| score['HHAR_device_shift'] += 0.35 if 'orientation_invariance' in tags else 0.0 | |
| score['HHAR_device_shift'] += 0.2 if 'fast_cpu' in tags or 'phase_tolerant_local_shape' in tags else 0.0 | |
| score['PAMAP2_multisensor'] += 0.3 if 'multi_view_cpu' in tags else 0.0 | |
| score['PAMAP2_multisensor'] += 0.25 if 'local_shape' in tags else 0.0 | |
| score['PAMAP2_multisensor'] += 0.25 if 'periodic_locomotion' in tags else 0.0 | |
| score['PAMAP2_multisensor'] += 0.2 if 'state_dynamics' in tags else 0.0 | |
| score['MHEALTH_small_scripted'] += 0.35 if 'fast_cpu' in tags else 0.0 | |
| score['MHEALTH_small_scripted'] += 0.25 if 'local_shape' in tags else 0.0 | |
| score['MHEALTH_small_scripted'] += 0.2 if 'interval_distribution' in tags else 0.0 | |
| score['MHEALTH_small_scripted'] += 0.2 if 'multi_view_cpu' in tags else 0.0 | |
| return {k: float(min(v, 1.0)) for k, v in score.items()} | |
| def jaccard_novelty(a: CandidateSpec, b: CandidateSpec) -> float: | |
| A = set(a.operators) | |
| B = set(b.operators) | |
| if not A and (not B): | |
| return 0.0 | |
| return 1.0 - len(A & B) / max(len(A | B), 1) | |