Time Series Forecasting
Transformers
Safetensors
fela-pdm
feature-extraction
fela
fourier-neural-operator
fno
cpu
on-device
predictive-maintenance
time-series
anomaly-detection
custom_code
Instructions to use lowdown-labs/fela-pdm with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use lowdown-labs/fela-pdm with Transformers:
# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("lowdown-labs/fela-pdm", trust_remote_code=True, dtype="auto") - Notebooks
- Google Colab
- Kaggle
| import os | |
| import sys | |
| import gradio as gr | |
| import numpy as np | |
| import torch | |
| sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) | |
| from modeling import load_model, validate_window | |
| WEIGHTS = os.environ.get("FELA_PDM_WEIGHTS", ".") | |
| MODELS = {} | |
| def _try_load(variant): | |
| try: | |
| return load_model(WEIGHTS, variant=variant) | |
| except Exception: | |
| return None | |
| for v in ("cmapss_FD001", "cwru"): | |
| MODELS[v] = _try_load(v) | |
| EXAMPLE_RUL = np.tile(np.linspace(0.3, 0.7, 30)[:, None], (1, 14)) | |
| def score_rul(text): | |
| m = MODELS.get("cmapss_FD001") | |
| if m is None: | |
| return "RUL weights not found. Set FELA_PDM_WEIGHTS to a dir with cmapss_FD001.safetensors + config.json." | |
| try: | |
| rows = [r for r in text.strip().splitlines() if r.strip()] | |
| arr = np.array( | |
| [[float(x) for x in r.replace(",", " ").split()] for r in rows], | |
| dtype=np.float32, | |
| ) | |
| except Exception: | |
| return "Could not parse. Provide 30 rows of 14 numbers (whitespace or comma separated)." | |
| if arr.shape != (30, 14): | |
| return f"Expected a (30, 14) window, got {arr.shape}." | |
| x = torch.from_numpy(arr).reshape(1, 30, 14) | |
| validate_window(x, m.cfg) | |
| rul = m.predict(x, task="rul") | |
| return f"estimated remaining useful life: {rul:.1f} cycles (capped at 125)" | |
| def load_rul_example(): | |
| return "\n".join((" ".join((f"{v:.3f}" for v in row)) for row in EXAMPLE_RUL)) | |
| def score_cwru(text, use_synth): | |
| m = MODELS.get("cwru") | |
| if m is None: | |
| return "Bearing weights not found. Set FELA_PDM_WEIGHTS to a dir with cwru.safetensors + config.json." | |
| if use_synth or not text.strip(): | |
| t = np.linspace(0, 1, 2048) | |
| sig = np.sin(2 * np.pi * 120 * t) + 0.2 * np.random.randn(2048) | |
| else: | |
| try: | |
| sig = np.array( | |
| [float(x) for x in text.replace(",", " ").split()], dtype=np.float32 | |
| ) | |
| except Exception: | |
| return ( | |
| "Could not parse. Provide 2048 whitespace- or comma-separated samples." | |
| ) | |
| if sig.size != 2048: | |
| return f"Expected 2048 samples, got {sig.size}." | |
| sig = (sig - sig.mean()) / (sig.std() + 1e-06) | |
| x = torch.from_numpy(sig.astype(np.float32)).reshape(1, 2048, 1) | |
| validate_window(x, m.cfg) | |
| idx, prob = m.predict(x, task="cls") | |
| return f"predicted fault class index: {idx} (probability {prob:.4f})" | |
| with gr.Blocks(title="FELA-PdM playground") as demo: | |
| gr.Markdown( | |
| "# FELA-PdM playground\nOn-device predictive maintenance. Feed a sensor window and see the model's call. For research and illustration only, not a safety-critical controller; do not act on the remaining-useful-life number without independent validation." | |
| ) | |
| with gr.Tab("Remaining useful life (C-MAPSS)"): | |
| gr.Markdown( | |
| "Paste 30 cycles of 14 normalized sensor values (30 rows, 14 numbers each). The FD001 head was not trained on FD002/FD003/FD004, so a window from those public NASA subsets is a real out-of-distribution test. The example below is synthetic and illustrative." | |
| ) | |
| rul_in = gr.Textbox(label="sensor window (30 x 14)", lines=8) | |
| rul_out = gr.Textbox(label="result") | |
| with gr.Row(): | |
| gr.Button("Load synthetic example").click(load_rul_example, outputs=rul_in) | |
| gr.Button("Score").click(score_rul, inputs=rul_in, outputs=rul_out) | |
| with gr.Tab("Bearing fault (CWRU)"): | |
| gr.Markdown( | |
| "Paste 2048 raw vibration samples (12 kHz), or tick the box to score a synthetic illustrative window. The output is a fault-class index (10 classes)." | |
| ) | |
| cwru_in = gr.Textbox(label="vibration window (2048 samples)", lines=4) | |
| cwru_synth = gr.Checkbox( | |
| label="use a synthetic illustrative window", value=True | |
| ) | |
| cwru_out = gr.Textbox(label="result") | |
| gr.Button("Score").click( | |
| score_cwru, inputs=[cwru_in, cwru_synth], outputs=cwru_out | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() | |