繁体   English   中英

具有类属性__iadd__(+ =)和numpy.random.randn()的奇怪行为

[英]Weird behavior with class attribute, __iadd__ (+=) and numpy.random.randn()

我一直在用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(.)替换np.random.randn(.)将解决此问题。 有人知道这是什么根源吗?

np.random.randn(1)返回一个包含单个元素的数组:

In [27]: np.random.randn(1)
Out[27]: array([-1.90409169])

第一次执行此行

self.x += np.random.randn(1)

self.x --initially一个Python整数-由numpy的阵列代替。 随后执行该行会修改x in-place ,因为这是numpy数组实现就地加法的方式。 因此, return self.x总是返回相同的数组。 因此,您在主要部分中创建的列表是一个包含重复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(1)替换为np.random.rand()以便self.x将保持标量而不是向上转换为数组。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM