赞
踩
对一篇文章,一般的做法是先进行分词,后续是对词语进行语义特征提取与建模,不过也有人是用句子或者单字粒度,个人实验的结果是字符级比分词好,句子级没有试过。
分词后是去除停用词以及标点符号,停用词表到github上搜索一下有挺多,里面是像咳、哇、哈这些没啥用的词,把他们去掉对文本语义没什么影响,却可以降低文本处理的复杂度,词的个数越少,表示一个词或者句子的向量维度就可以更低。
分词一般使用jieba库来分词,这里也推荐另一个 synonyms包。他是在jieba的基础上做的,在一些方面更方便,做一下对比:
总体感觉synonyms分词、词性标注一次性完成比较方便,功能也丰富。两者也可组合使用。
注意两个包组合使用时,jieba在前,synonyms在后,不然会报错。
import jieba
import jieba.posseg as pseq
import synonyms
引用synonyms的时候,会发现有这么一句输出,可以知道里面也是有用jieba的来分词的
分别用jieba、synonyms分词跟词性标注,发现结果是一样的。注意输入只能是一个字符串,不能输入多个,多个文本就用循环。
# 要分词的文本
text = '今天A区阳光明媚!'
# jieba分词,lcut直接返回分词列表
result1 = jieba.lcut(text)
print('jieba分词结果:',result1)
# jieba词性标注,返回的是一个迭代器,只能迭代一次
result2 = pseq.cut(text)
print('jieba词性标注结果:')
for word in result2:
# 迭代对象包含词、词性两个属性
print(word.word, word.flag)
输出为
jieba分词结果: [‘今天’, ‘A’, ‘区’, ‘阳光明媚’, ‘!’]
jieba词性标注结果:
今天 t
A eng
区 n
阳光明媚 nr
! x
text = '今天A区阳光明媚!'
# synonyms分词、词性标注
# 一次性返回两个列表,第一个列表是分词结果,第二个是词性标注结果
result3 = synonyms.seg(text)
print('synonyms分词结果:')
print(result3[0])
print('synonyms词性标注结果:')
print(result3[1])
输出为
synonyms分词结果:
[‘今天’, ‘A’, ‘区’, ‘阳光明媚’, ‘!’]
synonyms词性标注结果:
[‘t’, ‘eng’, ‘n’, ‘nr’, ‘x’]
对比可以发现,两个的分词跟词性标注结果是一样的。
向 ‘今天A区阳光明媚!’ 这句话的分词,可以发现有一些词语是分不出来的,可能是专用词或者特殊词之类的,这个时候可以给jieba导入一个自定义词典,他就可以将这些词成功分出来。synonyms添加词典也是用jieba添加即可
添加词典有两种方式:
# 添加单个词
jieba.add_word(word='A区',freq=5,tag='n')
# txt文件形式添加
# 每一行表示一个词:词 词频 词性
jieba.load_userdict('./自定义词典.txt')
添加词典后的分词结果
text = '今天A区阳光明媚!'
# 添加词典结果对比
result4=synonyms.seg(text)
print('添加词典前:')
print(result3[0],'\n')
print('添加词典后:')
print(result4[0])
输出为
添加词典前:
[‘今天’, ‘A’, ‘区’, ‘阳光明媚’, ‘!’]添加词典后:
[‘今天’, ‘A区’, ‘阳光明媚’, ‘!’]
可以发现添加词典后对新语料分词准确很多。
要去除停用词,首先得有一个停用词表,这里给github上的一个资源。分词后,筛选掉当中的停用词就好了,当然也可以筛选调某些词性或者标点符号,做法是一样的。
用这个读取文件,成为一个列表。
stopwords = [w.strip() for w in open('停用词表.txt', 'r', encoding='UTF-8').readlines()]
演示的用下面的代替:
stopwords = ['今天', '!']
result_clean = []
for word in result4[0]:
if word not in stopwords:
result_clean.append(word)
print('去除停用词结果', result_clean)
输出为:
去除停用词结果 [‘A区’, ‘阳光明媚’]
预处理这里也有看到有人用近义词替换,我试着效果不是很好。用的是synonyms.nearby(word)
# 返回一个元组,包含两个列表
# 第一个列表是近义词
# 第二个列表是对应的相似度
word='交叉口'
near=synonyms.nearby(word)
print('结果类型:',type(near))
print('结果长度:',len(near))
print('近义词:',near[0])
print('相似度:',near[1])
输出为
结果类型: <class ‘tuple’>
结果长度: 2
近义词: [‘交叉口’, ‘路口’, ‘交叉路口’, ‘中山路’, ‘街口’, ‘交口’, ‘和平路’, ‘中山北路’, ‘交叉处’, ‘东南侧’]
相似度: [1.0, 0.81871194, 0.7977913, 0.7161459, 0.6995231, 0.69011694, 0.6796811, 0.66988134, 0.6574828, 0.64784586]
line='未管所路口交叉口至加油站路段'
line=jieba.lcut(line)
line_new=[]
for word in line:
near_word=synonyms.nearby(word)
for i in range(1,len(near_word[0])):
if near_word[0][i] in line_new and near_word[1][i]>0.8:
word=near_word[0][i]
break
line_new.append(word)
print('未替换结果:',line)
print('分词结果:',line_new)
输出为
未替换结果: [‘未管’, ‘所’, ‘路口’, ‘交叉口’, ‘至’, ‘加油站’, ‘路段’]
分词结果: [‘未管’, ‘所’, ‘路口’, ‘路口’, ‘至’, ‘加油站’, ‘路段’]
知乎上的一个分词介绍,提供了其他的分词方法,不过没去试过:https://www.zhihu.com/question/19578687
github上的一个NLP项目,收集了很多资源:https://github.com/fighting41love/funNLP
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。