Как определить предложения, связанные с темой? - PullRequest
0 голосов
/ 30 августа 2018

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

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

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

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

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

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

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

Ответы [ 4 ]

0 голосов
/ 30 августа 2018

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

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

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

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


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

>>> 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 против S4-экзамена. Таким образом, возникает вопрос: «Есть ли способ заставить их расходиться?» и вы прыгнете в кроличью нору:

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

  • Какую функцию сходства использовать для сравнения «тема» / слово с предложением?

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

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

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

0 голосов
/ 30 августа 2018

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

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 голосов
/ 30 августа 2018

Решение

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 голосов
/ 30 августа 2018

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

lecture = 2
tutor = 1
exam = 1

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...