#python #arrays #numpy #multiplication
#питон #массивы #тупой #умножение
Вопрос:
Я пытаюсь умножить два массива на каждую возможную комбинацию элементов. Например
A = [1, 2, 3]
B = [1, 2, 3]
# Result -> [1, 2, 3, 2, 4, 6, 3, 6, 9]
Мои массивы имеют длину 10000. Я уже пробовал такой подход:
np.multiply.outer(data, data2)
Однако я получаю эту ошибку:
anaconda3libsite-packagespandascoreseries.py in __array_ufunc__(self, ufunc, method, *inputs, **kwargs)
724
725 inputs = tuple(extract_array(x, extract_numpy=True) for x in inputs)
--> 726 result = getattr(ufunc, method)(*inputs, **kwargs)
727
728 name = names[0] if len(set(names)) == 1 else None
MemoryError: Unable to allocate 74.5 GiB for an array with shape (100000, 100000) and data type float64
Как это сделать?
Комментарии:
1. Да,
np.multply.outer
это то, что вы хотите. Возможно, вам нужно найти компьютер с большим74.5 GB
объемом оперативной памяти :-). Или вам нужно будет сохранить ваши данные на диск, а не в память.2. как я могу заставить сделать это в памяти вместо этого?
3.
outer
отлично работает с этими двумя примерами массивов, не так ли, получая результат (3,3). Проблема не вmultiply.outer
этом, а в размере массивов. Вам действительно нужно формировать внешний продукт таких больших массивов? 100000*100000*8 = 80 Г
Ответ №1:
Ваши матрицы разрежены? означает, что многие ячейки имеют значение = 0? Если это так, вы могли бы использовать разреженную матрицу scipy. Этот модуль очень эффективно работает с большими массивами. Я считаю, что этот пример соответствует тому, о чем вы просите: https://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.kron.html#scipy.sparse.kron
Комментарии:
1. У меня есть два предложения: — Похоже, что этот тип умножения может быть выполнен кусками? как насчет умножения одной строки или подмножества A за раз? аналогично mathworks.com/matlabcentral/answers /… — Каково максимальное значение в массивах? Вы могли бы, например, изменить свой dtype массива на np.uint8, что сэкономит вам много памяти, но будьте осторожны, потому что этот dtype не допускает никакого значения, превышающего 2^8. (2^16, 2^32 и 2 ^ 64 также доступны) numpy.org/doc/stable/user/basics.types.html
2. значения — float64, я пробовал uint8, однако значения округляются до 0. Есть ли решение с помощью float?
3. Вы можете попробовать
numpy.half / numpy.float16
4. Изменение dtype просто откладывает ошибку памяти. Трудно применять эти меньшие dtypes во всех вычислениях и трудно ограничить количество временных буферов и т. Д.
Ответ №2:
Вот фрагментированное решение, которое должно выгружаться на диск в правильном порядке:
a = np.arange(10000)
b = a[::-1] # 'cause why not
chunk_size = 500
with open('output.dat', 'w') as f:
for c in a.split(np.arange(chunk_size, a.size 1, chunk_size)):
np.tofile(np.multiply.outer(c, b))
Каждый c
из них должен быть view into a
, поэтому единственные новые данные, которые вы создаете, — это with np.multiply.outer(c, b)
. Вы можете управлять размером промежуточного вывода, изменяя chunk_size
его таким образом, чтобы операция помещалась в память. Двоичные данные output.dat
будут выводом, который вы хотите сохранить, в порядке следования строк (C).