Как определить предложения, связанные с темой?

1

Я делаю проект, который требует от меня сортировки документа в соответствии с темой.

Например, у меня есть 4 темы, которые являются лекцией, репетитором, лабораторией и экзаменом. У меня есть некоторые предложения, которые:

  1. Лекция привлекала
  2. Репетитор очень приятный и активный
  3. Содержание лекции было слишком много в течение 2 часов.
  4. Экзамен кажется слишком сложным с еженедельной лабораторией.

И теперь я хочу сортировать эти предложения в теме выше, результат должен быть:

  • Лекция: 2
  • Репетитор: 1
  • Экзамен: 1

Я занимался исследованиями, и большинство инструкций, которые я нашел, это использование моделирования темы LDA. Но похоже, что я не могу решить свою проблему, потому что, поскольку я знаю поддержку LDA для определения темы в документе и не знаю, как предварительно выбирать тему вручную.

Может ли кто-нибудь помочь мне, пожалуйста? Я застрял с этим.

  • 1
    Добро пожаловать в StackOverflow. Пожалуйста, прочитайте и следуйте инструкциям публикации в справочной документации, как это было предложено при создании этой учетной записи. По теме , как спросить , и ... идеальный вопрос здесь. StackOverflow - это архив конкретных программных решений. Ваш вопрос, кажется, требует общего руководства для атаки на слабо определенные приложения.
  • 0
    Способ сделать это может сильно различаться в зависимости от типа документа. С чем мы работаем?
Показать ещё 2 комментария
Теги:
nltk

4 ответа

5
Лучший ответ

Это отличный пример, чтобы использовать что-то умнее, чем сопоставление строк =)

Давайте рассмотрим это:

  • Есть ли способ преобразовать каждое слово в векторную форму (т.е. Массив поплавков)?

  • Есть ли способ преобразовать каждое предложение в одну и ту же векторную форму (т.е. Массив с плавающей точкой те же размеры, что и векторная форма слова?


Сначала дайте словарный запас ко всем словам, возможным в вашем списке предложений (назовем его корпусом):

>>> from itertools import chain
>>> s1 = "Lecture was engaging"
>>> s2 = "Tutor is very nice and active"
>>> s3 = "The content of lecture was too much for 2 hours."
>>> s4 = "Exam seem to be too difficult compare with weekly lab."
>>> list(map(word_tokenize, [s1, s2, s3, s4]))
[['Lecture', 'was', 'engaging'], ['Tutor', 'is', 'very', 'nice', 'and', 'active'], ['The', 'content', 'of', 'lecture', 'was', 'too', 'much', 'for', '2', 'hours', '.'], ['Exam', 'seem', 'to', 'be', 'too', 'difficult', 'compare', 'with', 'weekly', 'lab', '.']]
>>> vocab = sorted(set(token.lower() for token in chain(*list(map(word_tokenize, [s1, s2, s3, s4])))))
>>> vocab
['.', '2', 'active', 'and', 'be', 'compare', 'content', 'difficult', 'engaging', 'exam', 'for', 'hours', 'is', 'lab', 'lecture', 'much', 'nice', 'of', 'seem', 'the', 'to', 'too', 'tutor', 'very', 'was', 'weekly', 'with']

Теперь давайте представим 4 ключевых слова в виде векторов, используя индекс слова в словаре:

>>> lecture = [1 if token == 'lecture' else 0 for token in vocab]
>>> lab = [1 if token == 'lab' else 0 for token in vocab]
>>> tutor = [1 if token == 'tutor' else 0 for token in vocab]
>>> exam = [1 if token == 'exam' else 0 for token in vocab]
>>> lecture
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> lab
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> tutor
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0]
>>> exam
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Точно так же мы прокручиваем каждое предложение и преобразуем его в векторную форму:

>>> [token.lower() for token in word_tokenize(s1)]
['lecture', 'was', 'engaging']
>>> s1_tokens = [token.lower() for token in word_tokenize(s1)]
>>> s1_vec = [1 if token in s1_tokens else 0  for token in vocab]
>>> s1_vec
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]

Повторяя то же самое для всех предложений:

>>> s2_tokens = [token.lower() for token in word_tokenize(s2)]
>>> s3_tokens = [token.lower() for token in word_tokenize(s3)]
>>> s4_tokens = [token.lower() for token in word_tokenize(s4)]
>>> s2_vec = [1 if token in s2_tokens else 0  for token in vocab]
>>> s3_vec = [1 if token in s3_tokens else 0  for token in vocab]
>>> s4_vec = [1 if token in s4_tokens else 0  for token in vocab]
>>> s2_vec
[0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0]
>>> s3_vec
[1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0]
>>> s4_vec
[1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1]

Теперь, учитывая векторную форму предложения и слов, вы можете использовать функции подобия, например, подобие косинуса:

>>> from numpy import dot
>>> from numpy.linalg import norm
>>> 
>>> cos_sim = lambda x, y: dot(x,y)/(norm(x)*norm(y))
>>> cos_sim(s1_vec, lecture)
0.5773502691896258
>>> cos_sim(s1_vec, lab)
0.0
>>> cos_sim(s1_vec, exam)
0.0
>>> cos_sim(s1_vec, tutor)
0.0

Теперь, делая это более систематически:

>>> topics = {'lecture': lecture, 'lab': lab, 'exam': exam, 'tutor':tutor}
>>> topics
{'lecture': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
 'lab':     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
 'exam':    [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
 'tutor':   [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0]}


>>> sentences = {'s1':s1_vec, 's2':s2_vec, 's3':s3_vec, 's4':s4_vec}

>>> for s_num, s_vec in sentences.items():
...     print(s_num)
...     for name, topic_vec in topics.items():
...         print('\t', name, cos_sim(s_vec, topic_vec))
... 
s1
     lecture 0.5773502691896258
     lab 0.0
     exam 0.0
     tutor 0.0
s2
     lecture 0.0
     lab 0.0
     exam 0.0
     tutor 0.4082482904638631
s3
     lecture 0.30151134457776363
     lab 0.0
     exam 0.0
     tutor 0.0
s4
     lecture 0.0
     lab 0.30151134457776363
     exam 0.30151134457776363
     tutor 0.0

Думаю, вы поняли. Но мы видим, что оценки по-прежнему связаны для s4-lab vs s4-exam. Поэтому возникает вопрос: "Есть ли способ заставить их расходиться?" и вы прыгнете в кроличью нору:

  • Как лучше представить предложение/слово как вектор фиксированного размера?

  • Какое сходство используется для сравнения "темы"/слова или предложения?

  • Что такое "тема"? Что представляет вектор?

Ответ выше - это то, что обычно называют одним горячим вектором для представления слова/предложения. Там гораздо сложнее, чем просто сравнение строк для "определения предложений, связанных с темой?" (например, кластеризация документов/классификация). Например, может ли документ/предложение иметь более одной темы?

Просмотрите эти ключевые слова, чтобы понять проблему "обработка естественного языка", "классификация документов", "машинное обучение". Между тем, если вы не возражаете, я думаю, что это близко для этого вопроса как "слишком широкое".

0

Решение

filename = "information.txt"


library = {"lecture": 0, "tutor": 0, "exam": 0}

with open(filename) as f_obj:
    content = f_obj.read() # read text into contents

words  = (content.lower()).split() # create list of all words in content

for k, v in library.items():
    for i in words:
        if k in i:
            v += 1 
            library[k] = v # without this line code count will not update 

for k, v in library.items():
    print(k.title() + ": "  + str(v))

Выход

(xenial)vash@localhost:~/pcc/12/alien_invasion_2$ python3 helping_topic.py 
Tutor: 1
Lecture: 2
Exam: 1
(xenial)vash@localhost:~/pcc/12/alien_invasion_2$

Этот метод будет считать дубликаты для вас

Наслаждайтесь!

0

Я предполагаю, что вы читаете текстовый файл или что-то в этом роде. Вот как я буду заниматься этим.

keywords = {"lecture": 0, "tutor": 0, "exam": 0}

with open("file.txt", "r") as f:
  for line in f:
    for key, value in keywords.items():
      if key in line.lower():
        value += 1

print(keywords)

Это ищет каждую строку для любого слова в словаре ключевых слов, и если совпадение найдено, оно увеличивает значение этого ключа.

Для этого вам не нужны никакие внешние библиотеки или что-то еще.

  • 0
    Спасибо, это решит мою проблему. Тем не менее, это может иметь проблему, что если предложения повторяют слово «лекция» дважды, это повлияет на результат.
  • 0
    Кроме того, если я хочу расширить мою программу, которая может анализировать предложение, является положительным или отрицательным. Вы знаете, какая библиотека будет поддерживать это? Я уже пытаюсь использовать nltk с классификатором scikit. Но только можете проверить результат, который уже видел. Например, я помечаю 200 предложений, которые являются комбинацией положительного и отрицательного, затем позволяю классификатору узнать и проверить, какой процент других помеченных 50 комментариев является правильным.
Показать ещё 1 комментарий
-2

Просто укажите переменные после тем, которые вы хотите

lecture = 2
tutor = 1
exam = 1

Вы можете использовать variable_name += 1 для увеличения переменной

  • 1
    Это не отвечает на вопрос. Как они определяют, содержит ли предложение термин? Также было бы лучше использовать dict для этого ИМО
  • 0
    Извините, я подумал, что когда вы сортируете документ в Python, текст читается как строка
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню