基于newaxis的for循环Python时间优化

2024-09-30 03:23:22 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要计算沿一条定义的直线(3D)等间距的n个点(3D)。 我知道这条线的起点和终点。首先,我用过

for k in range(nbin):
  step = k/float(nbin-1)
  bin_point.append(beam_entry+(step*(beamlet_intersection-beam_entry)))

然后,我发现对大数组使用append需要更多的时间,然后我修改了如下代码:

^{pr2}$

我得到一个建议,使用newaxis将进一步提高时间。 修改后的代码如下所示。

step      = arange(nbin) / float(nbin-1)
bin_point = start_point + ( step[:,newaxis,newaxis]*((end_pint - start_point))[newaxis,:,:] )  

但是,我不能理解newaxis函数,我也有一个疑问,如果改变起点和终点的结构或形状,同样的代码是否可以工作。类似地,axis如何使用下面的代码

 for j in range(32):      # for all los
   line_dist[j] = sqrt([sum(l) for l in (end_point[j]-start_point[j])**2])

抱歉这么笨重,要更清楚的结构的起点和终点都是

array([ [[1,1,1],[],[],[]....[]], 
        [[],[],[],[]....[]],
        [[],[],[],[]....[]]......,
        [[],[],[],[]....[]] ])

Tags: 代码inforbinsteprangefloatstart
3条回答

我没有完全理解你写的所有东西,但有些事情我已经可以告诉你了,也许它们会有所帮助。在

newaxis是一个标记而不是一个函数(事实上,它是普通的None)。它用于将(未使用的)维度添加到多维值。有了它,你可以从二维值(甚至更多)中生成三维值。输入值中已经存在的每个维度都必须用索引中的冒号:来表示(假设您想要使用所有值,否则它会比我们的用例复杂),要添加的维度用newaxis表示。在

示例:
输入为一维向量(1D):1,2,3
输出应为矩阵(2D)。
有两种方法可以实现这一点:向量可以用一个值填充每一行,或者向量可以只填充矩阵的第一行也是唯一一行。第一个由vector[:,newaxis]创建,第二个由vector[newaxis,:]创建。结果如下:

>>> array([ 7,8,9 ])[:,newaxis]
array([[7],
       [8],
       [9]])
>>> array([ 7,8,9 ])[newaxis,:]
array([[7, 8, 9]])

(多维值的维数当然是通过数组的嵌套来表示的。)

如果输入中有更多维度,请多次使用冒号(否则会忽略深层嵌套维度,即数组被视为简单值)。我不会在这里粘贴一个表示,因为当3D和4D值用嵌套括号写在2D显示器上时,由于光学复杂性,它不会澄清一些事情。我希望一切都能明朗起来。在

newaxis以这样一种方式重塑数组,以便在乘法时numpy使用广播。Here is a good tutorial on broadcasting。在

step[:, newaxis, newaxis]与{}相同(如果step是1d)。任何一种重塑数组的方法都应该非常快,因为在numpy中重塑数组是非常低俗的,它只是一个数组的视图,特别是因为你应该只做一次。在

对问题中newaxis版本的解释:这些是不是矩阵乘法,ndarray multiply是用broadcasting逐元素相乘。步进[:,newaxis,newaxis]是num_步数x 1 x 1,point[newaxis,:,:]是1 x num_points x num_维度。与shape(num_steps x 1 x 1)和(1 x num_points x num_dimensions)一起广播可以工作,因为广播规则是每个维度都应该是1或相同的;这只是意味着“将维度为1的数组重复与另一个数组对应维度相同的次数”。这将以非常有效的方式生成具有形状(num_steps x num_points x num_dimensions)的ndarray;i,j,k下标将是第i步沿着第j条线的第k个坐标(由第j对起点和终点给出)。在

演练:

>>> start_points = numpy.array([[1, 0, 0], [0, 1, 0]])
>>> end_points = numpy.array([[10, 0, 0], [0, 10, 0]])
>>> steps = numpy.arange(10)/9.0
>>> start_points.shape
(2, 3)
>>> steps.shape
(10,)
>>> steps[:,numpy.newaxis,numpy.newaxis].shape
(10, 1, 1)
>>> (steps[:,numpy.newaxis,numpy.newaxis] * start_points).shape
(10, 2, 3)
>>> (steps[:,numpy.newaxis,numpy.newaxis] * (end_points - start_points)) + start_points
array([[[  1.,   0.,   0.],
        [  0.,   1.,   0.]],
       [[  2.,   0.,   0.],
        [  0.,   2.,   0.]],
       [[  3.,   0.,   0.],
        [  0.,   3.,   0.]],
       [[  4.,   0.,   0.],
        [  0.,   4.,   0.]],
       [[  5.,   0.,   0.],
        [  0.,   5.,   0.]],
       [[  6.,   0.,   0.],
        [  0.,   6.,   0.]],
       [[  7.,   0.,   0.],
        [  0.,   7.,   0.]],
       [[  8.,   0.,   0.],
        [  0.,   8.,   0.]],
       [[  9.,   0.,   0.],
        [  0.,   9.,   0.]],
       [[ 10.,   0.,   0.],
        [  0.,  10.,   0.]]])

如您所见,这将产生正确的答案:)在本例中,广播(10,1,1)和(2,3)结果为(10,2,3)。你所拥有的是广播(10,1,1)和(1,2,3),两者完全相同,也产生(10,2,3)。在

问题的距离部分的代码不需要newaxis:输入的是num_points x num_维度,输出是num_points,因此必须删除一个维度。这实际上是你沿着的轴求和。这应该是有效的:

^{pr2}$

这里数字总和(…,axis=1)表示仅沿该轴求和,而不是所有元素:shape num_points x num_dimensions沿axis=1求和的ndarray将生成具有num_points的结果,这是正确的。在

编辑:删除了没有广播的代码示例。 编辑:修正了索引的顺序。 编辑:添加行距离

相关问题 更多 >

    热门问题