1.1 分词的概念(分词的正向最大、逆向最大、双向最大匹配法)
主流分词算法可以分为:基于字符串匹配的方法、基于统计的方法、基于理解的方法。
其中,基于字符串匹配的分词方法又称为机械分词方法,它需要有一个初始的充分大的词典,然后将待分词的字符串与词典中的元素进行匹配,若能成功匹配,则将该词切分出来。
按扫描方向的不同,字符串匹配分词方法可以分为正向匹配和逆向匹配;按照不同长度的匹配优先度可以分为最大匹配和最小匹配。
注:看到一个图很不错 ,对分类方法进行了小结,看着很清晰。

hanlp分词 配置 分词 匹配_hanlp分词 配置

1)正向最大匹配算法:
第一步:从左到右将句子按照字典最大长度m进行切分;
第二步:将切分的m个字符与字典中元素进行匹配,如果匹配成功,就把这个字符保存,如果匹配不成功,则将这m个字符的最后一个字去掉,再进行上述的匹配操作,重复进行,直到文本切分完成。
eg.
要切分的句子=“南京市长江大桥”,字典中最大长度m=5
第一步:取前m个字符=“南京市长江”;
第二步:查找字典,发现没有匹配成功,则将m个字符的最后一个字去掉,此时要匹配的字符=“南京市长”,再次进行匹配,发现匹配成功。接着,剩下的句子=“江大桥”,继续重复第一第二步,最后,切分为“江”、“大桥”。
整个句子切分完为:南京市长、江、大桥。
2)逆向最大匹配算法:
与正向匹配算法大致相同,不同的是逆向最大匹配从右向左匹配,如果匹配不成功,则去掉最左的字符。
逆向最大匹配算法效果要优于正向最大匹配算法。
eg.
要切分的句子=“南京市长江大桥”,字典中最大长度m=5
第一步:取后m个字符=“市长江大桥”;
第二步:查找字典,发现没有匹配成功,则将m个字符的最左一个字去掉,此时要匹配的字符=“长江大桥”,再次进行匹配,发现匹配成功。接着,剩下的句子=“南京市”,继续重复第一第二步,最后,切分为“南京市”。
整个句子切分完为:南京市、长江大桥。
3)双向最大匹配算法:
双向最大匹配是将正向最大匹配得到的结果和逆向最大匹配得到的结果进行比较,如果切分之后的数量不同,则取切分数量少的那个结果,如果切分之后的数量相同,则返回切分后单字数少的那个结果。
还是上面的例子,双向最大匹配的结果取为:南京市、长江大桥。

 

1.2 词、字符频率统计

1 from collections import Counter
2 import jieba
3 sentence="我来到北京大学学习"
4 char_res=Counter(sentence)
5 print(char_res)
6 ### Counter({'学': 2, '我': 1, '来': 1, '到': 1, '北': 1, '京': 1, '大': 1, '习': 1})
7 word_res = Counter(jieba.cut(sentence))
8 print(word_res)
9 ### Counter({'我': 1, '来到': 1, '北京大学': 1, '学习': 1})

 

2.1 语言模型中unigram、bigram、trigram的概念
N-gram是一种基于统计的分词方法。
基于统计方法的主要思想是:每个字都是词的最小单元,如果相连的字在不同的文本中出现的频率越多,这就越有可能是一个词。因此我们可以用相邻字出现的频率来衡量组词的可能性,当频率高于某个阈值时,我们可以认为这些字可能会构成一个词。
主要统计模型: N元文法模型(N-gram),隐马尔可夫模型(Hidden Markov Model,HMM),最大熵模型(ME),条件随机场(Conditional Random Fields,CRF)等 。

N-gram模型基于这样一种假设,第n个词出现只与前面n-1个词相关,而与其他词无关。
整句话的概率就是各个词出现概率的乘积。对于一个句子T,假设它由n个词w1,w2,w3,⋯,wn组成的,则p(T)=p(w1w2w3⋯wn)=p(w1)p(w2|w1)p(w3|w1w2)⋯p(wn|w1w2⋯wn−1),计算这个式子很麻烦,我们引入马尔科夫假设:一个词的出现仅依赖于它前面有限的几个词。如果一个词的出现仅依赖于它前面出现的一个词,我们就称之为bigram。则上式变为:p(T)=p(w1)p(w2|w1)p(w3w2)⋯p(wnwn−1)。
以此类推,N元模型就是假设当前词的出现概率只同它前面的N-1个词有关。(实际中通常只用到二元模型)

 

2.2 unigram、bigram频率统计

1 unigram = list(sentence)
2 uni_res = Counter(unigram)
3 print(uni_res)
4 # ### Counter({'学': 2, '我': 1, '来': 1, '到': 1, '北': 1, '京': 1, '大': 1, '习': 1})
5 bigram = ["".join(unigram[i:i+2]) for i in range(len(unigram)-1)]
6 big_res = Counter(bigram)
7 print(big_res)
8 ### Counter({'我来': 1, '来到': 1, '到北': 1, '北京': 1, '京大': 1, '大学': 1, '学学': 1, '学习': 1})

 

3.1 分词,去停用词,构造词表

1 import jieba
 2 import collections
 3 text = "今年,共有来自世界各地的2555部作品报名参加本届金爵奖四个单元的角逐,15部作品成功入围主竞赛单元的最终评选。7位主竞赛单元评委经过认真的观摩和真诚的交流,作出了郑重的评选。印度电影《木生日光下》获得“艺术贡献奖”;包轩鸣凭借在《春潮》中的出色镜头语言,获得“最佳摄影奖”;亚历山大·龙金、帕威尔·龙金以《兄弟会》携手获得“最佳编剧奖”;莎乐美·戴缪莉亚则因其在《呼吸之间》中的杰出表演捧起了“最佳女演员”的奖杯"
 4 stopwords = []
 5 with open("./stopwords.txt", 'r', encoding='utf-8') as fin:
 6     for index, line in enumerate(fin.readlines()):
 7         line = line.strip()
 8         stopwords.append(line)
 9 # print(len(stopwords))       ### 1217
10 
11 sent = jieba.cut(text)
12 words = collections.OrderedDict()
13 cnt = 0
14 for ele in sent:
15     if ele not in stopwords:
16         words[cnt] = ele
17         cnt += 1
18 print(words)
19 ### OrderedDict([(0, '今年'), (1, '共有'), (2, '来自'), (3, '世界各地'), (4, '2555'), (5, '部'), (6, '作品'), (7, '报名'), (8, '参加'), (9, '本届'), (10, '金爵'), (11, '奖'), (12, '四个'), (13, '单元'), (14, '角逐'), (15, '15'), (16, '部'), (17, '作品'), (18, '成功'), (19, '入围'), (20, '主'), (21, '竞赛'), (22, '单元'), (23, '最终'), (24, '评选'), (25, '位主'), (26, '竞赛'), (27, '单元'), (28, '评委'), (29, '经过'), (30, '认真'), (31, '观摩'), (32, '真诚'), (33, '交流'), (34, '作出'), (35, '郑重'), (36, '评选'), (37, '印度'), (38, '电影'), (39, '木'), (40, '生日'), (41, '光下'), (42, '获得'), (43, '艺术'), (44, '贡献奖'), (45, '包轩'), (46, '鸣'), (47, '凭借'), (48, '春潮'), (49, '中'), (50, '出色'), (51, '镜头'), (52, '语言'), (53, '获得'), (54, '最佳'), (55, '摄影奖'), (56, '亚历山大'), (57, '龙金'), (58, '帕'), (59, '威尔'), (60, '龙金以'), (61, '兄弟会'), (62, '携手'), (63, '获得'), (64, '最佳'), (65, '编剧奖'), (66, '莎'), (67, '乐美'), (68, '戴缪莉亚'), (69, '则'), (70, '呼吸之间'), (71, '中'), (72, '杰出'), (73, '表演'), (74, '捧起'), (75, '最佳'), (76, '女演员'), (77, '奖杯')])

之前写的关于tf-idf的一个博文