Performance 改进离散分布样本的标度
我最近开始和Julia一起玩,我现在正在做二维晶格上一些随机过程的Monte Carlo模拟。每个站点都有一些相关的激活率(平均每秒“做某事”的次数),我们可以假设这些激活率是近似恒定的。晶格点激活的顺序是相关的,因此我们需要一种随机选取一个特定位置的方法,其概率与其激活率成正比 看起来Performance 改进离散分布样本的标度,performance,random,julia,simulation,stochastic-process,Performance,Random,Julia,Simulation,Stochastic Process,我最近开始和Julia一起玩,我现在正在做二维晶格上一些随机过程的Monte Carlo模拟。每个站点都有一些相关的激活率(平均每秒“做某事”的次数),我们可以假设这些激活率是近似恒定的。晶格点激活的顺序是相关的,因此我们需要一种随机选取一个特定位置的方法,其概率与其激活率成正比 看起来StatsBase包中的sample(sites,weights(rates))正是我想要的,但是从测试我的代码结构(没有逻辑,只有循环和RNG)来看,sample()与站点数量成线性比例。这意味着我的整个运行时
StatsBase
包中的sample(sites,weights(rates))
正是我想要的,但是从测试我的代码结构(没有逻辑,只有循环和RNG)来看,sample()
与站点数量成线性比例。这意味着我的整个运行时的规模类似于N^(2+2),其中N在我的二维晶格的边长中(一个是总活动率增加的2倍,另一个是sample()
的规模)
现在,总活动率的增加是不可避免的,但我认为“随机选择权重”方法的比例可以改进。更具体地说,应该能够实现站点数量的对数缩放(而不是线性)。例如,考虑以下函数(并且,请原谅,糟糕的编码)
因为我们在每一步都要将“可选择的”站点的数量减少一半,所以从2^n个站点中选择一个特定站点需要n个步骤(因此采用对数比例)。但是,在其当前状态下,randompick()
比sample()
慢得多,因此缩放实际上是不相关的。有没有办法将此方法简化为一种可以与sample()
竞争的形式,从而利用改进的伸缩性
编辑:计算
cumrates
比例,如N^2,但这可以通过在整个代码中以正确(累积)形式使用rates
来解决。我认为您尝试的一个简单版本是:
function randompick(rates)
cumrates = cumsum(rates)
pick = rand()*cumrates[end]
searchsortedfirst(cumrates, pick)
end
调用searchsortedfirst
确实可以对数缩放,但是cumsum
只能线性缩放,因此消除了它可能具有的任何优势
如果速率
是恒定的,您可以提前预处理cumrates
,但如果是这种情况,您最好使用能够在恒定时间内采样的。包中提供了一个实现:
我在p.Hanusse的著作中发现了一种替代的抽样方法,它似乎不与N成比例,至少在允许的活动率具有相同数量级的情况下是如此
我们的想法是假设所有站点都具有相同的活动速率,等于最活跃站点的活动速率
maxrate
(这样,随机选取将减少为单个RNG调用rand(1:N)
)。一旦我们选择了一个站点,我们将其(恒定)活动速率分为两个贡献,原始活动速率和“无所事事”速率(第二个是恒定速率减去原始速率)。现在我们生成第二个随机数c=rand()*maxrate
。如果cHi。我认为,也许这个问题或建议更适合Julia的讨论论坛,而Stack Overflow更适合于具体问题,而话语则是想法和讨论的场所。您也可以考虑在StassBaseJL GITHUB页面上打开一个问题:谢谢您的建议。我想我之所以决定把它贴在这里,是因为我会很高兴有一个针对我的案例的解决方案,但我发现核心问题与我正在模拟的具体过程几乎没有关系。在任何情况下,对于任何感兴趣的人,请参阅下面我的答案,以了解我发现的针对我的案例的有效抽样方法。在发布问题后,我意识到,计算每次通话的累积费率会将缩放设置回线性(因此我进行了编辑)。我想,要想使这种方法有用,就需要在整个过程中使用累积利率。关于您的第二条评论,速率不是恒定的(即,特定站点的相关速率在该站点或其附近的某个激活事件后可能会发生变化),但只能采用一些预先确定的值。在这种情况下,您可以利用问题的结构,但我们需要更多关于利率如何变化的信息。
function randompick(rates)
cumrates = cumsum(rates)
pick = rand()*cumrates[end]
searchsortedfirst(cumrates, pick)
end
using Distributions
s = Distributions.AliasTable(rates)
rand(s)
function HanussePick(rates,maxrate)
site = rand(1:N^2)
slider = rand() * maxrate
return(site,rates[site]-slider)
end