Numpy中如何高效将多个旋转矩阵与同一向量相乘?
Absolutely! You can ditch that slow loop by leveraging NumPy's broadcasting and matrix multiplication capabilities—this is exactly the kind of problem vectorization was made for. Let's walk through how to do it properly.
First, Align the Array Shapes
First, make sure your ray_rotation_matrices is a 3-dimensional NumPy array with shape (N, 4, 4), where N is the total number of rotation matrices. If it’s currently a list of 4x4 arrays, convert it with:
ray_rotation_matrices = np.array(ray_rotation_matrices)
Next, define your homogeneous vector in a shape that plays nicely with broadcasting. Your original vector is (4, 1)—we can keep it that way, or even use a 1D array (NumPy handles broadcasting automatically for matrix multiplication):
vec = np.array([scale, 0, 0, 1]).reshape(4, 1)
Perform Vectorized Matrix Multiplication
Use NumPy's @ operator (which does matrix multiplication, not element-wise product) to compute all transformations in one go:
# Batch matrix multiplication: (N,4,4) @ (4,1) → (N,4,1) scan_points_homogeneous = ray_rotation_matrices @ vec # Extract the first 3 elements and remove the extra dimension scan_points = scan_points_homogeneous[:, :3, 0]
Why This Works
- The
@operator understands batch broadcasting: when you multiply a(N,4,4)array with a(4,1)vector, NumPy automatically expands the vector to match the batch dimensionNunder the hood. It then runs matrix multiplication between each(4,4)matrix and the(4,1)vector in optimized C code. - This is drastically faster than a Python for loop, especially as the number of matrices
Ngrows large.
Quick Verification
To confirm this matches your original loop, test with a small example:
import numpy as np # Test setup scale = 2.0 N = 3 ray_rotation_matrices = [np.eye(4) + 0.1*np.random.randn(4,4) for _ in range(N)] ray_rotation_matrices = np.array(ray_rotation_matrices) # Vectorized approach vec = np.array([scale, 0, 0, 1]).reshape(4,1) scan_points_vectorized = (ray_rotation_matrices @ vec)[:, :3, 0] # Original loop approach scan_points_loop = np.zeros((N, 3)) for i, rm in enumerate(ray_rotation_matrices): scan_point = rm @ np.vstack([scale, 0, 0, 1]) scan_points_loop[i] = np.hstack(scan_point[:3]) # Check for equality (within floating-point error) print(np.allclose(scan_points_vectorized, scan_points_loop)) # Should print True
Key Reminders
- Never use
*for matrix multiplication—it performs element-wise product. Always use@ornp.matmul()for matrix operations. - If you use a 1D vector
(4,)instead of(4,1),ray_rotation_matrices @ vecwill return a(N,4)array, and you can just take[:, :3]directly to get your result.
内容的提问来源于stack exchange,提问作者El Dude

