Gensim – это библиотека с открытым исходным кодом на Python, написанная Радимом Рехуреком, которая используется для тематического моделирования без учителя и обработки естественного языка (NLP). Она предназначена для извлечения семантических тем из документов.
Gensim может работать с большими текстовыми коллекциями. Этим она отличается от других программных библиотек машинного обучения, ориентированных на обработку в памяти. GenSim также предоставляет эффективные многоядерные реализации различных алгоритмов для увеличения скорости обработки. В нее добавлены более удобные средства для обработки текста, чем у конкурентов, таких как Scikit-learn, R и т. д.
В этом руководстве будут рассмотрены следующие концепции:
- Создание корпуса из заданного датасета.
- Матрицы TFIDF в Gensim.
- Создание биграммы и триграммы с помощью Gensim.
- Модели Word2Vec, с использованием Gensim.
- Модели Doc2Vec, с использованием Gensim.
- Создание тематической модели с LDA.
- Создание тематической модели с LSI.
Прежде чем двигаться дальше, давайте разберемся, что означают следующие термины:
- Корпус: коллекция текстовых документов.
- Вектор: форма представления текста.
- Модель: алгоритм, используемый для генерации представления данных.
- Тематическое моделирование: инструмент интеллектуального анализа информации, который используется для извлечения семантических тем из документов.
- Тема: повторяющаяся группа слов, часто встречающихся вместе.
Например:
У вас есть документ, состоящий из таких слов, как:
bat, car, racquet, score, glass, drive, cup, keys, water, game, steering, liquid.
Их можно сгруппировать по разным темам:
| Тема 1 | Тема 2 | Тема 3 |
|---|---|---|
| glass | bat | car |
| cup | racquet | drive |
| water | score | keys |
| liquid | game | sterring |
Некоторые из методов тематического моделирования:
- Латентно-семантический анализ (LSI)
- Латентное размещение Дирихле (LDA)
Теперь, когда у нас есть базовое понимание терминологии, давайте перейдем к использованию пакета Gensim. Сначала установите библиотеку с помощью следующих команд:
pip install gensim
# или
conda install gensimШаг 1. Создайте корпус из заданного датасета
Вам необходимо выполнить следующие шаги, чтобы создать свою коллекцию документов:
- Загрузите выбранный датасет.
- Проведите предварительную обработку вашего набора данных.
- Создайте словарь.
- Создайте Bag of Words.
1.1 Загрузите выбранный датасет:
У вас может быть файл .txt в качестве набора данных или вы также можете загрузить необходимые датасеты с помощью API Gensim Downloader.
import os
# прочитать текстовый файл как объект
doc = open('sample_data.txt', encoding ='utf-8')
Gensim Downloader API – это модуль, доступный в библиотеке Gensim, который представляет собой API для скачивания, получения информации и загрузки датасетов/моделей.
import gensim.downloader as api
# проверка имеющихся моделей и датасетов
info_datasets = api.info()
print(info_datasets)
# информация ы конкретном наборе данных
dataset_info = api.info("text8")
# загрузка набора данных "text8"
dataset = api.load("text8")
# загрузка предварительно обученной модели
word2vec_model = api.load('word2vec-google-news-300')
Здесь мы будем использовать текстовый файл как необработанный набор данных, которые представляют собой текст со страницы Википедии.
1.2 Предварительная обработка набора данных
В NLP под предварительной обработкой текста понимают процесс очистки и подготовки текстовых данных. Для этого мы воспользуемся функцией simple_preprocess(), которая возвращает список токенов после их токенизации и нормализации.
import gensim
import os
from gensim.utils import simple_preprocess
# прочитать текстовый файл как объект
doc = open('nlp-wiki.txt', encoding ='utf-8')
# предварительная обработка файла для получения списка токенов
tokenized = []
for sentence in doc.read().split('.'):
# функция simple_preprocess возвращает список слов каждого предложения
tokenized.append(simple_preprocess(sentence, deacc = True))
print(tokenized)
doc.close()
Токенизированный вывод:
[['the', 'history', 'of', 'natural', 'language', 'processing', 'generally', 'started', 'in', 'the', 'although', 'work', 'can', 'be', 'found', 'from', 'earlier', 'periods'], ['in', 'alan', 'turing', 'published', 'an', 'article', 'titled', 'intelligence', 'which', 'proposed', 'what', 'is', 'now', 'called', 'the', 'turing', 'test', 'as', 'criterion', 'of', 'intelligence'], ['the', 'georgetown', 'experiment', 'in', 'involved', 'fully', 'automatic', 'translation', 'of', 'more', 'than', 'sixty', 'russian', 'sentences', 'into', 'english'], ['the', 'authors', 'claimed', 'that', 'within', 'three', 'or', 'five', 'years', 'machine', 'translation', 'would', 'be', 'solved', 'problem'],
...1.3 Создание словаря
Теперь у нас есть предварительно обработанные данные, которые можно преобразовать в словарь с помощью функции corpora.Dictionary(). Этот словарь представляет собой коллекцию уникальных токенов.
from gensim import corpora
# сохранение извлеченных токенов в словарь
my_dictionary = corpora.Dictionary(tokenized)
print(my_dictionary)
Dictionary(410 unique tokens: ['although', 'be', 'can', 'earlier', 'found']...)
1.3.1 Сохранение словаря
Вы можете сохранить (или загрузить) свой словарь на диске напрямую, а также в виде текстового файла, как показано ниже:
# сохраните словарь на диске
my_dictionary.save('my_dictionary.dict')
# загрузите обратно
load_dict = corpora.Dictionary.load('my_dictionary.dict')
# сохраните словарь в текстовом файле
from gensim.test.utils import get_tmpfile
tmp_fname = get_tmpfile("dictionary")
my_dictionary.save_as_text(tmp_fname)
# загрузите текстовый файл с вашим словарем
load_dict = corpora.Dictionary.load_from_text(tmp_fname)
1.4 Создание Bag of Words
Когда у нас есть словарь, мы можем создать корпус Bag of Words с помощью функции doc2bow(). Эта функция подсчитывает число вхождений и генерирует целочисленный идентификатор для каждого слова. Результат возвращается в виде разреженного вектора.
# преобразование в слов Bag of Word
bow_corpus =[my_dictionary.doc2bow(doc, allow_update = True) for doc in tokenized]
print(bow_corpus)
[[(0, 1), (1, 1), (2, 1),
...
(407, 1), (408, 1), (409, 1)], []]
1.4.1 Сохранение корпуса на диск
Код для сохранения/загрузки вашего корпуса:
from gensim.corpora import MmCorpus
from gensim.test.utils import get_tmpfile
output_fname = get_tmpfile("BoW_corpus.mm")
# сохранение корпуса на диск
MmCorpus.serialize(output_fname, bow_corpus)
# загрузка корпуса
load_corpus = MmCorpus(output_fname)
Шаг 2: Создание матрицы TF-IDF в Gensim
TF-IDF (Term Frequency – Inverse Document Frequency) – это часто используемая модель обработки естественного языка, которая помогает вам определять самые важные слова для каждого документа в корпусе. Она была разработана для коллекций небольшого размера.
Некоторые слова могут не являться стоп-словами, но при этом довольно часто встречаться в документах, имея малую значимость. Следовательно, эти слова необходимо удалить или снизить их важность. Модель TFIDF берет текст, написанный на одном языке, и гарантирует, что наиболее распространенные слова во всем корпусе не будут отображаться в качестве ключевых слов.
Вы можете построить модель TFIDF, используя Gensim и корпус, который вы разработали ранее, следующий образом:
from gensim import models
import numpy as np
# Вес слова в корпусе Bag of Word
word_weight =[]
for doc in bow_corpus:
for id, freq in doc:
word_weight.append([my_dictionary[id], freq])
print(word_weight)
Вес слов перед применением TF-IDF:
[['although', 1], ['be', 1], ['can', 1], ['earlier', 1],
...
['steps', 1], ['term', 1], ['transformations', 1]]Код (применение модели TF-IDF):
# создать модель TF-IDF
tfIdf = models.TfidfModel(bow_corpus, smartirs ='ntc')
# TF-IDF вес слова
weight_tfidf =[]
for doc in tfIdf[bow_corpus]:
for id, freq in doc:
weight_tfidf.append([my_dictionary[id], np.around(freq, decimals=3)])
print(weight_tfidf)
Вес слов после применением TF-IDF:
[['although', 0.339], ['be', 0.19], ['can', 0.237], ['earlier', 0.339],
...
['steps', 0.191], ['term', 0.191], ['transformations', 0.191]]
Вы можете видеть, что словам, часто встречающимся в документах, теперь присвоены более низкие веса.
Шаг 3. Создание биграмм и триграмм с помощью Gensim
Многие слова употребляются в тексте вместе. Такие сочетания имеют другое значение, чем составляющие их слова по отдельности.
Например:
Beatboxing -> слова beat и boxing имеют собственные смысловые вариации, но вместе они представляют совсем иное значение.
Биграмма — группа из двух слов.
Триграмма — группа из трех слов.
Здесь мы будем использовать датасет text8, который можно загрузить с помощью API downloader Gensim. Код построения биграмм и триграмм:
import gensim.downloader as api
from gensim.models.phrases import Phrases
# загрузка набора данных "text8"
dataset = api.load("text8")
# извлечь список слов из датасета
data =[]
for word in dataset:
data.append(word)
# Биграм с использованием модели фразера
bigram_model = Phrases(data, min_count=3, threshold=10)
print(bigram_model[data[0]])
['anarchism', 'originated', 'as', 'a', 'term', 'of', 'abuse', 'first', 'used', 'against', 'early', 'working_class', 'radicals', 'including', 'the', 'diggers', 'of', 'the', 'english', 'revolution', 'and', 'the', 'sans_culottes', 'of', 'the', 'french_revolution', 'whilst', 'the', 'term', 'is', 'still' ...Для создания триграмм мы просто передаем полученную выше биграммную модель той же функции.
# Триграмма с использованием модели фразы
trigram_model = Phrases(bigram_model[data], threshold=10)
# Триграмма
print(trigram_model[bigram_model[data[0]]])
['anarchism', 'originated', 'as', 'a', 'term', 'of', 'abuse', 'first', 'used', 'against', 'early' ...Шаг 4: Создайте модель Word2Vec с помощью Gensim
Алгоритмы ML/DL не могут использовать текст напрямую, поэтому нам нужно некоторое числовое представление, чтобы эти алгоритмы могли обрабатывать данные. В простых приложениях машинного обучения используются CountVectorizer и TFIDF, которые не сохраняют связь между словами.
Word2Vec — метод преобразования текста для создания векторных представлений (Word Embeddings), которые отображают все слова, присутствующие в языке, в векторное пространство заданной размерности. Мы можем выполнять математические операции с этими векторами, которые помогают сохранить связь между словами.
Пример: queen — women + man = king.
Готовые векторно-семантические модели, такие как word2vec, GloVe, fasttext и другие можно загрузить с помощью API загрузчика Gensim. Иногда векторные представления определенных слов из вашего документа могут отсутствовать в упомянутых пакетах. Но вы можете решить данную проблему, обучив свою модель.
4.1) Обучение модели
import gensim.downloader as api
from multiprocessing import cpu_count
from gensim.models.word2vec import Word2Vec
# загрузка набора данных "text8"
dataset = api.load("text8")
# извлечь список слов из датасета
data =[]
for word in dataset:
data.append(word)
# Разделим данные на две части
data_1 = data[:1200] # используется для обучения модели
data_2 = data[1200:] # используется для обновления модели
# Обучение модели Word2Vec
w2v_model = Word2Vec(data_1, min_count=0, workers=cpu_count())
# вектор слов для слова "время"
print(w2v_model.wv['time'])
Вектор для слова «time»:
[-0.04681756 -0.08213229 1.0628034 -1.0186515 1.0779341 -0.89710116
0.6538859 -0.81849015 -0.29984367 0.55887854 2.138567 -0.93843514
...
-1.4128548 -1.3084044 0.94601256 0.27390406 0.6346426 -0.46116787
0.91097695 -3.597664 0.6901859 1.0902803 ]Вы также можете использовать функцию most_similar(), чтобы найти слова, похожие на переданное.
# слова, похожие на "time"
print(w2v_model.wv.most_similar('time'))
# сохранение и загрузка модели
w2v_model.save('Word2VecModel')
model = Word2Vec.load('Word2VecModel')
Cлова, наиболее похожие на «time»:
[('moment', 0.6137239933013916), ('period', 0.5904807448387146), ('stage', 0.5393826961517334), ('decade', 0.51670902967453), ('lifetime', 0.4878680109977722), ('once', 0.4843854010105133), ('distance', 0.4821343719959259), ('breteuil', 0.4815649390220642), ('preestablished', 0.47662678360939026), ('point', 0.4757876396179199)]4.2) Обновление модели
# построим словарный запас по образцу из последовательности предложений
w2v_model.build_vocab(data_2, update=True)
# обучение вектора слов
w2v_model.train(data_2, total_examples=w2v_model.corpus_count, epochs=w2v_model.epochs)
print(w2v_model.wv['time'])
На выходе вы получите новые веса для слов.
Шаг 5: Создание модели Doc2Vec с помощью Gensim
В отличие от модели Word2Vec, модель Doc2Vec генерирует векторное представление для всего документа или группы слов. С помощью этой модели мы можем найти взаимосвязь между различными документами, как показано ниже:
Если натренировать модель на литературе типа «Алиса в Зазеркалье». Мы можем сказать, что
Алиса в Зазеркалье == Алиса в Стране чудес.
5.1) Обучите модель
import gensim
import gensim.downloader as api
from gensim.models import doc2vec
# получить датасета
dataset = api.load("text8")
data =[]
for w in dataset:
data.append(w)
# Для обучения модели нам нужен список целевых документов
def tagged_document(list_of_ListOfWords):
for x, ListOfWords in enumerate(list_of_ListOfWords):
yield doc2vec.TaggedDocument(ListOfWords, [x])
# тренировочные данные
data_train = list(tagged_document(data))
# вывести обученный набор данных
print(data_train[:1])
Вывод – обученный датасет.
5.2) Обновите модель
# Инициализация модели
d2v_model = doc2vec.Doc2Vec(vector_size=40, min_count=2, epochs=30)
# расширить словарный запас
d2v_model.build_vocab(data_train)
# Обучение модели Doc2Vec
d2v_model.train(data_train, total_examples=d2v_model.corpus_count, epochs=d2v_model.epochs)
# Анализ выходных данных
analyze = d2v_model.infer_vector(['violent', 'means', 'to', 'destroy'])
print(analyze)
Вывод обновленной модели:
[-3.79053354e-02 -1.03341974e-01 -2.85615563e-01 1.37473553e-01
1.79868549e-01 3.42468806e-02 -1.68495290e-02 -1.86038092e-01
...
-1.20517321e-01 -1.48323074e-01 -5.70210926e-02 -2.15077385e-01]Шаг 6. Создание тематической модели с помощью LDA
LDA – популярный метод тематического моделирования, при котором каждый документ рассматривается как совокупность тем в определенной пропорции. Нам нужно вывести полезные качества тем, например, насколько они разделены и значимы. Темы хорошего качества зависят от:
- качества обработки текста,
- нахождения оптимального количества тем,
- настройки параметров алгоритма.
Выполните следующие шаги, чтобы создать модель.
6.1 Подготовка данных
Это делается путем удаления стоп-слов и последующей лемматизации ваших данных. Чтобы выполнить лемматизацию с помощью Gensim, нам нужно сначала загрузить пакет шаблонов и стоп-слова.
pip install pattern
# в python консоле
>>> import nltk
>>> nltk.download('stopwords')
import gensim
from gensim import corpora
from gensim.models import LdaModel, LdaMulticore
import gensim.downloader as api
from gensim.utils import simple_preprocess
import nltk
from nltk.stem.wordnet import WordNetLemmatizer
# nltk.download('stopwords')
from nltk.corpus import stopwords
import re
import logging
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s')
logging.root.setLevel(level=logging.INFO)
# загрузка stopwords
stop_words = stopwords.words('english')
# добавление stopwords
stop_words = stop_words + ['subject', 'com', 'are', 'edu', 'would', 'could']
lemmatizer = WordNetLemmatizer()
# загрузка датасета
dataset = api.load("text8")
data = [w for w in dataset]
# подготовка данных
processed_data = []
for x, doc in enumerate(data[:100]):
doc_out = []
for word in doc:
if word not in stop_words: # для удаления стоп-слов
lemmatized_word = lemmatizer.lemmatize(word) # лемматизация
if lemmatized_word:
print
doc_out.append(lemmatized_word)
else:
continue
processed_data.append(doc_out) # processed_data это список слов
# вывод образца
print(processed_data[0][:10])
['anarchism', 'originated', 'term', 'abuse', 'first', 'used', 'early', 'working', 'class', 'radical']6.2 Создание словаря и корпуса
Обработанные данные теперь будут использоваться для создания словаря и корпуса.
dictionary = corpora.Dictionary(processed_data)
corpus = [dictionary.doc2bow(l) for l in processed_data]
6.3 Обучение LDA-модели
Мы будем обучать модель LDA с 5 темами, используя словарь и корпус, созданные ранее. Здесь используется функция LdaModel(), но вы также можете использовать функцию LdaMulticore(), поскольку она позволяет выполнять параллельную обработку.
# Обучение
LDA_model = LdaModel(corpus=corpus, id2word=dictionary, num_topics=5)
# сохранение модели
LDA_model.save('LDA_model.model')
# показать темы
print(LDA_model.print_topics(-1))
Слова, которые встречаются в более чем одной теме и имеют малое значение, могут быть добавлены в список запрещенных слов.
6.4 Интерпретация вывода
Модель LDA в основном дает нам информацию по трем направлениям:
- Темы в документе
- К какой теме принадлежит каждое слово
- Значение фи
Значением фи является вероятность того, что слово относится к определенной теме. Для выбранного слова сумма значений фи дает количество раз, оно встречается в документе.
# вероятность принадлежности слова к теме
LDA_model.get_term_topics('fire')
bow_list =['time', 'space', 'car']
# сначала преобразуйте в bag of words
bow = LDA_model.id2word.doc2bow(bow_list)
# интерпретация данных
doc_topics, word_topics, phi_values = LDA_model.get_document_topics(bow, per_word_topics=True)
Шаг 7. Создание тематической модели с помощью LSI
Чтобы создать модель с LSI, просто выполните те же шаги, что и с LDA.
Только для обучения используйте функцию LsiModel() вместо LdaMulticore() или LdaModel().
from gensim.models import LsiModel
# Обучение модели с помощью LSI
LSI_model = LsiModel(corpus=corpus, id2word=dictionary, num_topics=7, decay=0.5)
# темы
print(LSI_model.print_topics(-1))
Заключение
Это только некоторые из возможностей библиотеки Gensim. Пользоваться ими очень удобно, особенно когда вы занимаетесь NLP. Вы, конечно, можете применять их по своему усмотрению.





