<class>属性,__iadd__(+=)和numpy.random.randn()的奇怪行为

2024-04-20 07:19:59 发布

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

我一直在用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(.)将解决此问题。有人知道这是怎么回事吗?你知道吗


Tags: 代码importselfnumpyaddobject过程example
2条回答

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总是返回相同的数组。因此,您在main部分中创建的列表是一个包含重复10次的相同对象的列表。你知道吗

解决这个问题的一种方法是使用np.random.randn()而不是np.random.randn(1)np.random.randn()返回一个标量,因此赋值self.x += np.random.randn(1)每次执行时都会创建一个新的self.x对象。你知道吗

通过引用返回数组self.x,因此有10个指向同一数组的指针。每次修改数组时,所有十个指针都指向相同的修改版本。你知道吗

如果每次都要返回数组的单独副本,可以在add_random函数中return self.x.copy()。你知道吗

另一种解决方法是用np.random.rand()替换np.random.rand(1),这样self.x将保持标量而不是向上转换为数组。你知道吗

相关问题 更多 >