转自:http://www.it165.net/pro/html/201403/10045.html
一、简单的随机抽样:一个总体的个数为N,如果通过逐个抽取的方法从中抽取
一个样本,且每次抽取时各个个体被抽到的概率相等,则这样的抽样为简单的随机抽样。
例如,从含有6个个体的总体中抽取一个容量为2的样本,则在抽样过程
中某个个体a被抽到的概率是多少?
2/6
(1) 第一次a被抽中 1/6
(2) 第一次未被抽中,第二次抽中 5/6 * 1/5 = 1/6
(3) 第一次抽中与第二次抽中是互斥事件,所以,在这次抽样过程中,
个体a被抽中的概率为 1/6 + 1/6 = 2/6。
上述抽样过程如何用计算机进行模拟呢?
思路:依次遍历总体N中的每一个元素,并通过一种随机测试对每个元素进行决策(选与不选),将被选元素输出。
所以,上述思路关键在于那个随机测试,由于是简单随机抽样,每个元素被选可能为n/N,所以代码如下:
1.
for
(
int
i = 0; i < N; i++)
2.
{
3.
if
(
rand
() % N < n)
4.
print i;
5.
}
这种做法虽然每个元素以n/N的概率被选,但又可能最后选取的元素小于n, 也极有可能大于n,因此这种做法不可。
我们以 (n-m) / (N - i) 的概率选取第t+1个元素。(m已经选取元素的个数, t已经遍历的元素数)
01.
select = n
02.
remaining = N
03.
for
(i = 0; i < n; i++)
04.
{
05.
if
(
rand
() % remaining < select)
06.
{
07.
print i;
08.
select--;
09.
}
10.
remaining--;
11.
}
这样,貌似每个元素不是以n/N的概率进行抽取的。
这里混淆了条件概率与无条件概率,每一个元素被选取的概率依赖于前一元素的选取情况。
(1)假设以等概率n/N的概率选择了第一个元素,那么在剩下N-1个元素中选择n-1个元素,等概率,
选取一个元素为(n-1)/(N-1),即第二个元素的概率为(n-1)/(N-1).
(2)不选择第一个元素(1-n/N),而选择了第二个元素,则选择第二个元素概率 n/(N-1).
(3)最终选取第二个元素的概率为(n/N)*((n-1)/(N-1)) + (1-n/N)*(n/(N-1)) = n/N.
所以上述代码模拟了随机抽样,可以采用归纳法进行证明。
若不选择元素t,则remaining--,即以 select /(remaining - 1) 概率选择第t+1个元素。
若选择元素t, 则select--, remaing--,即以(select-1) / (remaining - 1) 选择第t+1个元素。
可以这样理解:
图一中,若随机数一值落于select - remaining 区间中,remaining会一直缩小,如图二中。
当remaining与select重合的时候,每次都会选择一个数。通过这种限制,保证取得的数据个数正好为select。
二、蓄水池抽样
问题:样本总数N未知,从中取n个(n≤N),最终要求每个数等概率被取得,n/N.
步骤:1. 先将前n个元素放入蓄水池,对于后续元素,以n/a的概率决定是否取该元素( n < a ≤ N)。
2. 若选取了某个元素a(序号也为a),则要替换蓄水池中的一个元素,采用随机方法,以概率1/n来
选择一个元素(假如b)进行替换。
证明:元素a最终(即抽样结束)被选择的概率为 =
a被选中的概率 * { [ (a+1)未被选中 + (a+1)被选中 * (a未被(a+1)替换的概率)] *
[ (a+2)未被选中 + (a+2)被选中 * (a未被(a+2)替换的概率)] *…… *
[ (N)未被选中 + (N)被选中 * (a未被N替换的概率)] }
所以,每个元素被选取的概率为n/N,为等概率抽样。
代码:
1.
a = n + 1;
2.
while
has more input lines
3.
choice = random(1, a);
4.
if
( a <= n)
5.
swap(choice, a);
6.
a++
1. 将前n个元素放入蓄水池
2. choice为1-a之间的随机数字
3. 若 choice <=n, 即以n/a的概率选择这一行
4. choice同时为n中某个元素的下标,将此下标的元素进行替换。
在0-a直接随机选取一个数字,如果落到0-n的区间内,则说明概率为n/a.