повторяющиеся numy подмассивы - PullRequest
4 голосов
/ 19 ноября 2011

Это упрощение моего вопроса. У меня есть массив NumPy:

x = np.array([0,1,2,3])

и у меня есть функция:

def f(y): return y**2

Я могу вычислить f (x).

Теперь предположим, что я действительно хочу вычислить f (x) для повторного x:

x = np.array([0,1,2,3,0,1,2,3,0,1,2,3])

Есть ли способ сделать это без создания повторяющейся версии x и способом, который прозрачен для f?

В моем конкретном случае, f - это вовлеченная функция, а один из аргументов - x. Я хотел бы иметь возможность вычислять f, когда x повторяется, фактически не повторяя его, поскольку он не помещается в память.

Перезапись f для обработки повторяющихся x будет работать, и я надеялся, что для этого найдется умный способ создать подкласс массива numpy.

Любые советы приветствуются.

1 Ответ

8 голосов
/ 19 ноября 2011

Вы можете (почти) сделать это, используя несколько трюков с шагами.

Тем не менее, есть некоторые важные оговорки ...

import numpy as np
x = np.arange(4)
numrepeats = 3

y = np.lib.stride_tricks.as_strided(x, (numrepeats,)+x.shape, (0,)+x.strides)

print y
x[0] = 9
print y

Итак, y теперь является представлением x, где каждая строка x. Новая память не используется, и мы можем сделать y настолько большим, насколько захотим.

Например, я могу сделать это:

import numpy as np
x = np.arange(4)
numrepeats = 1e15

y = np.lib.stride_tricks.as_strided(x, (numrepeats,)+x.shape, (0,)+x.strides)

... и не использовать больше памяти, чем 32 байта, необходимых для x. (y будет использовать ~ 8 петабайт ОЗУ, в противном случае)

Однако, если мы изменим y, чтобы у него было только одно измерение, мы получим копию, которая будет использовать весь объем памяти. Невозможно описать «горизонтальное» мозаичное представление x, используя шаги и фигуру, поэтому любая фигура с менее чем двумя измерениями вернет копию.

Кроме того, если мы оперируем с y способом, который возвращает копию (например, y**2 в вашем примере), мы получим полную копию.

По этой причине, имеет смысл работать с вещами на месте. (например, y **= 2 или эквивалентно x **= 2. Оба будут выполнять одно и то же.)

Даже для универсальной функции вы можете передать x и поместить результат обратно в x.

1039 * Е.Г. *

def f(x):
    return x**3

x[...] = f(x)
print y

y также будет обновлено, так как это просто просмотр x.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...