Эмбеддинги и представление текста
ЧерновикМатериалы дорабатываются и будут дополняться.
Чему научимся
Нейросеть складывает и умножает числа, а слово «кот» числом не является. Чтобы модель могла прочитать отзыв, перевести фразу или продолжить текст, каждое слово нужно представить набором чисел. Желательно, чтобы близкие по смыслу слова получали похожие числовые представления: тогда модель сможет частично перенести знания о слове «кот» на слово «собака».
После занятия вы сможете:
- Вычислять косинусное сходство векторов слов и находить ближайшие слова.
- Объяснять, почему слова с похожим окружением получают похожие эмбеддинги, и обучать модель word2vec.
Сначала рассмотрим one-hot-кодирование слов, затем применим мешок слов (BoW, bag of words) для классификации предложений. После этого введём таблицу эмбеддингов и косинусное сходство, найдём близкие слова в небольшом наборе данных и обучим модель word2vec. В конце изучим свойства векторов, обученных на большом объёме данных.
One-hot: у каждого слова своя ось
Разобьём текст на токены. В этом примере токенами считаются слова между пробелами. Список токенов называют словарём, а положение слова в словаре — его индексом. Пусть слову «кот» соответствует индекс 0, слову «собака» — 1, «ракета» — 2, «самолёт» — 3.
Подавать индекс в модель как число нельзя: «ракета» не вдвое больше «собаки», и среднее «кота» и «ракеты» не равно «собаке». Индекс — лишь обозначение слова. Поэтому представим каждое слово вектором длины
Как сравнивать векторы
Чтобы понять, похожи ли два слова, нужно сравнить их векторы. Рассмотрим два способа сравнения.
Расстояние. Евклидово расстояние — длина отрезка между концами векторов. Формула обобщает теорему Пифагора на любое число координат: складываем квадраты разностей соответствующих координат и извлекаем корень:
Например, для
Косинусное сходство. Сравним направления векторов. Скалярное произведение
Полученное значение равно косинусу угла между векторами; его называют косинусным сходством. Оно принимает значения от
Для тех же
Векторы слов чаще сравнивают по косинусному сходству. Далее мы представим слово вектором, координаты которого показывают, как часто оно встречается рядом с другими словами. У часто встречающегося слова значения координат могут быть больше. Например, векторы
Сначала проверим вычисления в NumPy, записав формулы напрямую. Для массивов NumPy выражение a * b перемножает соответствующие координаты, np.sum складывает элементы, а np.sqrt извлекает квадратный корень.
import numpy as np
a = np.array([3, 4])
b = np.array([4, 3])
c = np.array([-4, 3])
print(a * b) # покоординатно: [3·4, 4·3]
print(np.sum(a * b)) # скалярное произведение a · b
print(np.sqrt(np.sum(a * a))) # длина |a|
print(np.sqrt(np.sum((a - b) ** 2))) # расстояние между a и b
Вывод:
[12 12]
24
5.0
1.4142135623730951
Для этих операций в NumPy предусмотрены более короткие записи: a @ b — скалярное произведение, np.linalg.norm(a) — длина вектора. Вычислим с их помощью косинусное сходство.
def cosine(a, b):
# a @ b — то же, что np.sum(a * b)
# np.linalg.norm(a) — то же, что np.sqrt(np.sum(a * a))
return a @ b / (np.linalg.norm(a) * np.linalg.norm(b))
print(cosine(a, b)) # почти одно направление
print(cosine(a, c)) # прямой угол
Вывод:
0.96
0.0
Что это даёт для one-hot
Применим обе меры к one-hot векторам слов:
cat = np.array([1, 0, 0, 0]) # кот
dog = np.array([0, 1, 0, 0]) # собака
rocket = np.array([0, 0, 1, 0]) # ракета
print(np.linalg.norm(cat - dog), np.linalg.norm(cat - rocket)) # расстояния
print(cosine(cat, dog), cosine(cat, rocket)) # косинусы
Вывод:
1.4142135623730951 1.4142135623730951
0.0 0.0
Векторы разных слов отличаются ровно в двух позициях, поэтому расстояние всегда равно
Мешок слов
Чтобы классифицировать предложение, нужно представить его в виде вектора. Самый простой способ — сложить one-hot-векторы слов в предложении. В полученном векторе длины
Возьмём восемь учебных коротких отзывов о фильмах: четыре положительных (метка 1) и четыре отрицательных (метка 0).
train_texts = [
"отличный фильм", "очень хороший фильм",
"хороший сюжет и отличная музыка", "актёры играют хорошо",
"скучный фильм", "очень плохой фильм",
"плохой сюжет и скучная музыка", "актёры играют плохо",
]
train_labels = [1, 1, 1, 1, 0, 0, 0, 0] # 1 — положительный, 0 — отрицательный
CountVectorizer из scikit-learn выполняет обе операции: fit формирует словарь, а transform преобразует тексты в мешки слов. По умолчанию он пропускает слова короче двух символов, например «и».
from sklearn.feature_extraction.text import CountVectorizer
bow = CountVectorizer()
X_train = bow.fit_transform(train_texts) # словарь + мешки для 8 отзывов
print(bow.get_feature_names_out()) # словарь в алфавитном порядке
print(X_train.shape) # (отзывов, слов в словаре)
print(X_train.toarray()) # сама таблица мешков
Вывод:
['актёры' 'играют' 'музыка' 'отличная' 'отличный' 'очень' 'плохо' 'плохой'
'скучная' 'скучный' 'сюжет' 'фильм' 'хороший' 'хорошо']
(8, 14)
[[0 0 0 0 1 0 0 0 0 0 0 1 0 0]
[0 0 0 0 0 1 0 0 0 0 0 1 1 0]
[0 0 1 1 0 0 0 0 0 0 1 0 1 0]
[1 1 0 0 0 0 0 0 0 0 0 0 0 1]
[0 0 0 0 0 0 0 0 0 1 0 1 0 0]
[0 0 0 0 0 1 0 1 0 0 0 1 0 0]
[0 0 1 0 0 0 0 1 1 0 1 0 0 0]
[1 1 0 0 0 0 1 0 0 0 0 0 0 0]]
X_train — матрица размера
Посмотрим на мешок для нового предложения:
x = bow.transform(["очень очень хороший фильм"]).toarray()[0]
print(x)
for word, count in zip(bow.get_feature_names_out(), x):
if count > 0:
print(word, count)
Вывод:
[0 0 0 0 0 2 0 0 0 0 0 1 1 0]
очень 2
фильм 1
хороший 1
Обучим логистическую регрессию на мешках слов. Модель присваивает каждому слову вес: положительный вес увеличивает оценку в пользу класса 1, отрицательный — в пользу класса 0. Выведем три слова с наименьшими и три слова с наибольшими весами.
from sklearn.linear_model import LogisticRegression
model = LogisticRegression(C=10) # C — обратная сила штрафа: чем больше C, тем слабее штраф
model.fit(X_train, train_labels) # подбираем по одному весу на каждое слово словаря
# model.coef_[0] — веса слов в том же порядке, что и словарь;
# сортируем пары (вес, слово) от самого отрицательного веса к самому положительному
weights = sorted(zip(model.coef_[0], bow.get_feature_names_out()))
for weight, word in weights[:3] + weights[-3:]: # три первых и три последних
print(word, round(weight, 2))
Вывод:
плохой -1.94
плохо -1.63
скучный -1.63
отличный 1.63
хорошо 1.63
хороший 1.94
У слов «фильм», «сюжет» и «актёры» веса равны нулю: они встречаются в отзывах обоих классов. Проверим модель на новых отзывах. Метод predict_proba возвращает вероятности классов, а столбец [:, 1] содержит вероятности положительного класса.
test_texts = ["хороший фильм", "прекрасный фильм", "фильм не плохой"]
probs = model.predict_proba(bow.transform(test_texts))[:, 1]
for text, p in zip(test_texts, probs):
print(text, round(p, 2))
Вывод:
хороший фильм 0.87
прекрасный фильм 0.5
фильм не плохой 0.13
Модель дала высокую вероятность положительному классу для отзыва «хороший фильм», а два других результата показывают ограничения метода. Для отзыва «прекрасный фильм» вероятность равна 0,5: слова «прекрасный» нет в словаре, а у единственного учтённого слова — «фильм» — вес равен нулю. Модель не учитывает сходство слов «прекрасный» и «отличный»: в мешке слов это разные признаки. Для отзыва «фильм не плохой» вероятность равна 0,13: слова «не» тоже нет в словаре, а мешок слов не сохраняет порядок. По той же причине слова «отличный» и «отличная» становятся разными признаками.
Первое ограничение можно смягчить с помощью эмбеддингов: если похожие слова получат близкие векторы, модель сможет использовать сходство слов «отличный» и «прекрасный». Порядок слов будут учитывать модели, рассматриваемые в следующем параграфе.
Эмбеддинг: таблица векторов
Сопоставим каждому слову вектор из
Пусть словарь состоит из четырёх слов,
Чтобы получить эмбеддинг слова, находим строку таблицы с таким же индексом. Индекс слова «собака» равен 1, поэтому её эмбеддинг хранится во второй строке таблицы при обычной нумерации строк с единицы:
Числа в таблице — обучаемые параметры нейросети. Всего в таблице
Для примеров возьмём небольшой учебный набор данных из десяти придуманных предложений о животных и полётах. Разобьём предложения на слова и присвоим каждому слову индекс в порядке первого появления.
text = """кот пьёт молоко
собака пьёт воду
кот ловит мышь
собака ловит мяч
кот спит дома
собака спит дома
ракета летит высоко
самолёт летит высоко
ракета несёт спутник
самолёт несёт пассажиров"""
sentences = [line.split() for line in text.splitlines()]
print(sentences[0])
Вывод:
['кот', 'пьёт', 'молоко']
vocab = [] # словарь: слова в порядке появления
for sentence in sentences:
for word in sentence:
if word not in vocab:
vocab.append(word)
word_to_id = {word: i for i, word in enumerate(vocab)} # слово → индекс
print(len(vocab))
print(vocab[:6])
print(word_to_id["собака"])
Вывод:
17
['кот', 'пьёт', 'молоко', 'собака', 'воду', 'ловит']
3
Как определить значения векторов слов? Мы хотим, чтобы похожие слова получали близкие векторы. Один из способов оценить сходство — сравнить слова, которые встречаются рядом с ними.
Слово узнают по окружению
«Утром шмыга пьёт молоко, днём ловит мышь, а ночью спит дома». Слова «шмыга» нет в словаре, но догадаться, кто это, нетрудно: шмыга пьёт молоко, ловит мышь и спит дома — точно как кот. Подсказали соседние слова.
На этой идее основан один из способов обучения эмбеддингов. Если слова встречаются в похожих контекстах, их значения могут быть близкими. В наших учебных предложениях слова «кот» и «собака» встречаются рядом со словами «пьёт», «ловит» и «спит», поэтому их окружение похоже. У слов «ракета» и «кот» в этом наборе данных почти нет общих соседей.
Представим окружение слов численно: подсчитаем, какие слова и как часто встречаются рядом.
Шаг 1. Кого считать соседом. Будем считать соседями слова те слова, которые расположены не далее чем в двух позициях от него слева или справа. Эту область называют окном, а число 2 — шириной окна. Поскольку в каждом предложении три слова, при ширине окна 2 соседями слова будут два остальных слова этого предложения. В предложении «кот пьёт молоко» у слова «кот» соседи «пьёт» и «молоко», у слова «пьёт» — «кот» и «молоко», у слова «молоко» — «кот» и «пьёт».
Шаг 2. Записываем соседей в таблицу. Пройдём по всем десяти предложениям и отметим соседей каждого слова. Слово «кот» встречается в трёх предложениях: «кот пьёт молоко», «кот ловит мышь», «кот спит дома». Значит, в нашем наборе данных рядом со словом «кот» по одному разу встретились «пьёт», «молоко», «ловит», «мышь», «спит» и «дома».
Запишем подсчёты в таблицу. Каждая строка соответствует слову, каждый столбец — возможному соседу, а в ячейке указано, сколько раз они встретились рядом. Такую таблицу называют матрицей совместной встречаемости. Каждую её строку можно рассматривать как вектор соответствующего слова: она описывает его окружение. На рисунке показаны строки четырёх слов; столбцы с нулями во всех четырёх строках («кот», «собака» и другие) опущены.
Шаг 3. Сравниваем строки. Теперь похожесть слов можно оценить по сходству соответствующих строк. Вычислим косинусное сходство по формуле из начала параграфа. В четырёх координатах строк «кот» и «собака» стоят единицы («пьёт», «ловит», «спит», «дома»), поэтому скалярное произведение строк равно 4. В каждой строке шесть единиц, поэтому её длина равна
У «ракеты» и «самолёта» по четыре единицы в строках, из которых три стоят в общих столбцах:
Построим такую таблицу в коде. Сначала создадим таблицу из нулей: по одной строке и столбцу для каждого из 17 слов словаря.
V = len(vocab)
counts = np.zeros((V, V)) # строка — слово, столбец — сосед, в клетке — сколько раз рядом
print(counts.shape)
Вывод:
(17, 17)
Теперь пройдём по предложениям. Для каждого слова переберём позиции в окне ширины 2 вокруг него и увеличим на 1 значение в ячейке (слово, сосед). Пропускаем только саму позицию текущего слова: если слово встретится в предложении дважды, второе вхождение будет учтено как сосед. Предложения состоят из трёх слов, поэтому в окно попадают все остальные слова предложения.
window = 2 # ширина окна
for sentence in sentences: # например, ['кот', 'пьёт', 'молоко']
for center, word in enumerate(sentence): # слово, чьих соседей записываем
left = max(center - window, 0)
right = min(center + window, len(sentence) - 1)
for position in range(left, right + 1): # позиции в окне вокруг слова
if position == center: # пропускаем само слово
continue
neighbour = sentence[position]
counts[word_to_id[word], word_to_id[neighbour]] += 1
row = counts[word_to_id["кот"]] # строка «кота»
print(row)
for word, count in zip(vocab, row):
if count > 0: # выводим только тех, кто стоял рядом
print(word, count)
Вывод:
[0. 1. 1. 0. 0. 1. 1. 0. 1. 1. 0. 0. 0. 0. 0. 0. 0.]
пьёт 1.0
молоко 1.0
ловит 1.0
мышь 1.0
спит 1.0
дома 1.0
В строке слова «кот» ненулевые значения соответствуют тем же шести соседям, что показаны на рисунке. В этом примере ближайшими соседями слова считаются слова с наибольшим косинусным сходством векторов. Функция nearest сравнивает строку выбранного слова со всеми остальными строками таблицы vectors и возвращает
def nearest(word, vectors, k=3):
v = vectors[word_to_id[word]]
scores = [(cosine(v, vectors[i]), other)
for i, other in enumerate(vocab) if other != word]
scores.sort(reverse=True) # сначала самые похожие
return [(other, round(float(score), 3)) for score, other in scores[:k]]
print(nearest("кот", counts))
print(nearest("ракета", counts))
Вывод:
[('собака', 0.667), ('спит', 0.333), ('дома', 0.333)]
[('самолёт', 0.75), ('летит', 0.408), ('высоко', 0.408)]
Получили те же значения, что и при ручном вычислении: около 0,667 для пары «кот» — «собака» и 0,75 для пары «ракета» — «самолёт». Строки таблицы уже служат векторами слов, но они очень длинные: каждая содержит
word2vec: учим векторы угадывать соседей
Короткие векторы можно получить с помощью обучения модели word2vec, предложенной Томашем Миколовым и его коллегами в 2013 году.
Идея проста. Сначала каждому слову случайно присваивают вектор из нескольких чисел. Его подают на вход небольшой нейросети, которая учится предсказывать слова из окружения. Если предсказание ошибочно, параметры модели, в том числе векторы, корректируют. В наших примерах «кот» и «собака» встречаются рядом с одними и теми же словами, поэтому обучение может сблизить их векторы. Так слова с похожим окружением получают похожие эмбеддинги.
Модель доступна в библиотеке gensim; установить её можно командой pip install gensim. Как и в scikit-learn, модель можно обучить одним вызовом: создать её и сразу передать предложения.
from gensim.models import Word2Vec
model = Word2Vec(
sentences, # список предложений, каждое — список слов
vector_size=10, # d: по 10 чисел на слово
window=2, # соседи — не дальше двух слов
min_count=1, # учитываем даже слова, встреченные один раз
sg=1, # по слову угадываем его соседей
sample=0, # не выбрасываем частые слова: данных очень мало
epochs=1000, # сколько раз пройти по всем предложениям
seed=0, workers=1, # чтобы результат повторялся
)
print(model.wv["кот"].round(2)) # эмбеддинг «кота»: 10 чисел
Вывод:
[ 0.19 1.1 0.82 0.53 1.96 0.42 -0.6 -0.53 -0.62 2.03]
Проверим результат обучения: спросим, какие слова могут стоять рядом с «котом». Метод predict_output_word возвращает наиболее вероятные слова из его окружения.
for word, p in model.predict_output_word(["кот"], topn=6):
print(word, round(float(p), 2))
Вывод:
пьёт 0.2
спит 0.2
ловит 0.2
мышь 0.18
молоко 0.12
дома 0.09
Это все шесть слов, которые встречались рядом с «котом» в учебных предложениях. Вероятность каждого — около 0,2, а не 1: модель распределяет вероятность между возможными соседями.
Теперь главное — сами векторы. Метод most_similar ищет слова с самыми похожими векторами по косинусу:
for word in ["кот", "ракета"]:
print(word, [(w, round(s, 2)) for w, s in model.wv.most_similar(word, topn=3)])
Вывод:
кот [('собака', 0.6), ('мышь', 0.43), ('летит', 0.42)]
ракета [('самолёт', 0.79), ('спутник', 0.59), ('высоко', 0.52)]
Ближайшее к слову «кот» — «собака», а к слову «ракета» — «самолёт». Модель не получала сведений о значениях этих слов: близкие векторы сформировались благодаря общим соседям. Сходство остальных слов составляет примерно 0,4–0,6. Эти результаты следует трактовать осторожно: модель обучена всего на десяти учебных предложениях.
Векторы, обученные на больших данных
При обучении на больших текстовых корпусах векторы могут отражать некоторые закономерности языка. Рассмотрим векторы GloVe, обученные исследователями Стэнфордского университета на двух миллиардах твитов. В упрощённом объяснении GloVe подбирает векторы так, чтобы их скалярные произведения приближали логарифмы частот совместной встречаемости слов. Этот подход, как и наша таблица соседей, использует статистику совместной встречаемости. Размерность векторов — 100. В файле data/glove-twitter.npz сохранены векторы 10 000 наиболее частотных английских и 2500 наиболее частотных русских слов.
data = np.load("data/glove-twitter.npz")
glove_words = data["words"].tolist() # список слов
glove = data["vectors"].astype(np.float32) # таблица 12 500 × 100
# длина каждого вектора 1, поэтому косинус равен скалярному произведению
glove /= np.linalg.norm(glove, axis=1, keepdims=True)
glove_id = {word: i for i, word in enumerate(glove_words)}
print(glove.shape)
print(glove_words[:6]) # самые частые слова (rt — ретвит)
print([w for w in glove_words if w[0] >= "а"][:6]) # самые частые русские
Вывод:
(12500, 100)
['rt', 'i', 'a', 'the', 'you', 'to']
['в', 'и', 'я', 'на', 'не', 'д']
Функция g возвращает вектор заданного слова, а similar находит glove @ v даёт косинусные сходства
def g(word):
return glove[glove_id[word]]
def similar(v, k=4, exclude=()):
scores = glove @ (v / np.linalg.norm(v)) # косинусы со всеми словами
order = np.argsort(-scores) # индексы по убыванию сходства
return [(glove_words[i], round(float(scores[i]), 2))
for i in order if glove_words[i] not in exclude][:k]
for word in ["cat", "excellent", "кот", "фильм"]: # cat — кошка, excellent — отличный
print(word, similar(g(word), exclude={word}))
Вывод:
cat [('dog', 0.88), ('kitty', 0.8), ('pet', 0.8), ('cats', 0.8)]
excellent [('fantastic', 0.79), ('great', 0.78), ('brilliant', 0.77), ('unique', 0.71)]
кот [('мальчик', 0.7), ('собака', 0.7), ('черный', 0.66), ('маленький', 0.66)]
фильм [('сериал', 0.84), ('кино', 0.77), ('смотреть', 0.77), ('клип', 0.71)]
Среди ближайших к cat («кошка») слов — dog («собака»), kitty («котёнок»), pet («домашний питомец») и cats («кошки»). Среди ближайших к excellent («отличный») — fantastic («потрясающий»), great («замечательный») и brilliant («блестящий»). Среди ближайших к слову «фильм» — «сериал», «кино» и «смотреть».
Аналогии. В некоторых моделях разности векторов могут отражать отношения между словами. Выражение
def analogy(a, b, c):
# a − b + c: из смысла слова a убираем смысл b и добавляем смысл c,
# затем ищем слово, ближайшее к получившемуся вектору
return similar(g(a) - g(b) + g(c), exclude={a, b, c})
print(analogy("king", "man", "woman")) # король − мужчина + женщина = ?
print(analogy("paris", "france", "germany")) # Париж − Франция + Германия = ?
print(analogy("cats", "cat", "dog")) # кошки − кошка + собака = ?
print(analogy("walked", "walk", "go")) # гулял − гулять + идти = ?
Вывод:
[('queen', 0.71), ('prince', 0.67), ('mother', 0.64), ('royal', 0.64)]
[('berlin', 0.75), ('london', 0.69), ('italy', 0.66), ('spain', 0.65)]
[('dogs', 0.92), ('animals', 0.79), ('bears', 0.69), ('puppy', 0.68)]
[('went', 0.84), ('came', 0.79), ('got', 0.78), ('just', 0.76)]
В этих примерах ближайшими оказались слова queen («королева»), berlin («Берлин»), dogs («собаки») и went («пошёл»). Это отражает закономерности обучающего корпуса, но не означает, что модель понимает пол, географию или грамматику так же, как человек.
Карта слов. Вектор из 100 координат нельзя напрямую изобразить на плоскости. Его можно спроецировать на неё, стараясь сохранить близость векторов. На рисунке показаны 36 английских слов из шести тематических групп и их переводы:
Названия тематических групп модели не сообщали. На этой карте слова из одной группы расположены рядом: числа — с числами, цвета — с цветами, страны — со странами.
Почему векторы антонимов могут быть близкими. Посчитаем косинусное сходство слов с противоположными значениями:
print(round(float(g("good") @ g("bad")), 2)) # good — хороший, bad — плохой
print(round(float(g("хороший") @ g("плохой")), 2))
print(similar(g("плохой"), exclude={"плохой"}))
Вывод:
0.82
0.76
[('хороший', 0.76), ('крутой', 0.66), ('тупой', 0.64), ('такой', 0.64)]
В этом наборе векторов ближайшим соседом слова «плохой» оказалось слово «хороший». Такой результат согласуется с идеей, что слова с похожим окружением могут иметь близкие векторы. В предложениях «фильм был хороший» и «фильм был плохой» эти слова встречаются в похожем контексте. Предварительно обученные векторы могут отражать сходство слов «отличный» и «прекрасный», а различать «хороший» и «плохой» классификатор учится на размеченных отзывах.
Попробуйте сами
- Добавьте к обучающим отзывам «прекрасный сюжет» с меткой 1. Заново обучите классификатор на мешках слов и вычислите вероятность положительного класса для отзыва «прекрасный фильм». Объясните, почему изменился прогноз. Для самопроверки: вероятность станет 0,78, потому что для слова «прекрасный» появится отдельный столбец с положительным весом.
- Вычислите вручную расстояние и косинусное сходство векторов
и , затем проверьте результат в NumPy. Для самопроверки: расстояние , косинусное сходство . - Добавьте в набор данных предложения «тигр ловит мышь» и «тигр спит дома», заново постройте словарь и матрицу
countsи найдите ближайшие к слову «тигр» слова по косинусному сходству. Сначала предскажите ответ по таблице соседей. Для самопроверки: сходство с «котом» — примерно 0,816, с «собакой» — примерно 0,612. - Спросите модель word2vec о словах из окружения «собаки» (
predict_output_word) и найдите слова с векторами, похожими на вектор слова «молоко» (most_similar). Сравните ответы с предложениями из набора данных. Для самопроверки: соседи «собаки» — «спит», «ловит», «пьёт», «мяч», «воду», «дома»; ближе всего к вектору слова «молоко» оказались «воду» (0,75) и «мышь» (0,61); интерпретируйте результат с учётом учебного набора данных. - Проверьте аналогии
analogy("girl", "boy", "brother")(девочка − мальчик + брат) иanalogy("he", "man", "woman")(он − мужчина + женщина), затем составьте собственную аналогию. Для самопроверки:sister(«сестра») — 0,92,she(«она») — 0,77.
Что стоит унести с собой
Векторы сравнивают по расстоянию или косинусному сходству. Для сравнения векторов слов часто используют косинусное сходство: оно зависит от их направления, но не от длины. В one-hot-представлении каждому слову соответствует отдельная координата, поэтому оно не отражает сходство слов. Мешок слов считает вхождения слов, но не сохраняет их порядок. Эмбеддинг — строка обучаемой таблицы размера
Самопроверка
Проверено 0 из 10
Подсказка
Сколько координат у one-hot вектора и чему это число равно?
Решение
B. У one-hot вектора столько координат, сколько слов в словаре, поэтому новое слово добавляет координату всем словам сразу. В каждом векторе по-прежнему одна единица и остальные нули.
Подсказка
Единицы стоят на разных позициях. Чему равно скалярное произведение? В скольких позициях векторы различаются?
Решение
C. Общих ненулевых позиций нет, поэтому скалярное произведение и косинус равны 0; различий две, поэтому расстояние
Подсказка
Место каждого числа в мешке задаёт словарь, а не предложение. Первое число — сколько раз встретился «кот», второе — «пьёт», и так далее.
Решение
B. «Кот» встречается дважды, «пьёт» и «молоко» — по разу, «собака» — ни разу. В варианте C числа записаны в порядке слов предложения, а не словаря. Порядок слов в предложении на мешок не влияет: «кот пьёт молоко кот» даёт тот же мешок
Подсказка
Какой столбец мешка слов соответствует слову «прекрасный»?
Решение
B. Незнакомое слово не попадает ни в один столбец, а «фильм» есть в отзывах обоих классов. Сходство «прекрасного» с «отличным» модель не видит.
Подсказка
Это таблица: сколько в ней строк и столбцов?
Решение
C.
Подсказка
Векторы направлены одинаково, отличается только длина.
Решение
B.
Подсказка
У каких слов в строке матрицы есть «пьёт», «ловит» и «спит»?
Решение
C. Три общих соседа есть только у «кота» и «собаки». Сходство определяется окружением, а не тем, было ли слово в словаре раньше.
Подсказка
При окне 1 соседи — только непосредственно соседние слова. У крайних слов сосед один.
Решение
C. (кот, пьёт), (пьёт, кот), (пьёт, молоко), (молоко, пьёт). Пары «кот–молоко» нет: слова стоят на расстоянии 2. Шесть пар получается при окне 2.
Подсказка
Сколько разных слов стоит рядом с «котом» и как между ними делится вероятность?
Решение
B. Каждый из шести соседей правильный, и честный ответ — поделить вероятность между ними, примерно по
Подсказка
Сравните предложения «фильм был хороший» и «фильм был плохой».
Решение
B. Векторы отражают окружение слов, а у антонимов оно почти общее. Сходство