2014-10-29 70 views
2

我有一个函数,它必须用f(x)来替换numpy数组X的每个元素x。如何修改一个numpy数组而不隐藏额外的内存分配?

def modify_inplace(X): 
    X = 2./(8. + numpy.exp(-X)) 

但是,这并不工作:

>>> X = numpy.random.random(size=(2,3)) 
>>> X 
array([[ 0.97476386, 0.76411101, 0.37690288], 
     [ 0.05462798, 0.44722799, 0.23570353]]) 
>>>> modify_inplace(X) 
>>> X 
array([[ 0.97476386, 0.76411101, 0.37690288], 
     [ 0.05462798, 0.44722799, 0.23570353]]) 

我知道,我可以简单地返回新的数组,但我不知道是否有可能修改numpy的阵列就地所以没有额外的内存将被分配?

Ashwini Chaudhary在下面提供了一个解决方案,但这不是我正在寻找的,因为我需要在没有任何其他malloc的情况下修改数组。

回答

6

A []真正的就地方法对于这种情况可能是:在@Ashwini乔杜里的做法

def modify_inplace(X): 
    np.exp(X, out=X) 
    X += 8. 
    np.power(X, -1, out=X) 
    X *= 2 

两个主要优点(这也是不错的):

  • 一个新的阵列并不需要分配
  • 没有数据要在操作后,复制

编辑:

需要注意的是更加复杂的表达式,其中X出现不止一次拷贝难以避免,例如:

(X + 2.)/(8. + np.exp(X)) 

这里当你改变X原地计算np.exp(X)它将不再有效计算其余的表达式...

+0

谢谢。在你使用两个X的第二个例子中,有什么可以成为避免内存分配的另一种解决方案? – psihodelia 2014-11-01 11:49:03

+0

@psihodelia在这种情况下,我只看到循环数组,计算表达式在一个临时变量中的答案,并替换旧的值...例如,可以在Cython中完成的例子 – 2014-11-01 23:54:52

3

目前你只需创建一个新的局部变量X,并给它分配一个新的值,来更新X指出函数使用切片分配内部对象:

>>> def modify_inplace(X): 
     X[:] = 2./(8. + numpy.exp(-X)) 
...  
>>> X = numpy.random.random(size=(2,3)) 
>>> X 
array([[ 0.21210661, 0.03573271, 0.07002263], 
     [ 0.77282535, 0.13973994, 0.82784145]]) 
>>> modify_inplace(X) 
>>> X 
array([[ 0.22704366, 0.22309233, 0.22390467], 
     [ 0.23635894, 0.22548971, 0.23705132]]) 
+0

谢谢。那么,在这种情况下,Numpy将不会分配任何额外的存储空间? – psihodelia 2014-10-29 14:08:18

+0

@psihodelia对于您的情况,首先将在内存中创建一个新数组,然后将原始数组的内容替换为该数组。之后,新的数组被垃圾收集,因为没有更多的引用。 – 2014-10-29 14:21:09

+1

但是这意味着这个数组不是就地修改的。虽然我的问题是如何避免内存分配和修改阵列 - 就像你会用C做的一样。 – psihodelia 2014-10-29 14:35:32