Python 的 Numpy np.random.choice 的 scala 等价物是什么?(scala 中的随机加权选择)
What is the scala equivalent of Python's Numpy np.random.choice?(Random weighted selection in scala)
我正在寻找 Scala 的等效代码或 python 的基础理论 np.random.choice(Numpy 作为 np)。我有一个类似的实现,它使用 Python 的 np.random.choice 方法来 select 从概率分布中随机移动。
输入列表:['pooh'、'rabbit'、'piglet'、'Christopher'] 和概率:[0.5、0.1、0.1、0.3]
我想 select 给定每个输入元素的相关概率,输入列表中的值之一。
Scala 标准库没有 np.random.choice
的等效项,但构建您自己的标准库应该不会太难,具体取决于您要模拟的 options/features。
例如,这是一种获得无限 Stream
提交项目的方法,其中任何一个项目相对于其他项目加权的概率。
def weightedSelect[T](input :(T,Int)*): Stream[T] = {
val items :Seq[T] = input.flatMap{x => Seq.fill(x._2)(x._1)}
def output :Stream[T] = util.Random.shuffle(items).toStream #::: output
output
}
有了这个,每个输入项都带有一个乘数。因此,为了获得字符 c
和 v
的无限伪随机选择,c
出现在 3/5 的时间,v
出现在 2/5 的时间:
val cvs = weightedSelect(('c',3),('v',2))
因此 np.random.choice(aa_milne_arr,5,p=[0.5,0.1,0.1,0.3])
示例的粗略等效为:
weightedSelect("pooh"-> 5
,"rabbit" -> 1
,"piglet" -> 1
,"Christopher" -> 3).take(5).toArray
或者你可能想要一个更好的(不那么伪的)随机分布,它可能会严重不平衡。
def weightedSelect[T](items :Seq[T], distribution :Seq[Double]) :Stream[T] = {
assert(items.length == distribution.length)
assert(math.abs(1.0 - distribution.sum) < 0.001) // must be at least close
val dsums :Seq[Double] = distribution.scanLeft(0.0)(_+_).tail
val distro :Seq[Double] = dsums.init :+ 1.1 // close a possible gap
Stream.continually(items(distro.indexWhere(_ > util.Random.nextDouble())))
}
结果仍然是指定元素的无限Stream
,但传入的参数有点不同。
val choices :Stream[String] = weightedSelect( List("this" , "that")
, Array(4998/5000.0, 2/5000.0))
// let's test the distribution
val (choiceA, choiceB) = choices.take(10000).partition(_ == "this")
choiceA.length //res0: Int = 9995
choiceB.length //res1: Int = 5 (not bad)
我正在寻找 Scala 的等效代码或 python 的基础理论 np.random.choice(Numpy 作为 np)。我有一个类似的实现,它使用 Python 的 np.random.choice 方法来 select 从概率分布中随机移动。
输入列表:['pooh'、'rabbit'、'piglet'、'Christopher'] 和概率:[0.5、0.1、0.1、0.3]
我想 select 给定每个输入元素的相关概率,输入列表中的值之一。
Scala 标准库没有 np.random.choice
的等效项,但构建您自己的标准库应该不会太难,具体取决于您要模拟的 options/features。
例如,这是一种获得无限 Stream
提交项目的方法,其中任何一个项目相对于其他项目加权的概率。
def weightedSelect[T](input :(T,Int)*): Stream[T] = {
val items :Seq[T] = input.flatMap{x => Seq.fill(x._2)(x._1)}
def output :Stream[T] = util.Random.shuffle(items).toStream #::: output
output
}
有了这个,每个输入项都带有一个乘数。因此,为了获得字符 c
和 v
的无限伪随机选择,c
出现在 3/5 的时间,v
出现在 2/5 的时间:
val cvs = weightedSelect(('c',3),('v',2))
因此 np.random.choice(aa_milne_arr,5,p=[0.5,0.1,0.1,0.3])
示例的粗略等效为:
weightedSelect("pooh"-> 5
,"rabbit" -> 1
,"piglet" -> 1
,"Christopher" -> 3).take(5).toArray
或者你可能想要一个更好的(不那么伪的)随机分布,它可能会严重不平衡。
def weightedSelect[T](items :Seq[T], distribution :Seq[Double]) :Stream[T] = {
assert(items.length == distribution.length)
assert(math.abs(1.0 - distribution.sum) < 0.001) // must be at least close
val dsums :Seq[Double] = distribution.scanLeft(0.0)(_+_).tail
val distro :Seq[Double] = dsums.init :+ 1.1 // close a possible gap
Stream.continually(items(distro.indexWhere(_ > util.Random.nextDouble())))
}
结果仍然是指定元素的无限Stream
,但传入的参数有点不同。
val choices :Stream[String] = weightedSelect( List("this" , "that")
, Array(4998/5000.0, 2/5000.0))
// let's test the distribution
val (choiceA, choiceB) = choices.take(10000).partition(_ == "this")
choiceA.length //res0: Int = 9995
choiceB.length //res1: Int = 5 (not bad)