Полное руководство по библиотеки Gensim для начинающих

Gensim – это библиотека с открытым исходным кодом на Python, написанная Радимом Рехуреком, которая используется для тематического моделирования без учителя и обработки естественного языка (NLP). Она предназначена для извлечения семантических тем из документов.

Gensim может работать с большими текстовыми коллекциями. Этим она отличается от других программных библиотек машинного обучения, ориентированных на обработку в памяти. GenSim также предоставляет эффективные многоядерные реализации различных алгоритмов для увеличения скорости обработки. В нее добавлены более удобные средства для обработки текста, чем у конкурентов, таких как Scikit-learn, R и т. д.

В этом руководстве будут рассмотрены следующие концепции:

  1. Создание корпуса из заданного датасета.
  2. Матрицы TFIDF в Gensim.
  3. Создание биграммы и триграммы с помощью Gensim.
  4. Модели Word2Vec, с использованием Gensim.
  5. Модели Doc2Vec, с использованием Gensim.
  6. Создание тематической модели с LDA.
  7. Создание тематической модели с LSI.

Прежде чем двигаться дальше, давайте разберемся, что означают следующие термины:

  • Корпус: коллекция текстовых документов.
  • Вектор: форма представления текста.
  • Модель: алгоритм, используемый для генерации представления данных.
  • Тематическое моделирование: инструмент интеллектуального анализа информации, который используется для извлечения семантических тем из документов.
  • Тема: повторяющаяся группа слов, часто встречающихся вместе.

Например:

У вас есть документ, состоящий из таких слов, как:
bat, car, racquet, score, glass, drive, cup, keys, water, game, steering, liquid.

Их можно сгруппировать по разным темам:

Тема 1Тема 2Тема 3
glassbatcar
cupracquetdrive
waterscorekeys
liquidgamesterring

Некоторые из методов тематического моделирования:

  • Латентно-семантический анализ (LSI)
  • Латентное размещение Дирихле (LDA)

Теперь, когда у нас есть базовое понимание терминологии, давайте перейдем к использованию пакета Gensim. Сначала установите библиотеку с помощью следующих команд:

pip install gensim
# или
conda install gensim

Шаг 1. Создайте корпус из заданного датасета

Вам необходимо выполнить следующие шаги, чтобы создать свою коллекцию документов:

  1. Загрузите выбранный датасет.
  2. Проведите предварительную обработку вашего набора данных.
  3. Создайте словарь.
  4. Создайте 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 – популярный метод тематического моделирования, при котором каждый документ рассматривается как совокупность тем в определенной пропорции. Нам нужно вывести полезные качества тем, например, насколько они разделены и значимы. Темы хорошего качества зависят от:

  1. качества обработки текста,
  2. нахождения оптимального количества тем,
  3. настройки параметров алгоритма.

Выполните следующие шаги, чтобы создать модель.

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 в основном дает нам информацию по трем направлениям:

  1. Темы в документе
  2. К какой теме принадлежит каждое слово
  3. Значение фи

Значением фи является вероятность того, что слово относится к определенной теме. Для выбранного слова сумма значений фи дает количество раз, оно встречается в документе.

# вероятность принадлежности слова к теме
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. Вы, конечно, можете применять их по своему усмотрению.

Максим
Я создал этот блог в 2018 году, чтобы распространять полезные учебные материалы, документации и уроки на русском. На сайте опубликовано множество статей по основам python и библиотекам, уроков для начинающих и примеров написания программ.
Мои контакты: Почта
admin@pythonru.comAlex Zabrodin2018-10-26OnlinePython, Programming, HTML, CSS, JavaScript