from random import random def crpgen(N = None, alpha = 1.0): """ A generator that implements the Chinese Restaurant Process """ counts = [] n = 0 while N == None or n < N: # Compute the (unnormalized) probabilities of assigning the new object # to each of the existing groups, as well as a new group assign_probs = [None] * (len(counts) + 1) for i in range(len(counts)): assign_probs[i] = counts[i] / (n + alpha) assign_probs[-1] = alpha / (n + alpha) # Draw the new object's assignment from the discrete distribution with # these probabilities (discrete_draw() handles the normalization) and # yield the assignment assignment = discrete_draw(assign_probs) yield assignment # Update the counts for next time, adding a new count if a new group was # created if assignment == len(counts): counts.append(0) counts[assignment] += 1 n += 1 def discrete_draw(p): """ Make a random draw from the discrete distribution parameterized by the vector of weights p, which need not be normalized (sum to 1) """ z = sum(p) a = random() tot = 0.0 for i in range(len(p)): tot += p[i] / z if a < tot: return i