
由于之前主要研究现代信号处理,对自然语言处理NLP不太了解,所以这篇文章诸位权当看个乐子。
福尔摩斯就不介绍了,大家都懂的,因此直接进入正题。本文使用Latent Dirichlet Allocation(LDA)主题模型分析福尔摩斯的原著小说和短篇小说中的文本。 LDA 是自然语言处理中的生成统计模型,可以发现文档中的潜在主题并推断主题中的单词概率,本文分为2个部分。在第1部分中,仅涉及福尔摩斯的原创作品。 2个数据集的总词数分别为203936个和454214,一共处理和分析了 658,150 个单词。福尔摩斯原著小说中共发现了4个主题,分别是“sir, holmes, think, case, watson“(“福尔摩斯与华生—友谊与主角”),“say, come, know, well, man”(“谜团和解谜”),“时间,小,房间,方式,发现”(“困难(例如时间和空间限制)”)和“人,得到,拿,问,做"(“案例的属性”)。在第 2 部分中,使用 3 部经典小说(简·奥斯汀的《理智与情感》、艾米莉·勃朗特的《呼啸山庄》和夏洛特·勃朗特的《简爱》)与福尔摩斯的短篇故事集来训练另一个 LDA 模型。第2部分新增的3部经典小说(《理智与情感》、《呼啸山庄》和《简爱》)分别为186302字、116537字和119580字,合计422419字。
首先开始第一部分,从第1组小说中加载和提取文本数据
data = readtable("SH_novels.csv",TextType="string");
head(data)

textData = data.Text;textData(1:4)

准备用于分析的文本数据
定义停用词列表
customStopWords = [stopWords "down" "upon" "back" "though" "away"];
reshape(customStopWords,[46 5])

然后进行处理
documents = preprocessText(textData);
documents(1:4)

创建词袋模型
bag = bagOfWords(documents)

词袋模型中删除总共出现不超过2次的词,并从词袋模型中删除任何不包含单词的文档。
bag = removeInfrequentWords(bag,2);
bag = removeEmptyDocuments(bag)

列出第一组小说中排名靠前的单词的频率
找出模型中排名前 20 的单词
k = 20;
T = topkwords(bag,k)

选择 LDA 模型的主题数量
随机留出 25% 的文档进行验证
numDocuments = numel(documents)
cvp = cvpartition(numDocuments,'HoldOut',0.25);
documentsTrain = documents(cvp.training);
documentsValidation = documents(cvp.test);
从训练文档创建一个词袋模型,删除总共不超过两次的单词,删除任何不包含单词的文档
bagTrain = bagOfWords(documentsTrain);
bagTrain = removeInfrequentWords(bagTrain,2);
bagTrain = removeEmptyDocuments(bagTrain);
选择与其他数量的主题相比最小化perplexity的主题
for i = 1:numel(numTopicsRange)
numTopicsTrain = numTopicsRange(i);
mdl = fitlda(bagTrain,numTopicsTrain, ...
'Solver','savb', ...
'Verbose',0);
[~,validationPerplexity(i)] = logp(mdl,documentsValidation);
timeElapsed(i) = mdl.FitInfo.History.TimeSinceStart(end);
end
显示图中每个主题数量的perplexity和时间
figure
yyaxis left
plot(numTopicsRange,validationPerplexity,'+-')
ylabel("Validation Perplexity")
yyaxis right
plot(numTopicsRange,timeElapsed,'o-')
ylabel("Time Elapsed (s)")
legend(["Validation Perplexity" "Time Elapsed (s)"],'Location','southeast')
xlabel("Number of Topics")

上图表明,拟合具有 3 个主题的模型效果还是不错的
LDA 模型拟合
尽管在上面的方法中发现这组文档的最佳主题数是 3,但在运行期间发现,拟合具有 4 个主题的 LDA 模型所需的时间也不多
rng("default")
numTopics = 4;
mdl = fitlda(bag,numTopics,Verbose=0);
使用Word Clouds可视化主题

列出第一组小说中每个主题的 5 个热门词
k = 5;
for topicIdx = 1:numTopics
"Topic "+ topicIdx + " in Novels:"
tbl = topkwords(mdl,k,topicIdx)
topWords(topicIdx) = join(tbl.Word,", ");
end
tbl = 5×2 table
Word |
Score |
|
1 |
"sir" |
0.0227 |
2 |
"holmes" |
0.0134 |
3 |
"think" |
0.0109 |
4 |
"case" |
0.0105 |
5 |
"watson" |
0.0104 |
tbl = 5×2 table
Word |
Score |
|
1 |
"say" |
0.0453 |
2 |
"come" |
0.0313 |
3 |
"know" |
0.0198 |
4 |
"well" |
0.0174 |
5 |
"man" |
0.0152 |
tbl = 5×2 table
Word |
Score |
|
1 |
"time" |
0.0185 |
2 |
"little" |
0.0147 |
3 |
"room" |
0.0120 |
4 |
"way" |
0.0116 |
5 |
"find" |
0.0115 |
tbl = 5×2 table
Word |
Score |
|
1 |
"man" |
0.0301 |
2 |
"get" |
0.0159 |
3 |
"take" |
0.0143 |
4 |
"ask" |
0.0137 |
5 |
"make" |
0.0127 |
查看第一组小说的主题概率
figure
bar(mdl.CorpusTopicProbabilities)
xlabel("Topic")
xticklabels(topWords);
ylabel("Probability")
title("Document Topic Probabilities in Novels")

figurebarh(mdl.DocumentTopicProbabilities,"stacked")xlim([0 1])title("Topic Mixtures in Novels")xlabel("Topic Probability")yticklabels(data.Title)legend(topWords, ... Location="southoutside", ... NumColumns=1)

使用分组条形图可视化多个主题的组合

未完待续

如若转载,请注明出处:https://www.yiheng8.com/96790.html