Instructions to use akisviete/azuolas-whisper-lt with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use akisviete/azuolas-whisper-lt with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("automatic-speech-recognition", model="akisviete/azuolas-whisper-lt")# Load model directly from transformers import AutoProcessor, AutoModelForSpeechSeq2Seq processor = AutoProcessor.from_pretrained("akisviete/azuolas-whisper-lt") model = AutoModelForSpeechSeq2Seq.from_pretrained("akisviete/azuolas-whisper-lt", device_map="auto") - Notebooks
- Google Colab
- Kaggle
Ąžuolas — lietuvių kalbos atpažinimo modelis
Ąžuolas atpažįsta lietuvišką kalbą iš garso įrašų. Tai whisper-large-v3
modelis, SFT apmokytas su visu LIEPA-3 garsynu — skaitoma kalba,
laisva kalba ir fonetiniai įrašai.
Iš viso apie 9,8 tūkst. valandų garso: 5 230 val. skaitomos kalbos, 4 359 val. laisvos kalbos ir 217 val. fonetinių įrašų. Pats LIEPA-3 garsynas yra maždaug 11,4 tūkst. valandų — likusi dalis nenaudota, nes reikia apdoroti tą dataset'o dalį, o tikslas buvo išvengti papildomo apdorojimo.
Modelis pavadintas simbolinio Ąžuolo vardu Ąžuolyno bibliotekos garbei. Jis didžiausias ir lėčiausias iš čia lyginamų lietuviškų modelių, tačiau tiksliausias.
Vienas svarbus dalykas prieš pradedant. Ąžuolas prigalvoja tekstą, kai garse nieko nėra — per tylą ar foninį šnypštimą jis „išgirsta" sklandžius lietuviškus sakinius. Tai reali problema, ne smulkmena. Kaip su tuo dirbti — skyriuje Ką reikia žinoti.
Rezultatai
Visi trys modeliai išbandyti su ta pačia programa — ta, kurią parašė
paprika-whisper-lt-v3 autorius
(kristijonasatpro/paprika).
Naudotos jo dekodavimo nuostatos ir jo teksto normalizavimas. Taip visi trys
lyginami vienodai, o ne kiekvienas savo taisyklėmis.
FLEURS LT — 985 įrašai, 2,96 val.
| modelis | dydis | WER % | WER % be skaitmenų | greitis |
|---|---|---|---|---|
| Ąžuolas (whisper-large-v3) | 1,55 mlrd. | 9,05 | 4,68 | 26× realaus laiko |
| paprika-whisper-lt-v3 (large-v3-turbo) | 0,81 mlrd. | 12,06 | 7,78 | 83× realaus laiko |
| kmynas-parakeet-lt-v3 (Parakeet-TDT) | 0,6 mlrd. | 17,73 | 13,57 | 819× realaus laiko |
Common Voice 26.0 LT — 5 877 įrašai, 8,50 val.
| modelis | WER % | greitis |
|---|---|---|
| Ąžuolas | 4,60 | 27× realaus laiko |
| paprika-whisper-lt-v3 | 8,60 | 76× realaus laiko |
| kmynas-parakeet-lt-v3 | 22,86 | 956× realaus laiko |
WER — žodžių klaidų dalis. Mažiau yra geriau.
Abu testai visiems trims modeliams yra iš kitos srities: nei FLEURS, nei Common Voice nėra LIEPA-3 dalis, ir jų įrašymo sąlygos kitokios. Tai verta pabrėžti, nes paprika autorius sąmoningai neskelbia tokio skaičiaus — jo paruoštas FLEURS rinkinys pasirodė esąs 44 iš 44 skaitmeninės tylos įrašų, ir visi iš jo gauti skaičiai buvo atšaukti. Tad ši lentelė yra pirmas šių trijų modelių palyginimas su nepažįstamu garsu ir su vienoda tvarka.
Greičiai išmatuoti viena RTX PRO 6000, fp16. Su kita įranga skaičiai bus kitokie. Ąžuolas maždaug 3× lėtesnis už paprika, nes turi 32 dekoderio sluoksnius, o turbo — tik 4. Kmynas yra visai kitos sandaros ir maždaug 30× spartesnis už Ąžuolą.
Kodėl yra stulpelis „be skaitmenų"
FLEURS atsakymuose skaičiai rašomi skaitmenimis (25), o šie modeliai rašo
žodžiais (dvidešimt penki). Formaliai tai klaida, nors atpažinta teisingai.
Paprika autorius įvertino, kad tai kainuoja „maždaug 4 WER". Pasitvirtino
beveik tiksliai, ir visiems trims vienodai:
| visas | be skaitmenų | skaitmenų kaina | |
|---|---|---|---|
| Ąžuolas | 9,05 | 4,68 | 4,37 |
| paprika-whisper-lt-v3 | 12,06 | 7,78 | 4,28 |
| kmynas-parakeet-lt-v3 | 17,73 | 13,57 | 4,16 |
Kaina beveik vienoda visiems, tad tai atsakymų teksto, o ne modelių savybė. Stulpelis „be skaitmenų" geriau parodo tikrą atpažinimo kokybę.
Tikras įrašas — 57 minutės iš renginio
Testų įrašai trumpi, tvarkingi ir skaitomi. O čia tie patys trys modeliai su tikru įrašu: Vido Mačiulio knygos „Kitas gyvenimas" pristatymu Ąžuolyno bibliotekoje. 57,1 minutės nerepetuotos kalbos su publika, persidengiančiais balsais ir plojimais (youtube.com/watch?v=BrfheG5EJR4).
Šįkart naudota visa paprika ilgų įrašų programa, ne tik nuostatos: tylos filtras, karpymas pauzėse, tada atpažinimas kiekvienoje dalyje atskirai.
| modelis | žodžių | teksto įvairumas | greitis | dažniausiai pasikartojusi frazė |
|---|---|---|---|---|
| Ąžuolas | 6 646 | 0,998 | 8,9× realaus laiko | „ir taip toliau aš" ×4 |
| paprika-whisper-lt-v3 | 6 636 | 0,998 | 35,0× realaus laiko | „ir taip toliau aš" ×4 |
| kmynas-parakeet-lt-v3 | 6 554 | 0,998 | 1 039× realaus laiko | „ir taip toliau aš" ×4 |
Kiek modelių tekstai sutampa tarpusavyje:
| Ąžuolas ↔ paprika | 93,1 % |
| Ąžuolas ↔ kmynas | 90,3 % |
| paprika ↔ kmynas | 88,6 % |
- Visi trys sutampa 92 žodžių ribose — 1,4 %. Nė vienas nepraleidžia ir neprigalvoja didelių gabalų. Būtent tai svarbiausia ilguose įrašuose, ir trumpų įrašų WER to nerodo.
- Teksto įvairumas 0,998 visiems — niekas neįstrigo kartodamas tą patį. Dažniausia frazė visuose trijuose tekstuose ta pati — „ir taip toliau aš", keturis kartus. Tai tikra kalbos frazė, ne modelio klaida. Taip veikia karpymas pauzėse; tie patys modeliai, karpant fiksuotu žingsniu, jau įstringa.
Šios lentelės greičiai išmatuoti fp32, o ne fp16, nes paprika programa garso požymius verčia į fp32. Todėl Ąžuolas čia rodo 8,9×, o FLEURS lentelėje su fp16 — 26×. Šių dviejų lentelių greičių tarpusavyje nelyginkite.
Patikrinta ir kita programa
Tie patys modeliai išmatuoti dar ir nepriklausoma programa (šio projekto
eval_compare.py, kitos nuostatos, kitas WER skaičiavimas):
| FLEURS / CV 26.0 | paprika programa | nepriklausoma | skirtumas |
|---|---|---|---|
| Ąžuolas | 9,05 / 4,60 | 9,12 / 4,97 | 0,07 / 0,37 |
| paprika-whisper-lt-v3 | 12,06 / 8,60 | 11,84 / 8,42 | 0,22 / 0,18 |
Dvi nepriklausomos programos sutampa 0,4 punkto ribose visur ir į abi puses. Todėl eiliškumu galima tikėti. Nė viena programa nepataikauja savo autoriaus modeliui: paprika programa pačią paprika įvertina net kiek griežčiau.
Dar viena patikra: kmynas modelis per šią programą gavo FLEURS 17,73 ir be skaitmenų 13,57, o jo pačio kortelėje paskelbta 17,15 ir 13,11. Skirtumas 0,6 ir 0,5 punkto. Tą skaičių gavo pats programos autorius su tuo pačiu modeliu, tad sutapimas rodo, kad programa perkelta teisingai.
Kaip naudoti
Modelis rašo mažosiomis raidėmis ir be skyrybos ženklų — taip užrašyti
LIEPA-3 atsakymai. Jis rašo ir taip, kaip pasakyta, o ne kaip taisyklinga:
turim, ne turime.
Jei reikia skyrybos, didžiųjų raidžių ar kalbėtojų žymų — tai atskiri modeliai.
Paprika saugykloje esantis transcribe_file.py visa tai padaro aplink Whisper
modelį ir veikia su šiuo per --model.
Formatai
Modelis paskelbtas trimis pavidalais. Svoriai visur tie patys — tas pats
best_model.pt, iš kurio gauti visi šios kortelės skaičiai — ir visur fp16.
| pavidalas | kur | kaip įkelti |
|---|---|---|
transformers |
akisviete/azuolas-whisper-lt |
WhisperForConditionalGeneration.from_pretrained(...) |
faster-whisper |
akisviete/azuolas-whisper-lt-ct2 |
WhisperModel(...) |
openai-whisper |
original/best_model.pt pagrindinėje saugykloje |
whisper.load_model(kelias) |
Abiejuose paruoštuose pavidaluose įrašytos 10 alignment_heads porų —
oficialus OpenAI rinkinys large-v3 modeliui (iš 640 dekoderio kryžminio
dėmesio galvų). Be jų faster-whisper pats pasirenka 320 porų iš paskutinės
dekoderio pusės; išmatuota, kad tada nulinės trukmės žodžių padvigubėja
(42 → 70).
Svoriai fp16. Jei dirbate procesoriumi, įkeldami nurodykite
dtype=torch.float32 — fp16 procesoriuje lėtas. Tikslumas nuo to nekinta:
skaičiai tie patys, tik kitaip užrašyti.
Trumpi įrašai
import torch, soundfile as sf
from transformers import WhisperForConditionalGeneration, WhisperProcessor
MODEL = "akisviete/azuolas-whisper-lt"
proc = WhisperProcessor.from_pretrained(MODEL, language="lithuanian", task="transcribe")
mdl = WhisperForConditionalGeneration.from_pretrained(MODEL, dtype=torch.float16).to("cuda").eval()
wav, sr = sf.read("irasas.wav", dtype="float32") # 16 kHz, vienas kanalas
f = proc(wav, sampling_rate=16000, return_tensors="pt")
ids = mdl.generate(f.input_features.to("cuda", torch.float16),
language="lithuanian", task="transcribe",
condition_on_prev_tokens=False,
temperature=(0.0, 0.2, 0.4, 0.6, 0.8, 1.0),
logprob_threshold=-1.0,
compression_ratio_threshold=1.35,
no_speech_threshold=0.6)
print(proc.decode(ids[0], skip_special_tokens=True))
Su faster-whisper — maždaug 4× greičiau ir mažiau atminties. vad_filter=True
kartu išsprendžia tylos problemą, aprašytą žemiau:
from faster_whisper import WhisperModel
m = WhisperModel("akisviete/azuolas-whisper-lt-ct2", device="cuda",
compute_type="float16")
segs, _ = m.transcribe("irasas.wav", language="lt", beam_size=5,
vad_filter=True, condition_on_previous_text=False)
for s in segs:
print(f"[{s.start:6.2f} -> {s.end:6.2f}] {s.text}")
Ilgi įrašai — karpykite patys
Supjaustykite garsą į dalis iki 22 sekundžių, kirpdami tylose tarp kalbos, ir atpažinkite kiekvieną dalį atskirai.
Kirpimo vietas imkite iš Silero VAD — raskite kalbos sritis ir kirpkite tarpų tarp jų viduriuose. Tai svarbu ne mažiau už patį ilgį: išmatuota, kad toks kirpimas duoda apie 4 punktais geresnį rezultatą nei paieška pagal garso lygį, kuri gali pataikyti į tylesnę vietą žodžio viduryje.
22 sekundės nėra spėjimas. Su 57 minučių įrašu išbandytos visos ribos ir palygintos su atskaitos tekstu:
| dalies ilgis | skirtumas nuo atskaitos |
|---|---|
| 16 s | 13,86 % |
| 22 s | 13,38 % |
| 28 s | 14,07 % |
| 40 s | 15,10 % |
| 60 s | 24,62 % |
Trumpesnės dalys verčia kirpti kalbos viduryje (prie 8 s taip nutinka 71 % kirpimų, prie 28 s — 56 %), ir kiekvienas nevykęs kirpimas prigalvoja žodžių abiejuose galuose. Ilgesnės dalys pradeda mesti tekstą: prie 60 s praleidimų penkis kartus daugiau. Tai patikrinta su dviem skirtingai apmokytais modeliais, ir geriausia riba nepasikeitė.
Du įspėjimai, abu patirti savo kailiu:
- Nenaudokite
chunk_length_sištransformers. Jis karpo fiksuotu žingsniu ir lipdo tekstą pagal persidengimus, o ko nesulipdo — išmeta. Paprika autorius išmatavo, kad taip tyliai prarandama 30 ir 52 žodžiai sandūrose. Tekstas atrodo tvarkingas, niekas nerodo, kad kažko nėra. - Per ilgos dalys sugenda tyliai. Prie 60 s tekste pritrūksta apie 13 % žodžių, o visi „sveikatos" rodikliai atrodo geri. Tik žodžių skaičius, palygintas su atskaita, tai parodo.
Ką reikia žinoti
Modelis prigalvoja tekstą per tylą, ir apsauga neveikia. Su 60 sekundžių įrašais: visiška tyla — 78 simboliai, tylus šnypštimas — 947 simboliai sklandaus lietuviško teksto, kambario fonas — 247. Pati Whisper apsauga nesuveikia: išmatuota tikimybė „nėra kalbos" per šnypštimą 0,0009, o originaliam large-v3 — 0,8154.
Du būdai, abu veikia:
- Išfiltruokite tylą prieš atpažinimą — paprastas garso lygio patikrinimas, kaip daro paprika programa. Užima mikrosekundes ir problemą pašalina.
- Naudokite
vad_filter=Truesufaster-whisper. Išmatuota: 0 simbolių visais trimis atvejais.
Kodėl taip atsitiko: dėl mokymo duomenų, ne dėl sandaros. Garsynas buvo paruoštas suklijuojant sakinių įrašus į 30 sekundžių langus be tarpų, tad modelis niekada nematė lango be kalbos ir neišmoko nutilti.
Kiti apribojimai:
- Rašo mažosiomis raidėmis, be skyrybos.
- 16 kHz, vienas kanalas. Vyrauja skaitoma ir laisva kalba. Tarmių dalies nėra — paprika v3 ją turi.
- Maždaug 3× lėtesnis už paprika. Išmatuota: 404 s prieš 128 s su 985 FLEURS įrašais.
- Ankstesnėse šios linijos versijose buvo sugedęs ilgų įrašų laiko žymėjimas.
Priežastis — langų klijavimas, kuris išjungdavo laiko žymų mokymą. Pataisyta
nustatant
no_timestamp_rate: 0.5; klaidų skaičius nukrito nuo 23 iki 0. Šioje versijoje laiko žymos patikimos, bet tekstui vis tiek geriau karpyti patiems. - Mokymo metu matytas 2,99 % WER yra iš tos pačios srities kaip ir mokymo duomenys. Tai ne tikras vertinimas — remkitės FLEURS ir CV skaičiais.
Kaip apmokyta
Metodas ne savas. Jis paimtas iš i4Ds/FHNW darbo Fine-tuning Whisper on Low-Resource Languages for Real-World Applications (arXiv:2412.15726) — ten aprašytas ir duomenų klijavimas, ir mokymo tvarka. Skirtumai nuo straipsnio surašyti šaltiniuose.
| pagrindas | openai/whisper-large-v3, apmokyti visi svoriai |
| duomenys | visas LIEPA-3 — 5 230 val. skaitoma + 4 359 val. laisva + 217 val. fonetinė |
| paruošimas | i4Ds Whisper-prep, klijavimas į 30 s langus, overlap_chance 0,4 |
| optimizatorius | AdamW + Muon, muon_ndim_threshold 2 |
| mokymo greitis | 2e-5, kosinusinis, 64 įšilimo žingsniai |
| Muon | momentas 0,95, svorių slopinimas 0,01 |
| AdamW (pagalbinis) | betos [0,9 · 0,98], eps 1e-6, svorių slopinimas 0,01 |
| paketas | 32 × 8 = 256 |
| epochos | 2 |
| reguliarizacija | žymų lyginimas 0,1, atsitiktinis gylis 0,1, max_grad_norm 1,0 |
| garso iškraipymai | SpecAugment ir deep SpecAugment |
| skaičių tikslumas | fp16, gradientų perskaičiavimas koduotuve ir dekoduotuve |
| laiko žymos | no_timestamp_rate 0,5, prompt_use_rate 0,5 |
| failas | 3,09 GB fp16 |
Muon taikomas tik dvimačiams svoriams transformerio blokuose. Įterptiniai vektoriai, konvoliucinis įėjimas, normalizavimo sluoksniai ir visi poslinkiai tvarkomi pagalbiniu AdamW.
Šaltiniai
Lyginti modeliai
paprika-whisper-lt-v3— https://huggingface.co/kristijonas/paprika-whisper-lt-v3kmynas-parakeet-lt-v3— https://huggingface.co/kristijonas/kmynas-parakeet-lt-v3openai/whisper-large-v3— https://huggingface.co/openai/whisper-large-v3nvidia/parakeet-tdt-0.6b-v3(kmynas pagrindas) — https://huggingface.co/nvidia/parakeet-tdt-0.6b-v3
Vertinimo programa (naudota visoms lentelėms)
kristijonasatpro/paprika— https://github.com/kristijonasatpro/paprika — Apache-2.0.chunk_longform.py— dekodavimo nuostatos ir karpymas pauzėse;eval_kmynas.py::norm— teksto normalizavimas.kristijonasatpro/kmynas— https://github.com/kristijonasatpro/kmynas — ilgų įrašų programa ir skolintų žodžių žodynas.
Pagrindinis mokymo šaltinis
Vincenzo Timmel, Claudio Paonessa, Reza Kakooee, Manfred Vogel, Daniel Perruchoud. Fine-tuning Whisper on Low-Resource Languages for Real-World Applications. arXiv:2412.15726, 2024 m. gruodžio 20 d., CC BY 4.0 — https://arxiv.org/html/2412.15726v1
FHNW (Šiaurės vakarų Šveicarijos taikomųjų mokslų universitetas) ir Noxenum. Būtent šis darbas aprašo metodą, kuriuo Ąžuolas paruoštas ir apmokytas, o
Whisper-prepbeiWhisper-finetuneyra jo kodas. Iš jo perimta: sakinių lygio įrašų klijavimas į 30 s langus su VAD pataisytomis laiko žymomis, kalbėtojo išlaikymas, persidengimai,no_timestamp_rateirprompt_use_ratepo 0,5, paketas 256, gradientų perskaičiavimas koduotuve ir dekoduotuve, atsitiktinis gylis ir SpecAugment.Kur nukrypta: jie pradėjo nuo
large-v2(šveicarų vokiečių kalbai jis pasirodė geresnis), Ąžuolas — nuolarge-v3; jų mokymo greitis 2e-4 ir tiesinis mažėjimas, Ąžuolo 2e-5 ir kosinusinis; jie naudojo 8 bitų AdamW, Ąžuolas — AdamW + Muon.Vertas dėmesio ir straipsnio 4.4 skyrius: autoriai patys pastebi, kad po tokio permokymo tikrų ilgų įrašų skaidymas ir atpažinimas pablogėja. Tas pats matyti ir čia — todėl kortelėje ir rašoma karpyti patiems.
Mokymo kodas
i4Ds/Whisper-finetune— https://github.com/i4Ds/Whisper-finetunei4Ds/Whisper-prep— https://github.com/i4Ds/Whisper-prepjumon/whisper-finetuning— https://github.com/jumon/whisper-finetuning — pirminis projektas, kurio duomenų dalį Whisper-prep atkartoja.
Naudotos šios pataisos, visos pasiūlytos ir pirminiams projektams. no_timestamp_rate
pataisa yra ta, dėl kurios šioje versijoje laiko žymos naudotinos:
| pataisa | projektas | ką pataiso |
|---|---|---|
| whisper-prep#6 | whisper-prep | palieka visą 30 s langą ir įrašo persidengiančio segmento pradžios laiką |
| whisper-prep#7 | whisper-prep | VTT MM:SS.mmm skaitymas, prarasta paskutinė eilutė, pasenęs buferis (perkelta iš jumon#33) |
| whisper-finetune#11 | whisper-finetune | įspėja, kad no_timestamp_training tyliai išjungia no_timestamp_rate |
| whisper-finetune#12 | whisper-finetune | priima vieną likusią pradžios žymą _get_partial_segment_start |
| whisper-finetune#13 | whisper-finetune | praleidžia nieko nekeičiantį kalbos map (~65 min. garso perrašymo per kiekvieną mokymą) |
Duomenys
- LIEPA-3 garsynas — Vilniaus universitetas / raštija.lt, CC BY 4.0 —
dėkojame. Svetainė: https://www.xn--ratija-ckb.lt (
www.raštija.lt). Naudota Hugging Face kopija: https://huggingface.co/datasets/meldynamics/liepa-3 - FLEURS — https://huggingface.co/datasets/google/fleurs
- Common Voice 26.0 (lietuvių), leidimas
cv-corpus-26.0-2026-06-12— https://commonvoice.mozilla.org/en/datasets — čia naudoti 5 877 įrašai (8,50 val.) - Tikras įrašas: Vido Mačiulio knygos „Kitas gyvenimas" pristatymas, Ąžuolyno biblioteka (https://azuolynobiblioteka.lt/) — https://www.youtube.com/watch?v=BrfheG5EJR4
Metodai
- Muon — https://kellerjordan.github.io/posts/muon/ ir Muon is Scalable for LLM Training, arXiv:2502.16982
- Silero VAD — https://github.com/snakers4/silero-vad
- Distil-Whisper, arXiv:2311.00430 — iš kur 22 sekundės. Jų 23 lentelė rodo,
kad geriausias gabalo ilgis seka mokymo lango ilgį: Whisper optimalus ties
30 s, Distil-Whisper ties 15 s, nes pastarojo mokymo imties vidurkis 7,1 s.
Ten pat ir haliucinacijų matavimas per pasikartojančias 5-gramas. Patys
autoriai naudoja persidengiantį
chunk_length_skarpymą; išbandyta su šiuo modeliu — Silero VAD karpymas už jį geresnis. - Semantic Segmentation with Bidirectional Language Models Improves Long-form ASR, arXiv:2305.18419 — išbandyta ir atmesta. Siūloma kirpti ties sakinių ribomis, o ne ties pauzėmis. Patikrinta su šiuo modeliu ir 57 minučių įrašu: pralaimi Silero VAD kirpimui. Pasirodo, kad svarbu pataikyti į tikrą tylą, o ne į sakinio ribą — Silero kerpa per sakinio vidurį dažniau, ir vis tiek yra geresnis.
Licencija
Svoriai — CC BY 4.0, perimant LIEPA-3 garsyno nuorodų grandinę (VU /
raštija.lt). Pagrindinis modelis openai/whisper-large-v3 — Apache-2.0.
Kontaktai
Dėl klausimų ir pasiūlymų rašykite akisviete@gmail.com.
- Downloads last month
- 36