Download src/postprocess.py from lab-ii/sakha-ocr: direct link, hf CLI and curl.
- Browser
- Download file 3.09 kB
-
https://huggingface.co/lab-ii/sakha-ocr/resolve/main/src/postprocess.py
- Command line
-
hf download hf://lab-ii/sakha-ocr/src/postprocess.py
-
curl -L -o postprocess.py https://huggingface.co/lab-ii/sakha-ocr/resolve/main/src/postprocess.py
3.09 kB
| """Постобработка распознанного текста словарём якутского языка. | |
| Прямое исправление текста спеллчекером вредит: на 5400 реальных строках оно | |
| подняло долю ошибок с 0.24% до 0.89%, испортив 838 строк против 44 улучшенных. | |
| Спеллчекер не видит изображение и «чинит» имена, русские вставки и обрывки | |
| слов на переносах. | |
| Поэтому словарь здесь только предлагает кандидатов, а решение принимает сама | |
| сеть: замена принимается, если выигрыш языковой модели перевешивает потерю | |
| по CTC. При весе 1.0 такая постобработка не испортила ни одной строки ни на | |
| одной из проверочных выборок, снимая при этом 5–8% ошибок там, где | |
| распознаватель слаб. | |
| Пакет sakhaspell необязателен: без него обработка просто не применяется. | |
| """ | |
| import os | |
| ALPHA = float(os.environ.get("SAKHA_LM_ALPHA", "1.0")) | |
| _state = {"ready": False, "rescore": None} | |
| def _load(): | |
| if _state["ready"]: | |
| return _state["rescore"] | |
| _state["ready"] = True | |
| try: | |
| import sakhaspell # noqa: F401 | |
| except ImportError: | |
| return None | |
| try: | |
| from lm_rescore import Rescorer | |
| except ImportError: | |
| return None | |
| _state["rescore"] = Rescorer | |
| return Rescorer | |
| class Corrector: | |
| """Ленивая обёртка: словарь и языковая модель грузятся при первом вызове.""" | |
| def __init__(self, charset, alpha=ALPHA): | |
| self.charset = charset | |
| self.alpha = alpha | |
| self._r = None | |
| self._tried = False | |
| def available(self): | |
| if not self._tried: | |
| self._tried = True | |
| cls = _load() | |
| if cls is not None: | |
| try: | |
| self._r = cls(self.charset, alpha=self.alpha) | |
| except Exception: | |
| self._r = None | |
| return self._r is not None | |
| def __call__(self, texts, logprobs): | |
| """Строки идут в порядке чтения, поэтому перенос виден по предыдущей.""" | |
| if not self.available(): | |
| return texts | |
| out, prev_hyphen = [], False | |
| for t, lp in zip(texts, logprobs): | |
| if not t or lp is None: | |
| out.append(t) | |
| prev_hyphen = bool(t) and t.rstrip().endswith(("-", "\u2010", "\u2011")) | |
| continue | |
| try: | |
| out.append(self._r(lp, t, prev_hyphen=prev_hyphen)) | |
| except Exception: | |
| out.append(t) | |
| prev_hyphen = t.rstrip().endswith(("-", "\u2010", "\u2011")) | |
| return out | |