фильтровать массив тензорных потоков с определенным условием над массивом numpy - PullRequest
0 голосов
/ 10 июня 2019

У меня есть имена массивов тензорного потока tf-array и имена пустых массивов np_array.Я хочу найти конкретные строки в tf_array относительно np-array.

    tf-array = tf.constant(
                [[9.968594,  8.655439,  0.,        0.       ],
                 [0.,        8.3356,    0.,        8.8974   ],
                 [0.,        0.,        6.103182,  7.330564 ],
                 [6.609862,  0.,        3.0614321, 0.       ],
                 [9.497023,  0.,        3.8914037, 0.       ],
                 [0.,        8.457685,  8.602337,  0.       ],
                 [0.,        0.,        5.826657,  8.283971 ]])

У меня также есть np-массив:

np_array = np.matrix(
 [[2, 5, 1],
  [1, 6, 4],
  [0, 0, 0],
  [2, 3, 6],
  [4, 2, 4]]

Теперь я хочу сохранить элементыв tf-array, в котором комбинация n (here n is 2) из них (их индекс) имеет значение np-array.Что это значит?

Например, в tf-array, в первом столбце, индексы, которые имеют значение: (0,3,4).Есть ли в np-array строка, содержащая любую комбинацию этих двух индексов: (0,3), (0,4) or (3,4).На самом деле такого ряда нет.Таким образом, все элементы в этом столбце стали zero.

Индексы для второго столбца в tf-array равны (0,1) (0,5) (1,5).Как видите, запись (1,5) доступна в np-array в первом ряду.Вот почему мы сохраняем их в tf-array.

. Таким образом, конечный результат должен быть таким:

[[0.        0.        0.        0.       ]
 [0.        8.3356    0.        8.8974   ]
 [0.        0.        6.103182  7.330564 ]
 [0.        0.        3.0614321 0.       ]
 [0.        0.        3.8914037 0.       ]
 [0.        8.457685  8.602337  0.       ]
 [0.        0.        5.826657  8.283971 ]]

Я ищу очень эффективный подход, так как у меня есть большое количество данных.

Update1

Я мог бы получить это с помощью приведенного ниже кода, который дает True, где есть значение и нулевая маска для false:

[[ True  True False False]
 [False  True False  True]
 [False False  True  True]
 [ True False  True False]
 [ True False  True False]
 [False  True  True False]
 [False False  True  True]]

with tf.Session() as sess:  
 where = tf.not_equal(tf-array, 0.0)
 print(sess.run(where))

Но как сравнить эту матрицу с np_array?

Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 11 июня 2019

Вот решение от https://stackoverflow.com/a/56510832/7207392 с необходимыми модификациями. Для простоты я использую np.array для всех данных. Я не специалист по tenortflow, поэтому если перевод не совсем понятен, вам нужно будет спросить кого-нибудь еще, как это сделать.

import numpy as np

def f(a1, a2, n):
    N,M = a1.shape
    a1p = np.concatenate([a1,np.zeros((1,a1.shape[1]),a1.dtype)], axis=0)
    a2 = np.sort(a2, axis=1)
    a2[:,1:][a2[:,1:]==a2[:,:-1]] = N
    y,x = np.where(np.count_nonzero(a1p[a2], axis=1) >= n)
    out = np.zeros_like(a1p)
    out[a2[y],x[:,None]] = a1p[a2[y],x[:,None]]
    return out[:-1]

a1 = np.array(
    [[9.968594,  8.655439,  0.,        0.       ],
     [0.,        8.3356,    0.,        8.8974   ],
     [0.,        0.,        6.103182,  7.330564 ],
     [6.609862,  0.,        3.0614321, 0.       ],
     [9.497023,  0.,        3.8914037, 0.       ],
     [0.,        8.457685,  8.602337,  0.       ],
     [0.,        0.,        5.826657,  8.283971 ]])

a2 = np.array(
 [[2, 5, 1],
  [1, 6, 4],
  [0, 0, 0],
  [2, 3, 6],
  [4, 2, 4]])

print(f(a1,a2,2))

Выход:

[[0.        0.        0.        0.       ]
 [0.        8.3356    0.        8.8974   ]
 [0.        0.        6.103182  7.330564 ]
 [0.        0.        3.0614321 0.       ]
 [0.        0.        3.8914037 0.       ]
 [0.        8.457685  8.602337  0.       ]
 [0.        0.        5.826657  8.283971 ]]
1 голос
/ 10 июня 2019

Один эффективный способ, который вы можете попробовать, - это установить битовые флаги для каждой строки, какое значение для (0,3,4) будет равно 1 << 0 | 1 << 3 | 1 << 4. У вас будет массив значений с флагами. Попробуйте, если << и | оператор работает в клочья. Сделайте то же самое для другого массива, я думаю, что массивы - это просто обернутые числа. Имея 2 массива флагов, сделайте побитовые "и" над ними. Если вы выполняете условие истинно для строк, результат будет иметь как минимум два ненулевых бита. Кроме того, бит бит может быть сделано также эффективно, Google для этого. </p>

Этот Hovever не будет работать с плавающей точкой - вам нужно конвертировать их в довольно маленькие целые.

import numpy as np



arr_one =  np.array(
 [[2, 5, 1],
  [1, 6, 4],
  [0, 0, 0],
  [2, 3, 6],
  [4, 2, 4]])

arr_two =  np.array(
 [[2, 0, 7],
  [1, 3, 4],
  [5, 5, 6],
  [1, 3, 6],
  [4, 2, 4]])




print('1 << arr_one.T[0] ' , 1 << arr_one.T[0] )


arr_one_flags = 1 << arr_one.T[0] | 1 << arr_one.T[1] | 1 << arr_one.T[2]

print('arr_one_flags ', arr_one_flags)

arr_two_flags = 1 << arr_two.T[0] | 1 << arr_two.T[1] | 1 << arr_two.T[2]

arr_and = arr_one_flags & arr_two_flags

print('arr_and ', arr_and)



def get_bit_count(value):
    n = 0
    while value:
        n += 1
        value &= value-1
    return n

arr_matches = np.array([get_bit_count(x) for x in arr_and])


print('arr_matches ', arr_matches )


arr_two_filtered = arr_two[arr_matches > 1]

print('arr_two_filtered ', arr_two_filtered )
...