NumPy - 故障向量化方法
NumPy - Trouble vectorizing method
我有三个数组,a
、b
和 c
。形状分别为(N, 2)
、(N, 3)
、(N, 3)
。
我需要比较 b
中每行的元素并更新 a
中同一行中的索引。我以为我已经了解如何矢量化此方法,但我认为我的尺寸不正确。
我目前拥有的是:
def to_cube(points):
cube = np.empty((len(points), 3), dtype=np.half)
delta = np.empty_like(cube)
q = ((2 / 3) * points[:, 0]) / 0.1
r = (((-1 / 3) * points[:, 0]) + ((np.sqrt(3) / 3) * points[:, 1])) / 0.1
cube[:, 0] = np.round(q)
cube[:, 1] = np.round(-q-r)
cube[:, 2] = np.round(r)
delta[:, 0] = np.abs(cube[:, 0] - q)
delta[:, 1] = np.abs(cube[:, 1] - (-q-r))
delta[:, 2] = np.abs(cube[:, 2] - r)
if delta[:, 0] > delta[:, 1] and delta[:, 1] > delta[:, 2]:
cube[:, 0] = -cube[:, 1] - cube[:, 2]
elif delta[:, 1] > delta[:, 2]:
cube[:, 1] = -cube[:, 0] - cube[:, 2]
else:
cube[:, 2] = -cube[:, 0] - cube[:, 1]
return cube
这会引发 ValueError: The truth value of an array with more than one element is ambiguous
。
查看条件后,很明显 delta[:, 0] > delta[:, 1]
的第一次检查将 return 形状为 (N, 1)
的数组。我如何更改它以针对 a
中的每一行,获取该行上的适当索引,然后根据条件更新 b
中的同一行以获得特定索引?
编辑:样本
此示例假定 q
和 r
已完成。这些矩阵表示 cube
和 delta
:
>>> cube
array([[275.0, -400.0, 124.0]], dtype=float16) # so this is a (1, 3) but could be (N, 3)
>>> cube[0]
array([275.0, -400.0, 124.0], dtype=float16)
>>> delta
array([[5., 10., 3.]], dtype=float16)
>>> delta[0]
array([5., 10., 3.], dtype=float16)
现在通过条件执行(值被子):
if 5.0 > 10.0 and 10.0 > 3.0:
cube[0] = -(-400.0) - 124.0
elif 10.0 > 3.0:
cube[1] = -(275.0) - 124.0
else:
cube[2] = -(275.0) - (-400.0)
return cube # array([275.0, -(275.0) - 124.0, 124.0], dtype=float16)
这显示了每行发生的情况,现在我需要对所有行执行此操作。
编辑:潜在解决方案(是否矢量化?)
有一种方法可以确保使用 for-range
:
独立访问行
def to_cube(points):
cube = np.empty((len(points), 3), dtype=np.half)
delta = np.empty_like(cube)
q = ((2 / 3) * points[:, 0]) / 0.1
r = (((-1 / 3) * points[:, 0]) + ((np.sqrt(3) / 3) * points[:, 1])) / 0.1
cube[:, 0] = np.round(q)
cube[:, 1] = np.round(-q-r)
cube[:, 2] = np.round(r)
delta[:, 0] = np.abs(cube[:, 0] - q)
delta[:, 1] = np.abs(cube[:, 1] - (-q-r))
delta[:, 2] = np.abs(cube[:, 2] - r)
for i in range(len(cube)):
if delta[i, 0] > delta[i, 1] and delta[i, 1] > delta[i, 2]:
cube[i, 0] = -cube[i, 1] - cube[i, 2]
elif delta[i, 1] > delta[i, 2]:
cube[i, 1] = -cube[i, 0] - cube[i, 2]
else:
cube[i, 2] = -cube[i, 0] - cube[i, 1]
return cube
但是,我现在"looping over"数组,似乎没有矢量化或广播。
任何感兴趣的人,这就是我解决问题的方法:
def to_cube(points):
cube = np.empty((len(points), 3), dtype=np.half)
delta = np.empty_like(cube)
q = ((2 / 3) * points[:, 0]) / 0.1
r = (((-1 / 3) * points[:, 0]) + ((np.sqrt(3) / 3) * points[:, 1])) / 0.1
cube[:, 0] = np.round(q)
cube[:, 1] = np.round(-q-r)
cube[:, 2] = np.round(r)
delta[:, 0] = np.abs(cube[:, 0] - q)
delta[:, 1] = np.abs(cube[:, 1] - (-q-r))
delta[:, 2] = np.abs(cube[:, 2] - r)
# define boolean arrays for where conditions exist
rxc = ((delta[:, 0] > delta[:, 1]) & (delta[:, 1] > delta[:, 2]))
ryc = (delta[:, 1] > delta[:, 2])
rzc = ~(rxc + ryc)
# update just those indices by condition
cube[rxc, 0] = -cube[rxc, 1] - cube[rxc, 2]
cube[ryc, 1] = -cube[ryc, 0] - cube[ryc, 2]
cube[rzc, 2] = -cube[rzc, 0] - cube[rzc, 1]
return cube
如果有人看到改进优化的空间,我很想知道!
我系统上的基准测试:
import numpy as np
from timeit import timeit
u = np.random.uniform
points = np.array([[u(0, 50), u(0, 50)] for _ in range(37000000)], dtype=np.half)
p = 'from __main__ import points, to_cube; to_cube(points)'
timeit(p, number=1)
# output: 17.94858811999
我有三个数组,a
、b
和 c
。形状分别为(N, 2)
、(N, 3)
、(N, 3)
。
我需要比较 b
中每行的元素并更新 a
中同一行中的索引。我以为我已经了解如何矢量化此方法,但我认为我的尺寸不正确。
我目前拥有的是:
def to_cube(points):
cube = np.empty((len(points), 3), dtype=np.half)
delta = np.empty_like(cube)
q = ((2 / 3) * points[:, 0]) / 0.1
r = (((-1 / 3) * points[:, 0]) + ((np.sqrt(3) / 3) * points[:, 1])) / 0.1
cube[:, 0] = np.round(q)
cube[:, 1] = np.round(-q-r)
cube[:, 2] = np.round(r)
delta[:, 0] = np.abs(cube[:, 0] - q)
delta[:, 1] = np.abs(cube[:, 1] - (-q-r))
delta[:, 2] = np.abs(cube[:, 2] - r)
if delta[:, 0] > delta[:, 1] and delta[:, 1] > delta[:, 2]:
cube[:, 0] = -cube[:, 1] - cube[:, 2]
elif delta[:, 1] > delta[:, 2]:
cube[:, 1] = -cube[:, 0] - cube[:, 2]
else:
cube[:, 2] = -cube[:, 0] - cube[:, 1]
return cube
这会引发 ValueError: The truth value of an array with more than one element is ambiguous
。
查看条件后,很明显 delta[:, 0] > delta[:, 1]
的第一次检查将 return 形状为 (N, 1)
的数组。我如何更改它以针对 a
中的每一行,获取该行上的适当索引,然后根据条件更新 b
中的同一行以获得特定索引?
编辑:样本
此示例假定 q
和 r
已完成。这些矩阵表示 cube
和 delta
:
>>> cube
array([[275.0, -400.0, 124.0]], dtype=float16) # so this is a (1, 3) but could be (N, 3)
>>> cube[0]
array([275.0, -400.0, 124.0], dtype=float16)
>>> delta
array([[5., 10., 3.]], dtype=float16)
>>> delta[0]
array([5., 10., 3.], dtype=float16)
现在通过条件执行(值被子):
if 5.0 > 10.0 and 10.0 > 3.0:
cube[0] = -(-400.0) - 124.0
elif 10.0 > 3.0:
cube[1] = -(275.0) - 124.0
else:
cube[2] = -(275.0) - (-400.0)
return cube # array([275.0, -(275.0) - 124.0, 124.0], dtype=float16)
这显示了每行发生的情况,现在我需要对所有行执行此操作。
编辑:潜在解决方案(是否矢量化?)
有一种方法可以确保使用 for-range
:
def to_cube(points):
cube = np.empty((len(points), 3), dtype=np.half)
delta = np.empty_like(cube)
q = ((2 / 3) * points[:, 0]) / 0.1
r = (((-1 / 3) * points[:, 0]) + ((np.sqrt(3) / 3) * points[:, 1])) / 0.1
cube[:, 0] = np.round(q)
cube[:, 1] = np.round(-q-r)
cube[:, 2] = np.round(r)
delta[:, 0] = np.abs(cube[:, 0] - q)
delta[:, 1] = np.abs(cube[:, 1] - (-q-r))
delta[:, 2] = np.abs(cube[:, 2] - r)
for i in range(len(cube)):
if delta[i, 0] > delta[i, 1] and delta[i, 1] > delta[i, 2]:
cube[i, 0] = -cube[i, 1] - cube[i, 2]
elif delta[i, 1] > delta[i, 2]:
cube[i, 1] = -cube[i, 0] - cube[i, 2]
else:
cube[i, 2] = -cube[i, 0] - cube[i, 1]
return cube
但是,我现在"looping over"数组,似乎没有矢量化或广播。
任何感兴趣的人,这就是我解决问题的方法:
def to_cube(points):
cube = np.empty((len(points), 3), dtype=np.half)
delta = np.empty_like(cube)
q = ((2 / 3) * points[:, 0]) / 0.1
r = (((-1 / 3) * points[:, 0]) + ((np.sqrt(3) / 3) * points[:, 1])) / 0.1
cube[:, 0] = np.round(q)
cube[:, 1] = np.round(-q-r)
cube[:, 2] = np.round(r)
delta[:, 0] = np.abs(cube[:, 0] - q)
delta[:, 1] = np.abs(cube[:, 1] - (-q-r))
delta[:, 2] = np.abs(cube[:, 2] - r)
# define boolean arrays for where conditions exist
rxc = ((delta[:, 0] > delta[:, 1]) & (delta[:, 1] > delta[:, 2]))
ryc = (delta[:, 1] > delta[:, 2])
rzc = ~(rxc + ryc)
# update just those indices by condition
cube[rxc, 0] = -cube[rxc, 1] - cube[rxc, 2]
cube[ryc, 1] = -cube[ryc, 0] - cube[ryc, 2]
cube[rzc, 2] = -cube[rzc, 0] - cube[rzc, 1]
return cube
如果有人看到改进优化的空间,我很想知道!
我系统上的基准测试:
import numpy as np
from timeit import timeit
u = np.random.uniform
points = np.array([[u(0, 50), u(0, 50)] for _ in range(37000000)], dtype=np.half)
p = 'from __main__ import points, to_cube; to_cube(points)'
timeit(p, number=1)
# output: 17.94858811999