前言
我们知道,在英文的行文中,单词之间是以空格作为自然分界符的,而中文只是字、句和段能通过明显的分界符来简单划界,唯独 词 没有一个形式上的分界符,虽然英文也同样存在短语的划分问题,不过在词这一层上,中文比之英文要复杂得多、困难得多。
在中文信息处理过程中,自动中文分词备受关注。中文分词大概可分为:
基于词典规则
基于机器学习
本篇主要介绍第一种
1、环境准备
windows 10
安装pyhanlp:pip install pyhanlp(这里可能安装不成功,可留言)
HanLP附带的迷你核心词典为例
jupyter notebook(python3)
java(jdk1.8)
2、词典分词
词典分词是最简单、最常见的分词算法,仅需一部词典和一套查词典的规则即可
加载词典
Java代码实现:
// 加载词典
TreeMap dictionary = IOUtil.loadDictionary("data/dictionary/CoreNatureDictionary.mini.txt");
通过 IOUtil.loadDictionary 得到一个 TreeMap
它的键是单词本身,而值是 CoreDictionary.Attribute
CoreDictionary.Attribute是一个包含词性和词频的结构,这些与词典分词无关,暂时忽略
Python代码实现:
from pyhanlp import *
def load_dictionary():
IOUtil = JClass('com.hankcs.hanlp.corpus.io.IOUtil') # 利用JClass取得Hanlp中的IOUtil工具类
path = HanLP.Config.CoreDictionaryPath.replace('.txt', '.mini.txt') # 获取HanLPde配置项Config中的词典路径
dic = IOUtil.loadDictionary([path])
return set(dic.keySet())
3、切分算法
现在我们已经有了词典,就剩下查字典的规则了,常用的规则有正向最长匹配、逆向最长匹配和双向最长匹配,它们都是基于完全切分过程。
(1)完全切分
Python代码实现:
def fully_segment(text, dic):
word_list = []
for i in range(len(text)): # i 从 0 到text的最后一个字的下标遍历
for j in range(i + 1, len(text) + 1): # j 遍历[i + 1, len(text)]区间
word = text[i:j] # 取出连续区间[i, j]对应的字符串
if word in dic: # 如果在词典中,则认为是一个词
word_list.append(word)
return word_list
dic = load_dictionary()
print(fully_segment('商品和服务', dic))
[‘商’, ‘商品’, ‘品’, ‘和’, ‘和服’, ‘服’, ‘服务’, ‘务’]
该程序输出了包含在词典中的所有可能的单词
Java代码实现:
/**
* 完全切分式的中文分词算法
*
* @param text 待分词的文本
* @param dictionary 词典
* @return 单词列表
*/
public static List segmentFully(String text, Map dictionary){
List wordList = new LinkedList(); //存储结果
for (int i = 0; i < text.length(); ++i){ //遍历每个字
for (int j = i + 1; j <= text.length(); ++j){ //遍历后续的字
String word = text.substring(i, j); //截取子串
if (dictionary.containsKey(word)){ //如果词典中包括
wordList.add(word); //加到结果中
}
}
}
return wordList; //返回最终分词结果
}
由上面结果我们可以知道,完全切分的结果就是所有出现在词典中的单词构成的列表。很明显,这结果并不是我们所希望的中文分词。
例如:商品和服务
我们希望得到的是:['