INPUT: text - (list) 文本列表 words - (list) 单词列表 alpha - (list) 话题概率分布,模型超参数 beta - (list) 单词概率分布,模型超参数 K - (int) 设定的话题数 iters - (int) 设定的迭代次数 OUTPUT: theta - (array) 话题的条件概率分布p(zk|dj),这里写成p(zk|dj)是为了和PLSA模型那一章的符号统一一下,方便对照着看 phi - (array) 单词的条件概率
(text, words, alpha, beta, K, iters)
| 84 | |
| 85 | #定义潜在狄利克雷分配函数,采用收缩的吉布斯抽样算法估计模型的参数theta和phi |
| 86 | def do_lda(text, words, alpha, beta, K, iters): |
| 87 | ''' |
| 88 | INPUT: |
| 89 | text - (list) 文本列表 |
| 90 | words - (list) 单词列表 |
| 91 | alpha - (list) 话题概率分布,模型超参数 |
| 92 | beta - (list) 单词概率分布,模型超参数 |
| 93 | K - (int) 设定的话题数 |
| 94 | iters - (int) 设定的迭代次数 |
| 95 | |
| 96 | OUTPUT: |
| 97 | theta - (array) 话题的条件概率分布p(zk|dj),这里写成p(zk|dj)是为了和PLSA模型那一章的符号统一一下,方便对照着看 |
| 98 | phi - (array) 单词的条件概率分布p(wi|zk) |
| 99 | |
| 100 | ''' |
| 101 | M = len(text) #文本数 |
| 102 | V = len(words) #单词数 |
| 103 | N_MK = np.zeros((M, K)) #文本-话题计数矩阵 |
| 104 | N_KV = np.zeros((K, V)) #话题-单词计数矩阵 |
| 105 | N_M = np.zeros(M) #文本计数向量 |
| 106 | N_K = np.zeros(K) #话题计数向量 |
| 107 | Z_MN = [] #用来保存每条文本的每个单词所在位置处抽样得到的话题 |
| 108 | #算法20.2的步骤(2),对每个文本的所有单词抽样产生话题,并进行计数 |
| 109 | for m in range(M): |
| 110 | zm = [] |
| 111 | t = text[m] |
| 112 | for n, w in enumerate(t): |
| 113 | v = words.index(w) |
| 114 | z = np.random.randint(K) |
| 115 | zm.append(z) |
| 116 | N_MK[m, z] += 1 |
| 117 | N_M[m] += 1 |
| 118 | N_KV[z, v] += 1 |
| 119 | N_K[z] += 1 |
| 120 | Z_MN.append(zm) |
| 121 | #算法20.2的步骤(3),多次迭代进行吉布斯抽样 |
| 122 | for i in range(iters): |
| 123 | print('{}/{}'.format(i+1, iters)) |
| 124 | for m in range(M): |
| 125 | t = text[m] |
| 126 | for n, w in enumerate(t): |
| 127 | v = words.index(w) |
| 128 | z = Z_MN[m][n] |
| 129 | N_MK[m, z] -= 1 |
| 130 | N_M[m] -= 1 |
| 131 | N_KV[z][v] -= 1 |
| 132 | N_K[z] -= 1 |
| 133 | p = [] #用来保存对K个话题的条件分布p(zi|z_i,w,alpha,beta)的计算结果 |
| 134 | sums_k = 0 |
| 135 | for k in range(K): |
| 136 | p_zk = (N_KV[k][v] + beta[v]) * (N_MK[m][k] + alpha[k]) #话题zi=k的条件分布p(zi|z_i,w,alpha,beta)的分子部分 |
| 137 | sums_v = 0 |
| 138 | sums_k += N_MK[m][k] + alpha[k] #累计(nmk + alpha_k)在K个话题上的和 |
| 139 | for t in range(V): |
| 140 | sums_v += N_KV[k][t] + beta[t] #累计(nkv + beta_v)在V个单词上的和 |
| 141 | p_zk /= sums_v |
| 142 | p.append(p_zk) |
| 143 | p = p / sums_k |