在寻找和理解pythonic方法以优化嵌套的for循环中的以下数组操作时,我将不胜感激:
def _func(a, b, radius):
"Return 0 if a>b, otherwise return 1"
if distance.euclidean(a, b) < radius:
return 1
else:
return 0
def _make_mask(volume, roi, radius):
mask = numpy.zeros(volume.shape)
for x in range(volume.shape[0]):
for y in range(volume.shape[1]):
for z in range(volume.shape[2]):
mask[x, y, z] = _func((x, y, z), roi, radius)
return mask
其中volume.shape
(182、218、200)和roi.shape
(3)都是ndarray
类型;并且radius
是int
方法1
这是向量化方法-
m,n,r = volume.shape
x,y,z = np.mgrid[0:m,0:n,0:r]
X = x - roi[0]
Y = y - roi[1]
Z = z - roi[2]
mask = X**2 + Y**2 + Z**2 < radius**2
可能的改进:我们可以通过numexpr
模块加快最后一步的速度-
import numexpr as ne
mask = ne.evaluate('X**2 + Y**2 + Z**2 < radius**2')
方法#2
我们还可以逐步构建与形状参数相对应的三个范围,并在运行中对三个元素进行减法运算,roi
而无需像之前使用那样实际创建网格np.mgrid
。通过broadcasting
出于效率目的使用会受益。实现看起来像这样-
m,n,r = volume.shape
vals = ((np.arange(m)-roi[0])**2)[:,None,None] + \
((np.arange(n)-roi[1])**2)[:,None] + ((np.arange(r)-roi[2])**2)
mask = vals < radius**2
简化版:感谢@Bi Rico在这里提出改进建议,因为我们可以使用它np.ogrid
以更简洁的方式执行这些操作,例如-
m,n,r = volume.shape
x,y,z = np.ogrid[0:m,0:n,0:r]-roi
mask = (x**2+y**2+z**2) < radius**2
运行时测试
功能定义-
def vectorized_app1(volume, roi, radius):
m,n,r = volume.shape
x,y,z = np.mgrid[0:m,0:n,0:r]
X = x - roi[0]
Y = y - roi[1]
Z = z - roi[2]
return X**2 + Y**2 + Z**2 < radius**2
def vectorized_app1_improved(volume, roi, radius):
m,n,r = volume.shape
x,y,z = np.mgrid[0:m,0:n,0:r]
X = x - roi[0]
Y = y - roi[1]
Z = z - roi[2]
return ne.evaluate('X**2 + Y**2 + Z**2 < radius**2')
def vectorized_app2(volume, roi, radius):
m,n,r = volume.shape
vals = ((np.arange(m)-roi[0])**2)[:,None,None] + \
((np.arange(n)-roi[1])**2)[:,None] + ((np.arange(r)-roi[2])**2)
return vals < radius**2
def vectorized_app2_simplified(volume, roi, radius):
m,n,r = volume.shape
x,y,z = np.ogrid[0:m,0:n,0:r]-roi
return (x**2+y**2+z**2) < radius**2
时间-
In [106]: # Setup input arrays
...: volume = np.random.rand(90,110,100) # Half of original input sizes
...: roi = np.random.rand(3)
...: radius = 3.4
...:
In [107]: %timeit _make_mask(volume, roi, radius)
1 loops, best of 3: 41.4 s per loop
In [108]: %timeit vectorized_app1(volume, roi, radius)
10 loops, best of 3: 62.3 ms per loop
In [109]: %timeit vectorized_app1_improved(volume, roi, radius)
10 loops, best of 3: 47 ms per loop
In [110]: %timeit vectorized_app2(volume, roi, radius)
100 loops, best of 3: 4.26 ms per loop
In [139]: %timeit vectorized_app2_simplified(volume, roi, radius)
100 loops, best of 3: 4.36 ms per loop
因此,一如既往地broadcasting
显示出疯狂地 10,000x
加快原始代码速度的魔力,并且比 10x
使用即时广播的操作创建网格要好得多!
Python 不仅支持 if 语句相互嵌套,while 和 for 循环结构也支持嵌套。所谓嵌套(Nest),就是一条语句里面还有另一条语句,例如 for 里面还有 for,while 里面还有 while,甚至 while 中有 for 或者 for 中有 while 也都是允许的。 当 2 个(甚至多个)循环结构相互嵌套时,位于外层的循环结构常简称为 外层循环或 外循环,位于内层的循环结构常简
问题内容: 我经常发现自己正在这样做: 在Python中有更简洁的方法吗?我在想一些类似的东西 问题答案: 您可以使用itertools.product:
问题内容: 因此,我正在研究UVA问题,并且我有4个嵌套循环来遍历多边形列表(每个多边形都包含一个点列表,其中每个点都包含一个整数x和y来表示其坐标,即,polygon [0]是一个点,其坐标为面[0] .x和面[0] .y)。 我试图减少程序中for循环的数量,以使其更高效并降低运行时间。我的代码如下: 我尝试通过使用itertools.product使其变得更加高效,如下所示: 无论如何,我的
我是Java的新手,我想使用循环来产生阶梯效果,但在每一行中添加越来越多的空格。这是我的密码- 最终的目标是让它打印以下内容: 但我的照片是这样的: 对不起,我知道这是初学者的东西,但我不知道还能去哪里。感谢任何帮助。多谢了。
这里是Uni learning Python编程入门课程的初学者。直到我明白了大部分,现在我很困惑。 有人能解释为什么这会产生它输出的模式吗? 外循环触发器和() 然后内部循环触发器和() 然后它不会打印(6),因为
本文向大家介绍clojure 解构嵌套向量,包括了clojure 解构嵌套向量的使用技巧和注意事项,需要的朋友参考一下 示例 您可以解构嵌套向量: