我一直在寻找一种紧凑的方法来创建一个矩阵,通过将相同的函数应用于不同大小的不同迭代的元素来计算。假设一个尺寸为 m = 3,一个尺寸为 n = 4
a = range(3)
b = range(4)
这只是最简单的示例,因为我可以自由地使用 numpy 向量来执行相同的操作。
我想用这种方式填充矩阵:
yawn = np.zeros((len(a), len(b)), dtype='float')
meh = lambda x, y: np.exp(x + y) / (1 + np.exp(x + y))
for i in a:
for j in b:
yawn[i,j] = meh(i,j)
预期结果确实是:
array([[ 0.5 , 0.73105858, 0.88079708, 0.95257413],
[ 0.73105858, 0.88079708, 0.95257413, 0.98201379],
[ 0.88079708, 0.95257413, 0.98201379, 0.99330715]])
我尝试使用类似 np.vectorize() 的内容或np.fromfunction()我已经很接近了:
meh_vec = np.vectorize(meh)
meh_vec(a, 3)
array([ 0.95257413, 0.98201379, 0.99330715])
但我可以弄清楚是否有办法做这样的事情:
meh_vec(a, b)
这不会导致 ValueError:
ValueError: operands could not be broadcast together with shapes (3,) (4,)
此外我读到:
The vectorize function is provided primarily for convenience, not for performance. The implementation is essentially a for loop.
是否有比 for 循环更紧凑、更快的解决方法?
最佳答案
将它们转换为可相互广播的开放
数组,以使用np.ix_
-
2D
数组
In [57]: x,y = np.ix_(a,b)
In [58]: np.exp(x + y) / (1 + np.exp(x + y))
Out[58]:
array([[0.5 , 0.73105858, 0.88079708, 0.95257413],
[0.73105858, 0.88079708, 0.95257413, 0.98201379],
[0.88079708, 0.95257413, 0.98201379, 0.99330715]])
或者,为了更明确地说明这一点,我们可以在输入的数组版本上使用 None/np.newaxis
手动扩展维度 -
In [64]: a = np.arange(3)
...: b = np.arange(4)
In [65]: np.exp(a[:,None] + b) / (1 + np.exp(a[:,None] + b))
Out[65]:
array([[0.5 , 0.73105858, 0.88079708, 0.95257413],
[0.73105858, 0.88079708, 0.95257413, 0.98201379],
[0.88079708, 0.95257413, 0.98201379, 0.99330715]])
为了进一步优化,我们可能需要存储 np.exp(a[:,None] + b)
并重新用于除法。另外,a[:,None] + b 可以重写为 np.add.outer(a,b) ,因为这基本上是外部添加。
关于python - 使用通过迭代计算的函数填充 numpy 矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52039411/