diffusion-asr-30h / README.md
Tachyeon's picture
Upload README.md with huggingface_hub
d4273a2 verified
|
Raw
History Blame Contribute Delete
5.78 kB
---
language: en
license: other
base_model:
- JetLM/SDAR-1.7B-Chat
- Qwen/Qwen3-ASR-0.6B
datasets:
- librispeech_asr
tags:
- automatic-speech-recognition
- speech
- diffusion
- lora
- block-diffusion
pipeline_tag: automatic-speech-recognition
---
# Diffusion ASR β€” trained adapter + LoRA (30h)
Trained weights for a speech-recognition system that pairs a **frozen** audio encoder with a
**frozen** block-diffusion language model, bridged by a small trained adapter and LoRA.
> **These are deltas, not a standalone model.** This repo contains only the ~5M-parameter
> adapter and the ~17M-parameter LoRA. To run anything you also need the two frozen base
> models (below) and the code from the project repo:
> **https://github.com/ipritamdash/diffusion-asr-research**
## What's in this repo
| File | Contents | Params | sha256 (first 16) |
|---|---|---|---|
| `ctc_sft30h_stair_best.pt` | audio adapter (incl. `gain`) + logit-scale `log_s` | 5,250,050 | `fe982b73182c5516` |
| `lora30h_stair_best.pt` | LoRA on the decoder (PEFT state dict, 392 tensors) | 17,432,576 | `d80455b2c66e3f1e` |
`ctc_sft30h_stair_best.pt` keys: `adapter`, `log_s`, `epoch` (40), plus dev metrics.
`lora30h_stair_best.pt` keys: `lora`, `epoch` (24), `dev_ce` (0.5147).
## Base models (frozen β€” download separately)
| Role | Repo | Pinned revision |
|---|---|---|
| Decoder (block-diffusion LM) | `JetLM/SDAR-1.7B-Chat` | `97cf0dc9a7e85433f3f71a6bbac6fec9d381294f` |
| Encoder (audio tower) | `Qwen/Qwen3-ASR-0.6B` | `5eb144179a02acc5e5ba31e748d22b0cf3e303b0` |
Use these exact revisions β€” the weights here were trained against them.
> **The base decoder must be loaded through the project repo's patched loader**
> (`qwen_sdar/sdar.py::load_patched_sdar`), which swaps the CUDA-only flash-attn for SDPA and
> adds the embeddings-input path. Loading stock `JetLM/SDAR-1.7B-Chat` with plain
> `from_pretrained` will **not** reproduce these results.
## Architecture
```
audio β†’ Qwen3-ASR-0.6B encoder β†’ adapter β†’ SDAR-1.7B decoder + LoRA β†’ text
frozen trained frozen trained
```
- **Adapter** (`Adapter` in `qwen_sdar/adapter.py`): `Conv1d(1024β†’1024, k=3, stride=2, pad=1)`
β†’ GELU β†’ `Linear(1024β†’2048)` β†’ `LayerNorm(2048)` β†’ Γ—`gain`. Per-frame; the stride-2 conv
pools the encoder's 12.5 Hz features to 6.25 Hz. `gain` is initialised to the RMS of the
decoder's token embeddings so the prefix matches their scale.
- **LoRA** (PEFT): `r=16`, `alpha=32`, `dropout=0`, on `q_proj, k_proj, v_proj, o_proj,
gate_proj, up_proj, down_proj`.
- Trained with **block-causal ("staircase") attention** at every stage, so the model can be
served on fast inference engines (see the project repo, `engine/`).
## Training
- **Data:** a 30-hour subset of LibriSpeech `train-clean-100`, with a 300-clip held-out dev split.
- **Staged, never joint:** grounding (adapter via CTC, decoder detached) β†’ SFT (adapter
through the frozen decoder) β†’ LoRA (adapter frozen).
- Only ~1% of the ~2.5B-parameter system is trained (encoder 0.78B + decoder 1.7B; ~22M trained).
## Results (held-out dev-300)
WER %, lower is better. `raw` = macro WER; `norm` = normalized corpus WER (Whisper normalizer).
| Decode | raw / norm |
|---|---|
| block-2 (best) | **6.96 / 6.48** |
| block-4 | 8.24 / 7.69 |
Also served on **LMDeploy's PyTorch diffusion engine** at parity (block-2: 7.33 / 6.71, within
the decoder's kernel noise), at RTF 0.0013 (~800Γ— real time, **block-4 decode**) under batching
on one L40S.
*Note: dev-300 is one in-domain held-out subset β€” not the standard `test-clean`/`test-other`
benchmark, and not evaluated on multiple datasets.*
## How to use
Clone the project repo (`github.com/ipritamdash/diffusion-asr-research`) and run inference in
**two steps, in two environments** β€” the encoder (`qwen-asr`) and the decoder (`transformers`)
have conflicting dependencies, so they don't share one env:
```bash
# 1. encoder env β€” audio -> features
pip install -r requirements-encoder.txt
python featurize.py --audio clip.wav --out features.pt
# 2. decoder env β€” features -> transcript (loads the adapter + LoRA from this repo)
pip install -r requirements-decode.txt
python decode.py --features features.pt \
--adapter ctc_sft30h_stair_best.pt --lora lora30h_stair_best.pt --block_length 2
```
Both steps need a CUDA GPU. For fast serving instead, see `engine/` (merge the LoRA with
`engine/merge_lora.py`, then run on LMDeploy).
Decode config: `block_length=2` (best) or 4, `denoising_steps=4`, `confidence_threshold=0.95`,
greedy, with top-1 fallback and EOS truncation.
## Intended use & limitations
- **Scope:** a research model for **English read speech** (LibriSpeech domain). Not evaluated
for streaming, other languages, or noisy/conversational audio.
- **In-domain, tuned set:** the 6.96 / 6.48 dev-300 numbers are on a held-out split of the same
`train-clean-100` pool the model was tuned on β€” read them as an *in-domain* result, not a
public benchmark.
- **Out-of-domain degrades sharply:** the earlier 10h version scored ~16% on `test-other` and
~40% on VoxPopuli; expect large degradation off clean read speech.
- **No standard-benchmark number for this 30h model:** `test-clean` / `test-other` were run
only for a separate 10h proof-of-concept, not this model β€” do **not** read 6.48 as a
`test-clean` score.
## Licensing
The adapter and LoRA weights here are trained deltas. Any use depends on the two frozen base
models, which are governed by **their own licenses** β€” check `JetLM/SDAR-1.7B-Chat` and
`Qwen/Qwen3-ASR-0.6B` before any redistribution, and do not redistribute a merged checkpoint
(which would embed the base weights) without confirming their terms.