Понимание 'tf.nn.nce_loss()' в тензорном потоке
Я пытаюсь понять функцию потери NCE в Tensorflow. Потеря NCE используется для задачи word2vec, например:
# Look up embeddings for inputs.
embeddings = tf.Variable(
tf.random_uniform([vocabulary_size, embedding_size], -1.0, 1.0))
embed = tf.nn.embedding_lookup(embeddings, train_inputs)
# Construct the variables for the NCE loss
nce_weights = tf.Variable(
tf.truncated_normal([vocabulary_size, embedding_size],
stddev=1.0 / math.sqrt(embedding_size)))
nce_biases = tf.Variable(tf.zeros([vocabulary_size]))
# Compute the average NCE loss for the batch.
# tf.nce_loss automatically draws a new sample of the negative labels each
# time we evaluate the loss.
loss = tf.reduce_mean(
tf.nn.nce_loss(weights=nce_weights,
biases=nce_biases,
labels=train_labels,
inputs=embed,
num_sampled=num_sampled,
num_classes=vocabulary_size))
более подробную информацию, пожалуйста, обратитесь к Tensorflow word2vec_basic.py
- Каковы матрицы ввода и вывода в функции NCE?
В модели word2vec мы заинтересованы в построении представлений для слов. В процессе обучения, учитывая скользкое окно, каждое слово будет иметь два вложения: 1) когда слово является центральным словом; 2) когда слово является контекстным словом. Эти два вложения называются входными и выходными векторами, соответственно. (больше объяснений входных и выходных матриц)
На мой взгляд, входная матрица - это embeddings
а выходная матрица - nce_weights
. Это правильно?
- Каково окончательное вложение?
Согласно сообщению s0urcer, также относящемуся к nce
, он говорит, что конечная матрица внедрения - это только входная матрица. В то время как некоторые другие говорят, final_embedding=input_matrix+output_matrix
. Что является правильным/более распространенным?
Ответы
Ответ 1
Давайте посмотрим на относительный код в примере word2vec (examples/tutorials/word2vec).
embeddings = tf.Variable(
tf.random_uniform([vocabulary_size, embedding_size], -1.0, 1.0))
embed = tf.nn.embedding_lookup(embeddings, train_inputs)
Эти две строки создают представления вложения. embeddings
- это матрица, в которой каждая строка представляет слово вектор. embedding_lookup
- это быстрый способ получить векторы, соответствующие train_inputs
. В примере word2vec train_inputs
состоит из некоторого числа int32
, представляющего id
целевых слов. В основном, это может быть размещено скрытым слоем.
# Construct the variables for the NCE loss
nce_weights = tf.Variable(
tf.truncated_normal([vocabulary_size, embedding_size],
stddev=1.0 / math.sqrt(embedding_size)))
nce_biases = tf.Variable(tf.zeros([vocabulary_size]))
Эти две строки создают параметры. Они будут обновляться оптимизатором во время обучения. Мы можем использовать tf.matmul(embed, tf.transpose(nce_weights)) + nce_biases
чтобы получить итоговый результат. Другими словами, последний слой внутреннего продукта в классификации может быть заменен им.
loss = tf.reduce_mean(
tf.nn.nce_loss(weights=nce_weights, # [vocab_size, embed_size]
biases=nce_biases, # [embed_size]
labels=train_labels, # [bs, 1]
inputs=embed, # [bs, embed_size]
num_sampled=num_sampled,
num_classes=vocabulary_size))
Эти строки создают nce loss
, @garej дал очень хорошее объяснение. num_sampled
относится к числу отрицательных выборок в алгоритме nce
.
Чтобы проиллюстрировать использование nce
, мы можем применить его в примере mnist (examples/tutorials/mnist/mnist_deep.py), выполнив следующие 2 шага:
1. Замените вставку на скрытый слой. Размер скрытого слоя - 1024
а num_output - 10
. Минимальное значение num_sampled
равно 1. Не забудьте удалить последний слой внутреннего продукта в deepnn()
.
y_conv, keep_prob = deepnn(x)
num_sampled = 1
vocabulary_size = 10
embedding_size = 1024
with tf.device('/cpu:0'):
embed = y_conv
# Construct the variables for the NCE loss
nce_weights = tf.Variable(
tf.truncated_normal([vocabulary_size, embedding_size],
stddev=1.0 / math.sqrt(embedding_size)))
nce_biases = tf.Variable(tf.zeros([vocabulary_size]))
2. Создайте потери и вычислите выходные данные. После вычисления результата мы можем использовать его для вычисления точности. Обратите внимание, что метка здесь не является горячим вектором, как в softmax. Этикетки являются оригинальной этикеткой обучающих образцов.
loss = tf.reduce_mean(
tf.nn.nce_loss(weights=nce_weights,
biases=nce_biases,
labels=y_idx,
inputs=embed,
num_sampled=num_sampled,
num_classes=vocabulary_size))
output = tf.matmul(y_conv, tf.transpose(nce_weights)) + nce_biases
correct_prediction = tf.equal(tf.argmax(output, 1), tf.argmax(y_, 1))
Когда мы установим num_sampled=1
, точность val будет около 98.8%
. И если мы установим num_sampled=9
, мы сможем получить почти ту же точность val, что и тренируемая softmax. Но учтите, что nce
отличается от softmax
.
Полный код обучения mnist
по nce
можно найти здесь. Надеюсь, это полезно.
Ответ 2
embeddings
Tensor - это ваша окончательная матрица вывода. Он сопоставляет слова векторам. Используйте это в графе предсказания слов.
train_input
матрица представляет собой партию centre-word: context-word
пары centre-word: context-word
(train_input
и train_label
соответственно), сформированные из текста обучения.
Хотя точная работа nce_loss
op еще не известна мне, основная идея заключается в том, что она использует однослойную сеть (параметры nce_weights
и nce_biases
) для сопоставления входного вектора (выбранного из embeddings
с использованием embed
op) в выходное слово, а затем сравнивает результат с обучающей меткой (смежным словом в тексте обучения), а также случайным num_sampled
(num_sampled
) всех других слов в vocab, а затем изменяет входной вектор (сохраняется в embeddings
) и параметры сети, чтобы свести к минимуму ошибку.
Ответ 3
Каковы матрицы ввода и вывода в функции NCE?
Возьмем, например, пропущенную грамматическую модель для этого предложения:
the quick brown fox jumped over the lazy dog
входные и выходные пары:
(quick, the), (quick, brown), (brown, quick), (brown, fox),...
Для получения дополнительной информации обратитесь к учебнику.
Каково окончательное вложение?
Конечным вложением, которое вы должны извлечь, обычно является {w} между входным и скрытым слоями.
Чтобы проиллюстрировать более интуитивно взглянуть на следующее изображение:
Один горячий вектор [0, 0, 0, 1, 0] является входным слоем в вышеприведенном графике, выход является вложением слова [10, 12, 19], а W (на графике выше) является матрицей в между.
Подробное объяснение читайте в этом уроке.
Ответ 4
1) Короче говоря, это правильно в целом, но только частично верно для рассматриваемой функции. Смотрите учебник:
Потеря оценки, сопоставимая с шумом, определяется с помощью модели логистической регрессии. Для этого нам необходимо определить весовые коэффициенты и смещения для каждого слова в словаре (также называемые output weights
в отличие от input embeddings
).
Таким образом, входные данные для функции nce_loss
представляют собой output weights
и небольшую часть nce_loss
input embeddings
, среди прочего.
2) "Окончательное" встраивание (иначе говоря, векторы Word, а также векторные представления слов) - это то, что вы называете input matrix
. Вложения - это строки (векторы) этой матрицы, соответствующие каждому слову.
Предупреждение На самом деле эта терминология сбивает с толку из-за использования концепций ввода и вывода в среде NN. Матрица вложений не является входом для NN, поскольку технически вход для NN является входным слоем. Вы получаете окончательное состояние этой матрицы в процессе обучения. Тем не менее, эта матрица должна быть инициализирована в программировании, потому что алгоритм должен начинаться с некоторого случайного состояния этой матрицы, чтобы постепенно обновлять ее во время обучения.
То же самое относится и к весам - они также должны быть инициализированы. Это происходит в следующей строке:
nce_weights = tf.Variable(
tf.truncated_normal([50000, 128], stddev=1.0 / math.sqrt(128)))
Каждый вектор вложения может быть умножен на вектор из матрицы весов (в виде строки в столбец). Таким образом, мы получим скаляр в output layer
NN. Норма этого скаляра интерпретируется как вероятность того, что целевое слово (из входного слоя) будет сопровождаться словом метки [или контекста], соответствующим месту скаляра в output layer
.
Итак, если мы говорим о входных данных (аргументах) для функции, то обе матрицы таковы: весовые коэффициенты и пакетное извлечение из вложений:
tf.nn.nce_loss(weights=nce_weights, # Tensor of shape(50000, 128)
biases=nce_biases, # vector of zeros; len(128)
labels=train_labels, # labels == context words enums
inputs=embed, # Tensor of shape(128, 128)
num_sampled=num_sampled, # 64: randomly chosen negative (rare) words
num_classes=vocabulary_size)) # 50000: by construction
Эта функция nce_loss
выводит вектор batch_size - в примере TensorFlow тензор shape(128,)
. Затем reduce_mean()
уменьшает этот результат до скалярного значения, взятого из этих 128 значений, что фактически является целью для дальнейшей минимизации.
Надеюсь это поможет.
Ответ 5
Из статьи Эффективное вложение слов вложения с шумо-контрастной оценкой:
NCE основан на снижении оценки плотности до вероятностной двоичной классификации. Основная идея состоит в том, чтобы обучить логистический классификатор регрессии, чтобы различать выборки из распределения данных и выборок из некоторого "шума" распределения
Мы могли бы выяснить, что при вложении слов НСЕ является отрицательной выборкой. (Разницу между этими двумя, см. Документ: Примечания по оценке контрастности шума и отрицательной выборке)
Поэтому вам не нужно вводить распределение шума. А также из цитаты, вы узнаете, что это фактически логистическая регрессия: вес и предвзятость были бы единственной потребностью в логистической регрессии. Если вы знакомы с word2vec, это просто добавляет смещение.