Что делает функция tf.nn.embedding_lookup?
tf.nn.embedding_lookup(params, ids, partition_strategy='mod', name=None)
Я не могу понять обязанности этой функции. Это похоже на таблицу поиска? Что означает возврат параметров, соответствующих каждому id (в ids)?
Например, в модели skip-gram
, если мы используем tf.nn.embedding_lookup(embeddings, train_inputs)
, то для каждого train_input
он находит соответствующее вложение?
Ответы
Ответ 1
Функция embedding_lookup
извлекает строки тензора params
. Поведение похоже на использование индексации с массивами в numpy. Например.
matrix = np.random.random([1024, 64]) # 64-dimensional embeddings
ids = np.array([0, 5, 17, 33])
print matrix[ids] # prints a matrix of shape [4, 64]
Аргументом params
может быть также список тензоров, в этом случае ids
будет распределен между тензорами. Например, учитывая список из 3 тензоров [2, 64]
, поведение по умолчанию состоит в том, что они будут представлять ids
: [0, 3]
, [1, 4]
, [2, 5]
.
partition_strategy
определяет способ распределения ids
среди списка. Разделение полезно для более масштабных проблем, когда матрица может быть слишком большой, чтобы держать ее в одной части.
Ответ 2
Да, эту функцию трудно понять, пока вы не получите точку.
В простейшей форме он похож на tf.gather
. Он возвращает элементы params
в соответствии с индексами, указанными ids
.
Например (если вы находитесь внутри tf.InteractiveSession()
)
params = tf.constant([10,20,30,40])
ids = tf.constant([0,1,2,3])
print tf.nn.embedding_lookup(params,ids).eval()
вернет [10 20 30 40]
, потому что первый элемент (индекс 0) параметров 10
, второй элемент params (индекс 1) равен 20
и т.д.
Аналогично,
params = tf.constant([10,20,30,40])
ids = tf.constant([1,1,3])
print tf.nn.embedding_lookup(params,ids).eval()
вернет [20 20 40]
.
Но embedding_lookup
больше. Аргумент params
может быть списком тензоров, а не одним тензором.
params1 = tf.constant([1,2])
params2 = tf.constant([10,20])
ids = tf.constant([2,0,2,1,2,3])
result = tf.nn.embedding_lookup([params1, params2], ids)
В этом случае индексы, указанные в ids
, соответствуют элементам тензоров согласно стратегии разбиения, где стратегия раздела по умолчанию - "mod".
В стратегии "mod" индекс 0 соответствует первому элементу первого тензора в списке. Индекс 1 соответствует элементу first тензора второй. Индекс 2 соответствует элементу first тензора третий и т.д. Просто индекс i
соответствует первому элементу тензора (i + 1) -го для всех индексов 0..(n-1)
, считая params - список тензоров n
.
Теперь индекс n
не может соответствовать тензору n + 1, так как в списке params
содержатся только тензоры n
. Таким образом, индекс n
соответствует элементу second первого тензора. Аналогично, индекс n+1
соответствует второму элементу второго тензора и т.д.
Итак, в коде
params1 = tf.constant([1,2])
params2 = tf.constant([10,20])
ids = tf.constant([2,0,2,1,2,3])
result = tf.nn.embedding_lookup([params1, params2], ids)
индекс 0 соответствует первому элементу первого тензора: 1
индекс 1 соответствует первому элементу второго тензора: 10
индекс 2 соответствует второму элементу первого тензора: 2
индекс 3 соответствует второму элементу второго тензора: 20
Таким образом, результатом будет:
[ 2 1 2 10 2 20]
Ответ 3
Другой способ взглянуть на это - предположим, что вы сглаживаете тензоры на один размерный массив, а затем выполняете поиск
(например, Tensor0 = [1,2,3], Tensor1 = [4,5,6], Tensor2 = [7,8,9]
Сглаженный тензор будет следующим:
[1,4,7,2,5,8,3,6,9]
Теперь, когда вы просматриваете [0,3,4,1,7], он будет играть [1,2,5,4,6]
(i, e), если значение поиска равно 7, и мы имеем 3 тензора (или тензор с 3 строками), тогда
7/3: (Напоминание 1, Коэффициент 2). Будет показан 2-й элемент Tensor1, который равен 6
Ответ 4
Когда тензор параметров находится в больших размерах, идентификаторы относятся только к верхней размерности. Возможно, это очевидно для большинства людей, но я должен запустить следующий код, чтобы понять это:
embeddings = tf.constant([[[1,1],[2,2],[3,3],[4,4]],[[11,11],[12,12],[13,13],[14,14]],
[[21,21],[22,22],[23,23],[24,24]]])
ids=tf.constant([0,2,1])
embed = tf.nn.embedding_lookup(embeddings, ids, partition_strategy='div')
with tf.Session() as session:
result = session.run(embed)
print (result)
Просто попробовав стратегию "div" и для одного тензора, это не имеет никакого значения.
Вот результат:
[[[ 1 1]
[ 2 2]
[ 3 3]
[ 4 4]]
[[21 21]
[22 22]
[23 23]
[24 24]]
[[11 11]
[12 12]
[13 13]
[14 14]]]
Ответ 5
Добавляя к ответу Ашера Штерна,
params
интерпретируется как разбиение большого тензора вложения. Это может быть один тензор, представляющий полный тензор вложения, или список X-тензоров одинаковой формы, за исключением первого измерения, представляющих тензоры вложенных вложений.
Функция tf.nn.embedding_lookup
написана с учетом того, что вложение (params) будет большим. Поэтому нам нужно partition_strategy
.