填充任意形状的数组(最好不使用for循环)

2024-09-27 20:19:20 发布

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

考虑一个数A的浮点数,维数为n,形状为D=[d1,...,dn]di是非负整数)。如何填充A以具有例如:

A[j1,...,jn]=sqrt(j1*...*jn)

其中0<=ji<=di。如果我知道n并且它是固定的,那么我就可以嵌套nfor循环来简单地填充ndarray。然而,在我的程序中不是这样的,除了这将是无效的事实。我想知道有没有办法

  • 填充给定任意形状D的数组A(例如,使用上面的公式或任何其他索引的非基督函数)。你知道吗
  • 最好避免使用pythonfor loops,并利用NumPy的底层功能。你知道吗

提前谢谢你的帮助。你知道吗


Tags: 程序整数sqrt事实d1形状jnndarray
2条回答

需要意识到的一个重要事实是,您可以使用broadcasting to solve this problem efficiently。所以对于2D的情况你可以

d1, d2 = (3, 4)
A = numpy.sqrt(numpy.arange(d1)[:, None] * numpy.arange(d2)[None, :])
# array([[0.        , 0.        , 0.        , 0.        ],
#        [0.        , 1.        , 1.41421356, 1.73205081],
#        [0.        , 1.41421356, 2.        , 2.44948974]])

一旦您对使用广播来做这些外部产品(或总和,或比较等)感到满意,我们就可以尝试解决nD的情况。你知道吗

查看上面代码的输入数组,我们发现它们有形状

(d1,  1)
( 1, d2)

所以要在nD中实现这一点,我们需要找到一种方法,它采用线性索引数组,并自动创建形状数组

(d1,  1,  1, ...)
( 1, d2,  1, ...)
( 1,  1, d3, ...)

Numpy提供了这样一个函数:numpy.meshgrid(..., sparse=True)

numpy.meshgrid(numpy.arange(3), numpy.arange(4), sparse=True)

知道了这一点,我们就可以把它放在一行:

D = (3, 4, 5)
numpy.sqrt(numpy.prod(numpy.meshgrid(*[numpy.arange(d) for d in D], sparse=True, indexing='ij')))
# array([[[0.        , 0.        , 0.        , 0.        , 0.        ],
#         [0.        , 0.        , 0.        , 0.        , 0.        ],
#         [0.        , 0.        , 0.        , 0.        , 0.        ]],
# 
#        [[0.        , 0.        , 0.        , 0.        , 0.        ],
#         [0.        , 1.        , 1.41421356, 1.73205081, 2.        ],
#         [0.        , 1.41421356, 2.        , 2.44948974, 2.82842712]],
# 
#        [[0.        , 0.        , 0.        , 0.        , 0.        ],
#         [0.        , 1.41421356, 2.        , 2.44948974, 2.82842712],
#         [0.        , 2.        , 2.82842712, 3.46410162, 4.        ]],
# 
#        [[0.        , 0.        , 0.        , 0.        , 0.        ],
#         [0.        , 1.73205081, 2.44948974, 3.        , 3.46410162],
#         [0.        , 2.44948974, 3.46410162, 4.24264069, 4.89897949]]])

绩效评估

为了评估这三种解决方案的性能,让我们计算几个不同张量大小的速度:

D=(2,3,4,5)

%timeit np.fromfunction(function=myfunc2, shape=D)
# 501 µs ± 9.34 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit np.fromfunction(function=creation_function, shape=D)
# 24.2 µs ± 455 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit numpy.sqrt(numpy.prod(numpy.meshgrid(*[numpy.arange(d) for d in D], sparse=True, indexing='ij')))
# 30.9 µs ± 1.02 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

D=(20,30,40,50)

%timeit np.fromfunction(function=myfunc2, shape=D)
# 4.64 s ± 36.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit np.fromfunction(function=creation_function, shape=D)
# 36.7 ms ± 1.17 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit numpy.sqrt(numpy.prod(numpy.meshgrid(*[numpy.arange(d) for d in D], sparse=True, indexing='ij')))
# 9 ms ± 237 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

D=(200,30,40,50)

%timeit np.fromfunction(function=myfunc2, shape=D)
# never completed
%timeit np.fromfunction(function=creation_function, shape=D)
# 508 ms ± 7.41 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit numpy.sqrt(numpy.prod(numpy.meshgrid(*[numpy.arange(d) for d in D], sparse=True, indexing='ij')))
# 88.1 ms ± 1.63 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

D=(200,300,40,50)

%timeit np.fromfunction(function=myfunc2, shape=D)
# never completed
%timeit np.fromfunction(function=creation_function, shape=D)
# 5.8 s ± 565 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit numpy.sqrt(numpy.prod(numpy.meshgrid(*[numpy.arange(d) for d in D], sparse=True, indexing='ij')))
# 1.29 s ± 15.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

不使用labmda的ibarronds solution的修改版本,适用于3以上的更高维度:

import numpy as np
def myfunc(*J):
    return np.sqrt(np.prod(np.array(J)))
myfunc2=np.vectorize(myfunc)

D=(2,3,4,5)

np.fromfunction(function=myfunc2 , shape=D)

请注意。不幸的是,他删除了他的答案,所以我将其复制到这里以供参考:

creation_function = lambda *args: np.sqrt(np.prod(np.array([*args]), axis=0))
np.fromfunction(function=creation_function, shape=D)

相关问题 更多 >

    热门问题