import pandas as pd import numpy as np import gensim from gensim.models import LdaModel, CoherenceModel import matplotlib.pyplot as plt import seaborn as sns from collections import defaultdict
# 导出每个时间窗的主题-词分布,老板可以打开 Excel 看 with pd.ExcelWriter('topic_word_dist.xlsx', engine='openpyxl') as writer: for period, data in per_slice_models.items(): lda = data['model'] rows = [] for tid inrange(K): for word, prob in lda.show_topic(tid, topn=20): rows.append({'主题': f'T{tid}', '词': word, '概率': f'{prob:.4f}'}) pd.DataFrame(rows).to_excel(writer, sheet_name=str(period), index=False)
四、主题强度词分布表
除了主题-词概率还要看主题-时间强度——把两个维度合并成一张表:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# 每个主题在每个时间窗的"代表词强度" strength_words = [] for period, data in per_slice_models.items(): lda = data['model'] for tid inrange(K): top_words = lda.show_topic(tid, topn=5) words = ', '.join([w for w, _ in top_words]) intensity = data['doc_topic_dist'].mean(axis=0)[tid] strength_words.append({ '时间窗': str(period), '主题': f'T{tid}', '强度': round(float(intensity), 4), '代表词': words })
defalign_topics(models_dict, K): """用 Hellinger 距离做主题对齐,返回映射 {period: {orig_id: aligned_id}}""" periods = list(models_dict.keys()) base = periods[0] # 以第一个时间窗为基准 alignment = {base: {i: i for i inrange(K)}} for prev, curr inzip(periods[:-1], periods[1:]): prev_model = models_dict[prev]['model'] curr_model = models_dict[curr]['model'] # 算所有主题对之间的距离 (K x K 矩阵) dist_matrix = np.zeros((K, K)) for i inrange(K): for j inrange(K): p = np.zeros(K); q = np.zeros(K) p[i] = 1; q[j] = 1 # 实际应该用主题的词分布算 Hellinger p_dist = np.array([prob for _, prob in prev_model.show_topic(i, topn=20)]) q_dist = np.array([prob for _, prob in curr_model.show_topic(j, topn=20)]) dist_matrix[i][j] = hellinger(p_dist, q_dist) # 贪心匹配:相似度最低的优先配对 mapping = {} used = set() pairs = [] for i inrange(K): for j inrange(K): pairs.append((dist_matrix[i][j], i, j)) pairs.sort() for dist, i, j in pairs: if i notin mapping and j notin used: mapping[i] = j used.add(j) # 没匹配上的分配新 ID for i inrange(K): if i notin mapping: new_id = max(used) + 1 mapping[i] = new_id used.add(new_id) alignment[curr] = mapping return alignment