NLP系列——文本预处理1

对一篇文章,一般的做法是先进行分词,后续是对词语进行语义特征提取与建模,不过也有人是用句子或者单字粒度,个人实验的结果是字符级比分词好,句子级没有试过。

分词后是去除停用词以及标点符号,停用词表到github上搜索一下有挺多,里面是像咳、哇、哈这些没啥用的词,把他们去掉对文本语义没什么影响,却可以降低文本处理的复杂度,词的个数越少,表示一个词或者句子的向量维度就可以更低。

1. 分词

分词一般使用jieba库来分词,这里也推荐另一个 synonyms包。他是在jieba的基础上做的,在一些方面更方便,做一下对比:

  • jieba:分词、词性标注
  • synonyms:分词、词性标注、近义词、语义相似度、词嵌入

总体感觉synonyms分词、词性标注一次性完成比较方便,功能也丰富。两者也可组合使用。

1.1 导入库

注意两个包组合使用时,jieba在前,synonyms在后,不然会报错。

import jieba
import jieba.posseg as pseq
import synonyms

引用synonyms的时候,会发现有这么一句输出,可以知道里面也是有用jieba的来分词的
synonyms导入的输出

1.2 分词

分别用jieba、synonyms分词跟词性标注,发现结果是一样的。注意输入只能是一个字符串,不能输入多个,多个文本就用循环。

1.2.1 jieba分词与词性标注

# 要分词的文本
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

1.2.2 synonyms分词与词性标注

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’]

对比可以发现,两个的分词跟词性标注结果是一样的。

1.3 导入自定义词库

向 ‘今天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区’, ‘阳光明媚’, ‘!’]

可以发现添加词典后对新语料分词准确很多。

2. 去除停用词

要去除停用词,首先得有一个停用词表,这里给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区’, ‘阳光明媚’]

3. 其他

预处理这里也有看到有人用近义词替换,我试着效果不是很好。用的是synonyms.nearby(word)

3.1 获取近义词

# 返回一个元组,包含两个列表
# 第一个列表是近义词
# 第二个列表是对应的相似度
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]

3.2 近义词替换

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值