Автор|Мауро Ди Пьетро Компилировать|ВКонтакте Источник | К науке о данных
Резюме
В этой статье я объясню, как анализировать текстовые данные и извлекать функции для моделей машинного обучения с использованием НЛП и Python.
Обработка естественного языка (NLP) — это область исследований в области искусственного интеллекта, изучающая взаимодействие между компьютерами и человеческим языком, в частности то, как компьютеры запрограммированы на обработку и анализ больших объемов данных на естественном языке.
NLP часто используется для классификации текстовых данных. Классификация текста — это задача классификации текстовых данных на основе их содержания. Наиболее важной частью классификации текста является разработка признаков: процесс создания признаков для моделей машинного обучения из необработанных текстовых данных.
В этой статье я объясню различные способы анализа текста и извлечения признаков, которые можно использовать для построения моделей классификации. Я представлю полезный код Python.
Код можно легко применить к другим подобным ситуациям (просто скопируйте, вставьте, запустите), и я прокомментировал его, чтобы вы могли понять пример (ссылка на полный код ниже).
Я буду использовать «Набор данных категорий новостей» (ссылка ниже), который дает вам заголовки новостей с 2012 по 2018 год, полученные из Huffington Post, и просит вас классифицировать их, используя правильную категорию.
Woohoo.Карта переформирована.com/RMI is RA/news…
В частности, я пропущу:
-
Настройки среды: импорт пакетов и чтение данных.
-
Обнаружение языка: узнайте, какие данные на естественном языке содержатся в нем.
-
Предварительная обработка текста: очистка и преобразование текста.
-
Анализ длины: измеряется с помощью различных показателей.
-
Анализ настроений: определение того, является ли статья положительной или отрицательной.
-
Распознавание именованных объектов: идентификация текста с предопределенными категориями, такими как имя человека, организация, местоположение.
-
Частота слов: найдите самые важные n букв.
-
Вектор слова: преобразование слова в вектор.
-
Тематическая модель: извлечение тем из корпуса.
Параметры среды
Во-первых, мне нужно импортировать следующие библиотеки.
## 数据
import pandas as pd
import collections
import json
## 绘图
import matplotlib.pyplot as plt
import seaborn as sns
import wordcloud
## 文本处理
import re
import nltk
## 语言检测
import langdetect
## 情感分析
from textblob import TextBlob
## 命名实体识别
import spacy
## 词频
from sklearn import feature_extraction, manifold
## word embedding
import gensim.downloader as gensim_api
## 主题模型
import gensim
Набор данных содержится в файле json, поэтому я сначала прочитаю его в список словарей с помощью пакета json, а затем преобразую в кадр данных pandas.
lst_dics = []
with open('data.json', mode='r', errors='ignore') as json_file:
for dic in json_file:
lst_dics.append( json.loads(dic) )
## 打印第一个
lst_dics[0]
Исходный набор данных содержит более 30 категорий, но для этого урока я буду использовать подмножество из 3 категорий: развлечения, политика и технологии (Entertainment, Politics, Tech).
## 创建dtf
dtf = pd.DataFrame(lst_dics)
## 筛选类别
dtf = dtf[ dtf["category"].isin(['ENTERTAINMENT','POLITICS','TECH']) ][["category","headline"]]
## 重命名列
dtf = dtf.rename(columns={"category":"y", "headline":"text"})
## 打印5个随机行
dtf.sample(5)
Чтобы понять состав набора данных, я буду изучать одномерное распределение (распределение вероятностей только одной переменной), отображая частоты меток с помощью гистограммы.
x = "y"
fig, ax = plt.subplots()
fig.suptitle(x, fontsize=12)
dtf[x].reset_index().groupby(x).count().sort_values(by=
"index").plot(kind="barh", legend=False,
ax=ax).grid(axis='x')
plt.show()
Набор данных несбалансирован: по сравнению с другими наборами данных доля технических новостей очень мала. Это может быть проблемой во время моделирования, и может быть полезно выполнить повторную выборку набора данных.
Теперь, когда все настроено, я начну с очистки данных, затем извлечения различных деталей из исходного текста и добавления их в качестве новых столбцов фрейма данных. Эта новая информация может служить скрытыми функциями для моделей классификации.
определение языка
Во-первых, я хочу убедиться, что использую тот же язык и используюlangdetectпакет, это очень просто. Для иллюстрации я буду использовать это в первом заголовке новостей в наборе данных:
txt = dtf["text"].iloc[0]
print(txt, " --> ", langdetect.detect(txt))
Мы добавляем столбец с информацией о языке для всего набора данных:
dtf['lang'] = dtf["text"].apply(lambda x: langdetect.detect(x) if
x.strip() != "" else "")
dtf.head()
Фрейм данных теперь имеет новый столбец. Используя тот же код, что и раньше, я вижу, сколько существует разных языков:
Несмотря на то, что существуют разные языки, английский является основным языком. Поэтому я хочу фильтровать новости на английском языке.
dtf = dtf[dtf["lang"]=="en"]
предварительная обработка текста
Предварительная обработка данных — это этап подготовки необработанных данных для включения их в модель машинного обучения. Для НЛП это включает в себя очистку текста, удаление стоп-слов, выделение корней.
Действия по очистке текста зависят от типа данных и требуемой задачи. Как правило, строки преобразуются в нижний регистр, а знаки препинания удаляются до того, как текст размечается.токенизация(Tokenization) — это процесс разделения строки на список (или «идентификацию») строк.
Возьмем, к примеру, заголовок первой новости:
print("--- original ---")
print(txt)
print("--- cleaning ---")
txt = re.sub(r'[^\w\s]', '', str(txt).lower().strip())
print(txt)
print("--- tokenization ---")
txt = txt.split()
print(txt)
Хотим ли мы сохранить все личности в списке? у нас нет. На самом деле мы хотим удалить все слова, не несущие дополнительной информации.
В этом примере самым важным словом является слово «песня», потому что оно может указать правильное направление любой модели классификации. Напротив, такие слова, как «и», «для», «тот», бесполезны, потому что они могут появляться почти во всех наблюдениях в наборе данных.
Это примеры стоп-слов. Стоп-слова обычно относятся к наиболее распространенным словам в языке, но у нас нет общего списка стоп-слов.
Мы можем создать общий список стоп-слов для английской лексики, используя NLTK (Natural Language Toolkit), набор библиотек и программ для символической и статистической обработки естественного языка.
lst_stopwords = nltk.corpus.stopwords.words("english")
lst_stopwords
Удалим эти стоп-слова из заголовка первой новости:
print("--- remove stopwords ---")
txt = [word for word in txt if word not in lst_stopwords]
print(txt)
Нужно быть очень осторожным со стоп-словами, потому что если убрать не тот логотип, можно потерять важную информацию. Например, убрав слово «Уилл», мы потеряли информацию о том, что этим человеком был Уилл Смит.
Имея это в виду, полезно внести некоторые изменения в исходный текст вручную, прежде чем удалять стоп-слова (например, заменив «Will Smith» на «Will_Smith»).
Теперь, когда у нас есть все полезные логотипы, пришло время применить трансформацию слова. вытекание (Stemming) и лемматизация (Lemmatization) оба дают корневую форму слова.
Разница между ними заключается в том, что основа может не быть реальным словом, а лемма - фактическим языковым словом (обычно быстрее происходит формирование основы). Все эти алгоритмы предоставляются NLTK.
Продолжая пример:
print("--- stemming ---")
ps = nltk.stem.porter.PorterStemmer()
print([ps.stem(word) for word in txt])
print("--- lemmatisation ---")
lem = nltk.stem.wordnet.WordNetLemmatizer()
print([lem.lemmatize(word) for word in txt])
Как видите, некоторые слова изменились: «joins» стало корневой формой «join», как и «cups». С другой стороны, «официальный» изменяется только с основой, а основа «offici» не является словом, а образуется путем опускания суффикса «-al».
Я поместлю все эти шаги предварительной обработки в одну функцию и применю ее ко всему набору данных.
'''
预处理.
:parameter
:param text: string - 包含文本的列的名称
:param lst_stopwords: list - 要删除的停用词列表
:param flg_stemm: bool - 是否应用词干
:param flg_lemm: bool - 是否应用引理化
:return
cleaned text
'''
def utils_preprocess_text(text, flg_stemm=False, flg_lemm=True, lst_stopwords=None):
## 清洗(转换为小写并删除标点和字符,然后删除)
text = re.sub(r'[^\w\s]', '', str(text).lower().strip())
## 标识化(从字符串转换为列表)
lst_text = text.split()
## 删除停用词
if lst_stopwords is not None:
lst_text = [word for word in lst_text if word not in
lst_stopwords]
## 词干化
if flg_stemm == True:
ps = nltk.stem.porter.PorterStemmer()
lst_text = [ps.stem(word) for word in lst_text]
## 引理化
if flg_lemm == True:
lem = nltk.stem.wordnet.WordNetLemmatizer()
lst_text = [lem.lemmatize(word) for word in lst_text]
## 从列表返回到字符串
text = " ".join(lst_text)
return text
Обратите внимание, что вы не должны применять стемминг и лемму одновременно. Я буду использовать последний здесь.
dtf["text_clean"] = dtf["text"].apply(lambda x: utils_preprocess_text(x, flg_stemm=False, flg_lemm=True, lst_stopwords))
Как и прежде, я создал новый столбец:
dtf.head()
print(dtf["text"].iloc[0], " --> ", dtf["text_clean"].iloc[0])
анализ длины
Важно смотреть на длину текста, потому что это простое вычисление, которое может предоставить много информации.
Например, возможно, нам посчастливилось обнаружить, что один класс систематически длиннее другого, и эта длина — единственная характеристика, необходимая для построения модели. К сожалению, это не так из-за одинаковой длины новостных заголовков, но попробовать стоит.
Существует несколько мер длины для текстовых данных. Приведу несколько примеров:
- количество слов: подсчитать количество идентификаторов в тексте (разделенных пробелами)
- количество символов: добавить количество символов для каждого идентификатора
- количество предложений: подсчитать количество предложений (разделенных точками)
- средняя длина слова: Сумма длин слов, деленная на количество слов (слов/слов)
- средняя длина предложения: Сумма длин предложений, деленная на количество предложений (слов/предложений).
dtf['word_count'] = dtf["text"].apply(lambda x: len(str(x).split(" ")))
dtf['char_count'] = dtf["text"].apply(lambda x: sum(len(word) for word in str(x).split(" ")))
dtf['sentence_count'] = dtf["text"].apply(lambda x: len(str(x).split(".")))
dtf['avg_word_length'] = dtf['char_count'] / dtf['word_count']
dtf['avg_sentence_lenght'] = dtf['word_count'] / dtf['sentence_count']
dtf.head()
Давайте посмотрим пример:
Как эти новые переменные распределяются относительно цели? Чтобы ответить на этот вопрос, я рассмотрю двумерное распределение (как две переменные влияют друг на друга).
Сначала я разделяю все наблюдения на 3 выборки (политика, развлечения, технологии), а затем сравниваю гистограммы и плотности выборок. Если распределения разные, то переменная предсказуема, потому что три группы имеют разные модели.
Например, давайте посмотрим, связано ли количество символов с целевой переменной:
x, y = "char_count", "y"
fig, ax = plt.subplots(nrows=1, ncols=2)
fig.suptitle(x, fontsize=12)
for i in dtf[y].unique():
sns.distplot(dtf[dtf[y]==i][x], hist=True, kde=False,
bins=10, hist_kws={"alpha":0.8},
axlabel="histogram", ax=ax[0])
sns.distplot(dtf[dtf[y]==i][x], hist=False, kde=True,
kde_kws={"shade":True}, axlabel="density",
ax=ax[1])
ax[0].grid(True)
ax[0].legend(dtf[y].unique())
ax[1].grid(True)
plt.show()
Три категории имеют одинаковое распределение длины. Здесь очень полезны графики плотности, потому что образцы бывают разных размеров.
анализ эмоций
Анализ тональности — это выражение субъективного восприятия текстовых данных с помощью чисел или классов. Из-за неоднозначности естественного языка вычисление эмоций является одной из самых сложных задач при обработке естественного языка.
Например, фраза «Это настолько плохо, что это хорошоСуществует несколько интерпретаций. Модель может присвоить положительный сигнал слову "хороший" и отрицательный сигнал слову "плохой", что приводит к нейтральному настроению. Это связано с тем, что контекст неизвестен.
Лучший способ — обучить собственную модель настроений, чтобы она соответствовала вашим данным. Когда не хватает времени или данных, можно использовать предварительно обученные модели, такие как Textblob и Vader.
- Textblob построен на NLTK, самом популярном, который назначает полярность словам и действует как среднее значение для оценки тональности всего текста.
- С другой стороны, Вейдер (словарь с учетом валентности и анализатор движения) представляет собой модель, основанную на правилах, особенно для данных социальных сетей.
Я добавлю функцию настроений, используя Textblob:
dtf["sentiment"] = dtf[column].apply(lambda x:
TextBlob(x).sentiment.polarity)
dtf.head()
print(dtf["text"].iloc[0], " --> ", dtf["sentiment"].iloc[0])
Есть ли закономерность между категориями и эмоциями?
Большинство заголовков нейтральны, за исключением политических новостей, которые носят негативный характер, и новостей о технологиях, которые носят позитивный характер.
Распознавание именованных объектов
Распознавание именованных сущностей (NER) — это процесс выделения именованных сущностей в неструктурированном тексте с предопределенными категориями (такими как имена людей, организации, местоположения, выражения времени, количества и т. д.).
Обучение модели NER требует очень много времени, поскольку требует очень богатого набора данных. К счастью, кто-то уже сделал эту работу за нас. Одним из лучших инструментов NER с открытым исходным кодом является SpaCy. Он предоставляет различные модели НЛП, которые способны распознавать многие типы сущностей.
Я собираюсь использовать модель SpaCy в нашем обычном заголовке (необработанный необработанный текст).en_core_web_lg(большая модель английского языка, обученная на сетевых данных), чтобы привести пример:
## 调用
ner = spacy.load("en_core_web_lg")
## 打标签
txt = dtf["text"].iloc[0]
doc = ner(txt)
## 展示结果
spacy.displacy.render(doc, style="ent")
Это круто, но как мы можем превратить это в полезную функцию? Вот что я делаю:
-
Запустите модель NER для каждого текстового наблюдения в наборе данных, как я сделал в предыдущем примере.
-
Для каждого заголовка новостей я помещаю все распознанные объекты и количество раз, когда один и тот же объект появляется в тексте, в новый столбец (называемый «теги»).
В этом примере:
{('Уилл Смит', 'ЧЕЛОВЕК'):1, («Дипло», «ЛИЧНОСТЬ»): 1, («Ники Джем», «ЧЕЛОВЕК»): 1, («Чемпионат мира 2018», «СОБЫТИЕ»): 1 }
-
Затем я создал бы новый столбец для каждой категории удостоверений (человек, организация, событие,...) и подсчитал количество сущностей, найденных для каждой категории удостоверений. В приведенном выше примере эта функция будет
tags_PERSON = 3
tags_EVENT = 1
## 标识文本并将标识导出到列表中
dtf["tags"] = dtf["text"].apply(lambda x: [(tag.text, tag.label_)
for tag in ner(x).ents] )
## utils函数计算列表元素
def utils_lst_count(lst):
dic_counter = collections.Counter()
for x in lst:
dic_counter[x] += 1
dic_counter = collections.OrderedDict(
sorted(dic_counter.items(),
key=lambda x: x[1], reverse=True))
lst_count = [ {key:value} for key,value in dic_counter.items() ]
return lst_count
## 计数
dtf["tags"] = dtf["tags"].apply(lambda x: utils_lst_count(x))
## utils函数为每个标识类别创建新列
def utils_ner_features(lst_dics_tuples, tag):
if len(lst_dics_tuples) > 0:
tag_type = []
for dic_tuples in lst_dics_tuples:
for tuple in dic_tuples:
type, n = tuple[1], dic_tuples[tuple]
tag_type = tag_type + [type]*n
dic_counter = collections.Counter()
for x in tag_type:
dic_counter[x] += 1
return dic_counter[tag]
else:
return 0
## 提取特征
tags_set = []
for lst in dtf["tags"].tolist():
for dic in lst:
for k in dic.keys():
tags_set.append(k[1])
tags_set = list(set(tags_set))
for feature in tags_set:
dtf["tags_"+feature] = dtf["tags"].apply(lambda x:
utils_ner_features(x, feature))
## 结果
dtf.head()
Теперь мы можем получить представление о распределении типов удостоверений. Возьмем в качестве примера ярлыки организации (компания и организация):
Для более глубокого анализа нам нужно использовать столбцы «теги», созданные в предыдущем коде. Давайте нарисуем наиболее часто используемый логотип для одной из категорий заголовков:
y = "ENTERTAINMENT"
tags_list = dtf[dtf["y"]==y]["tags"].sum()
map_lst = list(map(lambda x: list(x.keys())[0], tags_list))
dtf_tags = pd.DataFrame(map_lst, columns=['tag','type'])
dtf_tags["count"] = 1
dtf_tags = dtf_tags.groupby(['type',
'tag']).count().reset_index().sort_values("count",
ascending=False)
fig, ax = plt.subplots()
fig.suptitle("Top frequent tags", fontsize=12)
sns.barplot(x="count", y="tag", hue="type",
data=dtf_tags.iloc[:top,:], dodge=False, ax=ax)
ax.grid(axis="x")
plt.show()
Переходим к другому полезному применению NER: вы помните, как мы удалили стоп-слово для слова «Will» из имени «Will Smith»? Интересный способ исправить это — заменить «Will Smith» на «Will_Smith», чтобы он не пострадал от удаления стоп-слова.
Невозможно просмотреть весь текст в наборе данных, чтобы изменить имя, поэтому воспользуемся SpaCy. Как мы знаем, SpaCy может распознавать имя человека, поэтому мы можем использовать его для определения имени и последующего изменения строки.
## 预测
txt = dtf["text"].iloc[0]
entities = ner(txt).ents
## 打标签
tagged_txt = txt
for tag in entities:
tagged_txt = re.sub(tag.text, "_".join(tag.text.split()),
tagged_txt)
## 结果
print(tagged_txt)
частота слов
До сих пор мы видели, как можно реализовать разработку признаков, анализируя и обрабатывая весь текст.
Теперь мы изучим важность отдельных слов, рассчитав частоту n-грамм. N-грамма — это непрерывная последовательность из n элементов заданного образца текста. Когда n-грамма имеет размер 1, она называется униграммой (размер 2 — это биграмма).
Например, фраза «I like this article"можно разложить на:
- 4 униграммы: "I", "like", "this", "article"
- 3 биграммы: "I like", "like this", "this article"
Я буду использовать политические новости в качестве примера, чтобы проиллюстрировать, как вычислять частоты униграмм и биграмм.
y = "POLITICS"
corpus = dtf[dtf["y"]==y]["text_clean"]
lst_tokens = nltk.tokenize.word_tokenize(corpus.str.cat(sep=" "))
fig, ax = plt.subplots(nrows=1, ncols=2)
fig.suptitle("Most frequent words", fontsize=15)
## unigrams
dic_words_freq = nltk.FreqDist(lst_tokens)
dtf_uni = pd.DataFrame(dic_words_freq.most_common(),
columns=["Word","Freq"])
dtf_uni.set_index("Word").iloc[:top,:].sort_values(by="Freq").plot(
kind="barh", title="Unigrams", ax=ax[0],
legend=False).grid(axis='x')
ax[0].set(ylabel=None)
## bigrams
dic_words_freq = nltk.FreqDist(nltk.ngrams(lst_tokens, 2))
dtf_bi = pd.DataFrame(dic_words_freq.most_common(),
columns=["Word","Freq"])
dtf_bi["Word"] = dtf_bi["Word"].apply(lambda x: " ".join(
string for string in x) )
dtf_bi.set_index("Word").iloc[:top,:].sort_values(by="Freq").plot(
kind="barh", title="Bigrams", ax=ax[1],
legend=False).grid(axis='x')
ax[1].set(ylabel=None)
plt.show()
Если есть n букв, которые появляются только в одной категории (например, «республиканец» в политических новостях), то они могут стать новыми функциями. Более трудоемкий подход заключается в векторизации всего корпуса и использовании всех слов в качестве признаков (метод мешка слов).
Теперь я покажу вам, как добавить частоты слов в качестве признаков в фрейме данных. Нам нужно только научиться ScikitCountVectorizer, которая является одной из самых популярных библиотек машинного обучения в Python.
CountVectorizerПреобразуйте коллекцию текстовых документов в матрицу количества. В качестве примера я буду использовать 3 n-грамма: "box office"(часто появляется в индустрии развлечений)"republican"(часто в политике), "яблоко" (часто в технике).
lst_words = ["box office", "republican", "apple"]
## 计数
lst_grams = [len(word.split(" ")) for word in lst_words]
vectorizer = feature_extraction.text.CountVectorizer(
vocabulary=lst_words,
ngram_range=(min(lst_grams),max(lst_grams)))
dtf_X = pd.DataFrame(vectorizer.fit_transform(dtf["text_clean"]).todense(), columns=lst_words)
## 将新特征添加为列
dtf = pd.concat([dtf, dtf_X.set_index(dtf.index)], axis=1)
dtf.head()
Отличный способ визуализировать ту же информацию — использовать облако слов, где частота появления каждого логотипа показана размером и цветом шрифта.
wc = wordcloud.WordCloud(background_color='black', max_words=100,
max_font_size=35)
wc = wc.generate(str(corpus))
fig = plt.figure(num=1)
plt.axis('off')
plt.imshow(wc, cmap=None)
plt.show()
слово вектор
Недавно в области НЛП были разработаны новые языковые модели, основанные на структурах нейронных сетей, а не на более традиционных моделях n-грамм. Эти новые методы представляют собой набор методов языкового моделирования и изучения признаков, которые преобразуют слова в реальные векторы, отсюда и термин «встраивание слов».
Модели встраивания слов сопоставляют определенные слова с векторами, создавая вероятностное распределение токенов, которые появляются до и после выбранного слова. Эти модели быстро стали популярными, потому что, когда у вас есть реальные числа вместо строк, вы можете выполнять вычисления. Например, чтобы найти слова одного контекста, можно просто вычислить векторное расстояние.
Есть несколько библиотек Python, которые могут использовать эту модель. SpaCy — один из них, но поскольку мы его уже использовали, я расскажу о другом известном пакете: Gensim.
Это библиотека с открытым исходным кодом для неконтролируемых тематических моделей и обработки естественного языка с использованием современного статистического машинного обучения. Используя Gensim, я буду загружать предварительно обученныйGloVeМодель.
GloVeпредставляет собой алгоритм обучения без учителя для получения векторных представлений 300 слов.
nlp = gensim_api.load("glove-wiki-gigaword-300")
Мы можем использовать этот объект для сопоставления слов с векторами:
word = "love"
nlp[word]
nlp[word].shape
Теперь давайте посмотрим, какой самый близкий вектор слов, другими словами, слова, которые чаще всего встречаются в похожих контекстах.
Чтобы нарисовать векторный график в 2D-пространстве, мне нужно уменьшить размерность с 300 до 2. Я буду использовать t-распределенные вложения случайных соседей от Scikit, чтобы научиться делать это.
t-SNE — это инструмент для визуализации многомерных данных, который преобразует сходства между точками данных в совместные вероятности.
## 找到最近的向量
labels, X, x, y = [], [], [], []
for t in nlp.most_similar(word, topn=20):
X.append(nlp[t[0]])
labels.append(t[0])
## 降维
pca = manifold.TSNE(perplexity=40, n_components=2, init='pca')
new_values = pca.fit_transform(X)
for value in new_values:
x.append(value[0])
y.append(value[1])
## 绘图
fig = plt.figure()
for i in range(len(x)):
plt.scatter(x[i], y[i], c="black")
plt.annotate(labels[i], xy=(x[i],y[i]), xytext=(5,2),
textcoords='offset points', ha='right', va='bottom')
## 添加中心
plt.scatter(x=0, y=0, c="red")
plt.annotate(word, xy=(0,0), xytext=(5,2), textcoords='offset
points', ha='right', va='bottom')
тематическая модель
Пакет Genism посвящен тематическим моделям. Тематическая модель — это статистическая модель для обнаружения абстрактных «тем», которые появляются в наборе документов.
Я покажу, как извлекать темы с помощью LDA (скрытого распределения Дирихле): это порождающая статистическая модель, которая позволяет объяснить набор наблюдений ненаблюдаемыми группами, объясняя, почему определенные части данных похожи.
В основном документы представлены в виде случайной смеси по скрытым темам, и каждая тема характеризуется распределением по словам.
Давайте посмотрим, какие темы мы можем извлечь из технических новостей. Мне нужно указать количество тем, которые модель должна кластеризовать, я постараюсь использовать 3:
y = "TECH"
corpus = dtf[dtf["y"]==y]["text_clean"]
## 预处理语料库
lst_corpus = []
for string in corpus:
lst_words = string.split()
lst_grams = [" ".join(lst_words[i:i + 2]) for i in range(0,
len(lst_words), 2)]
lst_corpus.append(lst_grams)
## 将单词映射到id
id2word = gensim.corpora.Dictionary(lst_corpus)
## 创建词典 word:freq
dic_corpus = [id2word.doc2bow(word) for word in lst_corpus]
## 训练LDA
lda_model = gensim.models.ldamodel.LdaModel(corpus=dic_corpus, id2word=id2word, num_topics=3, random_state=123, update_every=1, chunksize=100, passes=10, alpha='auto', per_word_topics=True)
## 输出
lst_dics = []
for i in range(0,3):
lst_tuples = lda_model.get_topic_terms(i)
for tupla in lst_tuples:
lst_dics.append({"topic":i, "id":tupla[0],
"word":id2word[tupla[0]],
"weight":tupla[1]})
dtf_topics = pd.DataFrame(lst_dics,
columns=['topic','id','word','weight'])
## plot
fig, ax = plt.subplots()
sns.barplot(y="word", x="weight", hue="topic", data=dtf_topics, dodge=False, ax=ax).set_title('Main Topics')
ax.set(ylabel="", xlabel="Word Importance")
plt.show()
Попытка захватить 6-летний контент всего с 3 темами может быть немного сложной, но, как мы видели, все, что связано с Apple, заканчивается одной и той же темой.
в заключении
Эта статья представляет собой руководство, показывающее, как использовать NLP для анализа текстовых данных и извлечения признаков для моделей машинного обучения.
Я демонстрирую, как определить язык, на котором находятся данные, и как выполнить предварительную обработку и очистку текста. Затем я объяснил различные меры длины, анализ настроений с помощью Textblob и распознавание именованных сущностей с помощью SpaCy. Наконец, я объясню разницу между традиционным частотным подходом Scikit Learn и современными языковыми моделями Gensim.
Теперь вы знаете все основы НЛП, чтобы начать работать с текстовыми данными.
Оригинальная ссылка:к data science.com/text-согласно alaya…
Добро пожаловать на сайт блога Panchuang AI:panchuang.net/
sklearn машинное обучение китайские официальные документы:sklearn123.com/
Добро пожаловать на станцию сводки ресурсов блога Panchuang:docs.panchuang.net/