【问题标题】:Weighted sampling in FortranFortran 中的加权采样
【发布时间】:2015-11-28 04:14:53
【问题描述】:

在 Fortran 程序中,我想通过使用权重随机选择一个特定变量(特别是它的索引)。权重将在单独的向量中提供(元素 1 将包含变量 1 的权重,依此类推)。

我有以下代码,他在没有权重的情况下完成了这项工作(mind 是一个整数向量,带有原始数据集中每个变量的索引)

call rrand(xrand)
j = int(nn * xrand) + 1
mvar = mind(j)

【问题讨论】:

  • 你可以简单地添加一个循环

标签: fortran sampling weighted


【解决方案1】:

这里有两个例子。第一个是

integer, parameter :: nn = 5
real :: weight( nn ), cumsum( nn ), x

weight( 1:nn ) = [ 1.0, 2.0, 5.0, 0.0, 2.0 ]

do j = 1, nn
    cumsum( j ) = sum( weight( 1:j ) ) / sum( weight( 1:nn ) )   !! cumulative sum
enddo

x = rand()
do j = 1, nn
    if ( x < cumsum( j ) ) exit
enddo

第二个取自this page

real :: sum_weight
sum_weight = sum( weight( 1:nn ) )

x = rand() * sum_weight
do j = 1, nn
    if ( x < weight( j ) ) exit
    x = x - weight( j )
enddo

这与第一个基本相同。两者都使用权重(j)从 1,2,...,5 中随机抽取j。 100000 次试验给出了类似的分布

j     :    1           2           3           4       5
count :    10047       19879       50061       0       20013

编辑:下面附上一个最小的测试代码(用 gfortran-8/9 测试):

program main
    implicit none
    integer j, num( 5 ), loop
    real    weights( 5 )

    weights(:) = [ 1.0, 2.0, 5.0, 0.0, 2.0 ]
    num(:) = 0

    do loop = 1, 100000
        call random_index( j, weights )
        num( j ) = num( j ) + 1
    enddo

    do j = 1, size( weights )
        print *, j, num( j )
    enddo

contains

subroutine random_index( idx, weights )
    integer :: idx
    real, intent(in) :: weights(:)

    real x, wsum, prob

    wsum = sum( weights )

    call random_number( x )

    prob = 0
    do idx = 1, size( weights )
        prob = prob + weights( idx ) / wsum   !! 0 < prob < 1
        if ( x <= prob ) exit
    enddo
end subroutine

end program

【讨论】:

  • 谢谢 roydvib!我假设循环退出后 j 保留所选变量的索引。对吗?
  • 是的,j的值在退出循环后保持不变。因此,我们可以编写一个函数,接收 weight(:) 作为虚拟参数并返回从 DO 循环中获得的 j,例如。
  • @roygvib 谢谢你,但我不确定我是否理解它是如何工作的。当我运行它时,我似乎总是得到相同的 j 。你介意提供更多细节吗?似乎每次我运行这个 rand() 都会给出相同的数字。
  • @HermanToothrot 嗨,我在答案的底部附上了一个最小的测试/工作代码。代码稍作修改,以便子例程random_index() 可以以独立方式使用。那么您能否在您的环境中尝试此代码,看看它是否按预期工作? (我几乎忘记了细节,但我想我们正在计算给定权重的累积概率,并测试“x”落在某个“bin”(具有给定权重)中的位置。)
  • @roygvib 谢谢,是的,它正在工作,我不明白它必须在一个循环中。我实际上已经用你提供的第二个例子实现了它。
猜你喜欢
  • 2021-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-02
  • 2022-11-28
  • 1970-01-01
  • 2019-09-03
相关资源
最近更新 更多