我有一個由 N 個點組成的 Nx3 陣列,每個點都有 X、Y 和 Z 坐標。我需要旋轉每個點,所以我有 3x3 的旋轉矩陣。為此,我需要獲取旋轉矩陣和每個點的點積。問題是點陣列非常龐大(~1_000_000x3),因此計算旋轉點需要大量時間。
到目前為止,我提出的唯一解決方案是簡單的回圈迭代點陣列。這是帶有一段資料的示例:
# Given set of points Nx3: np.ndarray
points = np.array([
[285.679, 219.75, 524.733],
[285.924, 219.404, 524.812],
[285.116, 219.217, 524.813],
[285.839, 219.557, 524.842],
[285.173, 219.507, 524.606]
])
points_t = points.T
# Array to store results
points_rotated = np.empty((points_t.shape))
# Given rotation matrix 3x3: np.ndarray
rot_matrix = np.array([
[0.57423549, 0.81862056, -0.01067613],
[-0.81866133, 0.57405696, -0.01588193],
[-0.00687256, 0.0178601, 0.99981688]
])
for i in range(points.shape[0]):
points_rotated[:, i] = np.dot(rot_matrix, points_t[:, i])
# Result
points_rotated.T
# [[ 338.33677093 -116.05910163 526.59831864]
# [ 338.1933725 -116.45955203 526.6694408 ]
# [ 337.5762975 -115.90543822 526.67265381]
# [ 338.26949115 -116.30261156 526.70275207]
# [ 337.84863885 -115.78233784 526.47047941]]
我對使用 numpy 沒有信心,因為我對它很陌生,所以我相信至少有更優雅的方法可以做。我聽說過np.einsum()但我還不明白如何在這里實作它,我不確定它會更快。主要問題仍然是計算時間,所以我現在想知道如何讓它更快地作業?
非常感謝您!
uj5u.com熱心網友回復:
您可以在非 python 模式下使用 numba 并行化撰寫代碼:
@nb.njit("float64[:, ::1](float64[:, ::1], float64[:, ::1])", parallel=True)
def dot(a, b): # dot(points, rot_matrix)
dot_ = np.zeros((a.shape[0], b.shape[0]))
for i in nb.prange(a.shape[0]):
for j in range(b.shape[0]):
dot_[i, j] = a[i, 0] * b[j, 0] a[i, 1] * b[j, 1] a[i, 2] * b[j, 2]
return dot_
由于并行化和簽名以及使用代數,它必須比ko3答案np.dot更好。我已經測驗了類似的代碼(僅應用于陣列的上三角形),而不是在另一個答案中的點積,這表明至少快了 2 倍(據我所知)。
uj5u.com熱心網友回復:
如果迭代次數很大,可以試試 numba 的njit方法:
from numba import njit
points = np.array([
[285.679, 219.75, 524.733],
[285.924, 219.404, 524.812],
[285.116, 219.217, 524.813],
[285.839, 219.557, 524.842],
[285.173, 219.507, 524.606]
])
rot_matrix = np.array([
[0.57423549, 0.81862056, -0.01067613],
[-0.81866133, 0.57405696, -0.01588193],
[-0.00687256, 0.0178601, 0.99981688]
])
@njit
def compute(points, rot_matrix):
points_t = points.T
points_rotated = np.empty((points_t.shape))
for i in range(points.shape[0]):
points_rotated[:, i] = np.dot(rot_matrix, points_t[:, i])
return points_rotated.T
compute(points, rot_matrix)
它專為大型迭代而設計,應該會大大加快操作速度。查看檔案了解更多資訊。
uj5u.com熱心網友回復:
我嘗試了一些代碼來查看每個解決方案(基于我的系統)在 1,000,000 x 3 矩陣上的性能。
- 使用
np.matmul - 將 numba njit 與點積 (@) 一起使用
- 在您的代碼中使用 numba njit
這是三個函式的結果。
points = np.random.rand(1000000,3)
rot_matrix = np.array([
[0.57423549, 0.81862056, -0.01067613],
[-0.81866133, 0.57405696, -0.01588193],
[-0.00687256, 0.0178601, 0.99981688]
# Using np.matmul
def function_matmul(points, rot_matrix):
return np.matmul(rot_matrix @ points.T).T
# Using numba njit with dot product(@)
@njit
def function_numba_dot(points, rot_matrix):
return (rot_matrix, points.T).T
# Using numba njit with your code
@njit
def function_ori_code(points, rot_matrix):
points_t = points.T
points_rotated = np.empty((points_t.shape))
for i in range(points.shape[0]):
points_rotated[:, i] = np.dot(rot_matrix, points_t[:, i])
return points_rotated.T
%timeit function_matmul(points, rot_matrix)
16.5 ms ± 665 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit function_numba_dot(points, rot_matrix)
16.3 ms ± 69.4 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit function_ori_code(points, rot_matrix)
260 ms ± 4.37 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/488934.html
標籤:Python 数组 麻木的 迭代 numpy-ndarray
