Почему представления слов

В то время как овладение естественным языком легко для людей, это то, чего компьютеры еще не смогли достичь. Люди понимают язык различными способами, например, это может быть поиск его в словаре или осмысленная ассоциация со словами в одном предложении. Однако компьютеры и компьютерные программы еще не стали полностью человеческими, и им требуются другие методы для понимания человеческого языка. Поэтому в этом посте будут обсуждаться различные методы представления слов и предложений, чтобы компьютеры могли понимать язык. Представление слов является одним из основных понятий в обработке естественного языка.

Различные типы представления слов

Следующий текстовый файл используется в качестве наших данных для обучения, и мы будем реализовывать модели с использованием Python.

data.txt

Whilst mastering natural language is easy for humans, it is something that computers have not yet been able to achieve. Humans understand language through a variety of ways for example this might be through looking up it in a dictionary, or by associating it with words in the same sentence in a meaningful way. However, computers and computer programs are yet to be fully human like and they require other different methods to understand human language. Therefore, This post will discuss those different methods for representing words and sentences so that the computers can understand the language. Word representations is one of the basic concepts in Natural Language Processing.

Поиск в словаре

Простейшим подходом было бы присвоение каждому уникальному слову идентификатора, и всякий раз, когда компьютеру это нужно, он может просматривать этот словарь и искать сопоставления слово: идентификатор.

Код

import pandas as pd
import numpy as np
data = open("data.txt", "r")
words = data.read().split(" ")
uniqueWords = list(set(words))
dataframe = pd.DataFrame({'word': uniqueWords})
dataframe['ID'] = np.arange(len(dataframe))
dictionary = pd.Series(dataframe.ID.values,index=dataframe.word).to_dict()
print(dictionary)

Вывод

{'computer': 0, 'Whilst': 1, 'to': 2, 'post': 3, 'representing': 4, 'can': 5, 'computers': 6, 'yet': 7, 'this': 8, 'words': 9, 'have': 10, 'by': 11, 'human': 12, 'language': 13, 'sentence': 14, 'ways': 15, 'might': 16, 'fully': 17, 'language.': 18, 'Language': 19, 'require': 20, 'and': 21, 'same': 22, 'of': 23, 'other': 24, 'This': 25, 'mastering': 26, 'that': 27, 'is': 28, 'not': 29, 'something': 30, 'easy': 31, 'it': 32, 'basic': 33, 'humans,': 34, 'meaningful': 35, 'a': 36, 'through': 37, 'example': 38, 'dictionary,': 39, 'Natural': 40, 'programs': 41, 'natural': 42, 'one': 43, 'different': 44, 'they': 45, 'be': 46, 'However,': 47, 'been': 48, 'achieve.': 49, 'the': 50, 'for': 51, 'with': 52, 'are': 53, 'methods': 54, 'variety': 55, 'in': 56, 'like': 57, 'discuss': 58, 'will': 59, 'sentences': 60, 'understand': 61, 'up': 62, 'associating': 63, 'way.': 64, 'looking': 65, 'so': 66, 'Humans': 67, 'or': 68, 'able': 69, 'Processing.': 70, 'concepts': 71}

Горячее кодирование

Горячее кодирование представляет собой представление категориальных переменных в виде двоичных векторов. Для этого сначала требуется, чтобы категориальные значения были сопоставлены с целочисленными значениями. После этого каждое целочисленное значение представляется в виде двоичного вектора, состоящего из нулевых значений, кроме индекса целого числа, который помечен 1.

Код

import pandas as pd
data = "Whilst mastering natural language is easy for humans"
words = data.split(" ")
uniqueWords = list(set(words))
pd.set_option('display.max_columns', None)  # or 1000
pd.set_option('display.max_rows', None)  # or 1000
pd.set_option('display.max_colwidth', -1)
encoded = pd.get_dummies(uniqueWords)
print(encoded)

Вывод

Whilst  easy  for  humans  is  language  mastering  natural
0       0     0    0      0     1         0          0
0       0     0    1      0     0         0          0
1       0     0    0      0     0         0          0
0       0     0    0      1     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         1          0
0       0     1    0      0     0         0          0

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

Word2Vec

Word2vec — это группа связанных моделей, которые используются для создания встраивания слов. Эти модели представляют собой неглубокие двухслойные нейронные сети, обученные реконструировать лингвистические контексты слов. Word2Vec использует две архитектуры:

CBOW (непрерывный набор слов)

Модель CBOW предсказывает текущее слово с учетом контекстных слов в определенном окне. Входной слой содержит слова контекста, а выходной слой содержит текущее слово. Скрытый слой содержит количество измерений, в которых мы хотим представить текущее слово, присутствующее в выходном слое.

Пропустить грамм

Skip gram предсказывает слова окружающего контекста в определенном окне с учетом текущего слова. Входной слой содержит текущее слово, а выходной слой содержит контекстные слова. Скрытый слой содержит количество измерений, в которых мы хотим представить текущее слово, присутствующее на входном слое.

Мы можем реализовать нашу собственную модель word2vec, как в здесь. Поскольку это будет немного сложно, мы будем использовать Gensim, библиотеку с открытым исходным кодом.

Установите gensim с помощью pip: pip install gensim . Для работы gensim необходимо, чтобы на вашем компьютере был установлен компилятор C.

Код

from gensim.test.utils import common_texts, get_tmpfile
from gensim.models import Word2Vec
path = get_tmpfile("word2vec.model")
model = Word2Vec(common_texts, size=100, window=5, min_count=1, workers=4, sg=1)
model.save("word2vec.model")
data = open("data.txt", "r")
words = data.read().split(" ")
uniqueWords = list(set(words))
model = Word2Vec.load("word2vec.model")
model.train([uniqueWords], total_examples=1, epochs=1)
vector = model.wv['computer']  # numpy vector of a word
print(vector)

В приведенном выше параметре инициализации sg=1 означает, что для word2vec используется skipgram, а если sg=0, то используется CBOW.

[ 4.9868715e-03 -1.8589090e-03  3.0031594e-04  2.9146925e-03
 -3.2452017e-03 -7.4311241e-04 -1.9145171e-03 -5.4530974e-04
  4.6573239e-03  1.1992530e-04  4.7853105e-03  1.7248350e-03
  3.5876739e-03  3.8889768e-03 -5.2998489e-04 -1.4166962e-03
 -4.3162632e-05  2.4357813e-03 -3.8080951e-03  3.2026408e-04
  4.5342208e-03  2.2210747e-03 -4.1628005e-03 -2.9482227e-04
  1.4657559e-03  6.7928270e-04  3.9288746e-03 -6.6122646e-04
  2.6685249e-03  4.8840034e-04  1.2085927e-04  3.0190896e-03
 -7.6547149e-04  1.5170782e-04 -4.8838048e-03  4.1416250e-03
  2.9358426e-03  2.3107675e-03  3.2836150e-03  7.1993755e-04
 -4.4702408e-03  4.2963913e-03  2.5023906e-03  1.7557575e-03
 -2.6511985e-03 -3.3939728e-03 -2.2241778e-03 -4.5135348e-05
  4.9574287e-03  3.7588372e-03 -1.3408092e-03 -4.9382579e-03
  4.3825228e-03 -1.6619477e-03 -1.6158121e-03  4.9568298e-03
  3.9215768e-03  4.5300648e-03  3.0360357e-03 -4.8058927e-03
  4.3477896e-03 -2.0503579e-03 -3.2363960e-03  3.6514697e-03
  3.6383464e-03  4.6341033e-03  1.7352304e-03 -1.9575742e-03
 -4.8500290e-03  4.5880494e-03  4.2294217e-03  4.8814295e-04
 -2.4637496e-03 -1.2094491e-03 -5.1839469e-04 -1.6737969e-03
 -1.5651825e-03  3.5457567e-03 -3.4070832e-03 -1.0688258e-03
  1.6415080e-03 -4.7911871e-03 -3.2562783e-03 -4.6291049e-03
 -4.7947471e-03  3.7898158e-03  1.3356151e-03 -1.7311573e-03
  2.5905482e-03  4.4452478e-03 -1.7256130e-03  1.6168016e-03
 -3.4941530e-03  3.2339687e-03 -2.1139446e-03 -1.6573383e-03
  3.3507459e-03 -3.8317447e-03  1.1735468e-03  2.6007600e-03]

Проблемы с word2vec

В приведенной выше реализации word2vec рассматривает каждое слово в корпусе как атомарную сущность и генерирует вектор для каждого слова. Поэтому, если ваша модель раньше не встречала слова, она не будет знать, как его интерпретировать или как построить для него вектор. Затем вы вынуждены использовать случайный вектор, который далек от идеала. Это особенно может быть проблемой в таких доменах, как Twitter, где у вас есть много зашумленных и разреженных данных со словами, которые могли использоваться только один или два раза в очень большом корпусе. FastText, расширение модели word2vec, похоже, решает эту проблему.

Векторизация слов с помощью fastText

fastText — это библиотека для изучения представлений слов и классификации текста, созданная лабораторией Facebook AI Research (FAIR). fastText предоставляет предварительно обученные модели для более чем 157 языков. fastText рассматривает каждое слово как состоящее из символьных ngram. Следовательно, вектор слова составляется из суммы n граммов этого символа. Например, вектор слова «яблоко» представляет собой сумму векторов n-грамм «‹ap», «app», «appl», «apple», «apple›», «ppl», «pple», « pple›», «ple», «ple›», «le›».

Мы попробуем библиотеку Python, чтобы поиграть с fastText. Установите fasttext с помощью pip. В качестве предварительного требования вам также необходимо будет установить cython.

pip install cython
pip install fasttext

Код

import fasttext
model = fasttext.skipgram(‘data.txt’, ‘model’)
print(model.words)

Мы можем обучить модель быстрого текста с помощью алгоритмов skipgram или cbow, как указано выше. Это создаст два файла, model.vec и model.bin. Файл model.vec будет содержать слова в нашем наборе данных и их векторные представления. В то время как model.bin будет содержать все энграммы в нашем наборе данных и их векторы.

Вывод

{'However,', 'one', 'This', 'concepts', 'the', '', 'Language', 'Natural', 'humans,', 'so', 'language', 'in', 'words', 'can', 'understand', 'example', 'not', 'they', 'it', 'through', 'something', 'meaningful', 'and', 'basic', 'will', 'or', 'programs', 'achieve.', 'looking', 'representing', 'dictionary,', 'for', 'sentences', 'easy', 'Whilst', 'computers', 'discuss', 'be', 'sentence', 'is', 'a', 'fully', 'other', 'human', 'post', 'been', 'able', 'Humans', 'of', 'require', 'to', 'might', 'are', 'way.', 'variety', 'associating', 'this', 'same', 'like', 'by', 'methods', 'computer', 'natural', 'mastering', 'have', 'that', 'ways', 'up', 'yet', 'Processing.', 'language.', 'different', 'with'}

Вы можете распечатать вектор для данного слова, как показано ниже.

print(model['king'])

Вывод

[0.0027474919334053993, 0.0005356628098525107, 0.0018502300372347236, 0.0019693425856530666, 0.0016810859087854624, 5.2087707445025444e-05, 0.0018433697987347841, 0.0016153681790456176, -0.002230857964605093, -0.0011919416720047593, -0.0005365013494156301, -0.001287790248170495, -0.0005530542111955583, -0.002137718955054879, -0.0026757328305393457, -4.165512655163184e-05, 0.00331459054723382, -0.0012807429302483797, 0.0016897692112252116, -0.0004742142336908728, -0.00032369382097385824, -0.0037999653723090887, 0.00035349707468412817, -0.0005173433455638587, -0.0028595952317118645, 0.001419696374796331, 0.0019000013126060367, -0.0010566430864855647, 0.0015126612270250916, 0.005284277256578207, -0.0021161744371056557, 0.003028977895155549, 0.0022042596247047186, -0.0009013907983899117, 0.00024343356199096888, 0.0022169938310980797, 0.0015560443280264735, -0.0009531681425869465, 0.0005139008280821145, -0.0023698394652456045, 0.0008563402225263417, 0.0025476037990301847, 0.0008231972460635006, 0.0013018669560551643, 0.00041914713801816106, -0.0019356505945324898, 0.0008381576626561582, 0.0024166000075638294, 0.0023253299295902252, 0.0017737143207341433, 0.002373612718656659, -5.2668156058643945e-06, 0.0016419965540990233, -0.0008965937304310501, 0.002588749397546053, 0.00048569004866294563, 0.0009559484315104783, -0.003205464454367757, -0.0013440767070278525, 0.0014162956504151225, -0.0007057305774651468, -0.0017468031728640199, 0.0016367752104997635, -0.001270016306079924, 0.0023948214948177338, -0.0028532990254461765, -0.0016449828399345279, 0.0013536224141716957, 0.0036318846978247166, -0.0023201259318739176, 3.820220081252046e-05, 0.0003642759402282536, -0.0035634085070341825, -0.002077018143609166, 0.0030095563270151615, -0.000969761167652905, -0.0006986369844526052, -0.00021727499552071095, 2.108465378114488e-05, 0.001741308020427823, 0.0022944060619920492, -0.0012303885305300355, -0.003918013535439968, 0.0012680593645200133, -0.0021364684216678143, 0.001119954395107925, 2.959575613203924e-05, -0.0017336745513603091, -0.0016722858417779207, -0.0013483710354194045, 0.0004776633868459612, 0.0016805606428533792, -0.00017760173068381846, -0.0007585645071230829, -0.002412130357697606, 0.0005328738479875028, 0.0016983768437057734, -0.0001990617747651413, -0.0016818158328533173, -0.0009510386153124273]

Этот вектор представляет значение слова. В нашем наборе данных не было слова «король». Однако мы могли бы сгенерировать вектор для слова. Именно здесь fasttext выделяется среди других алгоритмов. Для невидимого слова fasttext может сгенерировать вектор из его энграмм. Как упоминалось выше, файл model.bin, который мы создали в ходе обучения, содержит векторы для ngrams. Вектор для невидимого слова вычисляется путем вычисления среднего значения всех векторов ngram этого слова (в основном начиная с 3-gram). Кроме того, мы можем вычислить вектор для предложения, рассчитав среднее значение всех векторов слов в предложении.

Поскольку наш набор данных был очень маленьким, модели не будут точными, и вектор может не отражать значение данного слова. fastText предоставляет предварительно обученные векторы для более чем 157 языков. Эти модели были обучены с использованием огромных корпусов текстов, и сгенерированные векторные представления могут быть очень точными. Вы можете скачать предварительно обученные векторы здесь. Затем вы можете использовать fasttext.load_model для загрузки предварительно обученной модели.

model = fasttext.load_model('model.bin')
print model.words # list of words in dictionary
print model['king'] # get the vector of the word 'king'