Automatic Speech Recognition
Transformers
Safetensors
Northern Kurdish
wav2vec2-bert
kurdish
badini
kurmanji
low-resource
Instructions to use computeram/badini-w2v-bert-normalized with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use computeram/badini-w2v-bert-normalized with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("automatic-speech-recognition", model="computeram/badini-w2v-bert-normalized")# pip install -U transformers accelerate # Load model directly from transformers import AutoProcessor, AutoModelForCTC processor = AutoProcessor.from_pretrained("computeram/badini-w2v-bert-normalized") model = AutoModelForCTC.from_pretrained("computeram/badini-w2v-bert-normalized", device_map="auto") - Notebooks
- Google Colab
- Kaggle
File size: 10,304 Bytes
33abe95 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | """
Badini Kurdish text normalizer — companion module for computeram/badini-w2v-bert-normalized.
Applies the same normalization used to evaluate this model (punctuation
handling, Badini number-word expansion, character/word-variant unification)
to raw CTC decoder output, so predictions match the quality reported for the
"normalized" evaluation numbers rather than the raw greedy-decode numbers.
Usage:
from badini_normalize import normalize_transcript
clean_text = normalize_transcript(raw_model_output)
"""
import re
import unicodedata as ud
USE_BADINI_FORMS = True
def number2word(text):
"""Convert numerals in `text` into spoken (Sorani) Kurdish words."""
unify = [
("٠|۰", "0"), ("١|۱", "1"), ("٢|۲", "2"), ("٣|۳", "3"), ("٤|۴", "4"),
("٥|۵", "5"), ("٦|۶", "6"), ("٧|۷", "7"), ("٨|۸", "8"), ("٩|۹", "9"),
]
for pat, rep in unify:
text = re.sub(pat, rep, text)
text = re.sub(r"([0-9]{1,3})[,،](?=[0-9]{3})", r"\1", text)
text = re.sub(r"(?<![0-9])-([0-9]+)", r"ناقس \1", text)
text = re.sub(r"(?<![0-9])% ?([0-9]+)", r"لە سەددا \1", text)
text = re.sub(r"([0-9]+) ?%", r"\1 لە سەد", text)
text = re.sub(r"\$ ?([0-9]+(\.[0-9]+)?)", r"\1 دۆلار", text)
text = re.sub(r"£ ?([0-9]+(\.[0-9]+)?)", r"\1 پاوەن", text)
text = re.sub(r"€ ?([0-9]+(\.[0-9]+)?)", r"\1 یۆرۆ", text)
text = re.sub(r"([0-9]+)\.([0-9]+)",
lambda m: _float_name(m.group(1), m.group(2)), text)
text = re.sub(r"([0-9]+)", lambda m: _integer_name(m.group(1)), text)
return text
def _float_name(integer_part, decimal_part):
leading_zeros = len(decimal_part) - len(decimal_part.lstrip("0"))
point = " پۆینت " + " سفر " * leading_zeros
return _integer_name(integer_part) + point + _integer_name(decimal_part)
def _integer_name(input_integer):
ones = ["", "یەک", "دوو", "سێ", "چوار", "پێنج", "شەش", "حەوت", "هەشت", "نۆ"]
teens = ["دە", "یازدە", "دوازدە", "سێزدە", "چواردە", "پازدە", "شازدە",
"حەڤدە", "هەژدە", "نۆزدە"]
tens = ["", "", "بیست", "سی", "چل", "پەنجا", "شەست", "هەفتا", "هەشتا", "نەوەد"]
hundreds = ["", "سەد", "دووسەد", "سێسەد", "چوارسەد", "پێنسەد", "شەشسەد",
"حەوتسەد", "هەشتسەد", "نۆسەد"]
thousands = ["", " هەزار", " ملیۆن", " ملیار", " بلیۆن", " بلیار",
" تریلیۆن", " تریلیار", " کوادرلیۆن"]
if input_integer == "0":
return "سفر"
output = ""
temp = input_integer
for i in range(0, len(input_integer), 3):
m = re.search(r"([0-9]{1,3})$", temp)
current_three = m.group(1) if m else ""
temp = temp[:len(temp) - len(current_three)]
current_three = current_three.rjust(3, "0")
C = int(current_three[0]); X = int(current_three[1]); I = int(current_three[2])
conjunction1 = " و " if (C != 0 and (X != 0 or I != 0)) else ""
conjunction2 = " و " if (X != 0 and I != 0) else ""
if X == 1:
current_three = hundreds[C] + conjunction1 + teens[I]
else:
current_three = hundreds[C] + conjunction1 + tens[X] + conjunction2 + ones[I]
magnitude = "" if current_three == "" else thousands[i // 3]
current_three += magnitude
conjunction3 = "" if output == "" else " و "
if current_three != "":
output = current_three + conjunction3 + output
output = output.replace("یەک هەزار", "هەزار")
return output
_SORANI_TO_BADINI = {
"یەک": "ئێک", "چوار": "چار", "حەوت": "هەفت", "نۆ": "نەه", "دە": "دەه",
"چواردە": "چاردە", "حەڤدە": "هەڤدە",
"سی": "سیه", "پەنجا": "پێنجی", "شەست": "شێست",
"هەفتا": "هەفتێ", "هەشتا": "هەشتێ", "نەوەد": "نۆت",
"چوارسەد": "چارسەد", "پێنسەد": "پێنجسەد",
"حەوتسەد": "هەفتسەد", "نۆسەد": "نەهسەد",
"هەزار": "هزار", "ملیۆن": "ملیون",
}
def to_badini_numbers(text):
out = []
for w in text.split():
if w in _SORANI_TO_BADINI:
out.append(_SORANI_TO_BADINI[w])
elif w[:-1] in _SORANI_TO_BADINI and w[-1:] in ('ێ', 'ی'):
out.append(_SORANI_TO_BADINI[w[:-1]] + w[-1])
elif w[:-2] in _SORANI_TO_BADINI and w[-2:] in ('یێ',):
out.append(_SORANI_TO_BADINI[w[:-2]] + w[-2:])
else:
out.append(w)
return " ".join(out)
def expand_numbers(text):
text = re.sub(r'(?<=\d)\s*/\s*(?=\d)', ' ', text)
text = number2word(text)
if USE_BADINI_FORMS:
text = re.sub(r'([،,؟!\.\-\;\:\"\'\»\«\(\)\[\]٪%؛/])', r' \1 ', text)
text = to_badini_numbers(text)
return re.sub(r'\s+', ' ', text).strip()
def normalize_chars(text):
text=text.replace('ك','ک').replace('ى','ی').replace('ي','ی').replace('ة','ە')
text=text.replace('ݒ','پ').replace('ݘ','چ').replace('ݵ','ێ')
text=text.replace('ﻩ','ه').replace('ھ','ه')
return text
def fix_ku_ko(text):
return re.sub(r'\bکو\b', 'کۆ', text)
def normalize_shared(text):
text=re.sub(r'(?<![ا-ی\w])دکەن\b','د کەن',text)
text=re.sub(r'(?<![ا-ی\w])دکەت\b','د کەت',text)
text=re.sub(r'(?<![ا-ی\w])دکەم\b','د کەم',text)
text=re.sub(r'(?<![ا-ی\w])دکەین\b','د کەین',text)
for a,b in [('دگەل','د گەل'),('لسەر','ل سەر'),('لپێش','ل پێش'),('لگەل','ل گەل'),
('بخۆڤە','ب خۆڤە'),('دناڤ','د ناڤ'),('لدویڤدا','ل دویڤدا'),('لدور','ل دور')]:
text=text.replace(a,b)
text=re.sub(r'\bب ڕێکا\b','برێکا',text)
for a,b in [('نەخۆشییا','نەخۆشیا'),('هاتییە','هاتیە'),('بووییە','بوویە'),
('گرێداییی','گرێدایی'),('دەریاییی','دەریایی'),('ئاساییی','ئاسای'),
('ئاسایی','ئاسای'),('پترییا','پتریا')]:
text=text.replace(a,b)
for a,b in [('دور','دۆر'),('توز','تۆز'),('تسونامی','تسۆنامی'),('گورەی','گۆرەی'),
('ڕوژێ','ڕۆژێ'),('تومەتبارکرن','تۆمەتبارکرن')]:
text=text.replace(a,b)
for a,b in [('ڤەگوهازتن','ڤەگوهاستن'),('پێشکەڤتی','پێشکەفتی'),('بەرەڤ','بەرەف'),
('چاڤدێڕیکڕنا','چاڤدێریکرنا'),('بەرامبەر','بەرانبەر')]:
text=text.replace(a,b)
for a,b in [('بچویک','بچیک'),('نموونە','نمونە'),('دووبارە','دوبارە'),
('کۆمپانییێن','کۆمپانیێن'),('نڤێسین','نڤیسین'),('نێزیکی','نیزیکی'),
('زارۆکێن','زاروکێن'),('چاوا','چەوا'),('تەمووزێ','تەموزێ'),
('شێوەیەکێ','شێوەکێ'),('گووت','گوت'),('قۆتابیان','قوتابیان'),
('نیڤدەولەتی','نێڤدەولەتی'),('ئیتاڵی','ئیتالی'),('ئاگاهداریێن','ئاگەهداریێن'),
('هاریکاریا','هاریکارییا'),('گەشتیێن','گەشتییێن'),('ساڵ','سال')]:
text=text.replace(a,b)
return re.sub(r'\s+', ' ', text).strip()
WORD_VARIANTS = {
'خوە':'خۆ', 'دەستپێکێ':'دەسپێکێ', 'دوماهیک':'دویماهیک',
'دویڤ':'دیف', 'گەهە':'گهە',
'بو':'بۆ','خو':'خۆ','کو':'کۆ','کوێ':'کۆێ','کویێ':'کۆیێ','کوژمێ':'کۆژمێ',
'زور':'زۆر','تومارکرن':'تۆمارکرن','نەخوشیا':'نەخۆشیا','مروڤ':'مرۆڤ','مروڤان':'مرۆڤان',
'کومەلێن':'کۆمەلێن','سەروک':'سەرۆک','سەروکێ':'سەرۆکێ','سەروکا':'سەرۆکا',
'فروکە':'فرۆکە','فروکەیەک':'فرۆکەیەک','ڕوژا':'ڕۆژا','ڕوژان':'ڕۆژان',
'توشی':'تووشی','ساڵا':'سالا','ساڵ':'سال','داکو':'دا کو',
'هەروەسا':'هەر وەسا','هەروەسان':'هەر وەسان','هەرچەندە':'هەر چەندە','هەردوو':'هەر دوو',
'بتنێ':'ب تنێ','ژبو':'ژ بۆ','ژبۆ':'ژ بۆ','شورەشا':'شۆڕەشا','پشتراست':'پشتڕاست',
'کەلتور':'کەلتوور','کەلتورێ':'کەلتوورێ','کەلتوری':'کەلتووری','برێكا':'برێکا',
'دەریای':'دەریایی','ساال':'سال','شێوەیەکێ':'شێوەکێ',
}
def strip_invisibles(text):
return re.sub(r'[\u200c\u200d\ufeff\u0640]', '', text)
def collapse_doubles(text):
return text.replace('وو','و').replace('یی','ی')
_DIGIT_MAP = str.maketrans('٠١٢٣٤٥٦٧٨٩', '0123456789')
def _front(text):
text = strip_invisibles(text)
text = ud.normalize('NFKC', text)
text = text.translate(_DIGIT_MAP)
text = normalize_chars(text)
text = expand_numbers(text)
return text
def _back(text):
text = ' '.join(WORD_VARIANTS.get(w, w) for w in text.split())
text = re.sub(r'\bر', 'ڕ', text)
text = fix_ku_ko(text)
text = normalize_shared(text)
text = collapse_doubles(text)
return text
def normalize(text):
text = _front(text)
text = re.sub(r'[،,؟!\.\-\;\:\"\'»«\(\)\[\]٪%؛/]', ' ', text)
return _back(text)
def normalize_punct_ext(text):
text = _front(text)
text = text.replace('?', '؟').replace(',', '،')
text = re.sub(r'([؟،\.\!\(\)«»":؛])', r' \1 ', text)
return _back(text)
def normalize_transcript(text):
"""Recommended: punctuation stripped, word-level normalization.
This is the configuration the model's reported WER/CER are measured on."""
return normalize(text)
def normalize_transcript_keep_punct(text):
"""Alternative: keeps the 11 punctuation marks the model was trained on."""
return normalize_punct_ext(text)
|