2016-04-06 27 views
7

Bernoulli dağılımını simüle etmek için rasgele bir sayıyı düşünmesi gereken bir yöntem yazdım. 0 ve 1 arasında bir sayı oluşturmak için random.nextDouble kullanıyorum ve sonra olasılık parametresi verilen değere dayanarak kararımı veririm.Spark - Rastgele Sayı Üretimi

Sorunum, Spark'in döngü eşleme işlevimin her yinelemesinde aynı rasgele sayıları oluşturmasıdır. DataFrame API kullanıyorum. Benim kod bu biçimi aşağıdaki gibidir: Her zaman myMethod denir yeni bir rastgele sayı ihtiyaç

class myClass extends Serializable { 
    val q = qProb 

    def myMethod(s: String, rand: Double) = { 
    if (rand <= q) // do something 
    else // do something else 
    } 
} 

:

İşte
val myClass = new MyClass() 
val M = 3 
val myAppSeed = 91234 
val rand = new scala.util.Random(myAppSeed) 

for (m <- 1 to M) { 
    val newDF = sqlContext.createDataFrame(myDF 
    .map{row => RowFactory 
     .create(row.getString(0), 
     myClass.myMethod(row.getString(2), rand.nextDouble()) 
    }, myDF.schema) 
} 

sınıftır. Ayrıca aşağıda gibi (Serializable uzamaz scala.util.Random v10) java.util.Random ile benim yöntemi içinde bir sayı oluşturmak çalıştı, ama yine de biraz araştırma yaptık döngü

val r = new java.util.Random(s.hashCode.toLong) 
val rand = r.nextDouble() 

için her içindeki aynı numaraları alıyorum ve Görünüşe göre bu, Sparks deterministik doğasıyla ilgili.

cevap

2

tekrarlanır aynı sekans rastgele jeneratör oluşturulan ve veri bölümlenmiş önce bir tohum ile başlatıldı olmasıdır sebebi. Her bölüm daha sonra aynı rastgele tohumdan başlar. (Tamamen dış

val myClass = new MyClass() 
val M = 3 

for (m <- 1 to M) { 
    val newDF = sqlContext.createDataFrame(myDF 
    .map{ 
     val rand = scala.util.Random 
     row => RowFactory 
     .create(row.getString(0), 
     myClass.myMethod(row.getString(2), rand.nextDouble()) 
    }, myDF.schema) 
} 
+0

biraz benim sorunu çözmek için bu değiştirilmiş . Rasgele değeri benim yöntemime aktardım ve oradan rastgele sayılar ürettim. Bu benim sorunumu çözdü, ama seri hale getirilebilirlik nedenlerinden dolayı 'java.util.Random' kullanmak zorunda kaldım. –

4

Sadece SQL işlevini rand kullanın:

import org.apache.spark.sql.functions._ 

//df: org.apache.spark.sql.DataFrame = [key: int] 

df.select($"key", rand() as "rand").show 
+---+-------------------+ 
|key|    rand| 
+---+-------------------+ 
| 1| 0.8635073400704648| 
| 2| 0.6870153659986652| 
| 3|0.18998048357873532| 
+---+-------------------+ 


df.select($"key", rand() as "rand").show 
+---+------------------+ 
|key|    rand| 
+---+------------------+ 
| 1|0.3422484248879837| 
| 2|0.2301384925817671| 
| 3|0.6959421970071372| 
+---+------------------+ 
+0

ama onun zarif ben muhtemelen gelecekte kullanıyor olacaktır çözüm, yani 1 –

2

göre this post için en iyi çözüm haritası içine new scala.util.Random koymak değil, ne yani sürücü kodunda: Belki en etkili yolu bunu yapmak için değil, ama şu çalışmalıdır.), ancak bir mapPartitionsWithIndex ara:

import scala.util.Random 
val myAppSeed = 91234 
val newRDD = myRDD.mapPartitionsWithIndex { (indx, iter) => 
    val rand = new scala.util.Random(indx+myAppSeed) 
    iter.map(x => (x, Array.fill(10)(rand.nextDouble))) 
} 
Bu oldukça sorunumu çözmedi