Как вычислить средневзвешенное значение тензора A вдоль оси с весами, заданными тензором B в тензорном потоке?

Я пытаюсь применить средневзвешенную схему к выходным данным RNN.
Выходные данные RNN представлены тензором A размерности (a,b,c).
Я могу просто взять tf.reduce_mean(A,axis=1), чтобы получить тензор C размерности (a,c).

Однако я хочу сделать "средневзвешенное" тензора A вдоль axis = 1.
Веса указаны в матрице B размерности (d,b).

Для d = 1 я могу выполнить tf.tensordot(A,B,[1,1]), чтобы получить результат измерения (a,c).
Теперь для d=a я не могу вычислить средневзвешенное значение.

Может ли кто-нибудь предложить решение?


person abhi    schedule 28.03.2019    source источник
comment
Попробуйте tf.reduce_sum(A * B[:, :, None], axis=1) / tf.reduce_sum(B, axis=1, keepdims=True). Если это сработает, я превращу это в ответ.   -  person Siyuan Ren    schedule 28.03.2019
comment
@SiyuanRen, не могли бы вы объяснить, что он делает?   -  person abhi    schedule 29.03.2019
comment
Вес @SiyuanRen уже нормализован. Так что нет необходимости в операции деления. Я думаю, что операция деления нормализует веса, так что в сумме они равны 1. Можете ли вы объяснить оценку первой части?   -  person abhi    schedule 29.03.2019


Ответы (2)


Я не совсем понимаю, почему B должен иметь размеры (d,b). Если B содержит веса для получения средневзвешенного значения A только по одному измерению, B должен быть только вектором (b,), а не матрицей.

Если B является вектором, вы можете сделать:

C = tf.tensordot(A,B,[1,0]), чтобы получить вектор C формы (a,c), который содержит средневзвешенное значение A по axis=1 с использованием весов, указанных в B.

Обновление:

Вы можете сделать что-то вроде:

A = A*B[:,:,None] 

который выполняет поэлементное умножение A и B, где B хранит веса, присвоенные каждому элементу в A. Затем:

C = tf.reduce_mean(A,axis=1)

выполнит средневзвешенное значение, поскольку каждый элемент в A был умножен на его вес.

person Guillem Cucurull    schedule 28.03.2019
comment
Я получил результаты для случая d=1. Мне нужно d=a case, потому что у меня есть веса для каждого входа, а размер партии определяется a и d. - person abhi; 29.03.2019
comment
Хорошо, извините, тогда вы можете сделать что-то вроде: A = A*B[:,:,None] (это выполняет поэлементное умножение A и B, где B хранит веса, присвоенные каждому элементу в A), а затем C = tf.reduce_mean(A,axis=1), что будет делать средневзвешенное значение, поскольку каждый элемент в A умножается на его вес. - person Guillem Cucurull; 30.03.2019

Поскольку B уже нормализовано, ответ будет

tf.reduce_sum(A * B[:, :, None], axis=1)

Индексирование с помощью None добавляет новое измерение, поведение, унаследованное от numpy.B[:,:, None], добавляет последнее измерение, поэтому результат имеет форму (a, b, 1). Вы можете добиться того же самого с tf.expand_dims, чье имя может иметь для вас больше смысла.

A имеет форму (a, b, c), а B[:, :, None] имеет форму (a, b, 1). Когда они перемножаются, расширенный B также будет рассматриваться как имеющий форму (a, b, c), причем последнее измерение будет c копиями одного и того же значения. Это называется трансляция.

Из-за того, как работает трансляция, тот же ответ также работает, если B имеет форму (1, b).

person Siyuan Ren    schedule 30.03.2019