我需要制作一个模拟器,用于输入列表,列表(元素是从rdm_lst随机选择的)列表。我:
lst = ["a", "a", "a"]
rdm_lst = ["a", "b", "c"]
def simulator(lst, rdm_lst):
sim = []
for i in lst:
if i == "a":
sim.append(np.random.choice(rdm_lst, size=1, p=[0.6, 0.2, 0.2]).tolist()[0])
elif i == "b":
sim.append(np.random.choice(rdm_lst, size=1, p=[0.2, 0.6, 0.2]).tolist()[0])
elif i == "c":
sim.append(np.random.choice(rdm_lst, size=1, p=[0.2, 0.2, 0.6]).tolist()[0])
return sim
simulator(rdm_lst)
输出是一个列表,我遇到的问题是,我不知道如何重复这个函数k时间,作为列表的结果列表,其中模拟器()的输入将是前一个列表,而不是第一个。我试过了,放:
return simulator(sim)
:
return sim
出现错误。请帮助。
听起来你在尝试实现一个马尔可夫链。
您可以通过使用dict
定义您的转换来简化您的代码(因为您的状态是标记的,并且您当前使用的是numpy
—在这种情况下,Pandas DataFrame将更直观,但这将完成)。
Px = {
'a': np.array([0.6, 0.2, 0.2]),
'b': np.array([0.2, 0.6, 0.2]),
'c': np.array([0.2, 0.2, 0.6]),
}
def simulator(xs, Px, k=1):
labels = list(Px)
return [
xs := [np.random.choice(labels, p=Px[x]) for x in xs]
for _ in range(k)
]
np.random.seed(0)
>>> simulator(['a', 'b', 'c'], Px, k=10)
[['a', 'b', 'c'],
['a', 'b', 'c'],
['a', 'c', 'c'],
['a', 'c', 'c'],
['a', 'c', 'a'],
['a', 'a', 'c'],
['b', 'c', 'c'],
['b', 'c', 'c'],
['a', 'c', 'a'],
['c', 'c', 'a']]
np.random.seed(0)
>>> simulator(['a', 'b', 'c'], Px, k=10)
[['a', 'b', 'c'],
['a', 'b', 'c'],
['a', 'c', 'c'],
['a', 'c', 'c'],
['a', 'c', 'a'],
['a', 'a', 'c'],
['b', 'c', 'c'],
['b', 'c', 'c'],
['a', 'c', 'a'],
['c', 'c', 'a']]
给定xs
一个初始状态列表,我们用列表理解构造一个新的状态列表:[np.random.choice(labels, p=Px[x]) for x in xs]
。然后将其赋值给xs
(使用"海象操作符"),并迭代k
数次。
有趣的东西有限状态马尔可夫链更常用的定义是带转移矩阵的:
P = np.c_[list(Px.values())]
>>> P
array([[0.6, 0.2, 0.2],
[0.2, 0.6, 0.2],
[0.2, 0.2, 0.6]])
(您可以单独映射标签,或者使用pandas
将标签作为索引和列)。
给定初始状态(1,0,0)
('a'
),经过两次转换后的预期状态分布是什么?
>>> np.array((1,0,0)) @ P @ P
array([0.44, 0.28, 0.28])
给定初始状态(1,0,0)
,终端期望状态分布是什么?
# approximation of v @ P^inf
>>> np.array((1,0,0)) @ np.linalg.matrix_power(P, int(10**9))
array([0.33333334, 0.33333334, 0.33333334])
更准确地说:什么是平稳分布(一种状态分布,它不受转换P
的影响)?
w, v = np.linalg.eig(P.T) # left eigen system
k = np.argmax(w)
assert np.allclose(w[k], 1), 'no stationary state!'
e = v[:, k]
e /= e.sum()
>>> e
array([0.33333333, 0.33333333, 0.33333333])
>>> e @ P
array([0.33333333, 0.33333333, 0.33333333])
因此,无论初始状态如何(因为所有状态都可以从任何初始状态到达),经过大量转换后的期望分布为每个状态的1/3。