您的位置:首页 > 其它

抽样 拉希里法的变形(Lahiri)

2016-01-28 13:14 357 查看
看spark1.3.0 kmeans源码碰到抽样理论问题:下面是摘录的程序注释与关键代码

// On each step, sample 2 * k points on average for each run with probability proportional
// to their squared distance from that run's centers. Note that only distances between points
// and new centers are computed in each iteration.
val rand = new XORShiftRandom(seed ^ (step << 16)^index)
pointsWithCosts.flatMap { case (p, c) =>
val rs = (0 until runs).filter { r =>
rand.nextDouble() < 2.0 * c(r) * k / sumCosts(r)
}
if (rs.length > 0) Some(p, rs) else None
}
}.collect()

对于这句
rand.nextDouble() < 2.0 * c(r) * k / sumCosts(r)
很不理解。
然后我就做了下面的测试,当然测试了很多种——从循环次数到数组的值、数组元素个数及分布形式都作了大范围测试,下面的仅仅是其中之一,但不失为好示例。

import scala.util.Random
val abf = new ArrayBuffer[Double]
var r = 0.0
for (i <- 1 to 4)
{
abf += 0.25//
}
r = abf.sum//随机数之和
var j = 0
val mx = abf.max
for (t <-1 to 500000;i<- 0 until 4)
{
if ( abf(i) > Random.nextDouble()*0.05 )//按照值越大取出的概率越大的策略
j += 1
}
println(j/500000.0)//打印5次中,平均每次取出了几个数
println(r)//打印随机数之和
println(mx)

输出结果:
4.0
1.0
0.25

Process finished with exit code 0

这个原理困扰了我近一天的时间,查阅了很多资料,现对上述测试总结如下:

0<y<xi (i=1,2,...N)的概率为xi ,所以对于第i次,j增加1的概率为xi ;
又因为∑xi =1,所以取到的次数为1.
而且满足线性性质:
(1) 随机数y乘以正因子α,取到的xi 个数为min(1/α,N),N为xi个数
(2) xi乘以正因子α,取到的xi 个数为1*α
(3) N的个数没限制,但做实验的次数要高:          for (t <-1 to 500000;i<- 1 until 2)             这里N=2,实验次数为500000


当然你也可以用随机数产生之和为1的数组来做测试。怎么之和为1呢?就是每个随机数除以随机数之和,就可以了。
这里的方法应该是对拉稀里法的扩展,Lahiri法本身没说明这些性质。
相关资料截图及链接:






http://wenku.baidu.com/link?url=BkQBiS_w4F_IxGhook6lf8DD4RWJfaWT3zMwuuPfJH8VT0cKggngjcgGdzSt06OaSI3Y5xYo5AnvuM4Z9_hBUj7Bf7qRLrrIwuNPF2UFPVC
http://www.doc88.com/p-0837238499730.html

然而,我对源码中的
seed ^ (step << 16) ^ index)
并未理解,除了提高速度,更加随机外,左移16位有何考量,index为何不左移?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: