简体   繁体   English

Python的Numpy np.random.choice的scala等效项是什么?(scala中的随机加权选择)

[英]What is the scala equivalent of Python's Numpy np.random.choice?(Random weighted selection in scala)

I was looking for Scala's equivalent code or underlying theory for pythons np.random.choice (Numpy as np). 我在寻找Scala的等效代码或python np.random.choice(Numpy为np)的基础理论。 I have a similar implementation that uses Python's np.random.choice method to select the random moves from the probability distribution. 我有一个类似的实现,它使用Python的np.random.choice方法从概率分布中选择随机移动。

Python's code Python的代码

Input list: ['pooh', 'rabbit', 'piglet', 'Christopher'] and probabilies: [0.5, 0.1, 0.1, 0.3] 输入列表:['pooh','rabbit','piglet','Christopher']和概率:[0.5、0.1、0.1、0.3]

I want to select one of the value from the input list given the associated probability of each input element. 考虑到每个输入元素的相关概率,我想从输入列表中选择一个值。

The Scala standard library has no equivalent to np.random.choice but it shouldn't be too difficult to build your own, depending on which options/features you want to emulate. Scala标准库没有np.random.choice等效项,但是构建您自己的库应该不难,具体取决于您要模拟的选项/功能。

Here, for example, is a way to get an infinite Stream of submitted items, with the probability of any one item weighted relative to the others. 例如,这里是一种获取提交项目的无限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
}

With this each input item is given with a multiplier. 这样,每个输入项都有一个乘数。 So to get an infinite pseudorandom selection of the characters c and v , with c coming up 3/5ths of the time and v coming up 2/5ths of the time: 因此,要获得字符cv的无限伪随机选择,其中c占时间的3/5,而v占时间的2/5:

val cvs = weightedSelect(('c',3),('v',2))

Thus the rough equivalent of the np.random.choice(aa_milne_arr,5,p=[0.5,0.1,0.1,0.3]) example would be: 因此, 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

Or perhaps you want a better (less pseudo) random distribution that might be heavily lopsided. 或者,也许您想要一个更好的(较少的伪)随机分布,该分布可能会严重偏离。

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())))
}

The result is still an infinite Stream of the specified elements but the passed-in arguments are a bit different. 结果仍然是指定元素的无限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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM