python 基于LDA长文本主题提取并预测分类
代码获取-更多实战项目见文章底部官网
全部代码已经上传csdn
下载地址: CSDN资源下载地址
Lda算法原理,知乎上有很完善的算法介绍,这里就不多废话了。
本文主要是用来做文本主题提取,再根据这些主题对现有的文本进行分类。因为数据问题,效果一般,算法设计思路,仅供参考。
数据准备
这一阶段主要是对你的问题本进行处理,清洗你的数据。中文文本预处理,主要包括去空格、去表单符号、去停用词、分词等。根据个人需求进行文本预处理。讲数据处理成下面数据格式即list套list的数据格式。
最初数据如下所示,一条一条文本,换行符分割。
在漆黑的夜空里看满天璀璨的星星,非常非常的密集,同时月亮也异常明亮。最主要的是在满天繁星中,靠近月亮的3颗星星排列成“勾”的样子,他们特别的明亮。
......................................................(省略好多数据)
沟里漂着很多死尸大人小孩都有,我顺着消流的方向走,看到臭水带着死尸流进了苹果园,我很怕!
经过初步处理后,也就是通过下文里面的deal_words()方法得到下面
[['满天璀璨', '星星', '月亮', '明亮', '靠近', '排列'],........., ['沟里', '漂着', '死尸','大人小孩']]
具体数据处理可以参照:数据预处理
LDA模型实现
思路:
- 将训练数据和预测数据混合并提取词典库
- 利用词典库将训练数据转换成one-hot编码
- 利用gensim提供的API做模型提取主题
- 将混入的预测数据转换成one-hot编码
- 预测分类主题
这里模型采用gensim提供的API进行实现,代码如下:
def lad_model(train_data):
# 读取预测分类数据
test_data = deal_words(read_text_file('./data/set/test_text.txt'))
# 拼接提取词典库
contents = train_data + test_data
# 根据文本获取词典
dictionary = corpora.Dictionary(contents)
# 词典创建语料库
corpus = [dictionary.doc2bow(doc) for doc in train_data]
#调用LDA模型,请求潜在主题数30;训练语料库2次
lda = gensim.models.ldamodel.LdaModel(corpus, num_topics=30, id2word=dictionary,
passes=2)
#导出模型分类数量
data = lda.print_topics(num_topics=3, num_words=5)
# 打印主题,10个主题,20个单词
for item in data:
print(item)
print("--------------------split line---------------------")
# 测试数据转换
test_vec = [dictionary.doc2bow(doc) for doc in test_data]
#预测并打印结果
for i, item in enumerate(test_vec):
topic = lda.get_document_topics(item)
keys = target.keys()
print('第',i+1,'条记录分类结果:',topic)
全部代码以及效果
lad模型代码以及处理数据代码。这里处理数据的核心代码text_deal.py,写在了同级目录(lda_demo)下面。
from lda_demo import text_deal as td
from gensim import corpora, models
import gensim
"""
读取text文件
intput:url
output:list结构的文本数据
"""
def read_text_file(url):
dream_text = open(url, 'r+', encoding='utf-8')
return dream_text.read().split("\n\n")
"""
停用词/分词
"""
def deal_words(contents):
# 去除空格
contents = td.remove_blank_space(contents)
# 获取分词结果
contents = td.cut_words(contents)
# 去除停用词
contents = td.drop_stopwords(contents)
return contents
def lad_model(train_data):
# 读取预测分类数据
test_data = deal_words(read_text_file('./data/set/test_text.txt'))
# 拼接提取词典库
contents = train_data + test_data
# 根据文本获取词典
dictionary = corpora.Dictionary(contents)
# 词典创建语料库
corpus = [dictionary.doc2bow(doc) for doc in train_data]
#调用LDA模型,请求潜在主题数30;训练语料库2次
lda = gensim.models.ldamodel.LdaModel(corpus, num_topics=30, id2word=dictionary,
passes=2)
#导出模型分类数量
data = lda.print_topics(num_topics=3, num_words=5)
# 打印主题,10个主题,20个单词
for item in data:
print(item)
print("--------------------split line---------------------")
# 测试数据转换
test_vec = [dictionary.doc2bow(doc) for doc in test_data]
#预测并打印结果
for i, item in enumerate(test_vec):
topic = lda.get_document_topics(item)
keys = target.keys()
print('第',i+1,'条记录分类结果:',topic)
if __name__ == '__main__':
# 据集读取
contents = read_text_file('./data/set/train_text.txt')
# 文本处理
contents = deal_words(contents)
# LDAmodel
lad_model(contents)
text_deal.py代码如下:
"""
自然语言处理---文本预处理
"""
import jieba
import pandas as pd
"""
加载初始数据信息
str:文件传输路径
index:所需真实值索引列表
"""
def read_data(str, index):
dream_data = pd.read_csv(str)
return dream_data.values[:, index]
"""
去掉文本中的空格
input:our_data为list文本数据
output:去除空格后的文本list
"""
def remove_blank_space(contents):
contents_new = map(lambda s: s.replace(' ', ''), contents)
return list(contents_new)
"""
判断单词是否为中文
input:word单个单词
output:是中文True,不是中文False
"""
def is_chinese(word):
if word >= u'\u4e00' and word <= u'\u9fa5':
return True
else:
return False
"""
判断短句是否为纯中文
input:words短句
output:是中文True,不是中文False
"""
def is_chinese_words(words):
for word in words:
if word >= u'\u4e00' and word <= u'\u9fa5':
continue
else:
return False
return True
"""
将文本数据格式化去除非中文字符
input:contents list结构的文本数据
output:去除非中文字符的数据
"""
def format_contents(contents):
contents_new = []
for content in contents:
content_str = ''
for i in content:
if is_chinese(i):
content_str = content_str + i
contents_new.append(content_str)
return contents_new
"""
对文本进行jieba分词
input:contents文本list
output:分词后的文本list
"""
def cut_words(contents):
cut_contents = map(lambda s: list(jieba.lcut(s)), contents)
return list(cut_contents)
"""
去除停用词/标点符号
input:contents文本list(list中保存list)
output:去除停用词后的文本list
"""
def drop_stopwords(contents):
# 初始化获取停用词表
stop = open('./data/word_deal/stop_word_cn.txt', encoding='utf-8')
stop_me = open('./data/word_deal/stop_one_mx.txt', encoding='utf-8')
key_words = open('./data/word_deal/key_words.txt', encoding='utf-8')
#分割停用词/自定义停用词/关键词
stop_words = stop.read().split("\n")
stop_me_words = stop_me.read().split("\n")
key_words = key_words.read().split("\n")
#定义返回后的结果
contents_new = []
#遍历处理数据
for line in contents:
line_clean = []
for word in line:
if (word in stop_words or word in stop_me_words) and word not in key_words:
continue
if is_chinese_words(word):
line_clean.append(word)
contents_new.append(line_clean)
return contents_new
运行效果
(1, '0.023*"说" + 0.018*"怀孕" + 0.016*"父亲" + 0.014*"里" + 0.011*"岁"')
--------------------split line---------------------
(25, '0.023*"说" + 0.012*"办公室" + 0.010*"是不是" + 0.009*"朋友" + 0.009*"大门"')
--------------------split line---------------------
(20, '0.014*"同学" + 0.010*"跑" + 0.010*"培训" + 0.010*"骑" + 0.009*"机构"')
--------------------split line---------------------
第 1 条记录分类结果: [(4, 0.24392343), (8, 0.1395505), (10, 0.09619252), (18, 0.16527545), (21, 0.17173427), (23, 0.11055296)]
第 2 条记录分类结果: [(5, 0.124014), (13, 0.28862998), (16, 0.099018164), (19, 0.09216843), (24, 0.12537746), (29, 0.22633219)]
第 3 条记录分类结果: [(7, 0.101059936), (10, 0.37497482), (21, 0.15868592), (23, 0.19114888), (29, 0.12510397)]
第 4 条记录分类结果: [(1, 0.082532495), (4, 0.17312291), (14, 0.072532885), (17, 0.38016438), (19, 0.050784156), (21, 0.21228231)]
- 文本处理根据自己需求一定要做好,清洗掉不必要的数据;否则影响主题分类。
- 语料库全面结果会更加友好吧,在语料库范围内分类效果还是比较好的,但是新数据效果一般。
欢迎批评指正!