Распространенный способ умножения массива массивов или двумерного массива на вектор - PullRequest
0 голосов
/ 25 февраля 2019

Я хочу получить результат ax = as_x-aseg_3d * aline_a

, где as_x и aline_a - это numpy векторы, а aseg_3d - это массив массивов.Форма as_x.shape и aline_a - это (S,), а форма aseg_3d также показана как (S,), как и должно быть для массива массивов.Результирующий топор также является массивом массивов, имеющих ту же форму, что и aseg_3d.

Проблема состоит в том, что aseg_3d является массивом массивов, поскольку массивы внутри имеют разную длину.Однако иногда они этого не делают, и тогда aseg_3d становится просто двумерным массивом.Затем приведенная выше муллипляция завершается с ошибкой ValueError: операнды не могут передаваться вместе с фигурами (S, N).

Я могу исправить это, выполнив: ax = as_x [:, None] -aseg_3d * aline_a [:,Нет]

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

Есть ли способ заставить его работать в обоих случаях: массив массивови 2D-массив?

Или, возможно, есть способ сохранить массив массивов dtype = "object", даже если все внутренние массивы имеют одинаковую длину?

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

Спасибо за все советы!

1 Ответ

0 голосов
/ 25 февраля 2019

Выражение, которое работает в любом случае:

Вы можете использовать транспонирование.Простой случай (просто умножение):

(vector * vec_of_vecs_or_2D.T).T

Полный пример OP:

(vector1 - vector2 * vec_of_vecs_or_2D.T).T

Пример:

>>> v = np.array([3, 5])
>>> A = np.array((*map(np.array,[[1,2],[1,2,3]]),))
>>> B = np.array([[1,2,4],[1,2,3]])
>>> 
>>> v
array([3, 5])
>>> A
array([array([1, 2]), array([1, 2, 3])], dtype=object)
>>> B
array([[1, 2, 4],
       [1, 2, 3]])
>>> 
>>> (v*B.T).T
array([[ 3,  6, 12],
       [ 5, 10, 15]])
>>> (v*A.T).T
array([array([3, 6]), array([ 5, 10, 15])], dtype=object)

Как это работает:

Если vec_of_vecs_or_2D является 1D объекта dtype, то транспонирование ничего не делает.

Если vec_of_vecs_or_2D действительно 2D, тогда транспонирование перемещает ось, соответствующую vector, в конец, поэтому vector передается правильно,и обратно потом.

Почему это дешево:

Обратите внимание, что транспонирование в numpy лениво.На самом деле он не перемещает никаких данных, он просто «меняет метки оси».

Например, для транспонирования массива 1000x1000 на моем ноутбуке требуется ~ 200 нс:

>>> a = np.arange(1_000_000).reshape(1000, 1000)
>>> timeit(lambda: a.T)
0.22008929261937737

В качестве альтернативы можно использовать массив массивов в любом случае:

Пример

>>> L1 = [np.arange(i, 2*i+2) for i in range(3)]
>>> L2 = [np.arange(i, i+3) for i in range(3)]
>>> L1
[array([0, 1]), array([1, 2, 3]), array([2, 3, 4, 5])]
>>> L2
[array([0, 1, 2]), array([1, 2, 3]), array([2, 3, 4])]

Метод 1 (некрасиво, но просто):

>>> A1 = np.array([*L1, None])[:-1]
>>> A2 = np.array([*L2, None])[:-1]
>>> A1
array([array([0, 1]), array([1, 2, 3]), array([2, 3, 4, 5])], dtype=object)
>>> A2
array([array([0, 1, 2]), array([1, 2, 3]), array([2, 3, 4])], dtype=object)

Метод 2: (не совсемкак некрасиво, но сложно)

>>> A1 = np.frompyfunc(L1.__getitem__, 1, 1)(range(len(L1)))
>>> A2 = np.frompyfunc(L2.__getitem__, 1, 1)(range(len(L2)))
>>> A1
array([array([0, 1]), array([1, 2, 3]), array([2, 3, 4, 5])], dtype=object)
>>> A2
array([array([0, 1, 2]), array([1, 2, 3]), array([2, 3, 4])], dtype=object)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...