最近学习node2vec接触到了这个算法,在此简单记录下,详细可见该博客https://blog.youkuaiyun.com/haolexiao/article/details/65157026
我这里直接以上述博客的例子结合代码简单整理下
假如有四个事件,概率分别是1/2,1/3,1/12,1/12(和为 1)。
构建Alias Table
- 将四个事件排成一列,分为1,2,3,4。

- 每个概率乘以四(事件数)。

- 然后拼凑使每列值为 1,并保证每列最多只包含两个事件。

即Alias Table构建完成,得到两个数组,alias:保存着每列中加入的事件,如图即为【2,null,1,1】;prab:保存着每列事件的概率,如图即为【2/3,1,1/3,1/3】。
代码实现思想:乘以事件数之后先将事件分成两部分,一个小于1(smaller),一个大于1(larger),然后分别从这两部分中取数据,用大的补小的使其为 1,如果大的剩余值小于1,加入smaller中,否则还是放回larger中,直到smaller或larger为空。
def alias_setup(probs):
'''
Compute utility lists for non-uniform sampling from discrete distributions.
Refer to https://hips.seas.harvard.edu/blog/2013/03/03/the-alias-method-efficient-sampling-with-many-discrete-outcomes/
for details
'''
K = len(probs)
q = np.zeros(K) #保存样本概率
J = np.zeros(K, dtype=np.int) #保存补1的事件
smaller = []
larger = []
for kk, prob in enumerate(probs):
q[kk] = K*prob
if q[kk] < 1.0:
smaller.append(kk)
else:
larger.append(kk)
while len(smaller) > 0 and len(larger) > 0:
small = smaller.pop()
large = larger.pop()
J[small] = large
q[large] = q[large] + q[small] - 1.0 #q[large]-(1-q[small])
if q[large] < 1.0:
smaller.append(large)
else:
larger.append(large)
return J, q #(alias,prab)
采样
根据Alias Table
随机生成 1—N(事件数) 一个数,确定选中哪列,然后在随机生成一个 0—1 的数,根据概率判断是取样该列的事件还是该列用来补 1 的事件。如选中3列后产生的随机数小于 1/3 则选黄色事件3,否则选蓝色事件1。
def alias_draw(J, q):
'''
Draw sample from a non-uniform discrete distribution using alias sampling.
'''
K = len(J)
kk = int(np.floor(np.random.rand()*K))
if np.random.rand() < q[kk]:
return kk
else:
return J[kk]
342



被折叠的 条评论
为什么被折叠?



