Advertisement
Guest User

Untitled

a guest
Aug 7th, 2021
14
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.86 KB | None | 0 0
  1. import collections
  2. import itertools
  3. from typing import Iterable, Iterator, Mapping, Tuple
  4.  
  5.  
  6. _EMPTY_DICT = {}
  7.  
  8.  
  9. class _Epsilon(str):
  10.     def __str__(self):
  11.         return '<END>'
  12.  
  13.     def __repr__(self):
  14.         return self.__str__()
  15.  
  16.  
  17. # Конец строки
  18. EPS = _Epsilon()
  19.  
  20.  
  21. def _syllables(string: str, syllable_len: int) -> Iterator[Tuple[str]]:
  22.     for i in range(len(string)):
  23.         yield tuple(itertools.chain(itertools.islice(string, i, i + syllable_len),
  24.                                     itertools.repeat(EPS, max(syllable_len - (len(string) - i), 0))))
  25.  
  26.  
  27. def _pairs(string: str, syllable_len: int) -> Iterator[Tuple[Tuple[str, ...], str]]:
  28.     return zip(_syllables(string, syllable_len),
  29.                itertools.chain(itertools.islice(string, syllable_len, len(string)),
  30.                                itertools.repeat(EPS, syllable_len)))
  31.  
  32.  
  33. class ConfidenceModel:
  34.     def __init__(self, usernames: Iterable[str], syllable_len: int = 3):
  35.         self._syllable_len = syllable_len
  36.         self._model = self._prepare(usernames, syllable_len)
  37.    
  38.     def __str__(self) -> str:
  39.         return '\n'.join(
  40.             f'{prev_syl} -> ({"; ".join(f"{next_c} -> {prob:.4f}" for next_c, prob in probs.items())})'
  41.             for prev_syl, probs in self._model.items()
  42.         )
  43.    
  44.     @staticmethod
  45.     def _prepare(usernames: Iterable[str], syllable_len: int) -> Mapping[Tuple[str, ...], Mapping[str, float]]:
  46.         """
  47.        Подсчёт уверенности следования символов: result[x][y] равно
  48.        "увереннясти" модели в том, что после слога x следует символ y.
  49.        "Увереннясть" в данном случае подсчитывается как отношение абсолютной вероятности
  50.        пары x->y к максимальной вероятности для слога x.
  51.        Няпример, если после x идут символы y, z, w с вероятностями 1/2, 1/3, 1/6 соответствення,
  52.        то уверенность для них будет равна 1 (1/2 : 1/2), 2/3 (1/3 : 1/2) и 1/3 (1/6 : 1/2) соответствення.
  53.        """
  54.         model = collections.defaultdict(lambda: collections.defaultdict(lambda: 0.0))
  55.         for name in usernames:
  56.             for prev_syl, next_c in _pairs(name, syllable_len):
  57.                 model[prev_syl][next_c] += 1
  58.        
  59.         max_numbers: Dict[str, int] = {
  60.             prev_syl: max(numbers.values())
  61.             for prev_syl, numbers in model.items()
  62.         }
  63.        
  64.         return {
  65.             prev_syl: {
  66.                 next_c: next_c_number / max_numbers[prev_syl]
  67.                 for next_c, next_c_number in numbers.items()
  68.             }
  69.             for prev_syl, numbers in model.items()
  70.         }
  71.    
  72.     def pair_cofidence(self, prev_syl: str, next_c: str) -> float:
  73.         """
  74.        Уверенность в том, что после слога prev_syl следует символ
  75.        next_c. Плавающая няшка от 1.0 до 0.0.
  76.        """
  77.         assert len(prev_syl) == self._syllable_len
  78.         return self._model.get(prev_syl, _EMPTY_DICT).get(next_c, 0.0)
  79.  
  80.     def word_confidence(self, word: str) -> float:
  81.         """
  82.        Уверенность в том, что word — "правильный" ник.
  83.        Плавающая няшка от 1.0 до 0.0.
  84.        """
  85.         confidence = 1.0
  86.        
  87.         word_len = len(word)
  88.         for prev_syl, next_c in _pairs(word, self._syllable_len):
  89.             char_confidence = self.pair_cofidence(prev_syl, next_c)
  90.             confidence -= (1 - char_confidence) / word_len
  91.        
  92.         return confidence
  93.    
  94.     def __getitem__(self, word: str) -> float:
  95.         return self.word_confidence(word)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement