Word Embeddings

In [1]:
import math

import numpy as np
import pandas as pd
from sklearn.datasets import make_moons, make_circles, make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.neural_network import MLPClassifier
import matplotlib.pyplot as plt
import seaborn as sns

import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Input, Dense, Conv2D, MaxPooling2D, UpSampling2D, Dropout, Lambda, Concatenate, Embedding
from keras.optimizers import RMSprop, Adam
from keras import regularizers, objectives, metrics
from keras.models import Model
from keras import backend as K

from IPython.display import display

%matplotlib inline
# sns.set()
Using TensorFlow backend.
/home/rbank/.pyenv/versions/3.6.2/lib/python3.6/importlib/_bootstrap.py:205: RuntimeWarning: compiletime version 3.5 of module 'tensorflow.python.framework.fast_tensor_util' does not match runtime version 3.6
  return f(*args, **kwds)

Работа с текст

  • Embedding е често първият слой в мрежата, който заменя one-hot-encoding.
  • Най-вече computational optimazation.
  • Ембединга е речник (dictionary), който пази n-мерен вектор с тегла за всяка дума от корпуса.
  • Да видим как се стигна до Embedding.
In [2]:
# one-hot-encoding на 3 думи от корпус 4 думи.

x = np.array([
    [1, 0, 0, 0],
    [0, 1, 0, 0],
    [0, 0, 1, 0]])
In [3]:
# Ще имаме първи слой с 10 неврона. 
# x има размер 4, което означава 40 тегла.

W1 = np.arange(40).reshape(4, 10)
print(W1)
[[ 0  1  2  3  4  5  6  7  8  9]
 [10 11 12 13 14 15 16 17 18 19]
 [20 21 22 23 24 25 26 27 28 29]
 [30 31 32 33 34 35 36 37 38 39]]
In [4]:
np.dot(x, W1)
Out[4]:
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24, 25, 26, 27, 28, 29]])
In [5]:
print([0, 0, 0, 1] @ W1)
[30 31 32 33 34 35 36 37 38 39]
  • Напрактика първия слой винаги ще връща вектора от тегла за конкретната дума от one-hot-encoding.
  • Няма нужда да се правят всички умножения в матриците.
  • Вече всяка дума се представя не със [0, 0, ... , 1, ... , 0] - one-hot-encoding,
  • А с вектор от стойности [0.12, 0.55, -1.4, ... , 0.14]
  • При трениране се получава латентно пространство и всяко измерение от вектора представлява скрита променлива на думите.
  • Тези скрити променливи взаимодействат по интересен начин.
  • Сходни думи имат сходни стойности за някои от латентните стойности.
  • Вместо да ползваме one-hot и да умножаваме матриците, keras ни предоставя класа Embedding.

Embedding

  • keras.layers.Embedding(input_dim, output_dim, embeddings_initializer='uniform', embeddings_regularizer=None, activity_regularizer=None, embeddings_constraint=None, mask_zero=False, input_length=None)
  • input_dim – броя на думите в корпуса
  • output_dim – броя на невроните с които представяме всяка дума (embedding size)

Това е за Embedding.

Сега да видим трениране на латентното пространство на word embeddings.

  • Има два основни вида unsupervised трениране на тези вектори.
  • И двата модела се опитват да моделират векторите на думите базирани на думите които се намират около тях в текста.
  • Word2Vec се опитва да моделира ко-появата (co-occurance), чрез прозорци, n-grams и невронни мрежи.
  • Glove се оптива да хване статистиката на ко-поява и след това прави факторизиране на матрицата (matrix factorization).

Word2Vec

  • Continous Bag of Words Model
  • Skip Gram Model

GloVe: Global Vectors for Word Representation

https://nlp.stanford.edu/projects/glove/

In [6]:
t = """
Сладолед
Сладоледът представлява сладък замразен десерт.

Прави се основно от мляко, масло и захар с добавка на аромати.

Той е висококалоричен продукт, съдържащ голямо количество мазнини, захар, витамини и въглехидрати.

Съществува голямо разнообразие според вкуса, опаковката и формата на неговите видове.

Според състава си сладоледът бива:

сметанов – поне 10% масленост и 16% захар
млечен – 4% масленост и до 20% захар
плодов – без мляко, само с натурални сокове, плодове (20 – 30%) и захар (25 – 30%)
шоколадов – поне 6% шоколад (или 2,5% какао)
орехов – 6 – 10% орехи (или други ядки)
мелба – с плодове и украса (бисквити, заливки и др.)
Сладкарски изделия
""" \
+ \
"""Торта
За информацията в тази статия или раздел не са посочени източници. Въпросната информация може да е непълна, неточна или изцяло невярна.
Имайте предвид, че това може да стане причина за изтриването на цялата статия или раздел.	

Торта за рожден ден, украсена със свещи

Резен от шварцвалдска черешова торта
Тортата (от италиански Torta) е сладкарско изделие, обикновено в кръгла форма и на етажи (тестените блатове се редуват със слоеве крем) и украсено с плодове, ядки, шоколад, сметана и други, което се приготвя и поднася при по-специални случаи - рождени и имени дни, юбилеи и подобни.

По принцип тортите в кулинарията биват солени и сладки. Солените се поднасят като предястие или като част от менюто на различни приеми. Сладките торти обаче са цяло изкуство, на което се учиш цял живот, защото разнообразието им е неизчерпаемо. По консистенция тортите биват сочни (сиропирани) и сухи.

Приготвят се от различни сладкарски основи (от един или няколко различни вида). Най-често употребяваните основи са:

пандишпанови платки и блатове в най-различни вкусове и цветове - ванилия, какао, карамел, различни видове ядки или с прибавка на краве масло, прясно мляко, сметана, претърпели термична обработка плодове;
маслени сладкарски основи от класическо ронливо маслено тесто или обогатено с ядки, линцер основа, многолистна маслена основа, кейкова основа;
ядкови основи - с участие на орехови, бадемови, лешникови ядки;
белтъчни основи - леко и тежко белтъчно тесто;
медени сладкарски основи.
Друг компонент на тортите са сладкарските сиропи. Те се приготвят от захар, глюкоза, пчелен мед, вода, хранителна киселина, оцветители и овкусители. Понякога захарта се карамелизира и се получава карамелов сироп, а с прибавка на какао и масло се получава какаов сироп. Киселината служи за инверсия на сиропа с цел предпазване от изкристализиране на захарта от сиропа.

Следващия компонент от приготвянето на торти е пълнежът. За пълнеж се използват различни сладкарски кремове - маслен, шоколадов, сметанов и комбинации между тях. Понякога се добавят и натрошени ядки, шоколад, крокант, желиращи вещества, ликьори, конфитюри, яйца, есенции, пресни плодове.

Операцията по сиропиране на сладкарските основи се нарича трампиране, а съединяването им с крем - зафилване. След зафилването е необходимо време за охлаждане и стягане на основите. Следащата операция е гарниране с крем, глазури, поръски, панировки, фарситури от различен произход.

Последна операция е украсяване с художествена цел от крем, глазури, поръски и плодове.

Готовите торти се съхраняват при хладилни условия или в сухи и тъмни складове при подходяща температура и ниска относителна влажност на въздуха.

Категории: Сладкарски изделия Десерти
"""
In [7]:
sentences = t.replace("\n",".").split(".")
from sklearn.feature_extraction.text import CountVectorizer
cv = CountVectorizer()
one_hot_sentence = cv.fit_transform(sentences).todense()
print(len(cv.vocabulary_))
print(one_hot_sentence.shape)
286
(76, 286)
In [8]:
co_occurance = one_hot_sentence.T.dot(one_hot_sentence)
In [9]:
df = pd.DataFrame(co_occurance, index=cv.vocabulary_, columns=cv.vocabulary_)
df
Out[9]:
сладолед сладоледът представлява сладък замразен десерт прави се основно от ... тъмни складове подходяща температура ниска относителна влажност въздуха категории десерти
сладолед 2 1 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 1 0 0
сладоледът 1 1 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
представлява 0 0 2 1 2 0 0 0 1 0 ... 0 0 0 0 0 0 0 0 0 0
сладък 0 0 1 1 2 0 0 0 1 0 ... 0 0 0 0 0 0 0 0 0 0
замразен 0 0 2 2 4 0 0 0 2 0 ... 0 0 0 0 0 0 0 0 0 0
десерт 0 0 0 0 0 1 0 0 0 0 ... 0 0 0 0 1 0 1 1 0 0
прави 0 0 0 0 0 0 1 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
се 0 0 0 0 0 0 0 1 0 0 ... 0 0 0 0 0 0 0 1 1 0
основно 0 0 1 1 2 0 0 0 1 0 ... 0 0 0 0 0 0 0 0 0 0
от 0 0 0 0 0 0 0 0 0 1 ... 0 0 0 0 0 0 0 0 0 0
мляко 0 0 0 0 0 0 0 0 0 1 ... 0 0 0 0 0 0 0 0 0 0
масло 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
захар 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
добавка 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
на 0 0 0 0 0 1 0 0 0 0 ... 0 0 0 0 1 0 1 2 0 0
аромати 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 1 0 0
той 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 1 0 0 1 0 1
висококалоричен 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
продукт 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 1 0 0
съдържащ 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
голямо 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
количество 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
мазнини 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 1 0 0
витамини 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
въглехидрати 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
съществува 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
разнообразие 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
според 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
вкуса 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
опаковката 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
време 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
охлаждане 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
стягане 0 0 0 0 0 1 0 0 0 0 ... 0 0 0 0 1 0 1 1 0 0
основите 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
следащата 0 0 0 0 0 0 0 0 0 0 ... 0 0 1 0 0 0 0 0 0 0
операция 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
гарниране 0 0 0 0 0 0 0 1 0 0 ... 0 0 0 0 0 0 0 1 1 0
глазури 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
поръски 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
панировки 0 0 0 0 0 1 0 0 0 0 ... 0 0 0 0 1 0 1 1 0 0
фарситури 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
различен 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
произход 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
последна 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
украсяване 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 1 0 0
художествена 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
готовите 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
съхраняват 0 0 0 0 0 0 0 0 0 0 ... 1 0 0 0 0 0 0 0 0 0
хладилни 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
условия 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
тъмни 0 0 0 0 0 0 0 0 0 0 ... 1 0 0 0 0 0 0 0 0 0
складове 0 0 0 0 0 0 0 0 0 0 ... 0 1 0 1 0 0 0 0 0 0
подходяща 0 0 0 0 0 0 0 0 0 0 ... 0 0 1 0 0 0 0 0 0 0
температура 0 0 0 0 0 0 0 0 0 0 ... 0 1 0 1 0 0 0 0 0 0
ниска 0 0 0 0 0 1 0 0 0 0 ... 0 0 0 0 3 1 1 2 0 1
относителна 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 1 2 0 0 0 0
влажност 0 0 0 0 0 1 0 0 0 0 ... 0 0 0 0 1 0 1 1 0 0
въздуха 1 0 0 0 0 1 0 1 0 0 ... 0 0 0 0 2 0 1 6 1 1
категории 0 0 0 0 0 0 0 1 0 0 ... 0 0 0 0 0 0 0 1 1 0
десерти 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 1 0 0 1 0 1

286 rows × 286 columns

In [10]:
ids = ['сладолед', 'торта', 'десерт']
small = df[ids]
small[(small.T != 0).any()].sort_values(ids, ascending=False)
Out[10]:
сладолед торта десерт
сладолед 2 0 0
плодов 1 0 1
въздуха 1 0 1
сладоледът 1 0 0
какао 1 0 0
изделия 1 0 0
обикновено 1 0 0
част 1 0 0
менюто 1 0 0
един 1 0 0
сиропа 1 0 0
друг 0 2 2
което 0 2 1
торта 0 2 0
имайте 0 1 1
цялата 0 1 1
консистенция 0 1 1
плодове 0 1 0
шоколад 0 1 0
орехи 0 1 0
украса 0 1 0
поднася 0 1 0
имени 0 1 0
кулинарията 0 1 0
предястие 0 1 0
сладките 0 1 0
участие 0 1 0
тежко 0 1 0
глюкоза 0 1 0
хранителна 0 1 0
... ... ... ...
хладилни 0 1 0
десерт 0 0 1
на 0 0 1
10 0 0 1
натурални 0 0 1
други 0 0 1
информацията 0 0 1
не 0 0 1
украсена 0 0 1
биват 0 0 1
цяло 0 0 1
неизчерпаемо 0 0 1
сочни 0 0 1
сухи 0 0 1
прибавка 0 0 1
прясно 0 0 1
орехови 0 0 1
белтъчни 0 0 1
киселина 0 0 1
какаов 0 0 1
служи 0 0 1
инверсия 0 0 1
приготвянето 0 0 1
тях 0 0 1
есенции 0 0 1
трампиране 0 0 1
стягане 0 0 1
панировки 0 0 1
ниска 0 0 1
влажност 0 0 1

66 rows × 3 columns

  • Няма да ни стигне времето да имплементираме моделите,
  • Но ще покажем как да ги използваме на готово.

gensim

Сваляне на претренирани вектори

  • Google word2vec от тук (1.5GB)
  • Stanford Glove от тук (800MB - 2GB)

или wget -c "https://s3.amazonaws.com/dl4j-distribution/GoogleNews-vectors-negative300.bin.gz"

Зареждане на вектори от Google Word2Vec

In [12]:
import gensim
model = gensim.models.KeyedVectors.load_word2vec_format('GoogleNews-vectors-negative300.bin', binary=True)  
In [13]:
# най-близки думи
model.most_similar(positive=['milk'], topn=10)
Out[13]:
[('dairy', 0.732360303401947),
 ('cow_milk', 0.6860158443450928),
 ('milk_powder', 0.6646485924720764),
 ('camels_Nancy_Riegler', 0.6561243534088135),
 ('powdered_milk', 0.6497933268547058),
 ('raw_milk', 0.6309322118759155),
 ('goat_milk', 0.6260650157928467),
 ('apple_juice', 0.6173229217529297),
 ('whey', 0.6159118413925171),
 ('chocolate_caramel_mousse', 0.6145174503326416)]
In [15]:
model.most_similar(positive=['panda'])
Out[15]:
[('giant_panda', 0.8250844478607178),
 ('pandas', 0.791919469833374),
 ('giant_pandas', 0.6932857036590576),
 ('panda_cub', 0.6871635317802429),
 ('Giant_panda', 0.6341897249221802),
 ('giant_panda_cub', 0.6139722466468811),
 ('orangutan', 0.6027069091796875),
 ('panda_cubs', 0.5879790782928467),
 ('Giant_Panda', 0.5849473476409912),
 ('captive_pandas', 0.583149790763855)]

Аритментика с думи

In [16]:
model.most_similar(positive=['king', 'woman'], negative=['man'], topn=1)
Out[16]:
[('queen', 0.7118192315101624)]
In [43]:
model.most_similar(positive=['grandfather', 'woman'], negative=['man'], topn=1)
Out[43]:
[('grandmother', 0.7433432936668396)]
In [53]:
model.most_similar(positive=['grandfather', 'young', 'man'], negative=['old'], topn=1)
Out[53]:
[('father', 0.6096605062484741)]
In [50]:
model.most_similar(positive=['paris', 'germany'], negative=['france'], topn=1)
Out[50]:
[('berlin', 0.48413652181625366)]

Можем да търсим и кое е излишното:

In [57]:
model.doesnt_match(["icecream", "cake", "chocolate", "whiskey"])
Out[57]:
'whiskey'
In [62]:
model.doesnt_match(["vegetable", "bicycle", "motorboat", "car", "plane"])
Out[62]:
'vegetable'
In [73]:
model.doesnt_match("breakfast cereal dinner lunch".split())
Out[73]:
'cereal'

Зареждане на модели от Stanford Glove

In [106]:
# from gensim.scripts.glove2word2vec import glove2word2vec
# glove_input_file = 'glove.txt'
# word2vec_output_file = 'word2vec.txt'
# glove2word2vec(glove_input_file, word2vec_output_file)

# След което зареждате, както Google Word2Vec

Туториал за tensorflow:

https://www.tensorflow.org/tutorials/word2vec

Използване на модела в Keras

In [92]:
embedding = model.get_keras_embedding(train_embeddings=False)
print(type(embedding))
print(embedding.trainable)
<class 'keras.layers.embeddings.Embedding'>
False
In [128]:
print(model.index2word[:20])
['</s>', 'in', 'for', 'that', 'is', 'on', '##', 'The', 'with', 'said', 'was', 'the', 'at', 'not', 'as', 'it', 'be', 'from', 'by', 'are']

Трениране на word2vec със собствен корпус

Изтегляне на wiki корпус

wget -c 'https://dumps.wikimedia.org/bgwiki/20171201/bgwiki-20171201-pages-articles-multistream.xml.bz2'

от https://dumps.wikimedia.org/bgwiki/

~300MB

In [3]:
from gensim.corpora.wikicorpus import WikiCorpus
from gensim.models.word2vec import Word2Vec
In [ ]:
wiki = WikiCorpus('bgwiki-20171201-pages-articles-multistream.xml.bz2', lemmatize=False, dictionary={})
sentences = list(wiki.get_texts())
In [100]:
print(len(sentences))
print(sentences[0])
175389
['папа', 'григорий', 'xiii', 'вечният', 'григориански', 'календар', 'от', 'октомври', 'йезуитът', 'христофор', 'клавий', 'важен', 'член', 'от', 'реформната', 'комисия', 'изчисление', 'по', 'костите', 'на', 'ръцете', 'пфениг', 'пощенска', 'марка', 'на', 'германската', 'поща', 'за', 'годишнината', 'на', 'григорианския', 'календар', 'григорианският', 'календар', 'понякога', 'наричан', 'грегориански', 'календар', 'нов', 'стил', 'съвременният', 'международно', 'признат', 'светски', 'календар', 'на', 'който', 'се', 'основава', 'международният', 'стандарт', 'iso', 'григорианският', 'календар', 'въведен', 'употреба', 'на', 'октомври', 'съответствие', 'була', 'от', 'февруари', 'на', 'папа', 'григорий', 'xiii', 'чието', 'име', 'носи', 'днес', 'той', 'поправя', 'древноримския', 'юлиански', 'календар', 'като', 'него', 'са', 'нанесени', 'някои', 'корекции', 'за', 'да', 'се', 'отчете', 'по', 'точно', 'дължината', 'на', 'тропическата', 'година', 'юлианския', 'календар', 'се', 'приема', 'че', 'времето', 'между', 'две', 'последователни', 'пролетни', 'равноденствия', 'дни', 'дробната', 'част', 'се', 'компенсира', 'като', 'една', 'на', 'всеки', 'четири', 'години', 'има', 'един', 'ден', 'повече', 'високосна', 'година', 'при', 'григорианския', 'календар', 'годините', 'кратни', 'на', 'не', 'са', 'високосни', 'изключение', 'на', 'годините', 'кратни', 'на', 'на', 'всеки', 'четири', 'века', 'се', 'пропускат', 'три', 'високосни', 'години', 'като', 'например', 'година', 'което', 'дава', 'средна', 'продължителност', 'на', 'годината', 'от', 'дни', 'тази', 'стойност', 'се', 'доближава', 'значително', 'до', 'на', 'тропическата', 'година', 'например', 'времето', 'между', 'пролетните', 'равноденствия', 'през', 'година', 'дни', 'григорианският', 'календар', 'възприет', 'различните', 'страни', 'по', 'различно', 'време', 'като', 'този', 'процес', 'продължава', 'почти', 'три', 'века', 'половина', 'въведен', 'българия', 'със', 'закон', 'гласуван', 'от', 'народното', 'събрание', 'на', 'март', 'като', 'отчитането', 'на', 'времето', 'единствено', 'по', 'нов', 'стил', 'започва', 'от', 'април', 'според', 'юлианския', 'календар', 'април', 'според', 'григорианския', 'календар', 'описание', 'григорианският', 'календар', 'слънчев', 'календар', 'зависим', 'от', 'периода', 'на', 'завъртането', 'на', 'земята', 'около', 'слънцето', 'който', 'дни', 'от', 'часа', 'по', 'минути', 'всяка', 'по', 'секунди', 'средната', 'тропическа', 'година', 'дни', 'часа', 'минути', 'секунди', 'тя', 'варира', 'слабо', 'една', 'до', 'две', 'минути', 'зависимост', 'от', 'началната', 'точка', 'точната', 'стойност', 'изчислена', 'на', 'януари', 'година', 'дни', 'средната', 'година', 'при', 'григорианския', 'календар', 'дни', 'за', 'да', 'може', 'броят', 'на', 'годишните', 'дни', 'да', 'цяло', 'число', 'през', 'определени', 'периоди', 'най', 'често', 'години', 'се', 'добавя', 'един', 'допълнителен', 'ден', 'февруари', 'годината', 'се', 'нарича', 'високосна', 'от', 'тук', 'следва', 'разпределението', 'на', 'високосните', 'години', 'всяка', 'година', 'кратна', 'на', 'високосна', 'всяка', 'година', 'кратна', 'на', 'но', 'не', 'на', 'не', 'високосна', 'всяка', 'година', 'кратна', 'на', 'високосна', 'григорианският', 'календар', 'се', 'дели', 'на', 'месеца', 'по', 'следния', 'начин', 'януари', 'дни', 'февруари', 'или', 'дни', 'март', 'дни', 'април', 'дни', 'май', 'дни', 'юни', 'дни', 'юли', 'дни', 'август', 'дни', 'септември', 'дни', 'октомври', 'дни', 'ноември', 'дни', 'декември', 'дни', 'всеки', 'период', 'от', 'седем', 'дни', 'се', 'казва', 'седмица', 'дните', 'на', 'български', 'се', 'наричат', 'така', 'понеделник', 'вторник', 'сряда', 'четвъртък', 'петък', 'събота', 'неделя', 'броенето', 'на', 'годините', 'календара', 'започва', 'годината', 'за', 'която', 'средновековните', 'схоластици', 'погрешно', 'приемат', 'че', 'година', 'на', 'раждането', 'на', 'исус', 'христос', 'според', 'евангелията', 'на', 'матей', 'на', 'лука', 'исус', 'се', 'ражда', 'по', 'време', 'на', 'управлението', 'на', 'ирод', 'велики', 'за', 'когото', 'съвременната', 'историческа', 'наука', 'сигурна', 'че', 'умира', 'през', 'пр', 'съществува', 'хипотеза', 'според', 'която', 'витлеемската', 'звезда', 'видима', 'на', 'небосвода', 'по', 'време', 'на', 'раждането', 'на', 'христос', 'комета', 'преминала', 'близост', 'до', 'земята', 'през', 'пр', 'епохата', 'започваща', 'тази', 'дата', 'се', 'нарича', 'новата', 'ера', 'нашата', 'ера', 'или', 'християнската', 'ера', 'годините', 'нея', 'се', 'бележат', 'със', 'сл', 'хр', 'след', 'христа', 'или', 'от', 'новата', 'ера', 'или', 'са', 'без', 'такова', 'уточнение', 'годините', 'преди', 'век', 'се', 'бележат', 'пр', 'хр', 'или', 'пр', 'преди', 'новата', 'ера', 'страни', 'новата', 'ера', 'се', 'бележи', 'със', 'съкращението', 'ad', 'но', 'също', 'така', 'може', 'да', 'без', 'това', 'уточнение', 'годините', 'преди', 'век', 'bc', 'григорианската', 'промяна', 'основната', 'разлика', 'между', 'григорианския', 'календар', 'предшественика', 'му', 'юлианския', 'се', 'състои', 'разпределянето', 'на', 'високосните', 'години', 'юлианския', 'календар', 'всяка', 'четвърта', 'година', 'високосна', 'има', 'един', 'допълнителен', 'ден', 'през', 'февруари', 'както', 'отбелязано', 'по', 'горе', 'средната', 'тропическа', 'година', 'се', 'определя', 'от', 'на', 'периода', 'на', 'завъртане', 'на', 'земята', 'около', 'слънцето', 'който', 'процес', 'отнема', 'дни', 'добавяйки', 'един', 'ден', 'на', 'всеки', 'четири', 'години', 'юлианският', 'календар', 'има', 'малко', 'по', 'голяма', 'средна', 'дължина', 'дни', 'това', 'постепенно', 'довело', 'до', 'забавяне', 'отчитането', 'на', 'дните', 'съответно', 'до', 'разликата', 'от', 'десет', 'дни', 'спрямо', 'време', 'видимият', 'признак', 'по', 'който', 'през', 'ти', 'век', 'това', 'установено', 'пролетното', 'равноденствие', 'отместено', 'по', 'рано', 'към', 'началото', 'на', 'март', 'което', 'църквата', 'използва', 'за', 'определяне', 'на', 'датата', 'за', 'честване', 'на', 'великден', 'за', 'пръв', 'път', 'нов', 'вариант', 'за', 'да', 'бъде', 'приведен', 'календарът', 'съответствие', 'време', 'предложен', 'от', 'калабрийския', 'доктор', 'алойзий', 'лилий', 'новият', 'календар', 'одобрен', 'на', 'февруари', 'чрез', 'папската', 'була', 'inter', 'gravissimas', 'на', 'папа', 'григорий', 'xiii', 'новият', 'календар', 'премахва', 'високосните', 'дни', 'за', 'годините', 'отговарящи', 'едновременно', 'на', 'следните', 'две', 'условия', 'годината', 'кратна', 'на', 'годината', 'не', 'кратна', 'на', 'както', 'юлианския', 'календар', 'годините', 'са', 'високосни', 'но', 'за', 'разлика', 'от', 'него', 'не', 'са', 'inter', 'gravissimas', 'постановява', 'също', 'че', 'четвъртък', 'октомври', 'ще', 'бъде', 'непосредствено', 'следван', 'от', 'петък', 'октомври', 'за', 'да', 'се', 'компенсира', 'отместването', 'натрупано', 'през', 'вековете', 'григорианският', 'календар', 'не', 'се', 'приема', 'едновременно', 'цяла', 'европа', 'той', 'наложен', 'от', 'григорий', 'xiii', 'страните', 'под', 'силно', 'влияние', 'на', 'католическата', 'църква', 'испания', 'португалия', 'полша', 'го', 'приемат', 'веднага', 'други', 'франция', 'др', 'съвсем', 'скоро', 'след', 'тях', 'протестантска', 'англия', 'приема', 'григорианския', 'календар', 'чак', 'през', 'век', 'русия', 'трябва', 'да', 'дочака', 'октомврийската', 'революция', 'за', 'да', 'го', 'приеме', 'през', 'като', 'се', 'оказва', 'че', 'октомврийската', 'революция', 'започнала', 'на', 'октомври', 'според', 'юлианския', 'календар', 'всъщност', 'започнала', 'на', 'ноември', 'българия', 'григорианският', 'календар', 'въведен', 'гражданския', 'живот', 'указ', 'на', 'цар', 'фердинанд', 'съгласно', 'който', 'iii', 'веднага', 'последван', 'от', 'датата', 'iv', 'държ', 'вест', 'бр', 'iii', 'сърбия', 'това', 'става', 'на', 'гърция', 'на', 'iii', 'разликите', 'календарите', 'създават', 'трудности', 'на', 'историците', 'защото', 'примерно', 'даден', 'английски', 'документ', 'датиран', 'от', 'януари', 'писан', 'по', 'късно', 'от', 'френски', 'документ', 'от', 'януари', 'същата', 'година', 'например', 'уилям', 'шекспир', 'мигел', 'де', 'сервантес', 'са', 'починали', 'на', 'една', 'съща', 'дата', 'април', 'но', 'всъщност', 'не', 'един', 'същи', 'ден', 'допълнителни', 'трудности', 'идват', 'от', 'факта', 'че', 'календарите', 'се', 'отдалечават', 'григорианската', 'поправка', 'от', 'дни', 'през', 'ти', 'ти', 'век', 'през', 'ти', 'век', 'дни', 'през', 'ти', 'век', 'дни', 'през', 'век', 'дни', 'григорианският', 'календар', 'не', 'предвижда', 'година', 'нула', 'вековете', 'хилядолетията', 'започват', 'годината', 'номер', 'следователно', 'последният', 'ден', 'от', 'старата', 'ера', 'декември', 'от', 'първата', 'година', 'преди', 'новата', 'ера', 'първото', 'столетие', 'продължава', 'от', 'януари', 'до', 'декември', 'второто', 'от', 'януари', 'до', 'декември', 'ви', 'век', 'третото', 'хилядолетие', 'започват', 'на', 'януари', 'григорианският', 'календар', 'малко', 'по', 'дълъг', 'от', 'реалното', 'време', 'на', 'обикаляне', 'на', 'земята', 'около', 'слънцето', 'вместо', 'дни', 'така', 'че', 'ако', 'периодът', 'се', 'запази', 'през', 'вековете', 'около', 'та', 'година', 'ще', 'трябва', 'да', 'се', 'отнеме', 'още', 'един', 'ден', 'хронологична', 'схема', 'dateformat', 'yyyy', 'imagesize', 'width', 'height', 'auto', 'barincrement', 'plotarea', 'left', 'right', 'bottom', 'top', 'colors', 'id', 'noir', 'value', 'black', 'id', 'canvas', 'value', 'rgb', 'id', 'gris', 'value', 'gray', 'id', 'grillemajor', 'value', 'rgb', 'id', 'bleuclair', 'value', 'rgb', 'id', 'rouge', 'value', 'red', 'id', 'rougeclair', 'value', 'rgb', 'id', 'bleuclair', 'value', 'rgb', 'id', 'grilleminor', 'value', 'rgb', 'period', 'from', 'till', 'timeaxis', 'orientation', 'horizontal', 'format', 'yyyy', 'alignbars', 'justify', 'scaleminor', 'unit', 'year', 'increment', 'start', 'gridcolor', 'grilleminor', 'scalemajor', 'unit', 'year', 'increment', 'start', 'gridcolor', 'grillemajor', 'canvas', 'canvas', 'bars', 'canvas', 'bardata', 'bar', 'epoque', 'barset', 'evennement', 'plotdata', 'bar', 'epoque', 'shift', 'width', 'from', 'start', 'till', 'end', 'color', 'gris', 'arri', 're', 'plan', 'from', 'start', 'till', 'text', 'юлиански', 'календар', 'color', 'rougeclair', 'anchor', 'from', 'from', 'till', 'end', 'text', 'григориански', 'календар', 'color', 'rouge', 'barset', 'evennement', 'color', 'noir', 'shift', 'width', 'from', 'till', 'text', 'испания', 'португалия', 'техните', 'владения', 'италия', 'жечпосполита', 'shift', 'from', 'till', 'text', 'франция', 'нидерландия', 'люксембург', 'брабант', 'зеландия', 'генерални', 'щати', 'савоя', 'shift', 'from', 'till', 'text', 'австрия', 'нидерландия', 'холандия', 'южни', 'провинции', 'католически', 'части', 'на', 'швейцария', 'германия', 'shift', 'from', 'till', 'text', 'унгария', 'from', 'till', 'text', 'нова', 'скотия', 'color', 'bleuclair', 'anchor', 'from', 'from', 'till', 'text', 'прусия', 'from', 'till', 'text', 'лотарингия', 'color', 'bleuclair', 'anchor', 'from', 'from', 'till', 'text', 'елзас', 'from', 'till', 'text', 'страсбург', 'from', 'till', 'text', 'протестантски', 'части', 'на', 'швейцария', 'германия', 'нидерландия', 'северни', 'провинции', 'дания', 'вкл', 'норвегия', 'исландия', 'shift', 'from', 'till', 'text', 'швеция', 'вкл', 'финландия', 'to', 'start', 'again', 'the', 'indentation', 'in', 'top', 'barset', 'break', 'at', 'blank', 'line', 'at', 'blank', 'line', 'at', 'blank', 'line', 'at', 'blank', 'line', 'from', 'till', 'text', 'великобритания', 'нейните', 'владения', 'at', 'blank', 'line', 'from', 'till', 'text', 'лотарингия', 'хабсбурги', 'франция', 'at', 'blank', 'line', 'at', 'blank', 'line', 'from', 'till', 'text', 'бохемия', 'моравия', 'to', 'start', 'again', 'the', 'indentation', 'in', 'top', 'barset', 'break', 'from', 'till', 'text', 'швейцария', 'граубюнден', 'from', 'till', 'text', 'аляска', 'русия', 'сащ', 'from', 'till', 'text', 'япония', 'from', 'till', 'text', 'египет', 'from', 'till', 'text', 'корея', 'from', 'till', 'text', 'албания', 'from', 'till', 'text', 'латвия', 'литва', 'from', 'till', 'text', 'българия', 'from', 'till', 'text', 'русия', 'естония', 'from', 'till', 'text', 'румъния', 'югославия', 'from', 'till', 'text', 'ссср', 'from', 'till', 'text', 'гърция', 'from', 'till', 'text', 'турция', 'to', 'start', 'again', 'the', 'indentation', 'in', 'top', 'barset', 'break', 'from', 'till', 'text', 'китай', 'shift', 'вижте', 'също', 'високосна', 'година', 'високосна', 'секунда', 'целогодишни', 'календари', 'юлиански', 'календар', 'новоюлиански', 'календар', 'църковен', 'календар', 'външни', 'препратки', 'григориански', 'календар', 'вечният', 'календар', 'papst', 'gregor', 'xiii', 'inter', 'gravissimas', 'папската', 'була', 'алтернативи', 'източници', 'категория', 'календари']
In [103]:
%time word2vec = Word2Vec(sentences, size=200, window=10, min_count=5, workers=8)
CPU times: user 25min 6s, sys: 0 ns, total: 25min 6s
Wall time: 4min 45s
In [4]:
# Запазване и зареждане на модела

# word2vec.save('bgwiki_word2vec.pkl')
# word2vec = Word2Vec.load("bgwiki_word2vec.pkl")
In [5]:
word2vec.wv.most_similar(positive=['жена', 'цар'], negative=['мъж'])
Out[5]:
[('царица', 0.5910613536834717),
 ('съпруга', 0.5418516397476196),
 ('шишман', 0.5248759388923645),
 ('царя', 0.5007351040840149),
 ('срацимир', 0.4924395978450775),
 ('подялба', 0.45563459396362305),
 ('княз', 0.4555596709251404),
 ('деспот', 0.4535294771194458),
 ('царят', 0.44551363587379456),
 ('тертер', 0.4402218461036682)]
In [122]:
word2vec.wv.most_similar(positive=['лондон', 'франция'], negative=['англия'])
Out[122]:
[('париж', 0.7006015777587891),
 ('женева', 0.5756803154945374),
 ('версай', 0.5394696593284607),
 ('ентернасионал', 0.5204002857208252),
 ('парижката', 0.5188260078430176),
 ('брюксел', 0.5180582404136658),
 ('виена', 0.5037818551063538),
 ('фонтенбло', 0.5002224445343018),
 ('лион', 0.4843534231185913),
 ('парижкото', 0.47921890020370483)]

И примера до който искахме да стигнем през цялото време!

In [107]:
word2vec.wv.most_similar(positive=['ракия', 'жена'], negative=['мъж'])
Out[107]:
[('боза', 0.6232482194900513),
 ('рецепта', 0.612866997718811),
 ('напитка', 0.6056855916976929),
 ('сливова', 0.5827717185020447),
 ('супа', 0.5814237594604492),
 ('чорба', 0.5782036781311035),
 ('салата', 0.5657293796539307),
 ('паста', 0.5535566806793213),
 ('приготвена', 0.5527642965316772),
 ('торта', 0.5489768981933594)]

Според българската уикипедия и word2vec алгоритъма:

  • Ракия се отнася към мъж, както
  • Боза се отнася към жена или
  • Салата към жена :D

Document Embedding

  • Ако знаем колко думи ще има в докимента или текста: Слепваме векторите за всяка дума.
  • Ако не знаем - можем да вземем сумата от векторите на всичките думи в изречениетио.
  • Можем да направим avg или да ползваме IDF.

  • По-напредничивите техники използват CNN и RNN.