Генерация матрицы из попарного сравнения одного вектора в TensorFlow

У меня есть вектор 1d и я хочу создать матрицу на основе попарного сравнения вектора в TensorFlow. Мне нужно сравнить каждый элемент вектора со всеми остальными (включая самого себя), и если они идентичны, соответствующее значение матрицы будет равно 1, а в противном случае -1. Например, есть вектор [1,2,3,4,1], тогда искомая матрица

[[1,-1,-1,-1,1],
 [-1,1,-1,-1,-1],
 [-1,-1,1,-1,-1],
 [-1,-1,-1,1,-1],
 [1,-1,-1,-1,1]].

Вопрос в том, как сгенерировать такую ​​матрицу в TensorFlow.


person ALeex    schedule 16.03.2018    source источник
comment
На самом деле я хочу сравнить элементы в векторе 1d. Скажем, длина вектора равна 5, тогда будет 25 сравнений и, следовательно, будет сгенерирована матрица 5x5 на основе результата каждого сравнения.   -  person ALeex    schedule 17.03.2018


Ответы (3)


Я не знаю, есть ли в TensorFlow что-то подобное, но в NumPy есть довольно простой подход. Он работает, беря все произведения элементов и выбирая места, где произведение двух элементов x и y равно x ** 2.0.

Учитывая вектор

v = np.array((1, 2, 3, 4, 1)).reshape(-1, 1) # shape == (5, 1)

вы можете построить матрицу «подобия», которую хотите, выполнив следующие действия:

sim = np.where(v.dot(v.T) == np.square(v), 1, -1)

sim будет выглядеть так:

array([[ 1, -1, -1, -1,  1],
       [-1,  1, -1, -1, -1],
       [-1, -1,  1, -1, -1],
       [-1, -1, -1,  1, -1],
       [ 1, -1, -1, -1,  1]])
person bnaecker    schedule 16.03.2018
comment
Спасибо за ваш ответ, я подумал о создании матрицы np, а затем преобразовать ее в тензор тензорного потока. Но, видимо, я не знаю, как связать np с tf graph. Вы случайно не знаете, как это работает? - person ALeex; 17.03.2018
comment
Я понятия не имею, но похоже, что вы можете использовать этот подход непосредственно в TensorFlow, не конвертируя все, что хранит ваши данные там, в ndarray и обратно. Посмотрите на tf.where(), это может указать вам правильное направление. Может быть, построить tf.constant из имеющегося у вас вектора, а затем выполнить операцию, которую я описал, заменив tf.where(), tf.square() и tf.matmul(). - person bnaecker; 17.03.2018
comment
Вы уверены, что tf.where() делает то же самое, что и np.where? - person ALeex; 17.03.2018
comment
Похоже, он выполняет ту же операцию, но может не допускать скаляров в качестве второго и третьего аргументов. Возможно, они должны быть тензорами того же ранга, что и первый аргумент. Я никогда не использовал его. - person bnaecker; 17.03.2018

Идея

Чтобы вычислить попарную операцию, вы можете сделать следующий трюк: разложить вектор на два двумерных вектора: [n, 1] и [1, n] и применить к ним операцию. Из-за трансляции он создаст матрицу [n, n], заполненную результатами операции для всех пар внутри вектора.

В вашем случае op — это сравнение, но это может быть любая бинарная операция.

Тензорный поток

Для иллюстрации вот два однострочника. Первый производит булеву парную матрицу, второй - матрицу -1 и 1 (то, что вы просили).

import tensorflow as tf

tf.InteractiveSession()
v = tf.constant([1, 2, 3, 4, 1])

x = tf.equal(v[:, tf.newaxis], v[tf.newaxis, :])
print(x.eval())

x = 1 - 2 * tf.cast(x, tf.float32)
print(x.eval())

Результат:

[[ True False False False  True]
 [False  True False False False]
 [False False  True False False]
 [False False False  True False]
 [ True False False False  True]]
[[ 1 -1 -1 -1  1]
 [-1  1 -1 -1 -1]
 [-1 -1  1 -1 -1]
 [-1 -1 -1  1 -1]
 [ 1 -1 -1 -1  1]]

Нампи

То же самое в numpy еще проще, используя np.where:

import numpy as np

v = np.array([1, 2, 3, 4, 1])

x = v[:, np.newaxis] == v[np.newaxis, :]
print(x)

x = np.where(x, 1, -1)
print(x)

Выход такой же:

[[ True False False False  True]
 [False  True False False False]
 [False False  True False False]
 [False False False  True False]
 [ True False False False  True]]
[[ 1 -1 -1 -1  1]
 [-1  1 -1 -1 -1]
 [-1 -1  1 -1 -1]
 [-1 -1 -1  1 -1]
 [ 1 -1 -1 -1  1]]
person Maxim    schedule 18.04.2018

Вот простой способ сделать это:

In [123]: x = tf.placeholder(tf.float32, shape=(1, 5))

In [124]: z = tf.equal(tf.matmul(tf.transpose(x), x), tf.square(x))

In [125]: y = 2 * tf.cast(z, tf.int32) - 1

In [126]: sess = tf.Session()

In [127]: sess.run(y, feed_dict={x: np.array([1, 2, 3, 4, 1])[None, :]})
Out[127]: 
array([[ 1, -1, -1, -1,  1],
       [-1,  1, -1, -1, -1],
       [-1, -1,  1, -1, -1],
       [-1, -1, -1,  1, -1],
       [ 1, -1, -1, -1,  1]], dtype=int32)
person ely    schedule 18.04.2018