Alias method

参考链接:

  1. python实现:https://lips.cs.princeton.edu/the-alias-method-efficient-sampling-with-many-discrete-outcomes/
import numpy        as np
import numpy.random as npr

def alias_setup(probs):
    K       = len(probs)
    q       = np.zeros(K)
    J       = np.zeros(K, dtype=np.int)

    # Sort the data into the outcomes with probabilities
    # that are larger and smaller than 1/K.
    smaller = []
    larger  = []
    for kk, prob in enumerate(probs):
        q[kk] = K*prob
        if q[kk] < 1.0:
            smaller.append(kk)
        else:
            larger.append(kk)

    # Loop though and create little binary mixtures that
    # appropriately allocate the larger outcomes over the
    # overall uniform mixture.
    while len(smaller) > 0 and len(larger) > 0:
        small = smaller.pop()
        large = larger.pop()

        J[small] = large
        q[large] = q[large] - (1.0 - q[small])

        if q[large] < 1.0:
            smaller.append(large)
        else:
            larger.append(large)

    return J, q

def alias_draw(J, q):
    K  = len(J)

    # Draw from the overall uniform mixture.
    kk = int(np.floor(npr.rand()*K))

    # Draw from the binary mixture, either keeping the
    # small one, or choosing the associated larger one.
    if npr.rand() < q[kk]:
        return kk
    else:
        return J[kk]

K = 5
N = 1000

# Get a random probability vector.
probs = npr.dirichlet(np.ones(K), 1).ravel()

# Construct the table.
J, q = alias_setup(probs)

# Generate variates.
X = np.zeros(N)
for nn in xrange(N):
    X[nn] = alias_draw(J, q)
  1. 算法思想:https://www.keithschwarz.com/darts-dice-coins/

Algorithm: Alias Method

  • Initialization:
    1. Create arrays AliasAlias and Prob , each of size n .
    2. Create a balanced binary search tree T .
    3. Insert n⋅pi into T for each probability i .
    4. For j=1 to n−1 :
      1. Find and remove the smallest value in T ; call it pl.
      2. Find and remove the largest value in T ; call it pg .
      3. Set Prob[l]=pl .
      4. Set Alias[l]=g .
      5. Set pg:=pg−(1−pl) .
      6. Add pg to T.
    5. Let i be the last probability remaining, which must have weight 1.
    6. Set Prob[i]=1 .
  • Generation:
    1. Generate a fair die roll from an n-sided die; call the side i .
    2. Flip a biased coin that comes up heads with probability Prob[i] .
    3. If the coin comes up "heads," return i .
    4. Otherwise, return Alias[i] .
  1. 思想简单介绍:https://blog.csdn.net/qq_33765907/article/details/79182355
  2. 各版本代码实现:https://blog.csdn.net/z69183787/article/details/53782322
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
def forward(self, l, ab, y, idx=None): K = int(self.params[0].item()) T = self.params[1].item() Z_l = self.params[2].item() Z_ab = self.params[3].item() momentum = self.params[4].item() batchSize = l.size(0) outputSize = self.memory_l.size(0) # the number of sample of memory bank inputSize = self.memory_l.size(1) # the feature dimensionality # score computation if idx is None: # 用 AliasMethod 为 batch 里的每个样本都采样 4096 个负样本的 idx idx = self.multinomial.draw(batchSize * (self.K + 1)).view(batchSize, -1) # sample positives and negatives idx.select(1, 0).copy_(y.data) # sample weight_l = torch.index_select(self.memory_l, 0, idx.view(-1)).detach() weight_l = weight_l.view(batchSize, K + 1, inputSize) out_ab = torch.bmm(weight_l, ab.view(batchSize, inputSize, 1)) # sample weight_ab = torch.index_select(self.memory_ab, 0, idx.view(-1)).detach() weight_ab = weight_ab.view(batchSize, K + 1, inputSize) out_l = torch.bmm(weight_ab, l.view(batchSize, inputSize, 1)) if self.use_softmax: out_ab = torch.div(out_ab, T) out_l = torch.div(out_l, T) out_l = out_l.contiguous() out_ab = out_ab.contiguous() else: out_ab = torch.exp(torch.div(out_ab, T)) out_l = torch.exp(torch.div(out_l, T)) # set Z_0 if haven't been set yet, # Z_0 is used as a constant approximation of Z, to scale the probs if Z_l < 0: self.params[2] = out_l.mean() * outputSize Z_l = self.params[2].clone().detach().item() print("normalization constant Z_l is set to {:.1f}".format(Z_l)) if Z_ab < 0: self.params[3] = out_ab.mean() * outputSize Z_ab = self.params[3].clone().detach().item() print("normalization constant Z_ab is set to {:.1f}".format(Z_ab)) # compute out_l, out_ab out_l = torch.div(out_l, Z_l).contiguous() out_ab = torch.div(out_ab, Z_ab).contiguous() # # update memory with torch.no_grad(): l_pos = torch.index_select(self.memory_l, 0, y.view(-1)) l_pos.mul_(momentum) l_pos.add_(torch.mul(l, 1 - momentum)) l_norm = l_pos.pow(2).sum(1, keepdim=True).pow(0.5) updated_l = l_pos.div(l_norm) self.memory_l.index_copy_(0, y, updated_l) ab_pos = torch.index_select(self.memory_ab, 0, y.view(-1)) ab_pos.mul_(momentum) ab_pos.add_(torch.mul(ab, 1 - momentum)) ab_norm = ab_pos.pow(2).sum(1, keepdim=True).pow(0.5) updated_ab = ab_pos.div(ab_norm) self.memory_ab.index_copy_(0, y, updated_ab) return out_l, out_ab
04-19

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值