Пример #1
0
    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
Пример #2
0
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))
Пример #3
0
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
Пример #4
0
    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
Пример #5
0
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)
Пример #6
0
    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
Пример #7
0
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
Пример #8
0
    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
Пример #9
0
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
Пример #10
0
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
Пример #11
0
 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)
Пример #14
0
 def __call__(self, batch: [str]) -> [[str]]:
     return [
         ru_sent_tokenize(x, self.shortenings, self.joining_shortenings,
                          self.paired_shortenings) for x in batch
     ]
Пример #15
0
def nltk_sent_and_tok(in_line):
    sentences = ru_sent_tokenize(in_line)
    line = [' '.join(word_tokenize(sentence)) for sentence in sentences]
    return line
Пример #16
0
    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
Пример #17
0
    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
Пример #18
0
            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)
Пример #19
0
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()
Пример #20
0
 def __call__(self, batch: [str]) -> [[str]]:
     return [ru_sent_tokenize(x, self.shortenings, self.joining_shortenings, self.paired_shortenings) for x in batch]
Пример #21
0
 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.")
Пример #22
0
 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]
Пример #23
0
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(
             'Привет.Тест (прим. ред. - на токенизацию). \"По моим наблюдениям, выгоднее было бы поставлять газ в '
             'Азию через Аравийское море. Проект иранской газовой трубы через Турцию — долгосрочная перспектива\", -'
             ' сказал Сайед Мухаммед Хусейн Адели.'),
         [
             'Привет.Тест (прим. ред. - на токенизацию).',
             '"По моим наблюдениям, выгоднее было бы поставлять газ в Азию через Аравийское море.',
             'Проект иранской газовой трубы через Турцию — долгосрочная перспектива", - сказал Сайед Мухаммед Хусейн '
             'Адели.'
         ])
Пример #25
0
    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