File size: 1,285 Bytes
bd47749 | 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 | """Pure-numpy inference for both Nexus safetensors models. No torch, no sklearn needed.
Usage:
from inference import predict
probs, labels = predict("no-edge-detector", X) # X: (n_features,) or (batch, n_features)
"""
import json, os, numpy as np
from safetensors.numpy import load_file
def _softmax(z):
z = z - z.max(axis=-1, keepdims=True); e = np.exp(z)
return e / e.sum(axis=-1, keepdims=True)
def _sigmoid(z):
return 1.0 / (1.0 + np.exp(-z))
def predict(model_dir, X):
cfg = json.load(open(os.path.join(model_dir, "config.json"), encoding="utf-8"))
T = load_file(os.path.join(model_dir, "model.safetensors"))
X = np.asarray(X, float)
if X.ndim == 1: X = X[None, :]
if "scaler_mean" in T:
sc = np.where(T["scaler_scale"] == 0, 1.0, T["scaler_scale"])
X = (X - T["scaler_mean"]) / sc
if cfg["type"] == "mlp":
h = X; n = cfg["n_layers"]
for i in range(n):
h = h @ T[f"W{i}"] + T[f"b{i}"]
if i < n - 1: h = np.maximum(h, 0.0) # relu
p = _softmax(h)
labels = [cfg["classes"][i] for i in p.argmax(1)]
return p, labels
else: # logistic
z = X @ T["coef"].reshape(-1) + float(T["intercept"].reshape(-1)[0])
return _sigmoid(z), None
|