Я делаю проект, который требует от меня сортировки документа в соответствии с темой.
Например, у меня есть 4 темы, которые являются лекцией, репетитором, лабораторией и экзаменом. У меня есть некоторые предложения, которые:
И теперь я хочу сортировать эти предложения в теме выше, результат должен быть:
Я занимался исследованиями, и большинство инструкций, которые я нашел, это использование моделирования темы LDA. Но похоже, что я не могу решить свою проблему, потому что, поскольку я знаю поддержку LDA для определения темы в документе и не знаю, как предварительно выбирать тему вручную.
Может ли кто-нибудь помочь мне, пожалуйста? Я застрял с этим.
Это отличный пример, чтобы использовать что-то умнее, чем сопоставление строк =)
Давайте рассмотрим это:
Есть ли способ преобразовать каждое слово в векторную форму (т.е. Массив поплавков)?
Есть ли способ преобразовать каждое предложение в одну и ту же векторную форму (т.е. Массив с плавающей точкой те же размеры, что и векторная форма слова?
Сначала дайте словарный запас ко всем словам, возможным в вашем списке предложений (назовем его корпусом):
>>> 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. Поэтому возникает вопрос: "Есть ли способ заставить их расходиться?" и вы прыгнете в кроличью нору:
Как лучше представить предложение/слово как вектор фиксированного размера?
Какое сходство используется для сравнения "темы"/слова или предложения?
Что такое "тема"? Что представляет вектор?
Ответ выше - это то, что обычно называют одним горячим вектором для представления слова/предложения. Там гораздо сложнее, чем просто сравнение строк для "определения предложений, связанных с темой?" (например, кластеризация документов/классификация). Например, может ли документ/предложение иметь более одной темы?
Просмотрите эти ключевые слова, чтобы понять проблему "обработка естественного языка", "классификация документов", "машинное обучение". Между тем, если вы не возражаете, я думаю, что это близко для этого вопроса как "слишком широкое".
Решение
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$
Этот метод будет считать дубликаты для вас
Наслаждайтесь!
Я предполагаю, что вы читаете текстовый файл или что-то в этом роде. Вот как я буду заниматься этим.
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)
Это ищет каждую строку для любого слова в словаре ключевых слов, и если совпадение найдено, оно увеличивает значение этого ключа.
Для этого вам не нужны никакие внешние библиотеки или что-то еще.
Просто укажите переменные после тем, которые вы хотите
lecture = 2
tutor = 1
exam = 1
Вы можете использовать variable_name += 1
для увеличения переменной
dict
для этого ИМО