文本处理技术
NLP项目主要流程
分词 (Word Segmentation)
所有分词需要依靠词库
常用开源分词工具:
Jieba分词 https://github.com/fxsjy/jieba
SnowNLP https://github.com/isnowfy/snownlp
LTP http://www.ltp-cloud.com/
HanNLP https://github.com/hankcs/HanLP/
支持三种分词模式:
- 精确模式,试图将句子最精确地切开,适合文本分析;
- 全模式,把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义;
- 搜索引擎模式,在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。
import jieba
sent = '南京市长江大桥'
#全模式
seg_list = jieba.cut(sent,cut_all=True)
print('/'.join(seg_list))
#精确模式,默认
seg_list = jieba.cut(sent,cut_all=False)
print('/'.join(seg_list))
#搜索引擎模式
seg_list = jieba.cut_for_search(sent)
print('/'.join(seg_list))
详细介绍:Python第三方库jieba(中文分词)入门与进阶(官方文档)
分词算法一:基于匹配规则:最大匹配
基于贪心算法,在词典中进行扫描,尽可能地选择与词典中最长单词匹配的词作为目标分词,然后进行下一次匹配,有前向和后向两种。
算法流程:
假设词典中最长的单词为 5 个(MAX_LENGTH),那么最大匹配的起始子串字数也为 5 个
(1)扫描字典,测试读入的子串是否在字典中
(2)如果存在,则从输入中删除掉该子串,重新按照规则取子串,重复(1)
(3)如果不存在于字典中,则从右向左减少子串长度,重复(1)
分词实例:
比如说输入 “北京大学生前来应聘”,
- 第一轮:取子串 “北京大学生”,正向取词,如果匹配失败,每次去掉匹配字段最后面的一个字
“北京大学生”,扫描 5 字词典,没有匹配,子串长度减 1 变为“北京大学”
“北京大学”,扫描 4 字词典,有匹配,输出“北京大学”,输入变为“生前来应聘” - 第二轮:取子串“生前来应聘”
“生前来应聘”,扫描 5 字词典,没有匹配,子串长度减 1 变为“生前来应”
“生前来应”,扫描 4 字词典,没有匹配,子串长度减 1 变为“生前来”
“生前来”,扫描 3 字词典,没有匹配,子串长度减 1 变为“生前”
“生前”,扫描 2 字词典,有匹配,输出“生前”,输入变为“来应聘”” - 第三轮:取子串“来应聘”
“来应聘”,扫描 3 字词典,没有匹配,子串长度减 1 变为“来应”
“来应”,扫描 2 字词典,没有匹配,子串长度减 1 变为“来”
颗粒度最小为 1,直接输出“来”,输入变为“应聘” - 第四轮:取子串“应聘”
“应聘”,扫描 2 字词典,有匹配,输出“应聘”,输入变为“”
输入长度为0,扫描终止
python实现:
word_prob = {"北京":0.03,"的":0.08,"天":0.005,"气":0.005,"天气":0.06,"真":0.04,"好":0.05,"真好":0.04,"啊":0.01,"真好啊":0.02,
"今":0.01,"今天":0.07,"课程":0.06,"内容":0.06,"有":0.05,"很":0.03,"很有":0.04,"意思":0.06,"有意思":0.005,"课":0.01,
"程":0.005,"经常":0.08,"意见":0.08,"意":0.01,"见":0.005,"有意见":0.02,"分歧":0.04,"分":0.02, "歧":0.005}
def word_segment_naive(input_str):
max_len=3
while len(input_str)>0:
if len(input_str)<max_len:
sub_str=input_str
else:
sub_str=input_str[0:max_len]
while len(sub_str)>0:
if sub_str in word_prob.keys() or len(sub_str)==1:
segments.append(sub_str)
input_str=input_str[len(sub_str):]
break
else:
sub_str=sub_str[:len(sub_str)-1]
return segments
print (word_segment_naive("北京的天气真好啊"))
缺点分析:
- 有可能细分在语义方面会更好
- 陷入局部最优
- 效率依赖max_len
- 歧义(不能考虑语义)
分词算法二:基于概率统计的方法:考虑语义
我们可以做这样的假设,我们可以获得所有的分词结果,然后把所有的分词结果放到一个"黑盒"里面,黑盒可以为我们判断这个分词结果语义概率(即这句话符合正常语句的可能性),然后选择那个概率最大的作为我们分词的结果。
这个“黑盒”就是语言模型(Language Model)
LM(语言模型)
通俗讲:语言模型时用来判断:是否一句话从语法上通顺
Noisy Channel Moedl:P(text | source) 等价于 P(source | text) *P(text)
Unigram、Bigram、N-gram:利用链式法则来计算句子语义概率。
评估语言模型:理想情况下:可以把特定的任务应用到两个语言模型中,看效果哪个好。
不依赖任何任务进行评估:预测下一个词是什么,类似于做填空题,可以选择出后面最好的预测
Perplexity = 2 − ( x ) 2^{-(x)} 2−(x)