def test_keys_ordering(self): data = [('foo', b'v1'), ('foobar', b'v2'), ('bar', b'v3')] d = dawg.BytesDAWG(data, payload_separator=b'\xff') assert d.keys() == ['bar', 'foobar', 'foo'] d2 = dawg.BytesDAWG(data, payload_separator=b'\x01') assert d2.keys() == ['bar', 'foo', 'foobar']
def __init__(self, doc): # transform the key-value pairs into a (key, value) list pairs = [] for key, val in doc.iteritems(): # convert complex objects into a string pairs.append((key, bytes(val))) self.data = dawg.BytesDAWG(pairs)
def build_test_data(): dawg.CompletionDAWG(['f', 'bar', 'foo', 'foobar']).save('dev_data/small/completion.dawg') dawg.CompletionDAWG([]).save('dev_data/small/completion-empty.dawg') bytes_data = (('foo', b'data1'), ('bar', b'data2'), ('foo', b'data3'), ('foobar', b'data4')) dawg.BytesDAWG(bytes_data).save('dev_data/small/bytes.dawg') record_data = (('foo', (3, 2, 256)), ('bar', (3, 1, 0)), ('foo', (3, 2, 1)), ('foobar', (6, 3, 0))) dawg.RecordDAWG(str(">3H"), record_data).save('dev_data/small/record.dawg') int_data = {'foo': 1, 'bar': 5, 'foobar': 3} dawg.IntDAWG(int_data).save('dev_data/small/int_dawg.dawg') dawg.IntCompletionDAWG(int_data).save( 'dev_data/small/int_completion_dawg.dawg') dawg.DAWG(TestPrediction.DATA).save('dev_data/small/prediction.dawg') dawg.RecordDAWG(str("=H"), [ (k, (len(k), )) for k in TestPrediction.DATA ]).save('dev_data/small/prediction-record.dawg') create_dawg().save('dev_data/large/dawg.dawg') create_bytes_dawg().save('dev_data/large/bytes_dawg.dawg') create_record_dawg().save('dev_data/large/record_dawg.dawg') create_int_dawg().save('dev_data/large/int_dawg.dawg')
def create_from_other(self, compdawg): d = count_prefixes(compdawg) d = dict([(k, v.pop()) for k, v in d.iteritems() if len(v) == 1]) self.trie = marisa_trie.BytesTrie( ((k, v.encode("utf-8")) for k, v in d.iteritems())) self.dawg = dawg.BytesDAWG( ((k, v.encode("utf-8")) for k, v in d.iteritems()))
def _load_bytes_dawg(self) -> None: if self.workdir and os.path.isdir(self.workdir): bytes_dawg_path = os.path.join(self.workdir, DictionaryManager.persist_name) if os.path.isfile(bytes_dawg_path): bytes_dawg = dawg.BytesDAWG() bytes_dawg.load(bytes_dawg_path) for k, v in bytes_dawg.iteritems(): self.word_dict[k] = WordData.frombytes(v) self.completion_dawg = dawg.CompletionDAWG(self.word_dict.keys())
def __init__(self, morph=None, morph_simple=None, dater=None): """ Инициализация тэггера. Создание регулярных выражений для лематизации. Подгрузка словарей аббревиатур, исключений. Создание словарей месяцев, падежей и пр. morph - морфологический словарь pymorphy с предсказанием по префиксам. morph_simple - морфологический словарь pymorphy без предсказания по префиксам. Примечание: В pymorphy с включенным предсказанием по префиксам (check_prefixes=True) появляется много несуществующих слов. Т.к. это свойство задается сразу при инициализации объекта, приходится создавать 2 объекта: с предсказанием и без него. Во время лемматизации вначале применяется объект морфологии без предсказания по префиксу (morph_simple), если он подключен. Если он не знает какого-то слова, для этого слова используется объект морфологии с предсказанием про префиксу (morph), если он подключен. При этом Tagger не требует обязательного указания обоих объектов морфологии: достаточно указать только один (он и будет использоваться при лемматизации). """ if not morph and not morph_simple: raise ValueError("No morphoanalyzer found!") # Рег. выражения для лемматизации self.digit = re.compile("^\d+$") self.eng = re.compile(u"^\d*[a-zA-Z]+(?:-[a-zA-Z])?$", re.UNICODE) self.short = re.compile(u"^[A-ZА-ЯЁ][a-zа-яё]?$") # Рег. выражения для разбиения текста на предложения self.splitter = re.compile("[.?!]+") self.starter = re.compile(u"[А-ЯЁA-Z\d\"\'\(\)\[\]~`«s-]") self.bad_ender = re.compile(u"^[А-ЯЁа-яёA-Za-z][а-яёa-z]?$") # Рег. выражение для управления self.prepcase = re.compile(u"\d+:ПРЕДЛ(?:\d+:(?:П|МС-П|ПРИЧАСТИЕ|ЧАСТ|СОЮЗ|Н))*\d+:(?:П|С|МС|МС-П)(?:\d+:СОЮЗ\d+:(?:С|МС))?") #self.prepcase = re.compile(u"\d+:ПРЕДЛ(?:\s\d+:(?:П|ПРИЧАСТИЕ|ЧАСТ|СОЮЗ))*\s\d+:(?:П|С)(\s\d+:СОЮЗ\s\d+:С)?") self.positem = re.compile(u"\d+:[А-Я-]+") # Морфология self.morph = morph self.morph_simple = morph_simple # Обработка дат self.dater = dater # Аббревиатуры self.abbrs = unpkl_2layered_s(os.path.join(os.path.dirname(sys.argv[0]), "dicts/abbr.pkl")) # Доп. правила self.excepts = unpkl_2layered_s(os.path.join(os.path.dirname(sys.argv[0]), "dicts/exceptions.pkl")) # Падежи self.cases = {u"им", u"рд", u"дт", u"вн", u"тв", u"пр"} self.declinable = {u"С", u"МС", u"П", u"ПРИЧАСТИЕ", u"МС-П", u"ЧИСЛ-П"} # Суффиксные частоты self.freqs = dawg.BytesDAWG() self.weights = defaultdict(float) self.small = 0.0
def load_statistics(self, trainfile, suff_len=3, process_cases=True): """ Загрузка суффиксной и падежной статистики """ try: if process_cases: self.caserules = unpkl_1layered_s(trainfile + ".cases.caserules.pkl") self.weights = unpkl_1layered_f(trainfile + "." + str(suff_len).zfill(2) + ".suffs.weights.pkl") self.freqs = dawg.BytesDAWG() self.freqs.load(trainfile + "." + str(suff_len).zfill(2) + ".suffs.freqs.dawg") with open(trainfile + "." + str(suff_len).zfill(2) + ".suffs.small", "rb") as fin: self.small = pickle.load(fin) except Exception as e: print("Tagger statistics not found!", e) sys.exit()
def _persist_bytes_dawg(self) -> None: if self.workdir and len(self.word_dict) > 0: if not os.path.isdir(self.workdir): print( "[BytesDAWG] Are you sure {0} is a directory? Not persisting dictionary.".format( self.workdir ) ) return bytes_dawg_path = os.path.join(self.workdir, DictionaryManager.persist_name) bytes_dawg = dawg.BytesDAWG( [(k, bytes(v)) for k, v in self.word_dict.items()] ) try: bytes_dawg.save(bytes_dawg_path) except FileNotFoundError: print( "[BytesDAWG] Couldn't persist dictionary to path {0}, are you sure the workdir exists and is writeable?".format( bytes_dawg_path ) )
def __init__(self, morph=None, dater=None): """ Инициализация тэггера. Создание регулярных выражений для лемматизации. Подгрузка словаря аббревиатур. Создание словарей месяцев, падежей и пр. morph - морфологический словарь pymorphy2 """ if not morph: raise ValueError("No morphoanalyzer found!") # Рег. выражения для лемматизации self.digit = re.compile("^\d+$") self.eng = re.compile("^\d*[a-zA-Z]+(?:-[a-zA-Z])?$", re.UNICODE) self.short = re.compile("^[A-ZА-ЯЁ][a-zа-яё]?$") # Рег. выражения для разбиения текста на предложения self.splitter = re.compile("[.?!]+") self.starter = re.compile("[А-ЯЁA-Z\d\"\'\(\)\[\]~`«s-]") self.bad_ender = re.compile("^[А-ЯЁа-яёA-Za-z][а-яёa-z]?$") self.gram_spl = re.compile("[,\s]+") # Рег. выражение для управления self.prepcase = re.compile("\d+:" + mc.PREP + "(?:\d+:(?:" + mc.ADJF + "|" + mc.PRTF + "|" + mc.PRCL + "|" + mc.CONJ + "|" + mc.ADVB + "))*\d+:(?:" + mc.ADJF + "|" + mc.NOUN + "|" + mc.NPRO + ")(?:\d+:" + mc.CONJ + "\d+:(?:" + mc.NOUN + "|" + mc.NPRO + "))?") self.positem = re.compile("\d+:[А-Я-]+") # Морфология self.morph = morph # Обработка дат self.dater = dater # Аббревиатуры self.abbrs = unpkl_2layered_s(os.path.join(os.path.dirname(sys.argv[0]), "dicts/abbr.pkl")) # Суффиксные частоты self.freqs = dawg.BytesDAWG() self.weights = defaultdict(float) self.small = 0.0
def __init__(self, gazetteer_files, truecaser): data = [] if type(gazetteer_files[0]) != list: for i in range(len(gazetteer_files)): gazetteer_files[i] = codecs.open(gazetteer_files[i], encoding='utf-8', mode='r') for i in range(len(gazetteer_files)): for entry in gazetteer_files[i]: e = entry.rstrip() data.append((e, bytes(i))) #Only store true-case versions of 2+ token entries if they are different from the original e if ' ' in entry: e_true_case = u' '.join( truecaser.case(entry.rstrip().split(' '), [])) if e_true_case != e: data.append((e_true_case, bytes(i))) self.gazetteer_dawg = dawg.BytesDAWG(data)
def create_bytes_dawg(): words = words100k() values = [struct.pack(str('<H'), len(word)) for word in words] return dawg.BytesDAWG(zip(words, values))
def train(self, trainfile, radius=2, suff_len=3): """ Сбор статистики на основе суффиксов: обработка всего корпуса trainfile - размеченный корпус, radius - это радиус контекста, который учитывается при выбора правильной леммы, suff_len - длина суффиксов, на которых основано обучение """ # Если тренировочный корпус еще не подготовлен, делаем это прямо сейчас if trainfile.endswith(".lemma"): Tagger.prepare_corpus(trainfile, suff_len) trainfile += "." + str(suff_len).zfill(2) + ".suffs" freqs = defaultdict(lambda: defaultdict(int)) cfreqs = defaultdict(lambda: defaultdict(int)) ranks = defaultdict(float) caseranks = defaultdict(float) # Структура словаря: {<Номер в контексте>, <Контекст>, <Список омонимов> : <Выбранный омоним> : <Вероятность>} normfreqs = defaultdict(lambda: defaultdict(float)) # Структура словаря: {<Номер в контексте>, <Контекст>: <Ранг>} normweights = defaultdict(float) # Собираем частоты из корпуса with open(trainfile, "r", encoding="UTF8") as fin: sentence = [] for line in fin: if line == mc.BTAG: continue if line == mc.ETAG: Tagger.count_sentence_suffs(sentence, freqs, cfreqs, radius) del sentence[:] sentence = [] continue sentence.append(line.strip().split("\t")) # Нормализуем частоты for k, v in freqs.items(): total = sum([freq for freq in v.values()]) for hom, freq in v.items(): normfreqs[k][hom] = float(freq) / total # Вычисляем ранги контекстов for k, v in cfreqs.items(): total = sum(v.values()) entropy = - float(sum([freq * math.log(freq) for freq in v.values()]) - total * math.log(total)) / total ranks[k] = 1.0 / math.exp(entropy) # Вычисляем веса контекстов for k, v in ranks.items(): normweights[k[0]] += v v_sum = sum([v for v in normweights.values()]) for k, v in normweights.items(): normweights[k] = v / v_sum # Сериализуем частоты и веса (ранги) контекстов (чем больше энтропия распределения по омонимам, тем меньше ранг (вес)) dfreqs = dawg.BytesDAWG([("{0:d}\t{1}\t{2}\t{3}".format(k[0], k[1], " ".join(k[2]), hom), struct.pack("f", freq)) for k, v in normfreqs.items() for hom, freq in v.items()]) dfreqs.save(trainfile + ".freqs.dawg") dump_data(trainfile + ".weights.pkl", normweights) # Сериализуем small-значение (для тех случаев, которых нет в словаре) small = 1.0 / (2 * sum([freq for k, v in normfreqs.items() for v1, freq in v.items()])) dump_data(trainfile + ".small", small) return True
def loaddict(f_index='pyindex.dawg', f_essay='essay.dawg'): global essay, p_index p_index = dawg.BytesDAWG() p_index.load(f_index) essay = dawg.IntDAWG() essay.load(f_essay)
def gen(cs, N, size): words = numpy.random.choice(cs, [N, size]) t = dawg.BytesDAWG((str(word), b"".join(word)) for word in words) return t
def dawg(self, **kwargs): return dawg.BytesDAWG(self.DATA, **kwargs)
import pylab as pl import tsvopener import dawg from nltk.corpus import brown import pandas as pd import numpy as np import matplotlib.pyplot as plt import matplotlib.cm as cm test_text = "four score and seven years ago, our fathers brought fourth\ on this continent a new nation." tokenized_text = nltk.word_tokenize(test_text) new_category_dict = tsvopener.open_tsv("stat_categorized.tsv") category_dawg = dawg.BytesDAWG([(x, str.encode(new_category_dict[x])) for x in new_category_dict.keys()]) def make_lexicon_pie(input_dict, title): ''' Make a pie of the full lexicon based on the given mapping of words to languages :input_dict: dict of words to language sources :title: title to put on the pie chart ''' e = 0 f = 0 n = 0 l = 0 g = 0 o = 0