NLP一般的处理流程为:原始文本(raw data)--->分词(Segmentation)---->清洗数据(Cleaning)---->标准化(Normalization)
---->特征提取(Feature Extraction)----->建模(Modeling)
1:分词
常见的分词工具有:
Jieba分词https://github.com/fxsjy/jieba
SnowNLP https://github.com/isnowfy/snownlp
LTP http://www.ltp-cloud.com/
HanNLP https://github.com/hankcs/HanLP/
如果我们要手动实现分词。则有前向最大匹配,后向最大匹配,双向最大匹配。
例子:我们经常有意见分歧
假设我们的词典为:[“我们”, “经常”, “有”, “有意见”,“意⻅见”,“分歧”]
最大匹配长度为5.
首先我们先取前5个字[我们经常有],去词典里寻找发现并没有这个词。于是
删除掉有,则变成了[我们经常],去词典里找,发现还是没有。
重复上述过程。再删除一个字,结果为[我们经]。继续删,结果为[我们]
出现在词典里。则第一个词分词成功。
接下来看[经常有意见],最后分词为经常。
以此类推。用前向最大匹配法获得的分词结果为[我们,经常,有意见,分歧]
下边我们来看具体的代码实现:
#前向最大匹配法分词
def segment(str,maxlen,dict):
len_str = len(str) #计算总共字符长度
my_list = [] #存储前向分词结果
while len_str >0 :
temp = str[0:maxlen]
while temp not in dict: #如果当前词不在字典里
if len(temp) ==1:
break
temp = temp[0:len(temp)-1] #则从后边删除一位
my_list.append(temp)
str = str[len(temp):] #重新赋值str 第一次[我们有意见]找出我们,第二次剔除掉我们,这里用切片的方式剔除。
len_str = len(str)
return my_list
result = segment('我们经常有意见分歧',5,['我们','经常', '有','有意见','意见','分歧'])
print(result)
运行结果如下:
接下来我们看最大后向匹配:
跟前向匹配相反。我们从最后开始分词。
第一次:[有意见分歧],词典中查无此词。则删除有。
第二次:[意见分歧],词典中查无此词。则删除有。
第三次:[见分歧]
第四次:[分歧],ok,得到第一个分词。
具体代码实现如下:
def back_segment(str,maxlen,dict):
len_str = len(str) #先计算str的总长度
my_list = []#用来存放结果
while len_str > 0 :
temp = str[-maxlen :] #取负数,表示取最后5位
while temp not in dict :
if(len(temp) ==1 ):
break
temp = temp[1:] #如果不在字典里,则向前进一位。
my_list.append(temp)
str = str[0:len(str) - len(temp)] #更新str,从0到temp的标志位
len_str = len(str) #重新计算str的总长度
return my_list
result = back_segment('我们经常有意见分歧',5,['我们','经常', '有','有意见','意见','分歧'])
print(result)
那么最大匹配分词有哪些缺点呢?
我们可以总结如下:
1:长度限制。
由于最大匹配必须设定一个最大长度,如果长度太长,则影响效率,如果长度太小,则会切分的很细。所以这个最大长度的选择是在效率与词长之间的一种妥协。
2:效率低。要不断的循环,判断。
如果规定最大词长为5,但是我们的词典里的词大部分都是2位或者3位,这就意味着我们是有2~3次的匹配是浪费掉的。
3:没有考虑语义。
OK,今晚先到这里吧。