引言:
在进行景区评论数据的LDA建模时,精确的分词是至关重要的。然而,通用的分词工具在处理特定领域的文本时可能表现不佳。针对这一挑战,本文探讨了如何利用本地词库,特别是搜狗词库中关于旅游领域的专业词汇,对Jieba分词进行精细化调整。通过这种方式,我们可以实现对景区评论数据的更精准、更有效的LDA建模,从而揭示出更深层次的见解和洞察。本文将探讨如何结合本地词库定制词典,优化分词过程,从而提升LDA模型的表现,为景区评论数据的分析与应用提供更可靠的基础。
正文
lda模型主题示意图
从主题结果来看分词结果有些词如中山市被分成 中 山市 这种,为后期的LDA建模带来了误差。
因此组建自己的词库很有必要,替换默认词典+自定义词典的方式,对jieba的分词进行更精细化的调整。
查找了很多资料最终选择使用搜狗词库去组建自己的词库
首先下载相关词库
下载后将.scel文件转换为.txt文件
词库格式转化
使用以下脚本进行转换
#!/usr/bin/python
# -*- coding: utf-8 -*-
import struct
import sys
import binascii
import pdb
# 搜狗的scel词库就是保存的文本的unicode编码,每两个字节一个字符(中文汉字或者英文字母)
# 找出其每部分的偏移位置即可
# 主要两部分
# 1.全局拼音表,貌似是所有的拼音组合,字典序
# 格式为(index,len,pinyin)的列表
# index: 两个字节的整数 代表这个拼音的索引
# len: 两个字节的整数 拼音的字节长度
# pinyin: 当前的拼音,每个字符两个字节,总长len
#
# 2.汉语词组表
# 格式为(same,py_table_len,py_table,{word_len,word,ext_len,ext})的一个列表
# same: 两个字节 整数 同音词数量
# py_table_len: 两个字节 整数
# py_table: 整数列表,每个整数两个字节,每个整数代表一个拼音的索引
#
# word_len:两个字节 整数 代表中文词组字节数长度
# word: 中文词组,每个中文汉字两个字节,总长度word_len
# ext_len: 两个字节 整数 代表扩展信息的长度,好像都是10
# ext: 扩展信息 前两个字节是一个整数(不知道是不是词频) 后八个字节全是0
#
# {word_len,word,ext_len,ext} 一共重复same次 同音词 相同拼音表
# 拼音表偏移,
startPy = 0x1540;
# 汉语词组表偏移
startChinese = 0x2628;
# 全局拼音表
GPy_Table = {}
# 解析结果
# 元组(词频,拼音,中文词组)的列表
GTable = []
def byte2str(data):
'''将原始字节码转为字符串'''
i = 0;
length = len(data)
ret = u''
while i < length:
x = data[i:i+2]
t = chr(struct.unpack('H', x)[0])
if t == u'\r':
ret += u'\n'
elif t != u' ':
ret += t
i += 2
return ret
# 获取拼音表
def getPyTable(data):
if data[0:4] != bytes(map(ord,"\x9D\x01\x00\x00")):
return None
data = data[4:]
pos = 0
length = len(data)
while pos < length:
index = struct.unpack('H', data[pos:pos +2])[0]
# print index,
pos += 2
l = struct.unpack('H', data[pos:pos + 2])[0]
# print l,
pos += 2
py = byte2str(data[pos:pos + l])
# print py
GPy_Table[index] = py
pos += l
# 获取一个词组的拼音
def getWordPy(data):
pos = 0
length = len(data)
ret = u''
while pos < length:
index = struct.unpack('H', data[pos:pos + 2])[0]
ret += GPy_Table[index]
pos += 2
return ret
# 获取一个词组
def getWord(data):
pos = 0
length = len(data)
ret = u''
while pos < length:
index = struct.unpack('H', data[pos:pos +2])[0]
ret += GPy_Table[index]
pos += 2
return ret
# 读取中文表
def getChinese(data):
# import pdb
# pdb.set_trace()
pos = 0
length = len(data)
while pos < length:
# 同音词数量
same = struct.unpack('H', data[pos:pos + 2])[0]
# print '[same]:',same,
# 拼音索引表长度
pos += 2
py_table_len = struct.unpack('H', data[pos:pos + 2])[0]
# 拼音索引表
pos += 2
py = getWordPy(data[pos: pos + py_table_len])
# 中文词组
pos += py_table_len
for i in range(same):
# 中文词组长度
c_len = struct.unpack('H', data[pos:pos +2])[0]
# 中文词组
pos += 2
word = byte2str(data[pos: pos + c_len])
# 扩展数据长度
pos += c_len
ext_len = struct.unpack('H', data[pos:pos +2])[0]
# 词频
pos += 2
count = struct.unpack('H', data[pos:pos +2])[0]
# 保存
GTable.append((count, py, word))
# 到下个词的偏移位置
pos += ext_len
def deal(file_name):
print
'-' * 60
f = open(file_name, 'rb')
data = f.read()
f.close()
if data[0:12] != bytes(map(ord,"\x40\x15\x00\x00\x44\x43\x53\x01\x01\x00\x00\x00")):
print
"确认你选择的是搜狗(.scel)词库?"
sys.exit(0)
# pdb.set_trace()
print
"词库名:", byte2str(data[0x130:0x338]) # .encode('GB18030')
print
"词库类型:", byte2str(data[0x338:0x540]) # .encode('GB18030')
print
"描述信息:", byte2str(data[0x540:0xd40]) # .encode('GB18030')
print
"词库示例:", byte2str(data[0xd40:startPy]) # .encode('GB18030')
getPyTable(data[startPy:startChinese])
getChinese(data[startChinese:])
if __name__ == '__main__':
# 将要转换的词库添加在这里就可以了
o = ['旅游词汇大全【官方推荐】.scel',"旅游词汇大全.scel","旅游词汇大全 (1).scel"]
for f in o:
deal(f)
# 保存结果
f = open('sougou.txt', 'w',encoding='utf-8')
for count, py, word in GTable:
# GTable保存着结果,是一个列表,每个元素是一个元组(词频,拼音,中文词组),有需要的话可以保存成自己需要个格式
# 我没排序,所以结果是按照上面输入文件的顺序
f.write((('{%(count)s}' % {'count': count} + py + ' ' + word))) # 最终保存文件的编码,可以自给改
f.write('\n')
f.close()
运行结果示意图
对词库进行去除和预处理
将众多词库解析统合后得到4000多个词条,接着进行去重和预处理
编写脚本entry_preprocessing.py进行处理
# Author: 冷月半明
# Date: 2024/1/26
# Description: 将统合后的词库进行预处理,只保留每行的中文字段,然后进行去重.
import re
# 读取文件并提取中文字段
def extract_chinese(file_path):
chinese_words = set() # 用集合来存储中文字段,实现去重
with open(file_path, 'r', encoding='utf-8') as file:
for line in file:
chinese = re.findall(r'[\u4e00-\u9fa5]+', line) # 使用正则表达式提取中文
if chinese:
chinese_words.add(chinese[0])
return chinese_words
# 文件路径
file_path = 'sougou.txt'
# 提取中文字段并去重
chinese_words = extract_chinese(file_path)
# 将中文字段保存到txt文件
output_file = 'chinese_words.txt'
with open(output_file, 'w', encoding='utf-8') as file:
for word in chinese_words:
file.write(word + '\n')
print(f"去重后的中文字段已保存到文件: {output_file}")
结果展示图
将txt文件作为custom_dict分词词库参与分词。
与此同时,也可以手动的像词库添加一些专业词汇或常用词汇以达到更优的分词效果。
重新建模后主题展示图
可以看到中山市的主题的话题关键词中 原先的中山已被中山市替换,说明从分词角度来说优化成功,LDA模型更加合理。
本文章仅供学习参考