Views
No views yet
| subfolder | recipe | params | NPU-compiles | FP32 PESQ | real-time int8 PESQ |
|---|---|---|---|---|---|
gru/ | dual-path GRU (faithful) | 36,783 | ✗ | 3.006 | 2.930 |
conv/ | dual-path conv | 41,063 | ✗ | 2.970 | 2.855 |
conv-hardened/ | conv + NPU-hardened | 36,288 | ✓ | 3.013 | 2.998 |
conv-hardened-deep/ | hardened + deep RF + ReLU6 | 46,248 | ✓* | 3.084 | 3.014 (int8) / 3.052 (hybrid) |
conv-hardened-deep/ uses the same op set as conv-hardened/ plus Clip
(ReLU6); its graph has not yet been through a stedgeai compile, conv-hardened/
has (topology verified on Neural-ART).gru/ is the faithful reproduction and the original quality reference. Its
GRU + 2-axis LayerNorm do not compile to the STM32N6 Neural-ART NPU.conv/ replaces the GRU bottleneck with a dual-path conv one (0 GRU /
0 LayerNormalization). Its ops map to the NPU, but the FIFO-state streaming
graph (conv/g_best_streaming_fp32.onnx, feat + N state_i_in -> est_mag + N state_i_out) crashes the Neural-ART codegen — kept as the CPU/onnxruntime
frame-by-frame reference.conv-hardened/ is the compile-verified NPU-deployable variant:
per-channel BatchNorm (folds into the convs), ReLU, plain ConvTranspose
upsampling, and a stateless windowed deploy graph
(conv-hardened/g_best_windowed_int8_static.onnx, signed QInt8,
feat_window (B,3,132,257) -> est_mag (B,64,257), window = receptive field
68 + 64 emitted frames) that compiles to Neural-ART — the artifact handed
to stedgeai. The hardened primitives also quantize far better (int8 drop
−0.016 vs −0.115 for conv/). It also ships a frame-by-frame streaming
graph — see below.conv-hardened-deep/ is the best model overall: the hardened recipe,
deeper (3 blocks) with an extra dilation stage (receptive field 196 frames ≈
3.1 s) and ReLU6 activations (bounded ranges quantize better; exports as
Clip). Window is 196+64=260 frames (feat_window (B,3,260,257)). It ships
two signed windowed int8 artifacts: g_best_windowed_int8_static.onnx
(everything int8, PESQ 3.014) and g_best_windowed_int8_decoder_fp32.onnx
(int8 except the decoder's QDQ nodes, PESQ 3.052 — the int8 loss is
decoder-localized; the decoder then runs as float epochs on the board).conv-hardened/) — throughput vs latency| graph | shape | algorithmic latency | latency/frame | RTF | PESQ |
|---|---|---|---|---|---|
g_best_windowed_int8_static.onnx | feat_window (B,3,132,257) -> est_mag (B,64,257) | 1.02 s block | 1.15 ms | 0.072 | 2.998 |
g_best_streaming_int8_static.onnx | feat (B,3,1,257) + 17 states -> est_mag (B,1,257) + 17 states | one 16 ms hop | 2.79 ms | 0.174 | 2.982 |
config.json, g_best (PyTorch {"generator": state_dict}), g_best_fp32.onnx
and g_best_int8_static.onnx (whole-utterance mask sub-network,
feat (B,3,T,F) -> est_mag (B,T,F)). conv/ additionally has
g_best_streaming_fp32.onnx and g_best_streaming_int8_static.onnx (single
frame + explicit state I/O — CPU/onnxruntime reference only; this variant's
streaming graph does not compile to Neural-ART). conv-hardened/ has both
NPU deploy graphs: g_best_windowed_{fp32,int8_static}.onnx (stateless windowed)
and g_best_streaming_{fp32,int8_static}.onnx (frame-by-frame, 17 FIFO states) —
see the two-deploy-paths table above. The ONNX graphs are the mask sub-network
only — STFT, feature build and phase recovery stay host-side.1import json, torch
2from huggingface_hub import hf_hub_download
3from common.env import AttrDict
4from lisennet.model import build_lisennet
5
6REPO, SUB = "claroche1/LiSenNet", "conv-hardened" # or "gru" / "conv"
7cfg = json.load(open(hf_hub_download(REPO, f"{SUB}/config.json")))
8ckpt = torch.load(hf_hub_download(REPO, f"{SUB}/g_best"), map_location="cpu", weights_only=True)
9model = build_lisennet(AttrDict(cfg)).eval()
10model.load_state_dict(ckpt["generator"]) # model(noisy_wav)["est"]conv-hardened/)68 + 64 = 132 feature frames and
read the 64 newest enhanced-magnitude frames (no state tensors to carry).1import numpy as np, onnxruntime as ort
2from huggingface_hub import hf_hub_download
3
4sess = ort.InferenceSession(
5 hf_hub_download("claroche1/LiSenNet", "conv-hardened/g_best_windowed_int8_static.onnx"),
6 providers=["CPUExecutionProvider"],
7)
8feat_window = np.zeros((1, 3, 132, 257), np.float32) # last 68+64 feature frames
9est_mag = sess.run(["est_mag"], {"feat_window": feat_window})[0] # (1, 64, 257)conv-hardened/, conv/)conv-hardened/ for the NPU-deployable graph (PESQ 2.982), or
conv/ for the CPU-only reference.1import numpy as np, onnxruntime as ort
2from huggingface_hub import hf_hub_download
3
4sess = ort.InferenceSession(
5 hf_hub_download("claroche1/LiSenNet", "conv-hardened/g_best_streaming_int8_static.onnx"),
6 providers=["CPUExecutionProvider"],
7)
8state_in = [i for i in sess.get_inputs() if i.name != "feat"] # FIFO states
9out_names = [o.name for o in sess.get_outputs()] # est_mag + state_*_out
10zeros = lambda s: np.zeros([d if isinstance(d, int) else 1 for d in s], np.float32)
11states = {i.name: zeros(i.shape) for i in state_in} # start-of-stream = zeros
12
13def step(feat_t): # feat_t: (1, 3, 1, 257)
14 res = sess.run(out_names, {"feat": feat_t, **states})
15 for i, v in zip(state_in, res[1:]):
16 states[i.name] = v
17 return res[0] # est_mag (1, 1, 257)