LES-eg2-665M-asr-en

lee1jun/LES-eg2-665M-asr-en

作者
lee1jun
任务
语音识别
下载量
68
点赞数
14
趋势分
14
许可证
apache-2.0
收录时间
2026/11/14

language: en license: apache-2.0 library_name: transformers pipeline_tag: automatic-speech-recognition inference: false base_model: google/embeddinggemma-2 tags: [ctc, embeddinggemma, word-ctc, custom-code] datasets: [openslr/librispeech_asr, MLCommons/peoples_speech, facebook/voxpopuli, edinburghcstr/ami, mozilla-foundation/common_voice_17_0, parler-tts/mls_eng, nvidia/Granary]

LES-eg2-665M-asr-en

English speech recognition from a frozen EmbeddingGemma 2: an 88M reader reads its audio as words of its own text-embedding space (LibriSpeech test-clean WER 1.74 greedy, 1.58 with the n-gram LM and reranker; Results).

Listen, Embed and Select (LES): EmbeddingGemma 2 listens, an 88M reader embeds every 40 ms of audio in its text-embedding space, and the closest words are selected.

EmbeddingGemma 2 ("eg2" in the model name) is used exactly as it is: its weights are not changed and it gives the same embeddings as before. A trained reader of 88M parameters turns the hidden states of its audio encoder and backbone into word-level CTC outputs, scored against EmbeddingGemma 2's own text embeddings of 407,736 words.

  • Accuracy: LibriSpeech test-clean WER 1.74 greedy, 1.61 with the n-gram LM and 1.58 with the reranker (Open ASR Leaderboard normaliser); seven more English test sets in the Results table.
  • Vocabulary control: add words, or replace the whole word table, without retraining (Your own word table).
  • Raw outputs for your own re-ranking: the scored 32-best list, every frame's word candidates, scoring of any hypothesis and a search over your own candidates (Re-ranking).
  • Embeddings from the same pass: EmbeddingGemma 2's own audio and text embeddings (EmbeddingGemma 2 embeddings).
  • Permissive: trained only on permissively licensed data (no GigaSpeech, SPGISpeech, TED-LIUM or Fisher), so the model files can be used commercially under Apache License 2.0 (Training data, NOTICE).

How it works

Architecture: audio passes through the frozen EmbeddingGemma 2 audio encoder, audio adapter and backbone; the trained 88M reader turns their hidden states into a blank logit and a unit vector per 40 ms soft token, scored by cosine against frozen EmbeddingGemma 2 text embeddings of every word

EmbeddingGemma 2 runs as its audio-language configuration (577M parameters in the paper): the audio encoder (two downsampling convolution layers and twelve conformer layers, USM architecture) turns Mel filterbank inputs into 25 soft tokens per second (d_A = 1536), the audio adapter projects them to the backbone's model dimension (d_M = 512), and the 24-layer bidirectional backbone processes them. The reader reads, for every soft token, the backbone input and its 24 layer outputs, the twelve conformer layers and the audio encoder output; it gives a blank logit and a unit vector that is compared by cosine with the word table, i.e. EmbeddingGemma 2 text embeddings (mean pooling, linear projection to d = 768, l2-normalisation) of every word.

Speech and words therefore meet in one embedding space. Each 40 ms soft token becomes a vector z(t) among the text embeddings of the vocabulary; greedy decoding emits the nearest word row when s · cos beats the blank logit, and the beam decoders keep the 16 nearest rows of every frame as candidates. The figure shows real cosines for one frame of "carriage" in a LibriSpeech dev-clean utterance, zoomed in twice: from the whole space to the target around z(t), then to the scores. The nearest row is "carriage" (cosine 0.46); the next ones, at 0.31-0.32, are words related in meaning (chariot, hearse) and spelling variants found in the vocabulary (carrage, carridge), all far below "carriage" and close to the blank head's score b(t)/s = 0.31.

Shared embedding space, zoomed in twice: a 40 ms soft token of the spoken word carriage lands at z(t) in the space of word embeddings; around z(t), arrows point to its five nearest word rows (carriage, chariot, carrage, carridge, hearse); their cosines and the blank head's score

PartParametersTrained here
EmbeddingGemma 2 audio encoder (2 downsampling conv + 12 conformer layers)304.8Mno (frozen)
EmbeddingGemma 2 audio adapter (1536 → 512)0.8Mno (frozen)
EmbeddingGemma 2 backbone (24 bidirectional layers, embedder included)271.0Mno (frozen)
EmbeddingGemma 2, audio-language configuration (577M in the paper)576.6M
Reader (12 x 768 Transformer, word-CTC head)88.0Myes
Total at inference (greedy, beam)664.6M
+ reranker heads (decoder="rerank" only)6.44Myes
+ no-LM reranker heads (decoder="rerank", profile="no_lm", instead of the ones above)6.44Myes
Total with the second pass671.1M

The word table (word_table.safetensors, 407,736 x 768, stored as row-wise INT8) is a cache of EmbeddingGemma 2 text embeddings, so it is not counted again. The vision encoder (167M) is not loaded.

Usage

pip install "torch>=2.11" torchvision "transformers>=5.20" safetensors numpy soundfile soxr
# torchvision: EmbeddingGemma 2's processor loads its image / video parts even for audio
pip install https://github.com/kpu/kenlm/archive/master.zip     # only for the beam decoders with the n-gram LM
pip install "sentence-transformers>=6.1"                         # only for add_words / set_vocabulary
import soundfile as sf
from transformers import AutoModel

model = AutoModel.from_pretrained("lee1jun/LES-eg2-665M-asr-en", trust_remote_code=True).to("cuda").eval()
audio, sr = sf.read("speech.flac", dtype="float32")

model.transcribe(audio, sampling_rate=sr)                    # greedy: "the transcript"
model.transcribe(audio, sampling_rate=sr, decoder="beam")    # + n-gram LM (downloads lee1jun/LES-eg2-asr-en-lm-4gram)
model.transcribe(audio, sampling_rate=sr, decoder="rerank")  # + the beam's 32-best list re-ranked by the reranker heads
model.transcribe(audio, sampling_rate=sr, decoder="rerank", profile="no_lm")  # second pass without the n-gram LM
model.transcribe([a1, a2, a3])                               # batches, any lengths

r = model.transcribe(audio, sampling_rate=sr, return_timestamps=True)
# {"text": ..., "duration": ..., "words": [{"word", "start", "end", "confidence"}, ...]}
r = model.transcribe(audio, sampling_rate=sr, decoder="rerank", return_nbest=True, return_candidates=True)
# {"text": ..., "nbest": [{"text", "words", "score", "ctc", "lmf", "n", "reranker", "chosen"}, ...],
#  "candidates": [{"time", "blank", "words": [(word, cosine, log p), ...]}, ...]}

EmbeddingGemma 2 (google/embeddinggemma-2, revision 914f7f89142e33e77833254d9c9b90c3cef7303b) is downloaded on first use and used frozen, without its vision encoder; its weights are not part of this repository. Audio at any sampling rate is resampled to 16 kHz.

Decoding options

OptionValues
decoder"greedy" (default), "beam" (word-CTC prefix beam search with n-gram shallow fusion), "rerank" (the beam's 32-best list re-ranked by the reranker heads)
lmbeam decoders: a KenLM binary / ARPA path or a Hub repo id; default lee1jun/LES-eg2-asr-en-lm-4gram
profilebeam decoders: "lm" (default) or "no_lm": no n-gram LM, so no download and no kenlm (alpha 0, beta 0; "rerank" uses its own reranker heads, see The reranker)
alpha, beta, weightsLM weight, word bonus and the N-best rescoring weights {"ctc", "lmf", "n", "reranker"}; defaults from decoding.json (alpha 0.15, beta 1.0, weights ctc 1, lmf 0.2, n 1, reranker 2, one setting for every domain)
gategreedy: "config" (dev-calibrated blank gate: none in this build, so every frame is scanned; gate=31.0 skips about 20 % of LibriSpeech frames without changing LibriSpeech dev transcripts, but changes 0.5 % of AMI and 3 % of TED-LIUM dev transcripts), "exact" (provably lossless), None (scan every frame), a float
bonusgreedy: bonus added to words seen in training (seen_vocab.json)
return_timestampsword start / end in seconds (spike-based, shifted back by the fitted delay 0.24 s; centres, not boundaries) and a confidence (cosine margin; below 0.02 is low)
return_nbestbeam decoders, inputs up to 40 s: adds "nbest", the scored 32-best list with the parts of each score (Your own re-ranking and search)
return_candidates, top_k, candidates_blank_max, candidates_formatevery decoder: adds "candidates", each frame's top_k (16) nearest word rows with cosine and log-probability, for the frames whose blank probability is at most candidates_blank_max (0.999, the frames the beam search expands; None: every frame); candidates_format="arrays": numpy arrays over every frame (Your own re-ranking and search)
return_embedding, embedding_dimadds "embedding", EmbeddingGemma 2's own audio embedding (below); embedding_dim 512 / 256 / 128 keeps the leading dimensions
long_form_s, window_s, overlap_saudio over 40 s is decoded in 28 s windows overlapping by at least 4 s; long_form_s=None decodes one sequence
batch_secondspadded audio per EmbeddingGemma 2 batch (default 300)

model.second_pass(lm, decoder=...) returns the beam decoder as an object for repeated use (build it again after changing the word table).

Your own word table

model.add_words(["embeddinggemma", "huggingface"])           # new vocabulary without retraining
model.set_vocabulary(["turn", "left", "right", "stop"])       # own word table: outputs only these words
model.reset_vocabulary()                                      # back to the shipped table

The decoders can only output words of the table, so the table is also a vocabulary control. add_words extends it. set_vocabulary(words) replaces it with exactly your list (commands, names, a domain glossary). Words already in the table keep their rows; other words get rows from EmbeddingGemma 2 by the training recipe (needs sentence-transformers). The reader is not retrained, and reset_vocabulary() restores the shipped table. Speech outside the list comes out as the nearest listed words or, mostly, as nothing; there is no explicit rejection. The beam decoders still apply the n-gram LM. model.save_pretrained(dir) saves the custom table (without this card).

EmbeddingGemma 2 embeddings

The model also returns EmbeddingGemma 2's own embedding (768-d, L2-normalised: the vector of SentenceTransformer("google/embeddinggemma-2").encode(...)), alone or together with the transcript:

r = model.transcribe(audio, sampling_rate=sr, return_embedding=True)   # {"text": ..., "embedding": tensor [768]}
e = model.embed_audio(audio, sampling_rate=sr)                         # embedding only (no reader, no word table)
q = model.embed_text("quarterly revenue guidance", prompt_name="query")  # text in the same space
score = q @ e                                                           # cosine: text-to-audio search
model.embed_audio([a1, a2], dim=256)                                    # Matryoshka sizes 512 / 256 / 128

return_embedding pools the EmbeddingGemma 2 pass the decoder already runs, so for audio up to 40 s the embedding costs nothing extra (audio decoded in windows, and audio of 29-30 s, takes one more EmbeddingGemma 2 pass). Up to 30 s the vectors equal sentence-transformers' (cosine ≥ 0.997, bf16 rounding). Longer audio is mean-pooled over 25 s pieces so that the whole input counts, whereas sentence-transformers encodes only the first 30 s. embed_text takes EmbeddingGemma 2's prompt names ("query", "document", ...; default none) or a literal prompt= and needs no sentence-transformers.

Results

Model, decodingParamsLS cleanLS otherTED-LIUM 3VoxPopuliEarnings-22AMIGigaSpeechSPGISpeechMean
This model, greedy (default)665M (88M)1.744.514.157.0213.3111.189.603.586.89
This model, decoder="beam" (n-gram LM)665M (88M)1.614.123.996.7713.0710.779.473.566.67
This model, decoder="rerank" (n-gram LM + reranker)671M (94M)1.584.003.886.7412.8210.759.343.686.60
This model, decoder="beam", profile="no_lm" (no LM)665M (88M)1.744.514.136.9813.2411.149.583.576.86
This model, decoder="rerank", profile="no_lm" (no LM, own reranker)671M (94M)1.754.534.037.0213.2011.039.483.696.84
nvidia/parakeet-tdt-0.6b-v2, greedy618M1.292.713.095.6410.8910.418.271.915.53
nvidia/parakeet-ctc-1.1b, greedy1,063M1.513.253.196.2712.9014.678.863.676.79
openai/whisper-large-v3, greedy1,543M1.503.123.568.6610.8914.698.462.686.70
  • Metric: word error rate (%) with the Open ASR Leaderboard text normaliser. Test sets: LibriSpeech test-clean / test-other, TED-LIUM 3 test (1,142 utterances) and the Open ASR Leaderboard test sets of VoxPopuli, Earnings-22, AMI (IHM), GigaSpeech and SPGISpeech. Mean is the mean of the eight WERs. Params: every weight loaded for inference; for this model, in parentheses, the weights trained here (the 88M reader, plus the 6.44M reranker heads for "rerank"), EmbeddingGemma 2 being frozen.
  • Beam decoders: the CC BY 4.0 word 4-gram of the LM repository (alpha 0.15, beta 1, beam 64). "rerank" re-ranks the beam's 32-best list with the reranker heads and the weights in decoding.json.
  • Tuning: one setting for all eight sets, chosen on LibriSpeech, VoxPopuli and AMI development audio. No test set and no Earnings-22 audio or text was used for training or tuning. Tuning each domain on its own development split did not help on average (mean 6.62 instead of 6.60 with the reranker).
  • Reproducibility: computed with the research implementation on these weights (full-precision word table, 120 s batches). This repository's remote code (INT8 table) reproduces the greedy numbers on LibriSpeech: 2,582 / 2,620 and 2,844 / 2,939 transcripts identical, WER 1.74 / 4.49 against 1.74 / 4.51. "beam" and "rerank" give the research pipeline's transcript for 1,549 of 1,600 spot-checked decodes (200 utterances each of 4 test sets).
  • Without the n-gram LM: profile="no_lm" (no LM download, no kenlm; "rerank" uses its own reranker heads) gives means of 6.86 ("beam") and 6.84 ("rerank"), against 6.67 and 6.60 with the LM: the n-gram LM brings most of the second pass's gain.
  • Other models: greedy decoding of the public checkpoints, run by us on the same audio, references, normaliser and scorer (Parakeet: NeMo; Whisper: transformers, fp16, English, Whisper's long-form decoding for the 0.1 % of inputs over 30 s). Params counts every weight loaded for inference. They were trained on other data (see their model cards). The scorer is the current leaderboard code, which merges split compounds ("shop boy" = "shop-boy"), so every row is lower than figures computed with a plain word edit distance (Parakeet-TDT on LibriSpeech test-clean: 1.29 here, 1.66 without merging).

N-best candidates

N-best candidates on four words of LibriSpeech dev-other: per emission frame the five nearest word rows with their cosines; greedy takes the top row of every frame (have been rightly fast, 2 errors), the reranker takes ripening from rank 4 (have been ripening fast, 1 error), the oracle path through the correct candidates is had been ripening fast

Each 40 ms frame offers several word rows; the beam search takes the 16 nearest per frame (the figure shows the top 5 for four words of a LibriSpeech dev-other utterance). Greedy decoding takes the top row of every frame, the beam search with the n-gram LM and the reranker choose a path through the candidates, and the oracle is the best path the list contains.

The beam's 32-best list (31.5 distinct hypotheses on average) holds much better transcripts than the decoders pick. The table gives the WER if the best hypothesis among the first k were picked (oracle WER, same normaliser and scorer):

Best of the first kLS cleanLS otherTED-LIUM 3VoxPopuliEarnings-22AMIGigaSpeechSPGISpeechMean
k = 1 (decoder="beam")1.614.123.996.7713.0710.779.473.566.67
k = 21.123.223.155.8811.628.648.342.695.58
k = 50.762.452.454.9610.076.607.261.984.57
k = 100.642.042.054.469.145.556.581.624.01
k = 320.481.611.553.777.964.205.681.193.31

Choosing the best of the top 10 would lower the mean WER from 6.67 to 4.01. The included reranker recovers 0.07 of that gap (mean 6.60); see Your own re-ranking and search.

Re-ranking

The reranker

decoder="rerank" re-scores the beam's 32-best list: each hypothesis gets score = 1 · ctc + 0.2 · lmf + 1 · n + 2 · reranker (the weights in decoding.json), and the largest wins. ctc is the hypothesis' CTC log-likelihood over the frame candidates, lmf its n-gram log-probability (natural log, with the end of sentence), n its word count and reranker the score of the reranker heads (reranker_heads.safetensors).

  • What it reads. A small Transformer (3 pre-norm layers, d = 256, 4 attention heads; 2.15M parameters per head, three heads from three training seeds whose scores are averaged, 6.44M in all) reads one hypothesis at a time. Each word is one token, the sum of its EmbeddingGemma 2 table row, the reader's frame vector at the word's best frame in its Viterbi CTC alignment (and the cosine between the two), and 14 numbers: the word's log-probability at that frame, whether and where it is among the frame's 16 candidates, the frame's blank log-probability, the frame's best log-probability and the margin to it, the length of the word's CTC segment and the gap to the previous word, its n-gram log-probability, a function-word flag, its length in characters, its position in the utterance, and two N-best consensus shares (the part of the list, weighted by the softmax of the hypotheses' scores, that has the same word within two frames, or anywhere). A summary token carries the hypothesis' ctc, lmf and n relative to the beam's best hypothesis; it gives the score.
  • How it was trained. Listwise: for each utterance, the softmax of the scores over its 32-best list is trained towards softmax(−word errors / τ) with a cross-entropy loss, so the heads learn to rank hypotheses by their errors. The lists come from about 23,000 held-out utterances of AMI, VoxPopuli and The People's Speech (audio and text outside the training data of the reader and of the n-gram LM, so the lists show real errors), decoded by this model with the n-gram LM; permissive data only, no test or Earnings-22 audio. The four weights were then tuned on the pooled LibriSpeech, VoxPopuli and AMI development audio.
  • Without the n-gram LM (profile="no_lm"): reranker_heads_nolm.safetensors has the same architecture and training, on 32-best lists decoded without any n-gram LM (alpha 0, beta 0), with the LM inputs (lmf and each word's n-gram log-probability) set to zero; the consensus shares weight the hypotheses without the LM, and score = ctc + 2 · reranker.
  • What it brings. Mean WER 6.67 → 6.60 with the LM and 6.86 → 6.84 without.
  • Caveats. The consensus shares and the scores relative to the beam's best depend on the list, so reranker scores compare only within one list. Trained on three domains; on SPGISpeech it is slightly worse than the plain beam (3.68 vs 3.56).

Your own re-ranking and search

The 32-best list holds much better transcripts than the decoders pick. Choosing the best hypothesis of the list would give a mean WER of 3.31 (best of the first 10: 4.01; AMI 10.75 → 4.20, Earnings-22 12.82 → 7.96; see the oracle table), against 6.60 with the included reranker, which recovers only 0.07 of the 2.66 points between the best beam (6.67) and the best of the first 10. Better re-ranking is where this model has the most room: a stronger language model, domain knowledge, or a better learned reranker can turn much of that gap into real gains, so please try your own. The decoders return their own scores, so you can recombine them, add your own, or run your own search:

import numpy as np

# 1. your own weights or features on the 32-best list (here an external LM score of each text, my_lm)
r = model.transcribe(audio, sampling_rate=sr, decoder="rerank", return_nbest=True)
best = max(r["nbest"], key=lambda h: h["ctc"] + 0.5 * h["lmf"] + h["n"] + 2 * h["reranker"] + my_lm(h["text"]))

# 2. hypotheses from anywhere (an LLM's correction, another recogniser), scored together with the 32-best list
s = model.score_hypotheses(audio, ["the corrected sentence"], sampling_rate=sr)
# the 32-best entries (the same scores as above) + yours: {..., "given": True, "in_nbest": False, "oov": []}

# 3. your own search over the frame candidates, without another audio pass
c = model.transcribe(audio, sampling_rate=sr, return_candidates=True, candidates_format="arrays")["candidates"]
c["logp"][c["ids"] == model.vocab.index("uh")] = -np.inf         # e.g. forbid a word, or bias / re-weight "logp"
nbest = model.beam_search(c, alpha=0.3, beta=0.5, nbest=10)      # any KenLM binary / ARPA file via lm=
  • return_nbest entries (beam order) hold the table words, the parts ctc, lmf, n and reranker (None for "beam"), the decoder's score (ctc + alpha · lmf + beta · n for "beam"; the weighted sum above for "rerank") and chosen. For "rerank", recombining the parts with decoding.json's weights reproduces the decoder's choice; for "beam" the choice is the search's own first hypothesis, whose pruned search score can rank differently from score.
  • return_candidates gives, per frame, time (shifted back like word times), blank (its probability) and words as (word, cosine, log p), best first; p is the softmax over the blank logit and s · cos with every row, as the beam decoders' candidates. candidates_format="arrays" gives numpy arrays over every frame: time and lp_blank [T], ids (indices into model.vocab), cos and logp [T, top_k], plus the fingerprint of the word table they index.
  • score_hypotheses(audio, hypotheses, decoder="rerank", include_nbest=True, lm=, alpha=, beta=, weights=) runs one EmbeddingGemma 2 pass (inputs up to 40 s; long_form_s=None for longer ones) and scores each hypothesis, a string or a list of table words, like an N-best entry. With include_nbest it returns the beam's own 32-best entries unchanged, then each of your hypotheses scored as one more entry of that list, so yours change neither the 32-best scores nor each other; include_nbest=False scores only yours, as one list. Words outside the table are listed in oov (never a candidate, read as a zero row by the reranker: add_words them first); chosen marks the largest score.
  • beam_search(candidates, lm=, alpha=, beta=, beam=, nbest=) is the beam decoders' search on candidates_format="arrays" candidates (one dict or a list); on unchanged candidates of an input up to 40 s it returns decoder="beam"'s N-best list. Candidates made before add_words / set_vocabulary are refused.
  • profile="no_lm" works for score_hypotheses and beam_search too (no kenlm needed).

Training data

CorpusLicenceHours
LibriSpeech 960 hCC BY 4.0960
Libri-light small + medium (our LibriSpeech-only reader's pseudo-labels)public domain audio4,991
The People's Speech, cleanCC BY 4.05,864
VoxPopuli English, transcribedCC0 1.0415
AMI IHMCC BY 4.072
Common Voice 17.0 EnglishCC0 1.01,575
Multilingual LibriSpeech English (15k h subset)CC BY 4.013,959
Granary pseudo-labels: YODAS2 English (CC BY 3.0 videos)CC BY 4.014,979
Granary pseudo-labels: VoxPopuli unlabelled EnglishCC BY 4.0 (audio CC0)3,032
Total45,847

Segments over 29 s were dropped. Transcripts are lower-cased and normalised to words; an utterance is kept only if every word is in the LibriSpeech vocabulary or occurs at least 3 times in these corpora. Sessions and videos that overlap evaluation sets were removed (Open ASR VoxPopuli test sessions; word 10-grams shared with evaluation references, e.g. YouTube re-uploads of GigaSpeech test talks).

Training: the reader was trained on LibriSpeech 960 h, then on the mix above (2 epochs on a 27.7k h subset, then 4 epochs on all of it), with EmbeddingGemma 2 frozen throughout. A 17,000-step partial run of the mix (about half an epoch) was the starting point of the final 4 epochs. The 4 epochs follow one cosine learning-rate schedule. Greedy mean WER of the eight sets at the start of epochs 3 and 4 and at the end: 7.35, 7.01 and 6.89; the last epoch still improved every set.

Limitations

  • English only; lower-case words without punctuation or casing. Numbers come out as words.
  • Non-streaming. Word times are spike-based estimates of word centres.
  • Words outside the table can only be produced after add_words.
  • Pseudo-labelled training data (Granary, Libri-light) carries the errors of the labelling models.

Acknowledgements and related work

This project started from an idea we took from the Embedding Gemma Transcribe Mac app: reading EmbeddingGemma 2's audio as words of its own text space. We thank the authors of the projects below.

Readers that score EmbeddingGemma 2 text embeddings of words (as this model does):

ProjectLanguageWhat it is
Embedding Gemma TranscribeEnglishmacOS app: frozen audio encoder and a trained reader that maps every audio slice to the closest of about 229,000 word embeddings, plus a punctuation model (weights not public)
mlboydaisuke/EmbeddingGemma-2-Transcribe-Reader (code, Core AI, LiteRT)Englishopen reproduction: 19.6M reader, scale × cosine against 200,000 word rows plus a blank logit, CTC on LibriSpeech 960 h; iOS, macOS and Android apps
karim23657/fa-eg2-persianPersianthe same reader with a Persian word table

Other speech recognisers on the EmbeddingGemma 2 audio encoder (subword or character outputs):

ProjectLanguageWhat it is
mstkyvz/embeddinggemma2-turkish-sttTurkishcharacter CTC reader, LoRA adapter, 4-gram LM
kuchris/embeddinggemma2asr-cantonese (code)Cantonesefrozen encoder, 20.8M CTC reader over characters and English words
Steveeeeeeen/embeddinggemma2-en-*EnglishCTC, RNN-T, TDT and other heads trained on 1,000 h of YODAS / Granary
harshit2312/stt-gemma_embedding-2Englishfrozen encoder, 13M causal CTC head, subword 6-gram LM, Core ML
AigizK/EmbeddingGemma2-Bashkir-CV25BashkirTransformer CTC reader over Gemma tokens
tc3oliver/Embed2ASR-v1 (code)English, Mandarinfrozen encoder, 9.66M GRU-CTC reader
MaorB/embeddinggemma-2-asr-hebrew-english-streamingHebrew, Englishtop encoder layers fine-tuned, streaming transducer over word pieces
0xanto/eg2-tamilTamiltop 2 encoder layers fine-tuned, CTC over 1,024 BPE units
bringagi/gemma-stt-hindiHinditop 2 encoder layers fine-tuned, character CTC, word 3-gram LM

Licence

Code: Apache 2.0 (LICENSE-CODE). Model files: Apache License 2.0 (LICENSE). EmbeddingGemma 2 keeps its own terms and the Gemma Prohibited Use Policy; the n-gram LM (lee1jun/LES-eg2-asr-en-lm-4gram) is CC BY 4.0. Attributions: NOTICE.

Citation

If you use this model, please cite it:

@misc{les_eg2_665m_asr_en,
  title        = "{LES-eg2-665M-asr-en}: English Speech Recognition from a Frozen {EmbeddingGemma 2} with a Word-Embedding {CTC} Reader",
  author       = {lee1jun},
  year         = {2026},
  month        = nov,
  publisher    = {Hugging Face},
  howpublished = {\url{https://huggingface.co/lee1jun/LES-eg2-665M-asr-en}},
  note         = {n-gram LM: \url{https://huggingface.co/lee1jun/LES-eg2-asr-en-lm-4gram}}
}

This model builds on EmbeddingGemma 2:

@article{embeddinggemma2,
  title   = {EmbeddingGemma 2: Unified and Efficient Multimodal Representations},
  author  = {Schechter Vera, Henrique and Dua, Sahil and others},
  journal = {arXiv preprint arXiv:2610.37364},
  year    = {2026}
}

Files

FileSize
LICENSE0.01 MiB
LICENSE-CODE0.01 MiB
NOTICE0.00 MiB
PROVENANCE.json0.00 MiB
README.md0.03 MiB
architecture.png0.24 MiB
architecture.svg0.01 MiB
config.json0.00 MiB
config.yaml0.00 MiB
configuration_eg2_word_ctc.py0.00 MiB
decoding.json0.00 MiB
embedding_space.png0.35 MiB
embedding_space.svg0.07 MiB
model.safetensors335.79 MiB
modeling_eg2_word_ctc.py0.07 MiB
nbest_paths.png0.18 MiB
nbest_paths.svg0.01 MiB
requirements.txt0.00 MiB
reranker_heads.safetensors24.58 MiB
reranker_heads_nolm.safetensors24.58 MiB
secondpass_eg2.py0.03 MiB
seen_vocab.json4.30 MiB
vocab.json4.54 MiB
word_table.safetensors300.19 MiB

Author

lee1jun (contact: lee1jun@kaist.ac.kr)

内容来源:Hugging Face 模型卡

在 Hugging Face 查看