Skip to content

Instantly share code, notes, and snippets.

@Lurunchik
Forked from bobylevalexey/howto_word2vec.md
Last active March 12, 2018 21:11
Show Gist options
  • Save Lurunchik/cb09aa42a3ae6b5cc289 to your computer and use it in GitHub Desktop.
Save Lurunchik/cb09aa42a3ae6b5cc289 to your computer and use it in GitHub Desktop.

###Полезные ссылки:

Сам по себе модуль хорошо документирован.

###Описание Word2Vec - штука, принимающая на вход массив из предложений(являющихся массивом из слов) и возвращающая некий объект. Этот некий объект реализует интерфейс dict, где ключами являются слова. И несколько методов, о которых расскажу дальше.

Установка

Не факт, что установится быстрая версия:

pip install gensim 

Узнать что установлена быстрая версия(как её установить так и не разобрался):

from gensim.models import word2vec
if word2vec.FAST_VERSION == 1:
    print 'Fast version installed'
else:
    print 'Slow version installed' 

###Использование

>>> from gensim.models.word2vec import Word2Vec
>>> sentences = [['first', 'sentence'], ['second', 'sentence']]
>>> w2v = Word2Vec(sentences, min_count=0, size=5) # сразу обучится на данных предложениях
>>>
>>> # выдаст вектор данного слова
>>> print w2v['sentence']
[ 0.02182626 -0.03014402 -0.06414173 -0.01990378  0.00629869]
>>>
>>> # выдаст на сколько схожи данные слова.
>>> print w2v.similarity('first', 'second')
-0.0315916442588
>>>
>>> # выдаст на сколько схожи данные множества слов.
>>> print w2v.n_similarity(['first', 'second'], ['sentence'])
0.286853689395
>>>
>>> # выдаст топ наиболее схожих слов (похоже как-то используя косинусную меру)
>>> print w2v.most_similar(positive=['first'], negative=['second'], topn=3) # topn=10 по умолчанию
[('sentence', -0.2769932746887207)]
>>>
>>> # выдаст топ наиболее схожих слов но сосчитанных как-то по другому
>>> print w2v.most_similar_cosmul(positive=['first'], negative=['second'])
[('sentence', 0.7118682861328125)]
>>>
>>> # выдаст самое лишнее слово
>>> print w2v.doesnt_match(['first', 'second', 'sentence'])
first

Так можно распознавать биграммы:

bigram_transformer = gensim.models.Phrases(sentences)
model = Word2Vec(bigram_transformed[sentences], size=100, ...)

Модель можно дообучить:

w2v.build_vocab(sentences) # расширить словарь
w2v.train(new_sentences) # дообучить на новых предложениях 

Модель можно сохранить и восстановить:

w2v.save('filename')
w2v = Word2Vec.load('filename') 

Так же модель можно вытащить из файла сишного формата word2vec. Например, чтоб использовать словари с ресурса http://ling.go.mail.ru/misc/dialogue_2015.html, нужно использовать binary=True

w2v = Word2Vec.load_word2vec_format('/path/to/word2vec_c_format_file_name', binary=True) 

И сохранить в этом же формате:

w2v.save_word2vec_format('/path/to/new_word2vec_c_format_file_name', binary=True) 

#####Некоторые параметры конструктора Word2Vec:

Параметр Зачем нужен
min_count Слова, встретившиеся меньше min_count раз, в словарь не добавятся.
sg Алгоритм обучения: если sg=1, то используется skip-gram, иначе - cbow. skip-gram более точный, а cbow более быстрый.
size Размерность вектора, в который преобразуется слово.
workers Кол-во процессов, чтоб распараллелить обучение.
max_vocab_size Максимальный размер словаря. Если слов больше, наименее встречаемые слова в словарь не попадут.

Как получить предложния?

Для получения массива предложений существует gensim.models.word2vec.LineSentence. Инициализируется с помощью имени файла или объекта файла с текстом. Строки считает предложениями. Предложения разбивает на слова по пробелам.

w2v = Word2Vec(LineSentence('/path/to/file')) 

В качестве токенизатора можно использовать text_tokenizer. Использование:

from text_tokenizer import text_tokenizer
w2v = Word2Vec(text_tokenizer('First sentence. Second sentence.'))
import re
sentence_split_by_dot_pattern = ur"(?<!\s\w\d\.)(?<!\w\.\w\.)(?<=[….?!])[\s+\n+]\s*(?=[\w\"\'«]|<\/?\s*p\s*>|-(?=\s*\w+))"
sentence_split_pattern = sentence_split_by_dot_pattern \
+ ur"|(?<![….!?]\s<\/p>)[\s+\n+]\s*(?=<\s*p\s*>|<\s*br\s*\/?>)|[….?!](?=<\/?\s*p\s*>|<br\s*\/?>)"
word_split_pattern = ur"(?P<word>(?:(?!_)(?:[\w/]|(?<=\w)[-'.](?=\w)))+)"
sentence_split_regexp = re.compile(sentence_split_pattern, flags=re.UNICODE)
word_split_regexp = re.compile(word_split_pattern, flags=re.UNICODE)
def split_text_into_part(text, part_regexp):
"""
:rtype: list[dict]
"""
initial_position = 0
positions = []
for m in part_regexp.finditer(text):
positions.append(
{'left': initial_position, 'length': m.start() - initial_position})
initial_position = m.end()
positions.append(
{'left': initial_position, 'length': len(text) - initial_position})
return [dict(positions[i], text=text) for i, text in
enumerate(part_regexp.split(text))]
def split_text_into_sentences(text):
return split_text_into_part(text, sentence_split_regexp)
def split_text_into_words(text):
return [(match.group(), match.start(), match.end() - match.start(),
match.lastgroup)
for match in word_split_regexp.finditer(text)]
def sent_tokenizer(sent):
return [word_tup[0] for word_tup in split.split_text_into_words(sent)]
def text_tokenizer(text):
return [sent_tokenizer(sent_dict['text'])
for sent_dict in split.split_text_into_sentences(text)]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment