- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我希望能够在 Python 的标准 Random 和 numpy 的 np.random.RandomState 之间来回转换。这两个都使用 Mersenne Twister 算法,因此应该是可能的(除非他们使用该算法的不同版本)。
我开始研究这些对象的 getstate/setstate 和 get_state/set_state 方法。但我不确定如何转换它们的细节。
import numpy as np
import random
rng1 = np.random.RandomState(seed=0)
rng2 = random.Random(seed=0)
state1 = rng1.get_state()
state2 = rng2.getstate()
检查我看到的每个状态:
>>> print(state1)
('MT19937', array([0, 1, 1812433255, ..., 1796872496], dtype=uint32), 624, 0, 0.0)
>>> print(state2)
(3, (2147483648, 766982754, ..., 1057334138, 2902720905, 624), None)
第一个状态是大小为 5 的元组,len(state1[1]) = 624
。
第二个状态是一个大小为 3 的元组,len(state2[1]) = 625
。看起来 state2 中的最后一项实际上是 state1 中的 624,这意味着数组实际上是相同的大小。到目前为止,一切都很好。这些似乎相当兼容。
不幸的是,内部数字没有明显的对应关系,因此 0 的种子会导致不同的状态,这是有道理的,因为 rng1.rand() = .548
和 rng2。随机()=.844
。因此,该算法似乎略有不同。
但是,我不需要它们完美对应。 我只需要能够确定性地设置一个 rng 的状态而不影响第一个 rng 的状态。
理想情况下,一旦我使用第一个状态设置第二个状态,而不调用任何随机方法,然后使用第二个设置第一个状态,第一个状态将保持不变,但这是不是必需的。
目前我有一个 hacked together 方法,它只是交换我可以从两个 rngs 中提取的 624 长度列表。但是,我不确定这种方法是否有任何问题。任何人都可以对此主题有更多了解吗?
这是我的方法,但我不确定它是否能正常工作。
np_rng = np.random.RandomState(seed=0)
py_rng = random.Random(0)
# Convert python to numpy random state (incomplete)
py_state = py_rng.getstate()
np_rng = np.random.RandomState(seed=0)
np_state = np_rng.get_state()
new_np_state = (
np_state[0],
np.array(py_state[1][0:-1], dtype=np.uint32),
np_state[2], np_state[3], np_state[4])
np_rng.set_state(new_np_state)
# Convert numpy to python random state (incomplete)
np_state = np_rng.get_state()
py_rng = random.Random(0)
py_state = py_rng.getstate()
new_py_state = (
py_state[0], tuple(np_state[1].tolist() + [len(np_state[1])]),
py_state[1]
)
py_rng.setstate(new_py_state)
编辑:
做一些调查,我检查了 10 次调用随机函数时状态发生了什么。
np_rng = np.random.RandomState(seed=0)
py_rng = random.Random(0)
for i in range(10):
np_rng.rand()
npstate = np_rng.get_state()
print([npstate[0], npstate[1][[0, 1, 2, -2, -1]], npstate[2], npstate[3], npstate[4]])
for i in range(10):
py_rng.random()
pystate = py_rng.getstate()
print([pystate[0], pystate[1][0:3] + pystate[1][-2:], pystate[2]])
['MT19937', array([2443250962, 1093594115, 1878467924, 2648828502, 1678096082], dtype=uint32), 2, 0, 0.0]
['MT19937', array([2443250962, 1093594115, 1878467924, 2648828502, 1678096082], dtype=uint32), 4, 0, 0.0]
['MT19937', array([2443250962, 1093594115, 1878467924, 2648828502, 1678096082], dtype=uint32), 6, 0, 0.0]
['MT19937', array([2443250962, 1093594115, 1878467924, 2648828502, 1678096082], dtype=uint32), 8, 0, 0.0]
['MT19937', array([2443250962, 1093594115, 1878467924, 2648828502, 1678096082], dtype=uint32), 10, 0, 0.0]
['MT19937', array([2443250962, 1093594115, 1878467924, 2648828502, 1678096082], dtype=uint32), 12, 0, 0.0]
['MT19937', array([2443250962, 1093594115, 1878467924, 2648828502, 1678096082], dtype=uint32), 14, 0, 0.0]
['MT19937', array([2443250962, 1093594115, 1878467924, 2648828502, 1678096082], dtype=uint32), 16, 0, 0.0]
['MT19937', array([2443250962, 1093594115, 1878467924, 2648828502, 1678096082], dtype=uint32), 18, 0, 0.0]
['MT19937', array([2443250962, 1093594115, 1878467924, 2648828502, 1678096082], dtype=uint32), 20, 0, 0.0]
[3, (1372342863, 3221959423, 4180954279, 418789356, 2), None]
[3, (1372342863, 3221959423, 4180954279, 418789356, 4), None]
[3, (1372342863, 3221959423, 4180954279, 418789356, 6), None]
[3, (1372342863, 3221959423, 4180954279, 418789356, 8), None]
[3, (1372342863, 3221959423, 4180954279, 418789356, 10), None]
[3, (1372342863, 3221959423, 4180954279, 418789356, 12), None]
[3, (1372342863, 3221959423, 4180954279, 418789356, 14), None]
[3, (1372342863, 3221959423, 4180954279, 418789356, 16), None]
[3, (1372342863, 3221959423, 4180954279, 418789356, 18), None]
[3, (1372342863, 3221959423, 4180954279, 418789356, 20), None]
我希望每个元组中的第一项只是他们正在使用的算法的版本。
有趣的是,624 个整数似乎没有变化。总是这样吗?
但是,我仍然不确定最后的 None 在 Python 版本中是什么意思,最后的 2 数字在 numpy 版本中是什么意思。
最佳答案
NumPy RandomState
状态的形式是 documented :
Returns: out : tuple(str, ndarray of 624 uints, int, int, float)
The returned tuple has the following items:
- the string ‘MT19937’.
- a 1-D array of 624 unsigned integer keys.
- an integer pos.
- an integer has_gauss.
- a float cached_gaussian.
最后两个条目指的是标准正态偏差生成器的状态:NumPy uses Box–Muller transform ,它会成对产生这些偏差。所以第一次调用高斯生成器会产生两个值,返回第一个,然后将第二个存储起来以备后用。然后第二个调用检索第二个值。因此,我们在这里有额外的状态需要存储和检索。
Python Random
状态的形式没有记录,但很容易从 source 中提取出来。 .从 CPython 3.6.1 开始,它看起来像这样:
def getstate(self):
"""Return internal state; can be passed to setstate() later."""
return self.VERSION, super().getstate(), self.gauss_next
同样,Python 会成对生成法线偏差,如果没有存储额外的法线偏差,则 self.gauss_next
为 None
,如果有,则为存储的偏差值可用。
要找出 super().getstate()
返回的内容,您需要深入研究 C source :它是一个长度为 625 的元组,包含构成 Mersenne Twister 状态的 624 个单词,以及该单词集合中的当前位置。因此,该元组中的最后一个条目对应于 NumPy 状态索引 2 处的值 pos
。
下面是一个从 Python 状态转换为 NumPy 状态的例子,忽略高斯信息的细节:
Python 3.6.1 (default, May 23 2017, 18:09:41)
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> import random
>>> np_rng = np.random.RandomState(seed=0)
>>> py_rng = random.Random(0)
>>> version, (*mt_state, pos), gauss_next = py_rng.getstate()
>>> np_rng.set_state(('MT19937', mt_state, pos))
从 Python Random
状态设置 NumPy RandomState
状态后,我们看到两个 RNG 生成的 float 重合:
>>> py_rng.random(), np_rng.uniform()
(0.8444218515250481, 0.8444218515250481)
>>> py_rng.random(), np_rng.uniform()
(0.7579544029403025, 0.7579544029403025)
>>> py_rng.random(), np_rng.uniform()
(0.420571580830845, 0.420571580830845)
这是反向转换:
>>> _, words, pos, _, _ = np_rng.get_state()
>>> py_rng.setstate((3, tuple(map(int, words)) + (pos,), None))
和以前一样,我们可以检查两个生成器的输出是否匹配:
>>> py_rng.random(), np_rng.uniform()
(0.5488135039273248, 0.5488135039273248)
>>> py_rng.random(), np_rng.uniform()
(0.7151893663724195, 0.7151893663724195)
>>> py_rng.random(), np_rng.uniform()
(0.6027633760716439, 0.6027633760716439)
>>> all(py_rng.random() == np_rng.uniform() for _ in range(1000000))
True
Python 和 NumPy 使用不同的算法来生成正态偏差(尽管使用的两种算法都成对生成这些偏差),因此即使我们转移与高斯相关的状态,我们也不能期望生成的正态偏差匹配。但是,如果您想做的只是以某种方式在 NumPy 状态对象中保留 Python 状态信息(反之亦然),以便从一种状态转换为另一种状态并再次返回不会丢失信息,这很容易做到:如果has_gauss
在 NumPy 状态下为零,使用 None
作为 Python 状态的最后一个条目,如果 has_gauss
不为零,则使用cached_gaussian
的值来自 Python 状态的最后一个条目中的 NumPy 状态。下面是实现这些转换的一对函数:
PY_VERSION = 3
NP_VERSION = 'MT19937'
def npstate_to_pystate(npstate):
"""
Convert state of a NumPy RandomState object to a state
that can be used by Python's Random.
"""
version, keys, pos, has_gauss, cached_gaussian = npstate
pystate = (
PY_VERSION,
tuple(map(int, keys)) + (int(pos),),
cached_gaussian if has_gauss else None,
)
return pystate
def pystate_to_npstate(pystate):
"""
Convert state of a Python Random object to state usable
by NumPy RandomState.
"""
version, (*keys, pos), cached_gaussian = pystate
has_gauss = cached_gaussian is not None
npstate = (
NP_VERSION,
keys,
pos,
has_gauss,
cached_gaussian if has_gauss else 0.0
)
return npstate
关于python - 与 numpy 的 np.random.RandomState 和 Python 的 random.Random 相互转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44313620/
在分析代码时,我偶然发现了以下代码段: msk = np.random.rand(len(df)) < 0.8 变量“msk”和“df”与我的问题无关。经过一些研究,我认为这种用法也与“随机”类有关。
出于几个合理的原因,我必须使用 BSD 的 random() 来生成非常大量的随机数,并且由于它的周期很短(~2^69,如果我没记错的话),这些数字的质量会降低对于我的用例来说很快。我可以使用我可以访
每种语言都有一个 random() 函数或类似的东西来生成伪随机数。我想知道下面会发生什么来生成这些数字?我没有编写任何需要这些知识的东西,只是想满足我自己的好奇心。 最佳答案 唐纳德·克努斯开创性的
我开发了一个简单的应用程序来生成测试数据系列,并且我使用随机种子将其构建为能够重复。我注意到以下情况并想知道为什么会这样: >>> random.seed(1) >>> [random.randint
random() * random() 和 random() ** 2 有区别吗? random() 从均匀分布中返回一个介于 0 和 1 之间的值。 在测试两个版本的随机平方数时,我注意到了一点不同
我发现 Python(及其生态系统)充满了奇怪的约定和不一致,这是另一个例子: np.random.rand Create an array of the given shape and popula
我想看看哪个随机数生成器包在我的神经网络中速度更快。 我目前正在从github上修改一段代码,其中numpy.random和random包都用于生成随机整数、随机选择、随机样本等。 我更改此代码的原因
我有一个 Python 大脚本。我在其他人的代码中启发了自己,所以我最终使用 numpy.random 模块来做一些事情(例如创建一个从二项分布中获取的随机数数组),在其他地方我使用模块 random
仅仅是因为“大型 API 综合症”还是生成在某些情况下更偏向的随机数?如果是……我认为控制偏见很重要。 最佳答案 他们是一样的,真的。只是一个方便的方法。检查 javadoc here .此外,您
我只是观察到,当使用 Python3 时,使用 random.shuffle 对列表进行洗牌需要大约一半的运行时间,而当为 显式提交函数 random.random >random 关键字参数。我检查
在python中随机模块,random.uniform()和random.random()有什么区别?它们都生成伪随机数,random.uniform() 生成均匀分布的数字,random.rando
是否可以在JMeter中生成“随机数”变量? 我已经记录了用户旅程 我已将旅程导入JMeter 我必须在用户旅程测试用例中输入一个唯一的4位数ID 在jmeter的当前默认值为2323 有没有一种方法
例如,如果我执行命令两次:ffmpeg -i input.mp4 -vf geq=r='random(1)*255':g='random(1)*255':b='random(1)*255' -stri
尽管随机生成器只创建一次,但输出始终是相同的随机结果(对于所有三个测试输出)。 来自稍大脚本的测试片段: let myRandGen = System.Random() let getRa
我正计划使用IntRange.random()(即(0..9999).random())在 Kotlin 中生成一个随机的5位代码。重要的是,恶意人员不能预测将要生成的数字的顺序。 IntRange.
您能否告诉我如何将 KDB 中的随机数生成器种子设置为或多或少的“随机”数? 我正在尝试执行以下操作: \S .z.i 但不知何故它不起作用。\S 似乎需要一个显式整数,而不是一个变量。 非常感谢!
我需要同时获得 /dev/random和 /dev/urandom在内核模块中。 get_random_bytes提供获取 /dev/urandom 的 API . 但是/dev/random 没有A
random.shuffle(lst_shuffle, random.random) 我知道后一部分是可选参数。但它究竟做了什么。我不明白这是什么意思。 这是来自文档。 random.random()
在树莓派 3 上: >>> import random >>> random.seed(0.9849899567458751) >>> random.random() 0.47871160253065
说我有一些python代码: import random r=random.random() r的值通常从哪里来? 如果我的操作系统没有随机数,那么它将在何处播种呢? 为什么不建议将其用于加密?有什么
我是一名优秀的程序员,十分优秀!