Как создать Тензор из единиц и нулей из тензора с указанием длины - PullRequest
0 голосов
/ 16 марта 2019

У меня есть следующий код, который вычисляет потерю нейронной сети.

loss = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y,logits = y_hat_logits)

y_hat_logits имеет размер 10x100 (100 выходов для каждого элемента пакета), однако это 100, потому что у меня есть дополненные данныетак что в действительности может быть так, что в каждом элементе пакета полезны только первые, например, 10, 20 или 30 фактических логитов, поэтому, когда я вычисляю потери, я хочу создать маску, чтобы логиты, которые соответствовали дополненным даннымустановлены в 0, прежде чем передать его моей функции потери.Я знаю, как определить, сколько логитов «полезно» в каждом элементе пакета, используя следующий код, который я нашел в Интернете:

def length(sequence):
   used = tf.sign(tf.reduce_max(tf.abs(sequence), axis= 2))
   length = tf.reduce_sum(used, axis=1)
   length = tf.cast(length, tf.int32)
   return length

Это вернет тензор формы 10x1, где значения соответствуютколичество полезных логитов, прежде чем я дополнил данные.Например, если первое значение в тензоре равно 5, это означает, что должны рассматриваться только первые 5 логитов в моем элементе пакета.Теперь я хочу взять этот тензор, и если первое значение равно 5, я хочу создать новую маску 10x100, где первая строка имеет 5 единиц и 95 нулей, так что я могу сделать поэлементное умножение моего y_hat_logits с этой маской, чтобы получить замаскированную версию y_hat_logits, где все логиты, соответствующие дополненным данным, установлены в 0.

Так, например, если length (sequence) возвращает тензор [5,3,1,0,7], яхотите создать маску, где первая строка [1,1,1,1,1,0, ..., 0], вторая строка [1,1,1,0, ..., 0],третья строка - [1,0, ..., 0], четвертая строка - [0, ..., 0], последняя строка - [1,1,1,1,1,1,1,0, ..., 0].Теперь меня беспокоит то, как это сделать с помощью команд tf, потому что это легко, если я использую массивы np.Я предполагаю, что должен сделать что-то вроде вложенного map_fn, но я не уверен, как именно это сделать.

При настройке моего графика я хочу передать y_hat_masked_logits в мою функцию потерь, которая будет элементоммудрый продукт моей маски 10х100 с моими логитами 10х100.Надеюсь, я прояснил вопрос.

Спасибо!


На самом деле я пытался реализовать еще одну реализацию с использованием map_fn и tf.slice, но я не добился прогресса.Это был бы более легкий подход?Взять кусочек размером 5 или что-то еще из 1-го ряда тензора, а затем от 0 до 100?

1 Ответ

0 голосов
/ 16 марта 2019

В Tensorflow уже есть функция, которую вы пытаетесь достичь. Пример ниже должен помочь вам:

lengths = np.array([5,3,1,0,7])
maxlen = tf.reduce_max(lengths)
# 7
mask = tf.sequence_mask(lengths, maxlen=maxlen, dtype=tf.int32)
# [[1 1 1 1 1 0 0]
#  [1 1 1 0 0 0 0]
#  [1 0 0 0 0 0 0]
#  [0 0 0 0 0 0 0]
#  [1 1 1 1 1 1 1]]
...