如何在Python中高效地生成具有随机斜率和截距的直线?

9
考虑一个非常基本的蒙特卡罗模拟直线 y = m * x + b,例如为了可视化参数 mb 的不确定性所产生的影响。 mb 都是从正态分布中采样得到的。作为来自MATLAB背景的人,我会这样写:
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(start=0, stop=5, step=0.1)

n_data = len(x)
n_rnd = 1000

m = np.random.normal(loc=1, scale=0.3, size=n_rnd) 
b = np.random.normal(loc=5, scale=0.3, size=n_rnd)

y = np.zeros((n_data, n_rnd))  # pre-allocate y

for realization in xrange(n_rnd):
    y[:,realization] = m[realization] * x + b[realization]

plt.plot(x, y, "k", alpha=0.05);

直线的蒙特卡罗模拟

这确实可以产生所需的输出结果,但我觉得可能有一种更符合 Python 风格的方式来完成。我的想法对吗?如果不是,能否给我提供一些代码示例,告诉我如何更高效地完成呢?

举个例子,用 MATLAB 可以很容易地使用 bsxfun() 来编写,而不需要使用循环。Python 中是否有类似的功能或者甚至有专门处理此类问题的包呢?

1个回答

9
您可以使用numpy数组广播,按照以下方式一步创建y数组。
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(start=0, stop=5, step=0.1)

n_data = len(x)
n_rnd = 1000

m = np.random.normal(loc=1, scale=0.3, size=n_rnd) 
b = np.random.normal(loc=5, scale=0.3, size=n_rnd)

y = m * x[:, np.newaxis] + b

for val in y.transpose():
    plt.plot(x, val, alpha=0.05)

# Or without the iteration:
# plt.plot(x, y, alpha=0.05)

plt.show()
< p > x[:, np.newaxis]强制使x成为一个形状为(50, 1)的列向量,而不是(50,),这意味着广播可以使用。

然后,您可以直接迭代numpy数组(而不是迭代其索引),但是您必须转置数组(使用y.transpose()),否则对于每次迭代,您将获得1000个随机数的x值。


1
太好了,正是我想要的。谢谢。你提供的页面底部有一个失效链接;对于那些感兴趣的人来说,这篇(非常有用的)文章可以在这里找到:EricsBroadcastingDoc。/编辑:不过,@Ffisegydd,还有一个后续问题:循环绘图比我之前做的更快吗?或者为什么你决定改变它? - Fred S
我觉得你可能误解了我的意思(或者是我误解了你的意思)。我明白你为什么要去掉我用来生成 y 的循环,这看起来非常像我在提问时所想到的。我只是想知道为什么你添加了一个 绘图 循环,因为它可以像我原来的代码一样不使用循环,只需使用 plt.plot(x, y, "k", alpha=0.05)。或者这是在内部迭代索引吗?抱歉,我有点困惑。 - Fred S
2
哦,我知道你的意思了,那是我自己的大脑短路。两种方法都可以,我不确定哪个更快,我甚至没有意识到我修改了你的原始代码。 - Ffisegydd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接