我一直使用Python和Numpy为随机过程建模,并使用以下代码见证奇怪的行为:
import numpy as np
class Example( object ):
def __init__( self ):
self.x = 0
def add_random( self ):
self.x += np.random.randn(1)
return self.x
if __name__ == '__main__':
example = Example()
state = []
for x in range(10):
state.append( example.add_random() )
print state
这将返回10个相同随机数的数组,而不是预期的10个不同的随机数。取消object.__iadd__
运算符和/或用常量替换np.random.randn(.)
将解决问题。任何人都知道这是什么根源?
答案 0 :(得分:4)
np.random.randn(1)
返回一个包含单个元素的数组:
In [27]: np.random.randn(1)
Out[27]: array([-1.90409169])
第一次执行此行
self.x += np.random.randn(1)
self.x
- 最初是一个Python整数 - 被一个numpy数组取代。该行的后续执行会修改x
就地,因为这是numpy数组如何实现就地添加。因此return self.x
始终返回相同的数组。因此,您在主要部分中创建的列表是包含重复10次的同一对象的列表。
解决此问题的一种方法是使用np.random.randn()
代替np.random.randn(1)
。 np.random.randn()
返回一个标量,因此赋值self.x += np.random.randn(1)
每次执行时都会创建一个新的self.x
对象。
答案 1 :(得分:2)
您将通过引用返回数组self.x
,因此您有10个指向同一数组的指针。每次修改数组时,所有十个指针都指向相同的修改版本。
如果您希望每次都返回数组的单独副本,则return self.x.copy()
函数中可以add_random
。
另一种解决方法是将np.random.rand(1)
替换为np.random.rand()
,以便self.x
保持标量而不是向上转换为数组。