🎯 Разбираем Word2Vec на примере
📖 Наше предложение
"я пошел гулять в лес"
🪟 Шаг 1: Определяем контекстное окно
Возьмем окно = 2 (смотрим по 2 слова слева и справа).
Для каждого слова собираем контекст:
| Слово (центр) | Слова слева | Слова справа | Контекст (вход) |
|---|---|---|---|
| я | - | пошел | [пошел] |
| пошел | я | гулять | [я, гулять] |
| гулять | пошел | в | [пошел, в] |
| в | гулять | лес | [гулять, лес] |
| лес | в | - | [в] |
🧠 Шаг 2: Инициализируем векторы
Пусть размер эмбеддинга = 3 (для простоты). Изначально все случайно:
import numpy as np
# Случайные начальные векторы
я = np.array([0.1, 0.5, -0.2])
пошел = np.array([-0.3, 0.8, 0.1])
гулять = np.array([0.4, -0.1, 0.7])
в = np.array([0.9, 0.2, -0.5])
лес = np.array([-0.2, -0.6, 0.3])
🔄 Шаг 3: Обучаем (алгоритм Skip-gram)
Берем пару (центр, контекстное слово). Например, ("гулять", "пошел"):
Как предсказываем:
центр = гулять = [0.4, -0.1, 0.7]
# Умножаем на матрицу весов (тоже обучаемая)
скрытый_слой = центр × W1 # W1 размер 3×2 (например)
# Получаем предсказание для всех слов
предсказание = скрытый_слой × W2 # W2 размер 2×5
# Получаем 5 чисел (по одному на каждое слово)
Softmax в вероятности:
logits = предсказание # например [1.2, 0.5, -0.8, 0.3, -0.1]
вероятности = exp(logits) / sum(exp(logits))
# Например получилось:
вероятности = [0.3, 0.2, 0.1, 0.25, 0.15]
Сравниваем с правильным ответом:
Правильное контекстное слово — "пошел" (индекс 1 в словаре).
Правильная вероятность = [0, 1, 0, 0, 0].
Ошибка:
ошибка = [0.3, 0.2, 0.1, 0.25, 0.15] - [0, 1, 0, 0, 0]
ошибка = [0.3, -0.8, 0.1, 0.25, 0.15]
🔧 Шаг 4: Обновляем веса
Через обратное распространение ошибки чуть-чуть меняем:
- Вектор слова "гулять"
- Матрицы W1 и W2
Чтобы в следующий раз вероятность "пошел" была выше.
📈 Шаг 5: Повторяем для всех пар
Все возможные пары (центр, контекст) из нашего окна:
| Центр | Контекстные слова |
|---|---|
| я | пошел |
| пошел | я, гулять |
| гулять | пошел, в |
| в | гулять, лес |
| лес | в |
Каждую пару прогоняем тысячи раз (эпохи), постепенно подкручивая векторы.
🏁 Шаг 6: Результат после обучения
Векторы начинают отражать смысл:
я = [0.8, 0.1, 0.7] # похож на "человек"
пошел = [0.7, 0.6, 0.2] # похож на "движение"
гулять = [0.6, 0.7, 0.3] # похож на "движение" (близок к "пошел")
в = [0.1, 0.2, 0.9] # похож на "направление"
лес = [0.2, 0.8, 0.6] # похож на "природа"
📊 Проверка похожести
Считаем косинусную близость:
from numpy import dot
from numpy.linalg import norm
cos_sim = lambda a,b: dot(a,b)/(norm(a)*norm(b))
print(cos_sim(пошел, гулять)) # 0.85 (очень близки)
print(cos_sim(пошел, лес)) # 0.12 (далеки)
print(cos_sim(в, лес)) # 0.45 (средне)
🎯 Итог
Мы обучили векторы так, что:
1. Похожие по смыслу слова ("пошел" и "гулять") — близко в пространстве
2. Разные слова ("пошел" и "лес") — далеко
3. Контекст ("в" + "лес") дают осмысленную комбинацию
Это и есть Word2Vec в чистом виде!
Оставить отзыв
Комментарии
Загрузка комментариев...
★ Оставить отзыв