def bracket_mask(self, text): text_temp = re.sub("\[", "<<", text) text_temp = re.sub("\]", ">>", text_temp) text_temp = re.sub("\+", "===", text_temp) parenthesis = re.findall("\([^()]*\)", text_temp) bracket = re.findall("\[[^\[\]]*\]", text) if not parenthesis and not bracket: return text for p in parenthesis: p = re.sub("[\(\)]", "", p) parts = [re.sub("\.\s*$", "", s) for s in ru_sent_tokenize(p)] new_p = " ; ".join(parts) #print ("P:", p) #print("new_p:",new_p,"\n") #print("text_temp:",text_temp) text_temp = re.sub(p, new_p, text_temp) text = re.sub("<<", "[", text_temp) text = re.sub(">>", "]", text) text = re.sub("===", "+", text) bracket = re.findall("\[[^\[\]]*\]", text) for p in bracket: p = re.sub("[\[\]]", "", p) parts = [re.sub("\.\s*$", "", s) for s in ru_sent_tokenize(p)] #parts = [re.sub("\.\s*$","",re.sub("\[","\[", re.sub("\]","\]",s))) for s in ru_sent_tokenize(p)] new_p = " ; ".join(parts) #print ("OLD:",p,"\n","NEW:",new_p) text = re.sub(p, new_p, text) return text
def main(): filename = input('Введите название файла с текстом в кодировке utf-8: ') text = reader(filename) sentences = ru_sent_tokenize(text) pos_list = pos_analyze(text) parameters = { 'V' : 0.0, 'S' : 0.0, 'A' : 0.0, 'SPRO' : 0.0, 'PART' : 0.0, 'DYN' : 0.0, 'SENTLEN' : 0.0 } count(pos_list, parameters) sent_count(sentences, parameters) points = award(parameters) sum_points = sum(points.values()) percents = {} for key, value in points.items(): num = round(value / sum_points * 100, 2) percents[key] = str(num) + '%' answer = ['Этот текст на ', percents['FIC'], ' относится к художественному стилю;\nна ', percents['PUB'],\ ' – к публицистическому;\nна ', percents['SCI'], ' – к научному;\nна ', percents['DOC'], ' – к деловому.'] print(''.join(answer))
def tokenize_with_lemmatization(text, min_len=min_sent_len, remove_stopwords=False): """tokenize and lemmatize text Parameters ---------- text : str text to process min_len : int minimum length of sentence to remain remove_stopwords: bool flag whether remove stop words """ text = preprocess_text(text) sentences = ru_sent_tokenize(text) res = [] cleaned_sentences = [] for sentence in sentences: sentence = sentence.strip() if len(sentence) >= min_len: res_sent = [] for word in word_tokenize(sentence): word = lemmatize_word(word, remove_stopwords) res_sent.append(word) cleaned_sentences.append(' '.join(res_sent)) res.append(sentence) return res, cleaned_sentences
def _sentence_collection(text_without_tables): shortenings_ = { 'зав', 'куб', 'о', 'тыс', 'мин', 'букв', 'обл', 'сек', 'русск', 'зам', 'коп', 'повел', 'яз', 'прим', 'гос', 'муж', 'обр', 'ед', 'рус', 'га', 'искл', 'дол', 'долл', 'авт', 'corp', 'корп', 'мн', 'жен', 'адм', 'ред', 'лат', 'проц', 'р', 'таб', 'мэр', 'юл', 'ул', 'евр', 'наст', 'км', 'кп', 'инн', 'ук', 'ип', 'ооо', 'пао', 'гк', 'пм' } #joining_shortenings_={'пл', 'см', 'св', 'кит', 'устар', 'стр', 'пер', 'ул', 'евр', # 'г', 'слав', 'им', 'д', 'тел', 'корп', 'рис', 'п', 'наст',"дог",'т','ч', # 'гг','увдо','доп','руб','млн','тыс', 'юр','физ','таб', 'рук', 'т.ч.', 'т.ч', 'т ч', # 'кв','эл',"м","с","т",'эт','мес','яр',"шт","млн", 'тыс','руб', 'cм', 'см'} joining_shortenings_ = {} paired_shortenings_ = {('т', 'п'), ('т', 'е'), ('у', 'е'), ('н', 'э'), ('и', 'о'), ('т', 'к'), ('т', 'д'), ('д', 'в'), ('т', 'ч'), ('с', 'м')} sentences = [] for sentence in text_without_tables: sentences.append( ru_sent_tokenize(sentence, shortenings=shortenings_, joining_shortenings=joining_shortenings_, paired_shortenings=paired_shortenings_)) sentences = [j for i in sentences for j in i] sentences = [i for i in sentences if len(i) > 0] return sentences
def split_sentences(html): """делим на предложения основную часть приговора""" soup = BeautifulSoup(html, 'html.parser') for script in soup(["script", "style"]): script.decompose() text = soup.text begin, main_part, end = divide_into_parts(text) return ru_sent_tokenize(main_part)
def sent_tokenize(self, text, word_tokenize=True, mask=True): #text = re.sub(";",".",text) if mask == True: text_after_mask = self.bracket_mask(text) else: text_after_mask = text text_after_word = " ".join(self.word_tokenize(text_after_mask)) sentences = ru_sent_tokenize(text_after_word) return sentences
def parse_json_line(path_nerus, n=30000, save_to='train_nerus.txt'): flag = 0 file = open(save_to, 'w+') for indx, text in tqdm(enumerate(load_gz_lines(path_nerus))): left_context_len, right_context_len = -1, -1 flag += 1 for sentence in ru_sent_tokenize(text['content']): left_context_len, right_context_len = right_context_len + 1, ( right_context_len + len(sentence)) + 1 annotation = (sentence, []) for indx, span in enumerate(text['annotations']): st_en = span['span'] if int(st_en['start']) >= left_context_len and int( st_en['end']) <= right_context_len: span = text['annotations'][indx] span['span']['start'] -= left_context_len span['span']['end'] -= left_context_len annotation[1].append(span) start = 0 labels = [] words = [] for ann in annotation[1]: piece = sentence[start:ann['span']['start']] ws = wordpunct_tokenize(piece) words += ws + [ann['text']] labels += (['O'] * len(ws)) + [ann['type']] start = ann['span']['end'] piece = sentence[start:] ws = wordpunct_tokenize(piece) words += ws labels += (['O'] * len(ws)) assert len(labels) == len( words), 'Mismatch len labels ans len sentence' for word, tag in zip(words, labels): file.write(word + ' ' + tag + '\n') file.write('\n') if flag == n: print('First {} lines executed'.format(n)) file.close() break
def sent_tokenize(self, text, word_tokenize=True, mask=False): #text = re.sub(";",".",text) if mask == True: text_after_mask = self.bracket_mask(text) else: text_after_mask = text # special characters text_after_mask = re.sub(" v\.?s\.? ", " vs ", text_after_mask) text_after_word = text_after_mask #text_after_word = " ".join(self.word_tokenize(text_after_mask)) sentences = ru_sent_tokenize(text_after_word) return sentences
def tokenize(text, min_len=25): """tokenize text Parameters ---------- text : str text to process min_len : int minimum length of sentence to remain """ text = preprocess_text(text) sentences = ru_sent_tokenize(text) res = [] for sentence in sentences: sentence = sentence.strip() if len(sentence) >= min_len: res.append(sentence) return res
def parsing(inputText): # текст - текст (list) + его абзацы text = {"text": inputText, "paragraphs": []} # параграфы - list параграфов paragraphs = text["text"] for p in paragraphs: # параграф - текст парграфа + предложения paragraph = {"paragraph": p, "sentences": []} text["paragraphs"].append(paragraph) # производим токенизацию предложений с использованием nltk sentences = ru_sent_tokenize(p) for s in sentences: # предложение - текст предложения + предложения + информация (для будущих шагов) sentence = {"sentence": s, "lexems": [], "info": []} text["paragraphs"][-1]["sentences"].append(sentence) # производим токенизацию предложений с использованием nltk lexems = nltk.word_tokenize(s, language="russian") for l in lexems: # лексема - лексема + варианты её морф.значений (из словаря pymorphy2) lexem = {"lexem": l, "variants": []} text["paragraphs"][-1]["sentences"][-1]["lexems"].append(lexem) morph = MorphAnalyzer().parse(l.lower()) morphCount = len(morph) wordCount = 0 for i in range(morphCount): # если вероятность слова > вероятности междометия (отн. других) # И ( # норм.форма == самой лексеме # ИЛИ ( # длина норм.формы менее, чем в 3 раза превышает длина лексемы # И данный вариант не "UNKN" # (иначе дальнейший такого варианта не имеет смысла) # ) # ) if morph[i].score >= 0.01 and ( morph[i].normal_form == l.lower() or len(morph[i].normal_form) // len(l) < 3 and {'UNKN'} not in morph[i].tag): # print(morph[i].normal_form, slovo.lower()) wordCount += 1 lexem["variants"].append(morph[i].tag) return text
def files2sentences_df(paths, min_char_len=1): # remove tags clean = re.compile(r"<.*?>") ws_clean = re.compile(r"\s+|\"+") res = [] total = len(paths) for f_name in tqdm(paths, total=total, leave=False, desc="files2sentences_df"): with open(f_name, "r", encoding="utf-8") as f: text = " ".join( [x.strip() for x in f.readlines()[2:-1] if len(x.strip())]) text = clean.sub(" ", text) text = ws_clean.sub(" ", text) if len(text): for sent in ru_sent_tokenize(text): if len(sent) > min_char_len: res.append(sent) return pd.DataFrame({"text": res})
def input(): sents = ru_sent_tokenize(input_text) for result in sents: #смотрим, как разделяет rusclasp clauses_num = [] begins = [] ends = [] split_punc = [] rusclasp_clauses = [] s = rusclasp.Splitter() result = s.split(input_text) entities = result['entities'] for section in entities: sec_num = section[2] clauses_num.append(sec_num) begins.append(sec_num[0][0]) ends.append(sec_num[0][1]) split_punc.append(sec_num[0][1] + 1) for x in sec_num: clause = input_text[x[0]:x[1]] rusclasp_clauses.append(clause) #проверяем, не выделил ли отдельно вводные конструкции with open('constructions.txt', 'r', encoding='utf-8') as f: constructions = f.read() for const in constructions.split('\n'): for rus_clause in rusclasp_clauses: if rus_clause != const: pass #тут нужно просто вывести ЭДЕ, так как в предложении нет вводных конструкций else: i=0 for rus_cl in rusclasp_clauses: if rus_cl == const: split_punc = split_punc table(split_punc) clause_section = clauses_num[i] linking_words(clause_section, split_punc) else: i+=1
def tokenize(self, text): return rusenttokenize.ru_sent_tokenize(text)
def __call__(self, batch: [str]) -> [[str]]: return [ ru_sent_tokenize(x, self.shortenings, self.joining_shortenings, self.paired_shortenings) for x in batch ]
def nltk_sent_and_tok(in_line): sentences = ru_sent_tokenize(in_line) line = [' '.join(word_tokenize(sentence)) for sentence in sentences] return line
def run(self, data: list): super().run(data) if len(data) != 2 or not isinstance(data[0], set) or not isinstance( data[1], str): raise ArgumentError( "Error data for relation extraction. " "Argument 'data' must be a List with 2 values, " "where first element is a set of keywords and " "second element is a string with text or filename") if len(data[1]) == 0: raise ArgumentError("Argument 'data[1]' string must not be empty") self.data.set_concepts(list(data[0])) keywords = sorted(data[0], key=len, reverse=True) if os.path.isfile(data[1]): if os.path.getsize(data[1]) == 0: raise FileDataError("Argument 'data[1]' is empty file") with open(data[1], 'r', encoding='utf-8') as file: data = file.read() else: data = data[1] data = data.lower() data = ru_sent_tokenize(data) nltk.download('punkt') if len(keywords) > 0: for isentence, sentence in tqdm( enumerate(data), desc="Preparing sentences for relation extraction"): num_entity = 1 sentence_words = word_tokenize(sentence, language="russian") sentence_words_normal = [ self.morph.parse(sentence_word)[0].normal_form for sentence_word in sentence_words ] for keyword in keywords: keyword_words = word_tokenize(str(keyword), language="russian") pos_start = None symbol = None if len(keyword_words) > 1: index_start = sentence.find(str(keyword)) if index_start > -1: pos_start = index_start symbol = sentence[pos_start + len(keyword)] pos_end = pos_start + len(keyword) else: try: index_start = sentence_words_normal.index(keyword) except ValueError: index_start = -1 if index_start > -1: pos_start = sentence.find( sentence_words[index_start]) symbol = sentence[pos_start + len(sentence_words[index_start])] pos_end = pos_start + len( sentence_words[index_start]) if index_start > -1: tag_pos = sentence.find('<', pos_start) if not symbol.isalnum() and sentence[tag_pos + 1] != '/': # pos_end = pos_start + len(sentence_words[index_start]) data[isentence] = data[ isentence][:pos_end] + ' </e' + str( num_entity ) + '>' + data[isentence][pos_end:] data[isentence] = data[ isentence][:pos_start] + '<e' + str( num_entity ) + '> ' + data[isentence][pos_start:] sentence = data[isentence] if num_entity == 1: self.pairs.append({}) self.pairs[len(self.pairs) - 1]['e1'] = keyword num_entity = 2 else: self.pairs[len(self.pairs) - 1]['e2'] = keyword break ipair = 0 while ipair < len(self.pairs): if len(self.pairs[ipair]) < 2: del self.pairs[ipair] ipair -= 1 ipair += 1 try: dataset = self.__convert_lines(data) sampler = torch.utils.data.SequentialSampler(dataset) loader = torch.utils.data.DataLoader(dataset, sampler=sampler, batch_size=1) result = self.__evaluate(loader) except: raise RelationExtractionError( 'Error occured during tokenization data for relation extraction. ' 'Please, check your data is not empty and contains russian text' ) for i, concepts in enumerate(self.pairs): self.data.add_relation(result[i], concepts['e1'], concepts['e2']) return self.data
def process_sentences_batch(self, sentences, min_advantage_treshold=1.0, max_tokens_count=None, token_length_sorting=True, supply_anal_dict=False, multisentences=False): """ Interface method for batchy estimation of corrections Given a batch of sentences it returns a batch of corrections :param sentences: list of input sentences :param supply_anal_dict: if true then returns anal dicts for all sentences, used for debugging and analysis of errors :param multisentences: if true then each element of batch may be a multiple sentence string, so we preprocess them by splitting into sentences. :return: list of corrected sentences """ if not max_tokens_count: max_tokens_count = ELMO_BATCH_TOKEN_SIZE # ############################################################################### if multisentences: # TODO make as function decorator? # we expect each input string is a multisentence, we need to split them into sentences # and then process it, after that we need to restore sentence structure by joining # sentences that occured in the same input string. # list of elementary sentences which are retrieved from input by sentence splitting: flat_sents_list = [] # list which stores how many consequent sentences are must be joined into one input string list_of_lengths = [] for each_string in sentences: el_sents = ru_sent_tokenize(each_string) list_of_lengths.append(len(el_sents)) flat_sents_list += el_sents sentences = flat_sents_list # ############################################################################### if token_length_sorting: # TODO make as function decorator? # sort sentences by token length # and save initial order # TODO use nltk tokenizer insted of split? - no speed advantage # results = sorted(enumerate(sentences), key=lambda x: len(x[1].split()), reverse=True) results = sorted(enumerate(sentences), key=lambda x: len(word_tokenize(x[1])), reverse=True) source_idxs, sentences = zip(*results) # ############################################################################### start_dt = dt.datetime.now() anal_dicts = self.prepare_analysis_dict_for_sentences_batch( sentences, max_tokens_count=max_tokens_count) middle_dt = dt.datetime.now() print("datetimes. calculation of elmo analysis dicts: %s" % (str(middle_dt - start_dt))) output_sentences = [] for sent_idx, each_data in enumerate(anal_dicts): sentence_hypothesis = self.make_fixes(each_data, min_advantage_treshold) # Letter caser: # restore capitalization: # output_sentence_tokens = self._lettercaser([each_data['input_sentence'].split()], # [sentence_hypothesis.split()])[0] output_sentence_tokens = self._lettercaser( [word_tokenize(each_data['input_sentence'])], [word_tokenize(sentence_hypothesis)])[0] # output_sentence = " ".join(output_sentence_tokens) output_sentence = detokenize(output_sentence_tokens) # output_sentences.append(sentence_hypothesis) output_sentences.append(output_sentence) fin_dt = dt.datetime.now() print("datetimes. making_fixes: %s" % (str(fin_dt - middle_dt))) print("datetimes. total calculation time: %s" % str(fin_dt - start_dt)) # ############################################################################### # restore ordering: # to return results in the same order if token_length_sorting: output_sentences_2 = [None] * len(sentences) anal_dicts_sorted = [None] * len(sentences) for idx, each_sentence in enumerate(output_sentences): output_sentences_2[source_idxs[idx]] = each_sentence anal_dicts_sorted[source_idxs[idx]] = anal_dicts[idx] anal_dicts = anal_dicts_sorted output_sentences = output_sentences_2 # ############################################################################### if multisentences: merged_sentences = [] merged_anal_dicts = [] sent_offset = 0 for each_length in list_of_lengths: # join each_length of output sentences into one and continue merged_sentence = " ".join( output_sentences[sent_offset:sent_offset + each_length]) merged_anal_dict_for_merged_sentences = anal_dicts[ sent_offset:sent_offset + each_length] sent_offset += each_length merged_sentences.append(merged_sentence) merged_anal_dicts.append(merged_anal_dict_for_merged_sentences) output_sentences = merged_sentences if supply_anal_dict: anal_dicts = merged_anal_dicts # ############################################################################### if supply_anal_dict: # TODO: anal_dicts has different sorting! Fix it? return output_sentences, anal_dicts else: return output_sentences
f.write("\n") f.write("Стемм: " + wordstem) f.write("\n") f.write("Потенциальные ошибки: ") f.write("\n") cleanMatches = set(matches) for curr in cleanMatches: f.write(curr) f.write("\n") counter += 1 text = remove_tags_1(text) punctuation = string.punctuation text = text.lower() sentences = ru_sent_tokenize(text) print("1//5!!!!!!!!!!!!!!!!!!") f.write("Предложения: ") f.write("/n") f.writelines(sentences) f.write("\n") [word.strip(string.punctuation) for word in sentences] words = word_tokenize(text) f.write("Слова: ") f.write("\n") listofwords = [] for current in words: listofwords.append(current) f.write(current) f.write("\n") duplicates = findDuplicates(sentences)
def load_wiki(file_name: str): """ Load the Wikipedia dump, tokenize all texts from this dump by sentences and create a generator. :param file_name: :return: a generator for each news line (all such lines are prepared and tokenized by sentences). """ with gzip.open(file_name, mode="rt", encoding="utf-8") as fp: cur_line = fp.readline() while len(cur_line) > 0: prep_line = cur_line.strip() if len(prep_line) > 0: yield from filter(lambda it2: len(it2) > 0, map(lambda it1: it1.strip(), ru_sent_tokenize(prep_line))) cur_line = fp.readline()
def __call__(self, batch: [str]) -> [[str]]: return [ru_sent_tokenize(x, self.shortenings, self.joining_shortenings, self.paired_shortenings) for x in batch]
for line in fin: if i >= num_lines: break i += 1 pbar.update(1) if args.news: line = line.strip() try: sents = json.loads(line.split(maxsplit=1)[1]) sents = [sanitizer(sent) for sent in sents] except: sents = [] print("Failed to load sentences.") else: line = sanitizer(line.strip()) sents = ru_sent_tokenize(line, SHORTENINGS, JOINING_SHORTENINGS, PAIRED_SHORTENINGS) for sent in sents: try: sent = sent.replace('\n', '') if len(sent) < args.min_characters: continue tokens, sent_prep = preprocessor(sent) if len(tokens) < args.min_tokens: continue except Exception as msg: print(f"WARNING: error {msg} for sent = {sent}") continue sent_tokenized = ' '.join(tokens) if len(sent_tokenized.split()) != len(sent_prep.split()): print("Tokenized and lemmatized texts have different lengths" ", skipping.")
def __call__(self, batch: [str]) -> [[str]]: return [[ x for line in text.split('\n') for x in ru_sent_tokenize( line, self.shortenings, self.joining_shortenings, self.paired_shortenings) if x ] for text in batch]
def deepmipt_sentenize(text): from rusenttokenize import ru_sent_tokenize with no_logger(LOGGER): chunks = ru_sent_tokenize(text) return find_substrings(chunks, text)
def test_ru_sent_tokenize(self): self.assertEqual( ru_sent_tokenize('купил за 5 руб. и остался доволен.'), ['купил за 5 руб. и остался доволен.']) self.assertEqual( ru_sent_tokenize('Я ему сказал и т.к. он не послушался за 500р.'), ['Я ему сказал и т.к. он не послушался за 500р.']) self.assertEqual(ru_sent_tokenize('Ура. Ура. 500р.'), ['Ура.', 'Ура.', '500р.']) self.assertEqual( ru_sent_tokenize( 'Среди других её представителей — Л. Р. Зиндер, Л. В. Бондарко, М. И. Матусевич.' ), [ 'Среди других её представителей — Л. Р. Зиндер, Л. В. Бондарко, М. И. Матусевич.' ]) self.assertEqual(ru_sent_tokenize('И. П. Павлов.'), ['И. П. Павлов.']) self.assertEqual(ru_sent_tokenize('Павлов И. П., Сеченов И. М.'), ['Павлов И. П., Сеченов И. М.']) self.assertEqual( ru_sent_tokenize('Основателем школы является Л. В. Щерба.'), ['Основателем школы является Л. В. Щерба.']) self.assertEqual( ru_sent_tokenize( 'Я ему сказале: "Чтобы ничего не трогале." Но он не послушался.' ), [ 'Я ему сказале: "Чтобы ничего не трогале."', 'Но он не послушался.' ]) self.assertEqual(ru_sent_tokenize('Нефть за $27/барр. не снится.'), ['Нефть за $27/барр. не снится.']) self.assertEqual(ru_sent_tokenize('Сказала я. Он оглянулся.'), ['Сказала я.', 'Он оглянулся.']) self.assertEqual( ru_sent_tokenize( 'Летописец Нестор относит их возникновение к I столетию н.э., когда св. Андрей, проповедуя в Киеве ' 'евангельское слово, отправился потом в Новгород, где он увидел чудо – парившихся в бане.' ), [ 'Летописец Нестор относит их возникновение к I столетию н.э., когда св. Андрей, проповедуя в Киеве ' 'евангельское слово, отправился потом в Новгород, где он увидел чудо – парившихся в бане.' ]) self.assertEqual( ru_sent_tokenize( '- Ну, хорошо, хочешь, я тебе тоннели покажу? - спрашивает наконец Мариам и сворачивает с одной ничем ' 'не примечательной улицы, застроенной обычными городскими многоэтажками, на другую точно такую же.' ), [ '- Ну, хорошо, хочешь, я тебе тоннели покажу? - спрашивает наконец Мариам и сворачивает с одной ничем ' 'не примечательной улицы, застроенной обычными городскими многоэтажками, на другую точно такую же.' ]) self.assertEqual(ru_sent_tokenize('Где они были эти …адцать лет?'), ['Где они были эти …адцать лет?']) self.assertEqual( ru_sent_tokenize( 'Православие... более всего подходит на роль такой идеи...'), ['Православие... более всего подходит на роль такой идеи...']) self.assertEqual( ru_sent_tokenize( 'Yolka стоит 2400р. без трех копеек сто долларов, между прочим.' ), ['Yolka стоит 2400р. без трех копеек сто долларов, между прочим.']) self.assertEqual( ru_sent_tokenize( 'А если лень читать всё - общее количество ответов: 8272! - то можно почитать книжку избранных мест.' ), [ 'А если лень читать всё - общее количество ответов: 8272! - то можно почитать книжку избранных мест.' ]) self.assertEqual(ru_sent_tokenize('Это стоило 50 т. к. вчера'), ['Это стоило 50 т. к. вчера']) self.assertEqual( ru_sent_tokenize( "Официально закрытие фастфудов назначено на предстоящее воскресенье, " "причём менеджеры не планируют снова открывать в этой стране рестораны " "McDonald's. Причин закрытия исландских McDonald's несколько." ), [ "Официально закрытие фастфудов назначено на предстоящее воскресенье, причём " "менеджеры не планируют снова открывать в этой стране рестораны McDonald's.", "Причин закрытия исландских McDonald's несколько." ]) self.assertEqual( ru_sent_tokenize( '12 января ожидается понижение до минус 44 — минус 48°C. ' 'В школах региона отменены занятия в начальных классах.'), [ '12 января ожидается понижение до минус 44 — минус 48°C.', 'В школах региона отменены занятия в начальных классах.' ]) self.assertEqual( ru_sent_tokenize( 'У государственных людей тоже есть дети, и если для них ночные заведения работать-таки будут… (а вы ' 'попробуйте им отказать) ну, в общем, не хотелось бы думать о волне народного возмущения.' ), [ 'У государственных людей тоже есть дети, и если для них ночные заведения работать-таки будут… (а вы ' 'попробуйте им отказать) ну, в общем, не хотелось бы думать о волне народного возмущения.' ]) self.assertEqual( ru_sent_tokenize( 'По сравнению с 2009 годом Россия опустилась в рейтинге на 9 позиций ' '(т. е. ситуация в ней улучшилась).'), [ 'По сравнению с 2009 годом Россия опустилась в рейтинге на 9 позиций (т. е. ситуация' ' в ней улучшилась).' ]) self.assertEqual( ru_sent_tokenize( 'Привет.Тест (прим. ред. - на токенизацию). \"По моим наблюдениям, выгоднее было бы поставлять газ в ' 'Азию через Аравийское море. Проект иранской газовой трубы через Турцию — долгосрочная перспектива\", -' ' сказал Сайед Мухаммед Хусейн Адели.'), [ 'Привет.Тест (прим. ред. - на токенизацию).', '"По моим наблюдениям, выгоднее было бы поставлять газ в Азию через Аравийское море.', 'Проект иранской газовой трубы через Турцию — долгосрочная перспектива", - сказал Сайед Мухаммед Хусейн ' 'Адели.' ])
def run(self, data: str) -> Struct: super().run(data) if not isinstance(data, str): raise ArgumentError("Error data for concept extraction. " "Argument 'data' must be a string") if len(data) == 0: raise ArgumentError("Argument 'data' string must not be empty") if os.path.isfile(data): if os.path.getsize(data) == 0: raise FileDataError("Argument 'data' is empty file") with open(data, 'r', encoding='utf-8') as file: data = file.read() data = Utils.clean(data.lower()) sentences = ru_sent_tokenize(data) input_ids = [] attention_masks = [] for sentence in tqdm( sentences, desc="Preparing sentences for concept extraction"): encoded = self.tokenizer.encode_plus(sentence, add_special_tokens=True, max_length=256, padding='max_length', truncation=True, return_attention_mask=True, return_tensors='pt') input_ids.append(encoded['input_ids']) attention_masks.append(encoded['attention_mask']) if len(input_ids) == 0 or len(attention_masks) == 0: raise ConceptExtractionError( 'Error occured during tokenization data for concept extraction. ' 'Please, check your data is not empty and contains russian text' ) dataset = torch.utils.data.TensorDataset( torch.cat(input_ids, dim=0), torch.cat(attention_masks, dim=0)) sampler = torch.utils.data.SequentialSampler(dataset) loader = torch.utils.data.DataLoader(dataset, sampler=sampler, batch_size=4) try: self.model.eval() except: raise ConceptModelError( 'Wrong concept extraction model. ' 'Please, load correct model for concept extraction.') keywords = [] for batch in tqdm(loader, desc="Concept extraction"): predictions = [] batch = tuple(t.to(self.device) for t in batch) with torch.no_grad(): result = self.model(batch[0], token_type_ids=None, attention_mask=batch[1]) logits = result.logits.detach().cpu().numpy() predictions.extend([list(p) for p in np.argmax(logits, axis=2)]) tokens_pred = [] for ipred, prediction in enumerate(predictions): idx = 0 while idx < len(prediction): label = prediction[idx] if label == 0: cur_tokens = [ self.tokenizer.convert_ids_to_tokens( batch[0][ipred].to('cpu').numpy())[idx] ] idx += 1 while prediction[idx] != 2: cur_tokens.append( self.tokenizer.convert_ids_to_tokens( batch[0][ipred].to('cpu').numpy())[idx]) idx += 1 tokens_pred.append(cur_tokens) idx += 1 for token_group in tokens_pred: keywords.append( self.tokenizer.convert_tokens_to_string(token_group)) keywords = list(set(keywords)) ikw = 0 while ikw < len(keywords): keyword_words = word_tokenize(keywords[ikw], language="russian") if len(keyword_words) == 1: mph = self.morph.parse(keywords[ikw])[0] if not mph.is_known or mph.tag.POS != 'NOUN': keywords.remove(keywords[ikw]) ikw -= 1 else: keywords[ikw] = mph.normal_form else: for keyword_word in keyword_words: mph = self.morph.parse(keyword_word)[0] if not mph.is_known or len(keyword_word) < 3: keywords.remove(keywords[ikw]) ikw -= 1 break ikw += 1 self.data.set_concepts(list(set(keywords))) return self.data