#python-3.x #nlp #spacy
#python-3.x #nlp #spacy
Вопрос:
Я работаю над задачей тематического моделирования, в которой я беру отзывы людей (текст) и пытаюсь извлечь из них важные темы.
Обратная связь довольно короткая, и я не знаю, является ли это тем, что ставит перед нами проблему. Ниже приведен мой код, есть ли что-то действительно очевидное, что я пропустил?
Я удаляю стоп-слова, лемматизирую, оставляю только существительные и удаляю стоп-слова. Однако я передаю их в модель, она работает не совсем так, как я надеялся
Одной из больших проблем является семантика, клиент может ссылаться на одно и то же понятие по-разному: магазин, бутик, магазин, супермаркет и т. Д… Все они относятся к магазину, но LDA рассматривает их как разные концепции и объединяет их в разные темы, хотя «Я люблю магазин» и «Я люблю магазин» — это одно и то же утверждение.
import spacy
import pandas as pd
from textblob import TextBlob
#set display options
pd.set_option('display.max_colwidth', 0)
pd.set_option('display.max_rows', 0)
#ingest data
df = pd.read_csv('surv.csv')
#import spacy language library and stopword dictionary
nlp = spacy.load('en_core_web_sm')
all_stopwords = nlp.Defaults.stop_words
#Limit DF to columns of interest and drop nulls
responses = df[['Comment', 'score']]
responses = responses.dropna()
#lemmatize the strings
def cleanup(row):
comment = row['Comment']
comment = nlp(comment)
sent = []
for word in comment:
sent.append(word.lemma_)
return " ".join(sent)
#keep only nouns
def only_nouns(row):
comment = row['nostops']
blob = TextBlob(comment)
x = blob.noun_phrases
return " ".join(x)
def pos(row):
comment = row['nostops']
comment = nlp(comment)
nouns = []
i=0
while i < len(comment)-1:
if comment[i].pos_ == 'NOUN':
nouns.append(comment[i])
i=i 1
return nouns
#remove the stop words
def remove_stops(row):
comment = row['Comment']
comment = comment.split(' ')
rem = []
for word in comment:
if word not in all_stopwords:
rem.append(word)
return " ".join(rem)
#What entities are defined in the document
def split_entities(row):
comment = row['Comment']
comment = nlp(comment)
entities = []
for ent in comment.ents:
entities.append(ent)
return entities
#Call functions
responses['lemmas'] = responses.apply(cleanup,axis=1)
responses['nostops'] = responses.apply(remove_stops,axis=1)
responses['nouns'] = responses.apply(pos, axis=1)
responses['nouns2'] = responses.apply(only_nouns, axis=1)
responses['entities'] = responses.apply(split_entities,axis=1)
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.decomposition import LatentDirichletAllocation
cv = CountVectorizer(max_df=0.9, min_df=2, stop_words='english')
document_term_matrix = cv.fit_transform(responses['nouns'])
lda = LatentDirichletAllocation(n_components=4, random_state=42)
lda.fit(document_term_matrix)
topic_results = lda.transform(document_term_matrix)
Ответ №1:
Общее предложение: вы пытались добавить TF-IDF в sklearn?Это хороший общий способ взвешивания слов на основе того, как часто они встречаются в документах и во всех документах, и это улучшает качество вывода LDA. Вы можете добавить его вместе с «CountVectorizer». Вот хороший полный пример из документов sklearn.
Конкретное предложение по вопросу слов, которые вы хотели бы рассматривать как синонимы («магазин, бутик, магазин, супермаркет»): я думаю, я бы добавил этап предварительной обработки, на котором я заменяю все эти отдельные слова одним и тем же токеном (например, преобразовать все вхождения «магазин, бутик,магазин, супермаркет» в «магазин»). Это требует ручного создания списков синонимов, но это простой способ решения проблемы.