Я пытаюсь создать синусоидальное изображение, но не вижу альтернативы без использования двух циклов for. Может ли кто-нибудь помочь мне векторизовать этот код?
import numpy as np
M, N = 1001, 1001
u = 100
v = 200
sin_img = np.zeros((M, N))
for m in range(M):
for n in range(N):
sin_img[m, n] = np.sin((2 * np.pi * u * m / M) + (2 * np.pi * v * n / N))
Я не знаю, что означает «векторизация», но если вы хотите избавиться от двух циклов for, вы можете использовать понимание списка:
sin_img = np.array([[np.sin((2 * np.pi * u * m / M) + (2 * np.pi * v * n / N))
for n in range(N)]
for m in range(M)])
Объяснение:
Код состоит из понимания списка внутри понимания списка. Каждое понимание списка делается следующим образом:
[some_expression for NAME in some_iterable]
где часть some_expression
может быть другим пониманием списка.
Под Vectorized OP подразумевается, что он не использует никаких явных циклов for и эффективно использует возможности вещания функций numpy. Кроме того, ваш метод кажется медленнее, чем тот, который был реализован OP на основе тестов.
Вот правильный vectorized
способ сделать это без каких-либо циклов.
5,5
, то эта матрица должна содержать наборы индексов для каждой из своих позиций и, следовательно, быть матрицей 5,5,2
. Таким образом, 0-я строка, 0-й столбец должны содержать (0,0)
, 4-я строка и 2-й столбец должны содержать (4,2)
и так далее.1001,1001,2
с помощью np.indices
, вы можете использовать его векторизованным способом в функциях numpy с 1001, 1001, 1
в каждой из двух частей.np.sin
в сумме двух частей.idx_sin_img = np.stack(np.indices((M,N)), axis=-1) #(1001,1001,2)
out = np.sin((2 * np.pi * u * idx_sin_img[...,0] / M) +
(2 * np.pi * v * idx_sin_img[...,1] / N))
out.shape
(1001, 1001)
Просто чтобы подтвердить, что он дает тот же результат -
np.all(sin_img == out) #sin_img is from OP's own code
#True
Ориентиры -
Пожалуйста, проверьте мой ответ для правильного векторизованного решения. Подход к пониманию списка кажется медленнее, чем то, что вы реализовали самостоятельно.