Что делает функция 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.