В этом блоге мы собираемся использовать некоторые концепции НЛП, чтобы резюмировать эссе или биографию. Мы будем анализировать каждое предложение и искать наиболее лаконичные предложения, которые, казалось бы, описывают весь отрывок. Эти предложения будут нашим резюме.
Шаги
- Мы разбиваем текст на предложения и разбиваем предложения на слова.
- Мы игнорируем стоп-слова (слова, которые не имеют значения для предложения, например, я, есть, был, был)
- Слова, которые имеют значение в предложении, имеют корень (рыба-рыба, рыба-рыба: так, чтобы слова можно было составить вместе)
- Записываются случаи появления этих слов.
- Мы находим правильные предложения (в отрывке), которые включают большинство широко используемых слов.
- Эти предложения будут нашим резюме
Код
from nltk.corpus import stopwords from nltk.stem.porter import PorterStemmer from nltk.tokenize import word_tokenize stem = PorterStemmer() stop_words = set(stopwords.words('english'))
Импорт зависимостей и настройка нашего стеммера и набора, в котором хранятся все стоп-слова
sentences = [] for sentence in text.split('.'): sent = [] for word in sentence.split(' '): sent.append(word.lower()) sentences.append(sent)
Наличие двухмерного списка, в котором будут храниться предложения и слова.
char_sent = [] for sentence in sentences: sent = [] for word in sentence: full_word = ''.join(x for x in word if x.isalpha()) if full_word =='': continue if full_word in stop_words: pass else: sent.append(stem.stem(full_word)) char_sent.append(sent)
Мы создаем новый список, который удалит все не буквенно-цифровые символы из слова, и если слово окажется стоп-словом, мы удалим его из списка. Затем мы сокращаем слово и помещаем его в наш только что созданный список.
word_count = {} for sentence in char_sent: for word in sentence: if word in word_count.keys(): word_count[word]+=1 else: word_count[word] = 1
Здесь мы подсчитываем количество вхождений каждого слова и сохраняем их в словаре.
no_of_lines = len(sentences)//5
Эта строка кода сообщает нам, какой длины должна быть сводка (количество строк). Здесь это будет пятая часть от общего количества предложений в тексте.
sentence_priority = {} for i, sentence in enumerate(sentences): sum = 0 for word in sentence: sum+=word_count[word] try: sentence_priority[text.split('.')[i]] = sum/len(sentence) except ZeroDivisionError: sentence_priority[text.split('.')[i]] = 0
Переменная sum будет хранить сумму вхождений каждого слова (в тексте) из словаря word_count, созданного ранее. Мы находим среднее значение, разделив его на количество слов в предложении. Затем мы сохраняем фактическое предложение вместе с вычисленным средним значением в переменной предложения_priority.
count = list({sentence_priority[word] for word in sentence_priority}) count.sort(reverse=True)
Находим рассчитанные средние значения и сортируем их (в порядке убывания).
ordered_word = {} for num in count: for word in sentence_priority: try: if word_tokenize(word.strip())[0].lower()== 'it' or word_tokenize(word.strip())[0].lower()== 'he' or word_tokenize(word.strip())[0].lower()== 'she' or word_tokenize(word.strip())[0].lower()== 'they' or word_tokenize(word.strip())[0].lower()== 'their': continue except IndexError: continue if sentence_priority[word] == num: ordered_word[word]=num
Мы перебираем средние значения в count, и у нас есть вложенный цикл, который перебирает предложения в фразе_priority. Если первое слово оказывается местоимением, мы не можем оставить его в качестве краткого содержания, поэтому игнорируем его. В противном случае мы сохраняем его в словаре заказанное_слово. Итак, мы упорядочили наши предложения: в одном из них больше всего ключевых моментов вверху, а в другом меньше всего внизу.
summary = list(ordered_word.keys())[:int(no_of_lines)] indexes = [] for point in summary: indexes.append(text.split('.').index(point)) indexes.sort()
Мы находим сводку, которая представляет собой фрагмент первого индекса «no_of_lines» из словаря order_word. Затем мы находим индекс каждого пункта в аннотации по отношению к полному тексту. Мы упорядочиваем указатели таким образом, чтобы сводка была упорядочена в правильном порядке по отношению к полному тексту.
summary = [] for value in indexes: summary.append(' '.join(text.split('.')[value].split('\n')).lstrip())
Затем мы перебираем индексы и добавляем окончательную сводку к сводному списку.
print('------------Summary------------') for value in summary: print(value) print()
Наконец распечатайте резюме
Вывод
Вот и все! Мы смогли создать наш собственный простой текстовый сумматор, используя базовые концепции НЛП. Это резюме может быть не самым точным, но оно все же дает самые краткие моменты текста.