danielbodart commited on
Commit
f224286
Β·
verified Β·
1 Parent(s): 8c2f9b0

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +184 -0
README.md ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ library_name: coreml
3
+ license: cc-by-4.0
4
+ tags:
5
+ - coreml
6
+ - asr
7
+ - speech-recognition
8
+ - streaming
9
+ - nemotron
10
+ - nvidia
11
+ - rnnt
12
+ - fastconformer
13
+ - apple-silicon
14
+ - neural-engine
15
+ language:
16
+ - en
17
+ base_model: nvidia/nemotron-speech-streaming-en-0.6b
18
+ pipeline_tag: automatic-speech-recognition
19
+ ---
20
+
21
+ # Nemotron Speech 600M β€” CoreML (Streaming)
22
+
23
+ Native CoreML conversion of [nvidia/nemotron-speech-streaming-en-0.6b](https://huggingface.co/nvidia/nemotron-speech-streaming-en-0.6b), a 600M-parameter streaming ASR model using FastConformer encoder + RNNT decoder. Optimized for Apple Neural Engine (ANE) on Apple Silicon.
24
+
25
+ Converted directly from the original NeMo checkpoint via coremltools, with 3-level numerical validation against the PyTorch reference.
26
+
27
+ Sibling project: **[danielbodart/nemotron-speech-600m-onnx](https://huggingface.co/danielbodart/nemotron-speech-600m-onnx)** β€” ONNX Runtime version for Linux (CUDA + CPU).
28
+
29
+ ## Performance
30
+
31
+ | Metric | Value |
32
+ |--------|-------|
33
+ | Encoder ANE utilization | **93%** (1486/1597 ops on Neural Engine) |
34
+ | Inference speed | **~15.5x realtime** on Apple Silicon |
35
+ | Encoder CPU ops | 7% (softmax, attention masking β€” see config.json for breakdown) |
36
+ | Decoder | 100% CPU (CPU_ONLY compute units) |
37
+
38
+ No manual ANE optimizations applied β€” coremltools compiler routes ops automatically.
39
+
40
+ ## Available Precisions
41
+
42
+ | Variant | Encoder | Decoder | Total | Compute Units | Notes |
43
+ |---------|---------|---------|-------|---------------|-------|
44
+ | `fp16/` | 1.1 GB | 17 MB | ~1.1 GB | Encoder: CPU+ANE, Decoder: CPU | Recommended |
45
+
46
+ Future: INT8 quantization via coremltools (can halve encoder size on ANE).
47
+
48
+ ## Model Architecture
49
+
50
+ Two CoreML models (decoder and joint network are fused into one):
51
+
52
+ | Model | Input | Output | Compute |
53
+ |-------|-------|--------|---------|
54
+ | **Encoder** | mel `[1, 128, 65]` + caches (FP32 in, FP16 out) | encoded `[1, 1024, 7]` + caches | CPU_AND_NE |
55
+ | **Fused Decoder+Joint** | enc_frame `[1, 1024, 1]` + token `[1, 1]` + LSTM h,c (FP32 in, FP16 out) | logits `[1, 1025]` + LSTM h,c | CPU_ONLY |
56
+
57
+ Mel spectrogram preprocessing runs on the host (not in CoreML).
58
+
59
+ ### Important: ANE stride padding
60
+
61
+ CoreML output MLMultiArrays may have non-contiguous strides due to ANE alignment padding. For example, the encoder output `[1, 1024, 7]` may have physical strides `[32768, 32, 1]` instead of C-contiguous `[7168, 7, 1]`. **Callers must use stride-aware copy, not flat memcpy.**
62
+
63
+ ## Runtime Configuration
64
+
65
+ All parameters needed to run the model are documented in [`config.json`](config.json), including I/O specs, cache shapes, the streaming protocol, and ANE profiling results.
66
+
67
+ ### Audio Preprocessing
68
+
69
+ | Parameter | Value |
70
+ |-----------|-------|
71
+ | Sample rate | 16000 Hz |
72
+ | Sample format | S16_LE (16-bit signed little-endian) |
73
+ | Pre-emphasis | 0.97 |
74
+ | FFT size | 512 |
75
+ | Hop length | 160 samples (10ms) |
76
+ | Window length | 400 samples (25ms) |
77
+ | Window type | Hann |
78
+ | Mel bands | 128 |
79
+ | Mel norm | Slaney |
80
+ | Mel layout | **Band-major** `[n_mels, n_frames]` (not frame-major) |
81
+
82
+ ### Encoder Streaming
83
+
84
+ | Parameter | Value |
85
+ |-----------|-------|
86
+ | Chunk size | 56 mel frames (560ms audio) |
87
+ | Pre-encode cache | 9 mel frames (prepended from previous chunk) |
88
+ | Total input frames | 65 per chunk (56 + 9) |
89
+ | Layers | 24 |
90
+ | Dimension | 1024 |
91
+ | `cache_last_channel` shape | `[1, 24, 70, 1024]` FP32 in, FP16 out (init zeros) |
92
+ | `cache_last_time` shape | `[1, 24, 1024, 8]` FP32 in, FP16 out (init zeros) |
93
+ | `cache_last_channel_len` | `[1]` int32 (init zero) |
94
+
95
+ Feed cache outputs back as next chunk's cache inputs. Convert FP16 outputs to FP32 before feeding back (model expects FP32 inputs).
96
+
97
+ ### RNNT Decoder
98
+
99
+ | Parameter | Value |
100
+ |-----------|-------|
101
+ | Blank token ID | 1024 |
102
+ | Vocab size | 1025 (1024 tokens + blank) |
103
+ | Max symbols per frame | 10 |
104
+ | Prediction layers | 2 (LSTM) |
105
+ | Prediction hidden | 640 |
106
+ | `input_states_1/2` shape | `[2, 1, 640]` FP32 in, FP16 out (init zeros) |
107
+
108
+ For each encoder output frame: feed single frame `[1, 1024, 1]` to decoder, argmax logits over 1025 vocab, if not blank emit token and loop (up to 10), if blank move to next frame. Feed decoder states back for next symbol/frame.
109
+
110
+ ## Files
111
+
112
+ ```
113
+ config.json # Machine-readable runtime parameters + ANE profile
114
+
115
+ fp16/
116
+ β”œβ”€β”€ encoder.mlmodelc/ # Pre-compiled encoder (load directly with MLModel)
117
+ β”‚ β”œβ”€β”€ model.mil
118
+ β”‚ β”œβ”€β”€ coremldata.bin
119
+ β”‚ └── weights/weight.bin
120
+ β”œβ”€β”€ encoder.mlpackage/ # Source encoder (for runtime compilation fallback)
121
+ β”‚ └── Data/com.apple.CoreML/
122
+ β”‚ β”œβ”€β”€ model.mlmodel
123
+ β”‚ └── weights/weight.bin
124
+ β”œβ”€β”€ decoder.mlmodelc/ # Pre-compiled fused decoder+joint
125
+ β”œβ”€β”€ decoder.mlpackage/ # Source fused decoder+joint
126
+ └── metadata.json # Cache shapes, vocab size, model parameters
127
+ ```
128
+
129
+ ## Usage
130
+
131
+ Download:
132
+
133
+ ```bash
134
+ # Download compiled models (recommended)
135
+ hf download danielbodart/nemotron-speech-600m-coreml fp16/ config.json --local-dir ./model
136
+
137
+ # Download only .mlmodelc (skip .mlpackage to save space)
138
+ hf download danielbodart/nemotron-speech-600m-coreml fp16/encoder.mlmodelc/ fp16/decoder.mlmodelc/ fp16/metadata.json config.json --local-dir ./model
139
+ ```
140
+
141
+ Load with CoreML (Swift):
142
+
143
+ ```swift
144
+ import CoreML
145
+
146
+ let config = MLModelConfiguration()
147
+ config.computeUnits = .cpuAndNeuralEngine
148
+
149
+ let encoder = try MLModel(contentsOf: URL(fileURLWithPath: "model/fp16/encoder.mlmodelc"),
150
+ configuration: config)
151
+
152
+ let decConfig = MLModelConfiguration()
153
+ decConfig.computeUnits = .cpuOnly
154
+ let decoder = try MLModel(contentsOf: URL(fileURLWithPath: "model/fp16/decoder.mlmodelc"),
155
+ configuration: decConfig)
156
+ ```
157
+
158
+ Load with CoreML (Python/coremltools):
159
+
160
+ ```python
161
+ import coremltools as ct
162
+
163
+ encoder = ct.models.MLModel("model/fp16/encoder.mlpackage")
164
+ decoder = ct.models.MLModel("model/fp16/decoder.mlpackage")
165
+ ```
166
+
167
+ ## Conversion Reproducibility
168
+
169
+ All conversion and validation scripts are in the companion GitHub repo: **[danielbodart/nemotron-speech-600m-coreml](https://github.com/danielbodart/nemotron-speech-600m-coreml)**
170
+
171
+ - `convert.py` β€” NeMo β†’ CoreML conversion (wrap, trace, convert, compile)
172
+ - `validate.py` β€” 3-level validation (wrapper equiv, CoreML vs PyTorch, end-to-end transcript)
173
+ - `wrappers.py` β€” PyTorch wrappers (EncoderWrapper, FusedDecoderJointWrapper)
174
+
175
+ Requires macOS with Apple Silicon, Python 3.10, coremltools 9.0b1.
176
+
177
+ ## Related
178
+
179
+ - **[danielbodart/nemotron-speech-600m-onnx](https://huggingface.co/danielbodart/nemotron-speech-600m-onnx)** β€” ONNX Runtime version for Linux (CUDA + CPU, FP16/INT8)
180
+ - **[nvidia/nemotron-speech-streaming-en-0.6b](https://huggingface.co/nvidia/nemotron-speech-streaming-en-0.6b)** β€” Original NeMo model
181
+
182
+ ## License
183
+
184
+ The original model is licensed under [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/) by NVIDIA.