mazesmazes commited on
Commit
1c9abe3
·
verified ·
1 Parent(s): 470aa82

Update model card for granite-qwen-frozen-4

Browse files
Files changed (1) hide show
  1. README.md +90 -121
README.md CHANGED
@@ -3,23 +3,33 @@ license: mit
3
  language:
4
  - en
5
  datasets:
6
- - speechbrain/LoquaciousSet
 
 
 
 
 
 
 
7
  base_model:
8
- - zai-org/GLM-ASR-Nano-2512
9
- - Qwen/Qwen3-0.6B
10
  pipeline_tag: automatic-speech-recognition
11
  tags:
12
  - asr
13
  - speech-recognition
14
  - audio
15
  - qwen
16
- - glm-asr
 
17
  library_name: transformers
18
  ---
19
 
20
  # Tiny Audio
21
 
22
- A speech recognition model trained in 24 hours on a single GPU for ~$12. Built with [Tiny Audio](https://github.com/alexkroman/tiny-audio)—a minimal, hackable ASR framework.
 
 
23
 
24
  ## Quick Start
25
 
@@ -29,6 +39,7 @@ from transformers import pipeline
29
  pipe = pipeline("automatic-speech-recognition", model="mazesmazes/tiny-audio", trust_remote_code=True)
30
  result = pipe("audio.wav")
31
  print(result["text"])
 
32
  ```
33
 
34
  ## Usage Examples
@@ -56,7 +67,6 @@ result = pipe(audio)
56
  ### Batch Processing
57
 
58
  ```python
59
- # Process multiple files
60
  files = ["audio1.wav", "audio2.wav", "audio3.wav"]
61
  results = pipe(files, batch_size=4)
62
  for r in results:
@@ -65,67 +75,25 @@ for r in results:
65
 
66
  ### Word-Level Timestamps
67
 
68
- ```python
69
- result = pipe("audio.wav", return_timestamps="word")
70
- # Returns:
71
- # {
72
- # "text": "hello world",
73
- # "chunks": [
74
- # {"text": "hello", "timestamp": (0.0, 0.5)},
75
- # {"text": "world", "timestamp": (0.6, 1.0)}
76
- # ]
77
- # }
78
- ```
79
-
80
- ### Streaming Inference
81
 
82
  ```python
83
- from tiny_audio import ASRModel, ASRProcessor
84
- import torch
85
-
86
- model = ASRModel.from_pretrained("mazesmazes/tiny-audio")
87
- processor = ASRProcessor.from_pretrained("mazesmazes/tiny-audio")
88
-
89
- # Load and process audio
90
- import librosa
91
- audio, sr = librosa.load("audio.wav", sr=16000)
92
- inputs = processor(audio, sampling_rate=16000, return_tensors="pt")
93
-
94
- # Stream tokens
95
- for token in model.generate_streaming(inputs["input_features"]):
96
- print(token, end="", flush=True)
97
  ```
98
 
99
- ### Using with torch directly
100
 
101
  ```python
102
- from tiny_audio import ASRModel, ASRProcessor
103
- import torch
104
- import librosa
105
-
106
- # Load model and processor
107
- model = ASRModel.from_pretrained("mazesmazes/tiny-audio")
108
- processor = ASRProcessor.from_pretrained("mazesmazes/tiny-audio")
109
-
110
- # Load audio (16kHz)
111
- audio, sr = librosa.load("audio.wav", sr=16000)
112
-
113
- # Process
114
- inputs = processor(audio, sampling_rate=16000, return_tensors="pt")
115
-
116
- # Generate
117
- with torch.no_grad():
118
- output = model.generate(
119
- input_features=inputs["input_features"],
120
- attention_mask=inputs["attention_mask"],
121
- max_new_tokens=256
122
- )
123
-
124
- # Decode
125
- text = processor.batch_decode(output, skip_special_tokens=True)[0]
126
- print(text)
127
  ```
128
 
 
 
129
  ### GPU Inference
130
 
131
  ```python
@@ -135,106 +103,107 @@ pipe = pipeline(
135
  "automatic-speech-recognition",
136
  model="mazesmazes/tiny-audio",
137
  trust_remote_code=True,
138
- device="cuda" # or device=0
 
139
  )
140
  ```
141
 
142
- ### Half Precision
143
 
144
- ```python
145
- pipe = pipeline(
146
- "automatic-speech-recognition",
147
- model="mazesmazes/tiny-audio",
148
- trust_remote_code=True,
149
- torch_dtype=torch.float16,
150
- device="cuda"
151
- )
152
- ```
 
 
 
 
 
 
 
 
 
 
153
 
154
  ## Architecture
155
 
156
  ```
157
- Audio (16kHz) → GLM-ASR Encoder (frozen) → MLP Projector (trained) → Qwen3 (frozen) → Text
158
  ```
159
 
160
- Only the projector is trained (~12M params). The encoder and decoder remain frozen, leveraging their pretrained knowledge.
161
-
162
  | Component | Model | Parameters | Status |
163
  |-----------|-------|------------|--------|
164
- | Audio Encoder | GLM-ASR-Nano-2512 | ~600M | Frozen |
165
- | Projector | 2-layer MLP | ~12M | Trained |
166
- | Language Model | Qwen3-0.6B | ~600M | Frozen |
 
167
 
168
  ### How It Works
169
 
170
- 1. **Audio Encoder**: GLM-ASR converts 16kHz audio into frame-level embeddings (768-dim)
171
- 2. **Projector**: A 2-layer MLP with frame stacking bridges the audio and text embedding spaces
172
- 3. **Language Model**: Qwen3 generates text autoregressively, conditioned on the projected audio
173
 
174
- The projector reduces sequence length via frame stacking: `output_len = (input_len - 5) // 5 + 1`
175
 
176
  ## Model Specifications
177
 
178
  | Specification | Value |
179
  |---------------|-------|
180
  | Input | Audio (16kHz mono) |
181
- | Output | Text transcription |
182
- | Max Audio Length | ~30 seconds (limited by encoder) |
183
- | Vocabulary | Qwen3 tokenizer |
184
  | Languages | English only |
185
- | Generation | Greedy decoding (num_beams=1, do_sample=False) |
186
 
187
  ## Training Details
188
 
189
  | | |
190
  |---|---|
191
- | **Dataset** | LoquaciousSet (25,000 hours) |
192
- | **Hardware** | Single NVIDIA A40 |
193
- | **Time** | ~24 hours |
194
- | **Cost** | ~$12 |
195
- | **Optimizer** | AdamW |
196
- | **Learning Rate** | 1e-4 |
197
- | **Batch Size** | 4 |
198
- | **Steps** | 50,000 |
 
199
 
200
  ## Limitations
201
 
202
- - **English only**: Not trained on other languages
203
- - **Sample rate**: Expects 16kHz audio (other rates resampled automatically)
204
- - **Audio length**: Best for clips under 30 seconds
205
  - **Accuracy**: May degrade on:
206
- - Heavily accented speech
207
  - Noisy or low-quality audio
208
- - Domain-specific terminology
209
- - Overlapping speakers
210
- - **No punctuation**: Output is lowercase without punctuation by default
211
-
212
- ## Requirements
213
-
214
- ```
215
- transformers>=4.40.0
216
- torch>=2.0.0
217
- torchaudio>=2.0.0
218
- ```
219
-
220
- Optional for streaming:
221
- ```
222
- librosa
223
- soundfile
224
- ```
225
 
226
  ## Files
227
 
228
  | File | Description |
229
  |------|-------------|
230
  | `config.json` | Model configuration |
231
- | `model.safetensors` | Projector weights (~48MB) |
 
232
  | `preprocessor_config.json` | Audio preprocessing config |
233
- | `tokenizer.json` | Tokenizer |
234
- | `tokenizer_config.json` | Tokenizer config |
235
- | `special_tokens_map.json` | Special tokens |
236
 
237
- Note: Only the projector weights are stored. The encoder (GLM-ASR) and decoder (Qwen3) are loaded from their respective HuggingFace repos.
 
 
 
 
 
 
238
 
239
  ## Citation
240
 
@@ -258,9 +227,9 @@ If you use this model, please cite:
258
 
259
  ## Acknowledgments
260
 
261
- - [GLM-ASR](https://huggingface.co/zai-org/GLM-ASR-Nano-2512) for the audio encoder
262
- - [Qwen3](https://huggingface.co/Qwen/Qwen3-0.6B) for the language model
263
- - [LoquaciousSet](https://huggingface.co/datasets/speechbrain/LoquaciousSet) for training data
264
 
265
  ## License
266
 
 
3
  language:
4
  - en
5
  datasets:
6
+ - mythicinfinity/libriheavy
7
+ - MLCommons/peoples_speech
8
+ - fixie-ai/common_voice_17_0
9
+ - speechcolab/gigaspeech
10
+ - kensho/spgispeech
11
+ - facebook/voxpopuli
12
+ - edinburghcstr/ami
13
+ - sanchit-gandhi/tedlium-data
14
  base_model:
15
+ - ibm-granite/granite-speech-5.0-470m-turboctc
16
+ - Qwen/Qwen3.5-2B
17
  pipeline_tag: automatic-speech-recognition
18
  tags:
19
  - asr
20
  - speech-recognition
21
  - audio
22
  - qwen
23
+ - granite-speech
24
+ - lora
25
  library_name: transformers
26
  ---
27
 
28
  # Tiny Audio
29
 
30
+ An English speech recognition model that outputs punctuated, capitalized, formatted text. Built with [Tiny Audio](https://github.com/alexkroman/tiny-audio)—a minimal, hackable ASR framework.
31
+
32
+ A frozen Granite Speech encoder is connected to a frozen Qwen3.5-2B decoder through a trained MLP projector, with LoRA adapters on the decoder. Only ~80M parameters are trained.
33
 
34
  ## Quick Start
35
 
 
39
  pipe = pipeline("automatic-speech-recognition", model="mazesmazes/tiny-audio", trust_remote_code=True)
40
  result = pipe("audio.wav")
41
  print(result["text"])
42
+ # The quarterly revenue grew by 12% according to Dr. Smith.
43
  ```
44
 
45
  ## Usage Examples
 
67
  ### Batch Processing
68
 
69
  ```python
 
70
  files = ["audio1.wav", "audio2.wav", "audio3.wav"]
71
  results = pipe(files, batch_size=4)
72
  for r in results:
 
75
 
76
  ### Word-Level Timestamps
77
 
78
+ Timestamps come from forced alignment of the transcript against the audio and are returned under a `words` key:
 
 
 
 
 
 
 
 
 
 
 
 
79
 
80
  ```python
81
+ result = pipe("audio.wav", return_timestamps=True)
82
+ print(result["text"])
83
+ for word in result["words"]:
84
+ print(word)
 
 
 
 
 
 
 
 
 
 
85
  ```
86
 
87
+ ### Speaker Labels
88
 
89
  ```python
90
+ result = pipe("meeting.wav", return_speakers=True, num_speakers=2)
91
+ for word in result["words"]:
92
+ print(word)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  ```
94
 
95
+ `return_speakers=True` implies `return_timestamps=True`. You can pass `num_speakers`, or `min_speakers` / `max_speakers`, when the speaker count is known.
96
+
97
  ### GPU Inference
98
 
99
  ```python
 
103
  "automatic-speech-recognition",
104
  model="mazesmazes/tiny-audio",
105
  trust_remote_code=True,
106
+ device="cuda",
107
+ torch_dtype=torch.bfloat16,
108
  )
109
  ```
110
 
111
+ ## Benchmarks
112
 
113
+ Word error rate (%, lower is better) on 1,000 samples per dataset, scored with the [Tiny Audio eval harness](https://github.com/alexkroman/tiny-audio/tree/main/scripts/eval) (`ta eval`) after text normalization.
114
+
115
+ | Dataset | WER |
116
+ |---------|----:|
117
+ | LibriSpeech test-clean | 1.80 |
118
+ | SPGISpeech | 2.24 |
119
+ | LibriSpeech test-other | 3.09 |
120
+ | TED-LIUM | 3.74 |
121
+ | LoquaciousSet † | 6.10 |
122
+ | Common Voice | 6.62 |
123
+ | VoxPopuli | 6.96 |
124
+ | AMI (IHM) | 8.88 |
125
+ | GigaSpeech | 9.07 |
126
+ | Earnings22 † | 10.54 |
127
+ | People's Speech | 17.69 |
128
+ | AMI (SDM) | 23.59 |
129
+ | **Mean (12 sets)** | **8.36** |
130
+
131
+ † Held out: no data from this source was used in training.
132
 
133
  ## Architecture
134
 
135
  ```
136
+ Audio (16kHz) → Granite Speech encoder (frozen) → MLP projector (trained) → Qwen3.5-2B + LoRA (trained adapters) → Text
137
  ```
138
 
 
 
139
  | Component | Model | Parameters | Status |
140
  |-----------|-------|------------|--------|
141
+ | Audio Encoder | [granite-speech-5.0-470m-turboctc](https://huggingface.co/ibm-granite/granite-speech-5.0-470m-turboctc) | ~470M | Frozen |
142
+ | Projector | 2-layer MLP (hidden 4096) | 12.6M | Trained |
143
+ | Language Model | [Qwen3.5-2B](https://huggingface.co/Qwen/Qwen3.5-2B) | ~2B | Frozen |
144
+ | LoRA adapters | r=64, alpha=64, all linear layers | 67.3M | Trained |
145
 
146
  ### How It Works
147
 
148
+ 1. **Audio encoder**: Granite Speech turns 16kHz audio into frame-level embeddings.
149
+ 2. **Projector**: A 2-layer MLP maps those embeddings into the decoder's embedding space. Each projected frame replaces an `<audio>` placeholder token in the prompt.
150
+ 3. **Language model**: Qwen3.5-2B, adapted with LoRA, generates the transcript conditioned on the projected audio and the prompt *"Transcribe the speech with proper punctuation and capitalization"*.
151
 
152
+ At inference, 0.25s of silence is prepended to each clip (`inference_lead_in_seconds`). This keeps the first word from being dropped on clips that start mid-speech.
153
 
154
  ## Model Specifications
155
 
156
  | Specification | Value |
157
  |---------------|-------|
158
  | Input | Audio (16kHz mono) |
159
+ | Output | Punctuated, capitalized text with formatted numbers |
160
+ | Max Audio Length | ~30 seconds per call |
161
+ | Vocabulary | Qwen3.5 tokenizer |
162
  | Languages | English only |
163
+ | Generation | Greedy decoding (num_beams=1, do_sample=False), max 256 new tokens |
164
 
165
  ## Training Details
166
 
167
  | | |
168
  |---|---|
169
+ | **Data** | LibriHeavy (medium), People's Speech (clean), Common Voice 17, GigaSpeech (M), SPGISpeech (M), VoxPopuli, AMI (IHM + SDM), TED-LIUM: one pass, ~3.8M utterances |
170
+ | **Hardware** | Single NVIDIA H100 80GB |
171
+ | **Steps** | 58,861 |
172
+ | **Batch Size** | 64 |
173
+ | **Optimizer** | AdamW (fused), cosine schedule, 1,000 warmup steps, no weight decay |
174
+ | **Learning Rate** | 1e-3 (projector), 1e-4 (LoRA) |
175
+ | **Precision** | bf16 (projector held in fp32) |
176
+
177
+ The training recipe is [`configs/experiments/granite_qwen_frozen.yaml`](https://github.com/alexkroman/tiny-audio/blob/main/configs/experiments/granite_qwen_frozen.yaml).
178
 
179
  ## Limitations
180
 
181
+ - **English only**: Not trained on other languages.
182
+ - **Sample rate**: Expects 16kHz audio (other rates are resampled automatically).
183
+ - **Audio length**: Best for clips under 30 seconds. Chunk longer audio.
184
  - **Accuracy**: May degrade on:
185
+ - Far-field and overlapping speech (see AMI SDM)
186
  - Noisy or low-quality audio
187
+ - Rare names and domain-specific terminology
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
 
189
  ## Files
190
 
191
  | File | Description |
192
  |------|-------------|
193
  | `config.json` | Model configuration |
194
+ | `model.safetensors` | Projector weights (~50MB) |
195
+ | `adapter_config.json` / `adapter_model.safetensors` | LoRA adapters for the decoder (~270MB) |
196
  | `preprocessor_config.json` | Audio preprocessing config |
197
+ | `tokenizer.json` / `tokenizer_config.json` / `chat_template.jinja` | Tokenizer |
198
+ | `asr_*.py`, `projectors.py`, `alignment.py`, `diarization.py` | Custom model code (loaded with `trust_remote_code=True`) |
 
199
 
200
+ Only the projector and LoRA weights are stored here. The encoder (Granite Speech) and decoder (Qwen3.5-2B) are downloaded from their own Hugging Face repos.
201
+
202
+ The previous GLM-ASR + Qwen3-0.6B model is still available at revision `glm-asr-qwen3-0.6b`:
203
+
204
+ ```python
205
+ pipe = pipeline("automatic-speech-recognition", model="mazesmazes/tiny-audio", revision="glm-asr-qwen3-0.6b", trust_remote_code=True)
206
+ ```
207
 
208
  ## Citation
209
 
 
227
 
228
  ## Acknowledgments
229
 
230
+ - [Granite Speech](https://huggingface.co/ibm-granite/granite-speech-5.0-470m-turboctc) for the audio encoder
231
+ - [Qwen3.5](https://huggingface.co/Qwen/Qwen3.5-2B) for the language model
232
+ - The LibriHeavy, People's Speech, Common Voice, GigaSpeech, SPGISpeech, VoxPopuli, AMI, and TED-LIUM teams for training data
233
 
234
  ## License
235