mlboydaisuke commited on
Commit
d976309
Β·
verified Β·
1 Parent(s): 92370c2

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +112 -0
README.md ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ language:
4
+ - en
5
+ pipeline_tag: automatic-speech-recognition
6
+ tags:
7
+ - litert
8
+ - tflite
9
+ - android
10
+ - gpu
11
+ - wav2vec2
12
+ - ctc
13
+ - speech-recognition
14
+ base_model: facebook/wav2vec2-base-960h
15
+ ---
16
+
17
+ # wav2vec2-base-960h CTC β€” LiteRT (GPU)
18
+
19
+ English speech recognition with [wav2vec2-base-960h](https://huggingface.co/facebook/wav2vec2-base-960h)
20
+ running **fully on the LiteRT `CompiledModel` GPU** (ML Drift) β€” and with **zero FFT anywhere**:
21
+ the raw 16 kHz waveform goes straight into the 1D-conv feature extractor, so there is no mel/fbank
22
+ step even on the host. Character-level CTC (29 chars + specials), greedy decode, no language model.
23
+
24
+ ![wav2vec2 CTC word onsets](assets/hero.png)
25
+ *Real model output: char-CTC word onsets for J.F. Kennedy's 1961 inaugural address
26
+ (U.S. National Archives recording, public domain).*
27
+
28
+ Ships as **two GPU graphs** β€” the fused graph exceeds the Mali whole-graph shader-compile limit
29
+ (a graph can be op-clean and still fail to compile when fused; each half compiles and runs fully
30
+ delegated):
31
+
32
+ | File | Size | Input | Output | API |
33
+ | ---- | ---- | ----- | ------ | --- |
34
+ | `w2v2_asr_frontend_fp16.tflite` | 9 MB | waveform `[1, 256000]` | features `[1, 799, 768]` | CompiledModel GPU |
35
+ | `w2v2_asr_head_fp16.tflite` | 180 MB | features `[1, 799, 768]` | CTC logits `[1, 799, 32]` | CompiledModel GPU |
36
+
37
+ ## Pipeline
38
+
39
+ `16 kHz mono PCM in [-1, 1], zero-padded to the fixed 16 s window β†’ [GPU] conv frontend β†’
40
+ [GPU] 12-layer transformer + lm_head β†’ host greedy-CTC over the valid frames`
41
+
42
+ - Valid frames for `n` samples: run `L=(L-k)//s+1` over the conv stack
43
+ `(10,5)(3,2)(3,2)(3,2)(3,2)(2,2)(2,2)` β€” 50 Hz frames (16 s β†’ 799).
44
+ - Blank id 0 (`<pad>`), `|` = word delimiter (`tokens.txt`, index-ordered).
45
+ - Greedy char-CTC without an LM has the model's known spelling quirks on hard words
46
+ (e.g. GRAVED/GRAVE); add a beam+LM host-side if you need the last WER point.
47
+
48
+ ## Minimal usage β€” Python
49
+
50
+ ```python
51
+ import numpy as np, torch, torchaudio
52
+ from ai_edge_litert.interpreter import Interpreter
53
+
54
+ wave, sr = torchaudio.load("speech.wav") # 16 kHz mono, [-1,1]
55
+ x = torch.zeros(1, 256000); n = min(wave.shape[1], 256000)
56
+ x[0, :n] = wave[0, :n]
57
+
58
+ def run(path, inp):
59
+ it = Interpreter(model_path=path); it.allocate_tensors()
60
+ d = it.get_input_details()[0]
61
+ it.set_tensor(d["index"], inp.astype(np.float32)); it.invoke()
62
+ return it.get_tensor(it.get_output_details()[0]["index"])
63
+
64
+ feat = run("w2v2_asr_frontend_fp16.tflite", x.numpy())
65
+ logits = run("w2v2_asr_head_fp16.tflite", feat)[0] # [799, 32]
66
+
67
+ L = n
68
+ for k, s in [(10,5),(3,2),(3,2),(3,2),(3,2),(2,2),(2,2)]:
69
+ L = (L - k) // s + 1
70
+ tokens = open("tokens.txt").read().splitlines()
71
+ out, prev = [], -1
72
+ for i in logits[:L].argmax(-1):
73
+ if i != prev and i != 0: out.append(tokens[int(i)])
74
+ prev = i
75
+ print("".join(out).replace("|", " ").strip())
76
+ ```
77
+
78
+ ## Minimal usage β€” Kotlin (Android)
79
+
80
+ ```kotlin
81
+ val frontend = CompiledModel.create(frontendPath, CompiledModel.Options(Accelerator.GPU), null)
82
+ val head = CompiledModel.create(headPath, CompiledModel.Options(Accelerator.GPU), null)
83
+ val fIn = frontend.createInputBuffers(); val fOut = frontend.createOutputBuffers()
84
+ val hIn = head.createInputBuffers(); val hOut = head.createOutputBuffers()
85
+
86
+ fIn[0].writeFloat(pcm) // [-1,1] floats, zero-padded to 256000
87
+ frontend.run(fIn, fOut)
88
+ hIn[0].writeFloat(fOut[0].readFloat()) // features [1,799,768]
89
+ head.run(hIn, hOut)
90
+ val logits = hOut[0].readFloat() // [799 * 32], readback syncs the GPU
91
+ // greedy CTC over the valid frames: argmax per frame, drop blanks (id 0) + repeats,
92
+ // map through tokens.txt, '|' -> space
93
+ ```
94
+
95
+ ## On-device performance (Pixel 8a, CompiledModel GPU)
96
+
97
+ - frontend 448 ms + head 391 ms per 16 s window (RTF β‰ˆ 0.05); GPU compile 0.7 s + 1.5 s.
98
+ - Device logits vs desktop float reference: corr 0.9928 (valid region), per-frame argmax
99
+ agreement 97.0 %; transcript matches the desktop reference.
100
+
101
+ ## Conversion notes
102
+
103
+ Converted with litert-torch, numerically exact (tflite vs PyTorch: corr 1.000000):
104
+ GELU β†’ tanh-GELU; frontend GroupNorm β†’ 4D-reshape group-norm (avoids GATHER_ND);
105
+ pos_conv weight-norm folded to a static weight; the all-valid bidirectional attention mask
106
+ removed (fixed window β†’ plain SDPA). The CTC head is a plain Linear β€” logits come out raw.
107
+
108
+ ## Sources & license
109
+
110
+ - Model: [facebook/wav2vec2-base-960h](https://huggingface.co/facebook/wav2vec2-base-960h) β€” Apache-2.0.
111
+ - Paper: [wav2vec 2.0: A Framework for Self-Supervised Learning of Speech Representations](https://arxiv.org/abs/2006.11477).
112
+ - Hero audio: J.F. Kennedy inaugural address (1961), U.S. National Archives β€” public domain.