我们将涉及以下几点
使用LDA进行主题建模
使用pyLDAvis可视化主题模型
使用t-SNE可视化LDA结果
相关视频:文本挖掘:主题模型(LDA)及R语言实现分析游记数据
文本挖掘:主题模型(LDA)及R语言实现分析游记数据
时长12:59
In?[1]:
from?scipy?import?sparse?as?sp
Populating?the?interactive?namespace?from?numpy?and?matplotlib
In?[2]:
docs?=?array(p_df\['PaperText'\])?预处理和矢量化文档
In?[3]:
from?nltk.stem.wordnet?import?WordNetLemmatizer
from?nltk.tokenize?import?RegexpTokenizer
def?docs_preprocessor(docs):
tokenizer?=?RegexpTokenizer(r'\\w+')
for?idx?in?range(len(docs)):
docs\[idx\]?=?docs\[idx\].lower()??#?Convert?to?lowercase.
docs\[idx\]?=?tokenizer.tokenize(docs\[idx\])??#?Split?into?words.
#?删除数字,但不要删除包含数字的单词。
docs?=?\[\[token?for?token?in?doc?if?not?token.isdigit()\]?for?doc?in?docs\]
#?删除仅一个字符的单词。
docs?=?\[\[token?for?token?in?doc?if?len(token)?>?3\]?for?doc?in?docs\]
#?使文档中的所有单词规则化
lemmatizer?=?WordNetLemmatizer()
docs?=?\[\[lemmatizer.lemmatize(token)?for?token?in?doc\]?for?doc?in?docs\]
return?docs
In?[4]:
docs?=?docs_preprocessor(docs)?计算双字母组/三元组:
主题非常相似,可以区分它们是短语而不是单个单词。
In?[5]:
from?gensim.models?import?Phrases
#?向文档中添加双字母组和三字母组(仅出现10次或以上的文档)。
bigram?=?Phrases(docs,?min_count=10)
trigram?=?Phrases(bigram\[docs\])
for?idx?in?range(len(docs)):
for?token?in?bigram\[docs\[idx\]\]:
if?'_'?in?token:
#?Token?is?a?bigram,?add?to?document.
docs\[idx\].append(token)
for?token?in?trigram\[docs\[idx\]\]:
if?'_'?in?token:
#?token是一个二元组,添加到文档中。
docs\[idx\].append(token)
Using?TensorFlow?backend.
/opt/conda/lib/python3.6/site-packages/gensim/models/phrases.py:316:?UserWarning:?For?a?faster?implementation,?use?the?gensim.models.phrases.Phraser?class
warnings.warn("For?a?faster?implementation,?use?the?gensim.models.phrases.Phraser?class")删除
In?[6]:
from?gensim.corpora?import?Dictionary
#?创建文档的字典表示
dictionary?=?Dictionary(docs)
print('Number?of?unique?words?in?initital?documents:',?len(dictionary))
#?过滤掉少于10个文档或占文档20%以上的单词。
dictionary.filter\_extremes(no\_below=10,?no_above=0.2)
print('Number?of?unique?words?after?removing?rare?and?common?words:',?len(dictionary))
Number?of?unique?words?in?initital?documents:?39534
Number?of?unique?words?after?removing?rare?and?common?words:?6001
清理常见和罕见的单词,我们最终只有大约6%的词。
矢量化数据:
第一步是获得每个文档的单词表示。
In?[7]:
corpus?=?\[dictionary.doc2bow(doc)?for?doc?in?docs\]
In?[8]:
print('Number?of?unique?tokens:?%d'?%?len(dictionary))
print('Number?of?documents:?%d'?%?len(corpus))
Number?of?unique?tokens:?6001
Number?of?documents:?403
通过词袋语料库,我们可以继续从文档中学习我们的主题模型。
训练LDA模型?
In?[9]:
from?gensim.models?import?LdaModel
In?[10]:
%time?model?=?LdaModel(corpus=corpus,?id2word=id2word,?chunksize=chunksize,?\
alpha='auto',?eta='auto',?\
iterations=iterations,?num\_topics=num\_topics,?\
passes=passes,?eval\_every=eval\_every)
CPU?times:?user?3min?58s,?sys:?348?ms,?total:?3min?58s
Wall?time:?3min?59s如何选择主题数量?
LDA是一种无监督的技术,这意味着我们在运行模型之前不知道在我们的语料库中有多少主题存在。 主题连贯性是用于确定主题数量的主要技术之一。
但是,我使用了LDA可视化工具pyLDAvis,尝试了几个主题并比较了结果。 四个似乎是最能分离主题的最佳主题数量。
In?[11]:
import?pyLDAvis.gensim
pyLDAvis.enable_notebook()
import?warnings
warnings.filterwarnings("ignore",?category=DeprecationWarning)
In?[12]:
Out[12]:
我们在这看到什么?
左侧面板,标记为Intertopic Distance Map,圆圈表示不同的主题以及它们之间的距离。类似的主题看起来更近,而不同的主题更远。图中主题圆的相对大小对应于语料库中主题的相对频率。
如何评估我们的模型??
将每个文档分成两部分,看看分配给它们的主题是否类似。 =>越相似越好
将随机选择的文档相互比较。 =>越不相似越好
In?[13]:
from?sklearn.metrics.pairwise?import?cosine_similarity
p_df\['tokenz'\]?=?docs
docs1?=?p_df\['tokenz'\].apply(lambda?l:?l\[:int0(len(l)/2)\])
docs2?=?p_df\['tokenz'\].apply(lambda?l:?l\[int0(len(l)/2):\])
领取专属 10元无门槛券
私享最新 技术干货