七叶笔记 » golang编程 » Jiebago 结巴分词

Jiebago 结巴分词

一时兴起,想再看看结巴分词。

以前研究时随手找了一个结巴分词来测试使用,发现非常强大,也就玩了一下,然后就没有然后了~。

在github里搜索到了两个结巴分词,共显示两个热度比较高的,链接如下:

以前还没在意,直接使用了一个星星最多的,仔细看了一下

yanyiwu/gojieba 是基于 wangbin/jiebago 分词之上做了一些改进而来的。

今天只说wangbin/jiebago 的分词。

README.md

作者在redme的首行就公布了一些历史:

结巴分词 是由 @fxsjy 使用 Python 编写的中文分词组件,Iiebago 是结巴分词的 Golang 语言实现。

使用

可以看到分词的使用是比较简单的,直接引入相关类使用调几个方法就能输出词汇

 package main

import (
        "fmt"

        "github.com/wangbin/jiebago"
)

var seg jiebago.Segmenter

func init() {
        seg.LoadDictionary("dict.txt")
}

func print(ch <-chan string) {
        for word := range ch {
                fmt.Printf(" %s /", word)
        }
        fmt.Println()
}

func Example() {
        fmt.Print("【全模式】:")
        print(seg.CutAll("我来到北京 清华大学 "))

        fmt.Print("【精确模式】:")
        print(seg.Cut("我来到北京清华大学", false))

        fmt.Print("【新词识别】:")
        print(seg.Cut("他来到了网易杭研大厦", true))

        fmt.Print("【搜索引擎模式】:")
        print(seg.CutForSearch("小明硕士毕业于中国科学院 计算所 ,后在日本京都大学深造", true))
}  

输出结果:

 【全模式】: 我 / 来到 / 北京 / 清华 / 清华大学 / 华大 / 大学 /

【精确模式】: 我 / 来到 / 北京 / 清华大学 /

【新词识别】: 他 / 来到 / 了 / 网易 / 杭研 / 大厦 /

【搜索引擎模式】: 小明 / 硕士 / 毕业 / 于 / 中国 / 科学 / 学院 / 科学院 / 中国科学院 / 计算 / 计算所 / , / 后 / 在 / 日本 / 京都 / 大学 / 日本京都大学 / 深造 /  

分词速度

  • 2MB / Second in Full Mode
  • 700KB / Second in Default Mode
  • Test Env: AMD Phenom(tm) II X6 1055T CPU @ 2.8GHz; 《金庸全集》
  • 作者更多信息请参考文档。

    算法

    • 基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图 (DAG)
    • 采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合
    • 对于未登录词,采用了基于汉字成词能力的 HMM 模型,使用了 Viterbi 算法

    jieba分词词性标记含义

    jieba为自然语言语言中常用工具包,jieba具有对分词的词性进行标注的功能,词性类别如下:

    创建自定义分词字典

    项目中有 userdict.txt,然后写入你的分词,一个词占一行;每一行分三部分:词语、词频(可省略)、词性(可省略),用空格隔开,顺序不可颠倒,这就是为啥上面要把 词性提出的原因

    比如

     李小福 2 nr
    
    “李小福”是个词语 词频是2(词频越高相应的权重越大)词性是人名  

    加载用户词典:

     ...
      d := &Dict{freqMap: make(map[string]float64), posMap: make(map[string]string)}
    err := LoadDictionary(d, "../userdict.txt")
    if err != nil {
    t.Fatalf(err.Error())
    }
    ...  

    添加token:

     ...
      d := &Dict{freqMap: make(map[string]float64), posMap: make(map[string]string)}
    LoadDictionary(d, "../userdict.txt")
    d.AddToken(Token{"好用", 99, "a"})
    ...  

    测试用户词典:

     func TestUserDict(t *testing.T) {
    seg.LoadUserDictionary("../userdict.txt")
    defer seg.LoadDictionary("../dict.txt")
    sentence := "李小福是创新办主任也是 云计算 方面的专家; 什么是八一双鹿例如我输入一个带“韩玉赏鉴”的标题,在自定义词库中也增加了此词为N类型"
    
    cutResult := [] Segment {
    Segment{"李小福", "nr"},
    Segment{"是", "v"},
    Segment{"创新办", "i"},
    Segment{"主任", "b"},
    Segment{"也", "d"},
    Segment{"是", "v"},
    Segment{"云计算", "x"},
    Segment{"方面", "n"},
    Segment{"的", "uj"},
    Segment{"专家", "n"},
    Segment{";", "x"},
    Segment{" ", "x"},
    Segment{"什么", "r"},
    Segment{"是", "v"},
    Segment{"八一双鹿", "nz"},
    Segment{"例如", "v"},
    Segment{"我", "r"},
    Segment{"输入", "v"},
    Segment{"一个", "m"},
    Segment{"带", "v"},
    Segment{"“", "x"},
    Segment{"韩玉赏鉴", "nz"},
    Segment{"”", "x"},
    Segment{"的", "uj"},
    Segment{"标题", "n"},
    Segment{",", "x"},
    Segment{"在", "p"},
    Segment{"自定义词", "n"},
    Segment{"库中", "nrt"},
    Segment{"也", "d"},
    Segment{"增加", "v"},
    Segment{"了", "ul"},
    Segment{"此", "r"},
    Segment{"词", "n"},
    Segment{"为", "p"},
    Segment{"N", "eng"},
    Segment{"类型", "n"}}
    
    result := chanToArray(seg.Cut(sentence, true))
    if len(cutResult) != len(result) {
    t.Fatal(result)
    }
    for i := range result {
    if result[i] != cutResult[i] {
    t.Fatal(result[i])
    }
    }
    }  

    总结

    感觉就是简单好用,至于有没更深层次的问题,估计需要高频的业务才有结果。

    相关文章