精华内容
下载资源
问答
  • perl 分词程序

    2012-06-19 16:14:02
    perl分词程序,正确率在90%以上;希望对大家有帮助
  • 中文分词工具

    2012-10-28 20:16:53
    这是一个中文分词工具 里面详细描述了 使用的方法
  • 在icwb2-data/scripts目录下含有对分词进行自动评分的perl脚本score。 我们在统一测试环境下,对上述流行分词软件和THULAC进行了测试,使用的模型为各分词软件自带模型。THULAC使用的是随软件提供的简单模型Model...

    一.中文分词

    二.准确率评测:

    THULAC:与代表性分词软件的性能对比

    我们选择LTP-3.2.0 、ICTCLAS(2015版) 、jieba(C++版)等国内具代表性的分词软件与THULAC做性能比较。我们选择Windows作为测试环境,根据第二届国际汉语分词测评(The SecondInternational Chinese Word Segmentation Bakeoff)发布的国际中文分词测评标准,对不同软件进行了速度和准确率测试。

     

    在第二届国际汉语分词测评中,共有四家单位提供的测试语料(Academia Sinica、 City University 、Peking University 、MicrosoftResearch), 在评测提供的资源icwb2-data中包含了来自这四家单位的训练集(training)、测试集(testing), 以及根据各自分词标准而提供的相应测试集的标准答案(icwb2-data/scripts/gold).在icwb2-data/scripts目录下含有对分词进行自动评分的perl脚本score。

    我们在统一测试环境下,对上述流行分词软件和THULAC进行了测试,使用的模型为各分词软件自带模型。THULAC使用的是随软件提供的简单模型Model_1。评测环境为 Intel Core i5 2.4 GHz 评测结果如下:

    除了以上在标准测试集上的评测,我们也对各个分词工具在大数据上的速度进行了评测,结果如下:

    CNKI_journal.txt(51 MB)

    分词数据准备及评测由BosonNLP完成:11 款开放中文分词引擎大比拼(2015年发布)

    分词的客观量化测试离不开标注数据,即人工所准备的分词“标准答案”。在数据源方面,我们将测试分为: 1.新闻数据:140篇,共30517词语; 2.微博数据:200篇,共12962词语; 3.汽车论坛数据(汽车之家)100篇:共27452词语; 4.餐饮点评数据(大众点评):100条,共8295词语。

     

    准确度计算规则:

    将所有标点符号去除,不做比较

    参与测试的部分系统进行了实体识别,可能造成词语认定的不统一。我们将对应位置替换成了人工标注的结果,得到准确率估算的上界。

    经过以上处理,用SIGHAN 分词评分脚本比较得到最终的准确率,召回率和F1值。

    以上所有数据采用北大现代汉语基本加工规范对所有数据进行分词作为标准。具体数据下载地址请参见附录。通过这四类数据综合对比不同分词系统的分词准确度。

     

    转载于:https://my.oschina.net/u/3793864/blog/3057631

    展开全文
  • perl实现的中文词性标注 读入按“中国/n 人民/n”方式分好词的文件训练 再读入分词文件测试 输出标好词性的文件
  • 中文分词词典

    2020-12-24 11:33:43
    虽然是愚人节,但是这个不是愚人节玩笑,最近花了一些时间在MeCab身上,越发喜欢这个来自岛国的开源分词系统,今天花了一些时间训练了一个更适用的模型和词典,打包提供给大家使用,因为数据和词典涉及到一些版权...

    虽然是愚人节,但是这个不是愚人节玩笑,最近花了一些时间在MeCab身上,越发喜欢这个来自岛国的开源分词系统,今天花了一些时间训练了一个更适用的模型和词典,打包提供给大家使用,因为数据和词典涉及到一些版权问题,所以打包文件里只是mecab用于发布的二进制词典和模型文件,目前在mac os和linux ubuntu系统下测试无误,其他系统请自行测试使用:

    使用前请按上述文档安装mecab,下载这个中文分词模型和词典之后解压,解压后得到一个mecab-chinese-data目录,执行:

    mecab -d mecab-chinese-data

    扬帆远东做与中国合作的先行

    扬帆v,*,*,*,*,*,扬帆,*,*

    远东ns,*,*,*,*,*,远东,*,*

    做v,*,*,*,*,*,做,*,*

    与p,*,*,*,*,*,与,*,*

    中国ns,*,*,*,*,*,中国,*,*

    合作v,*,*,*,*,*,合作,*,*

    的u,*,*,*,*,*,的,*,*

    先行vn,*,*,*,*,*,先行,*,*

    EOS

    上述第二列提供了词性标注结果。

    如果想得到单行的分词结果,可以这样执行:

    mecab -d ./mecab-chinese-data/ -O wakati

    扬帆远东做与中国合作的先行

    扬帆 远东 做 与 中国 合作 的 先行

    如果想直接对文件分词,可以这样执行:

    mecab -d ./mecab-chinese-data/ INPUT -o OUTPUT

    具体可以参考上述两个文档,另外我在mac下测试了一下中文维基百科语料的切分速度,大概700多M的语料,不到90秒切分完毕,大概7M/s的切分速度完全达到了工业届的使用标准。另外Mecab还支持Nbest输出,多种输出格式,全切分模式,系统词典和用户词典定制等等,同时通过SWIG提供了perl, ruby, python, java的调用接口,非常方便。

    以下是在backoff2005 人民日报语料库上的测试结果:

    === SUMMARY:

    === TOTAL INSERTIONS:3803

    === TOTAL DELETIONS:1981

    === TOTAL SUBSTITUTIONS:5004

    === TOTAL NCHANGE:10788

    === TOTAL TRUE WORD COUNT:104372

    === TOTAL TEST WORD COUNT:106194

    === TOTAL TRUE WORDS RECALL:0.933

    === TOTAL TEST WORDS PRECISION:0.917

    === F MEASURE:0.925

    === OOV Rate:0.058

    === OOV Recall Rate:0.482

    === IV Recall Rate:0.961

    ###pku_test.result380319815004107881043721061940.9330.9170.9250.0580.4820.961

    召回率93.3%,准确率91.7%, F值为92.5%, 虽然还没有一个单纯针对这个测试语料比赛的分词结果好,但是测试了一些其他语料后觉得这个版本完全可以作为一个基准版本使用,另外mecab也提供了用户定制词典接口,方便用户按自己的需求定制使用。

    最后提供一个demo仅供测试使用: 中文分词Demo

    展开全文
  • python实现的简单中文分词

    千次阅读 2020-12-30 06:13:19
    作为一个python初学者+自然语言处理初学者,我用python写了一个简单的中文分词器,整个程序 加上注释100行左右,算是一个小练习。1、数据来源 [1]数据来自 Bakeoff2005 官方网站:...

    作为一个python初学者+自然语言处理初学者,我用python写了一个简单的中文分词器,整个程序 加上注释100行左右,算是一个小练习。

    1、数据来源 [1]

    数据来自 Bakeoff2005 官方网站:http://sighan.cs.uchicago.edu/bakeoff2005/ 下载其中的 icwb2-data.tar.bz2 解压后取出以下文件:

    训练数据:icwb2-data/training/pku_ training.utf8

    测试数据:icwb2-data/testing/pku_ test.utf8

    正确分词结果:icwb2-data/gold/pku_ test_ gold.utf8

    评分工具:icwb2-data/script/socre

    2、算法描述

    算法是最简单的正向最大匹配(FMM):

    用训练数据生成一个字典

    对测试数据从左到右扫描,遇到一个最长的词,就切分下来,直到句子结束

    注:这是最初的算法,这样做代码可以控制在60行内,后来看测试结果发现没有很好地处理数字问题, 才又增加了对数字的处理。

    3、源代码及注释

    #! /usr/bin/env python

    # -*- coding: utf-8 -*-

    # Author: minix

    # Date:   2013-03-20

    # Email:  minix007@foxmail.com

    import codecs

    import sys

    # 由规则处理的一些特殊符号

    numMath = [u'0', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9']

    numMath_suffix = [u'.', u'%', u'亿', u'万', u'千', u'百', u'十', u'个']

    numCn = [u'一', u'二', u'三', u'四', u'五', u'六', u'七', u'八', u'九', u'〇', u'零']

    numCn_suffix_date = [u'年', u'月', u'日']

    numCn_suffix_unit = [u'亿', u'万', u'千', u'百', u'十', u'个']

    special_char = [u'(', u')']

    def proc_num_math(line, start):

    """ 处理句子中出现的数学符号 """

    oldstart = start

    while line[start] in numMath or line[start] in numMath_suffix:

    start = start + 1

    if line[start] in numCn_suffix_date:

    start = start + 1

    return start - oldstart

    def proc_num_cn(line, start):

    """ 处理句子中出现的中文数字 """

    oldstart = start

    while line[start] in numCn or line[start] in numCn_suffix_unit:

    start = start + 1

    if line[start] in numCn_suffix_date:

    start = start + 1

    return start - oldstart

    def rules(line, start):

    """ 处理特殊规则 """

    if line[start] in numMath:

    return proc_num_math(line, start)

    elif line[start] in numCn:

    return proc_num_cn(line, start)

    def genDict(path):

    """ 获取词典 """

    f = codecs.open(path,'r','utf-8')

    contents = f.read()

    contents = contents.replace(u'\r', u'')

    contents = contents.replace(u'\n', u'')

    # 将文件内容按空格分开

    mydict = contents.split(u' ')

    # 去除词典List中的重复

    newdict = list(set(mydict))

    newdict.remove(u'')

    # 建立词典

    # key为词首字,value为以此字开始的词构成的List

    truedict = {}

    for item in newdict:

    if len(item)>0 and item[0] in truedict:

    value = truedict[item[0]]

    value.append(item)

    truedict[item[0]] = value

    else:

    truedict[item[0]] = [item]

    return truedict

    def print_unicode_list(uni_list):

    for item in uni_list:

    print item,

    def divideWords(mydict, sentence):

    """

    根据词典对句子进行分词,

    使用正向匹配的算法,从左到右扫描,遇到最长的词,

    就将它切下来,直到句子被分割完闭

    """

    ruleChar = []

    ruleChar.extend(numCn)

    ruleChar.extend(numMath)

    result = []

    start = 0

    senlen = len(sentence)

    while start < senlen:

    curword = sentence[start]

    maxlen = 1

    # 首先查看是否可以匹配特殊规则

    if curword in numCn or curword in numMath:

    maxlen = rules(sentence, start)

    # 寻找以当前字开头的最长词

    if curword in mydict:

    words = mydict[curword]

    for item in words:

    itemlen = len(item)

    if sentence[start:start+itemlen] == item and itemlen > maxlen:

    maxlen = itemlen

    result.append(sentence[start:start+maxlen])

    start = start + maxlen

    return result

    def main():

    args = sys.argv[1:]

    if len(args) < 3:

    print 'Usage: python dw.py dict_path test_path result_path'

    exit(-1)

    dict_path = args[0]

    test_path = args[1]

    result_path = args[2]

    dicts = genDict(dict_path)

    fr = codecs.open(test_path,'r','utf-8')

    test = fr.read()

    result = divideWords(dicts,test)

    fr.close()

    fw = codecs.open(result_path,'w','utf-8')

    for item in result:

    fw.write(item + ' ')

    fw.close()

    if __name__ == "__main__":

    main()

    4、测试及评分结果

    使用 dw.py 训练数据 测试数据, 生成结果文件

    使用 score 根据训练数据,正确分词结果,和我们生成的结果进行评分

    使用 tail 查看结果文件最后几行的总体评分,另外socre.utf8中还提供了大量的比较结果, 可以用于发现自己的分词结果在哪儿做的不够好

    注:整个测试过程都在Ubuntu下完成 $ python dw.py pku_training.utf8 pku_test.utf8 pku_result.utf8

    $

    perl score pku_training.utf8 pku_test_gold.utf8 pku_result.utf8 > score.utf8

    $

    tail -14 score.utf8

    === SUMMARY:

    === TOTAL INSERTIONS:   4623

    === TOTAL DELETIONS:    1740

    === TOTAL SUBSTITUTIONS:        6650

    === TOTAL NCHANGE:      13013

    === TOTAL TRUE WORD COUNT:      104372

    === TOTAL TEST WORD COUNT:      107255

    === TOTAL TRUE WORDS RECALL:    0.920

    === TOTAL TEST WORDS PRECISION: 0.895

    === F MEASURE:  0.907

    === OOV Rate:   0.940

    === OOV Re

    call Rate:    0.917

    === IV Recall Rate:     0.966

    基于词典的FMM算法是非常基础的分词算法,效果没那么好,不过足够简单,也易于入手,随着学习的深入,我可能还会用Python实现其它的分词算法。

    展开全文
  • CRFSegment 用CRF++实现基于条件随机场模型的中文分词 更多详细介绍可以查看文章:
  • 基于HMM的中文分词

    万次阅读 多人点赞 2018-05-19 17:33:04
    隐马尔可夫模型(HMM)在中文分词中的应用 隐马尔可夫模型的详细解释 隐马尔可夫模型的一些范例介绍 隐马尔可夫模型中有两个序列,一个是状态序列,另一个是观测序列,其中状态序列是隐藏的。用具体的例子来解释...

    隐马尔可夫模型(HMM)在中文分词中的应用

    隐马尔可夫模型的详细解释

    隐马尔可夫模型的一些范例介绍

    隐马尔可夫模型中有两个序列,一个是状态序列,另一个是观测序列,其中状态序列是隐藏的。用具体的例子来解释。

          假设一个房间内有N个装有球的盒子,在这些盒子中分别有M种不同颜色的球,我根据某一个概率分布(初始概率分布,在中文分词中就是一句话中第一个字符对应的状态概率)随机地选取一个初始的盒子,从中根据不同颜色的球的概率分布(发射概率,在中文分词中就是每一个字对应的状态概率),随机选择出一个球,然后我将这个球拿给房间外的你看。这个时候你能看到的就只是不同颜色的球的序列(观测序列),我选择的盒子的序列(状态序列)你是不知道的。

    训练阶段参数估计

    一个HMM可以由下面几个部分组成:

    (1)模型中的状态数量N(上例中盒子的数量)

    在中文分词中一般只有4个状态:STATES={‘B’,‘M’,‘E’,‘S’},例如:小明是中国人,对应的状态序列就是:B,E,S,B,M,E

    (2)从每个状态可能输出的不同符号的数目M(上例中不同颜色球的个数)

    在中文分词中就是对应每一个字符

     

    在中文分词中就是状态序列STATES={‘B’,‘M’,‘E’,‘S’}的转移概率,这个状态概率矩阵是在训练阶段参数估计中得到。在中文分词中状态转移矩阵是一个4*4的矩阵,我在实验中是通过统计训练数据中状态转移的频数确定矩阵,为了确保,需要对频数矩阵除以对应每一行状态的统计数,即A[key0][key1]/count(key0),为了保证数据的精度,我这里取了对数,并且以字典输出方便查看。

    {'B': {'B': -3.14e+100, 'M':-1.9594399657636383, 'E': -0.15191340104766693, 'S': -3.14e+100},

    'M': {'B': -3.14e+100, 'M':-1.0983633205740504, 'E': -0.40558961540346977, 'S': -3.14e+100},

    'E': {'B':-0.78182902092047468, 'M': -3.14e+100, 'E': -3.14e+100, 'S':-0.62312924475978682},

    'S': {'B': -0.74289298827998818,'M': -3.14e+100, 'E': -3.14e+100, 'S': -0.81330579119502522}}

    可以看到对应状态‘B’后面只能接‘M’和‘E’;状态‘M’后面只能接‘M’和‘E’;状态‘E’后面只能接‘B’和‘S’;状态‘S’后面只能接‘B’和‘S’。

     

    在中文分词中发射概率指的是每一个字符对应状态序列STATES={‘B’,‘M’,‘E’,‘S’}中每一个状态的概率,通过对训练集每个字符对应状态的频数统计得到。我是通过字典的形式保存,就可能出现某个字符在某一个状态没有频数,导致后面矩阵计算错误。为保证每个字符都在STATES的字典中,在构建发射概率矩阵是先初始化。

     

    在中文分词初始状态概率指的是每一句话第一个字符的对应状态概率。在我实验中通过训练的得到的初始状态概率分布为,

    {'B': -0.48164247830489765,'M': -3.14e+100, 'E': -3.14e+100, 'S': -0.96172723110752845}

    可以看到第一个字符的初始状态只能是‘B’和‘S’。

    这个时候我们就完成了训练阶段的参数估计,得到了三个概率矩阵,分别是:

    TransProbMatrix: 转移概率矩阵(array_A)

    EmitProbMatrix: 发射概率矩阵(array_B)

    InitStatus: 初始状态分布(array_pi)

    测试阶段Viterbi算法

    在这里我们要做的是对测试数据进行分词,首先要做的就是对测试数据中每一个字符进行状态标注,这里使用的是Viterbi算法进行标注。

    给一个测试语句‘小明是中国人’,首先标注第一个字‘小’,由于是第一个字,这里只需要用到初始状态概率矩阵和发射矩阵,

    初始状态概率矩阵:

    {'B': -0.48164247830489765,'M': -3.14e+100, 'E': -3.14e+100, 'S': -0.96172723110752845}

    发射概率矩阵:

    {‘B’:{‘小’:-6.04291273032},‘M’:{‘小’:-6.50192547556},‘E’:{‘小’:-7.88369576318},‘S’:{‘小’:-6.60403172082}}

    然后标注概率矩阵tab为:

        for state in STATES:
            tab[0][state] = array_pi[state] + array_b[state]['小']

    这里我对矩阵取对数,所有只用‘+’即可,则得到第一个字‘小’的标注概率:

    tab[0][‘B’]=-6.52455520862

    tab [0][‘M’]=-3.14e+100

    tab [0][‘E’]=-3.14e+100

    tab [0][‘S’]=-7.56575895193

    这里可以看到path[0][‘B’]> path[0][‘S’],则这句语句第一个字‘小’标注为‘B’

    然后计算第二个字明,这时就需要状态转移概率矩阵array_A。这里有两个迭代过程,对于‘明’每一个状态state0都需要计算前一个字‘小’可能的每一个状态state1的概率prob,然后取max,

    for state0 in STATES:
    
        for state1 in STATES:
    
            prob=tab[i-1][state1]+array_a[state1][state0]+array_b[state0][sentence[i]]

    这实际上就是一个动态规划最优路径的问题,对前一个字‘小’的每个状态state根据状态转移矩阵array_a和‘小’的标注概率tab,再加上这个字‘明’的发射概率array_b,得到‘明’这个字的标记概率

    tab[1][‘B’]= -14.742836926340019

    tab [1][‘M’]=-14.836146344717278

    tab [1][‘E’]= -12.832943424756692

    tab [1][‘S’]=-17.961024112859207

    这里可以看到tab [1][‘E’]最大,这个就是‘明’这个字的标注为‘E’。然后对测试数据依次进行这个操作。

    在测试阶段使用Viterbi标注时需要注意:若测试集中出现某一个字符,但这个字符在训练集中未出现,这个时候发射概率是没有的,这里需要做平滑处理,我这里采用的方式是:将所有未在训练集中出现的字符统一发射概率为发射概率矩阵的中位数。

    在这里测试数据的标注已经得到,最后一步需要做的就是根据标注的状态进行分词。这里有几种情况:

    (1)测试数据只有一个字符,直接输出

    (2)测试数据标注的最后一个字符的状态不是‘S’和‘E’,这里需要进行修改

            if tag[-1] == 'B' or tag[-1] == 'M':    #最后一个字状态不是'S'或'E'则修改
                if tag[-2] == 'B' or tag[-2] == 'M':
                    tag[-1] = 'S'
                else:
                    tag[-1] = 'E'

    最后整个分词器就已经实现,这里需要对最后的分词结果进行测试,测试资源

    这里写一下score脚本的使用方法,

    (1)这是一个perl的脚本,在windows系统中首先要下载一个ActivePerl的解释器,配置环境变量。

    (2)然后score需要GNU diffutils的支持,下载地址

    (3)然后需要修改score脚本中的语句,指定diff的安装目录$diff,$tmp1和$tmp2分别指定黄金标准分词文件和测试集切分文件。

     

    我这里指定了tmp的路径,但是评分脚本“score”是用来比较两个分词文件的,需要三个参数:

    1. 训练集词表(The training setword list)

    2. “黄金”标准分词文件(The gold standard segmentation)

    3. 测试集的切分文件(The segmentedtest file)

    我在cmd中的命令输入为:

    perl score CTB_training_words.utf8CTB_test_gold.utf8 output.txt

    最后的分词结果为

    实验代码:

    GitHub链接:https://github.com/CQUPT-Wan/HMMwordseg.git

    这个项目里面有我实现HMM中文分词的训练集,测试集和黄金标准分词文件

    import pandas as pd
    import codecs
    from numpy import *
    import numpy as np
    import sys
    import re
    STATES = ['B', 'M', 'E', 'S']
    array_A = {}    #状态转移概率矩阵
    array_B = {}    #发射概率矩阵
    array_E = {}    #测试集存在的字符,但在训练集中不存在,发射概率矩阵
    array_Pi = {}   #初始状态分布
    word_set = set()    #训练数据集中所有字的集合
    count_dic = {}  #‘B,M,E,S’每个状态在训练集中出现的次数
    line_num = 0    #训练集语句数量
    
    #初始化所有概率矩阵
    def Init_Array():
        for state0 in STATES:
            array_A[state0] = {}
            for state1 in STATES:
                array_A[state0][state1] = 0.0
        for state in STATES:
            array_Pi[state] = 0.0
            array_B[state] = {}
            array_E = {}
            count_dic[state] = 0
    
    #对训练集获取状态标签
    def get_tag(word):
        tag = []
        if len(word) == 1:
            tag = ['S']
        elif len(word) == 2:
            tag = ['B', 'E']
        else:
            num = len(word) - 2
            tag.append('B')
            tag.extend(['M'] * num)
            tag.append('E')
        return tag
    
    
    #将参数估计的概率取对数,对概率0取无穷小-3.14e+100
    def Prob_Array():
        for key in array_Pi:
            if array_Pi[key] == 0:
                array_Pi[key] = -3.14e+100
            else:
                array_Pi[key] = log(array_Pi[key] / line_num)
        for key0 in array_A:
            for key1 in array_A[key0]:
                if array_A[key0][key1] == 0.0:
                    array_A[key0][key1] = -3.14e+100
                else:
                    array_A[key0][key1] = log(array_A[key0][key1] / count_dic[key0])
        # print(array_A)
        for key in array_B:
            for word in array_B[key]:
                if array_B[key][word] == 0.0:
                    array_B[key][word] = -3.14e+100
                else:
                    array_B[key][word] = log(array_B[key][word] /count_dic[key])
    
    #将字典转换成数组
    def Dic_Array(array_b):
        tmp = np.empty((4,len(array_b['B'])))
        for i in range(4):
            for j in range(len(array_b['B'])):
                tmp[i][j] = array_b[STATES[i]][list(word_set)[j]]
        return tmp
    
    #判断一个字最大发射概率的状态
    def dist_tag():
        array_E['B']['begin'] = 0
        array_E['M']['begin'] = -3.14e+100
        array_E['E']['begin'] = -3.14e+100
        array_E['S']['begin'] = -3.14e+100
        array_E['B']['end'] = -3.14e+100
        array_E['M']['end'] = -3.14e+100
        array_E['E']['end'] = 0
        array_E['S']['end'] = -3.14e+100
    
    def dist_word(word0,word1,word2,array_b):
        if dist_tag(word0,array_b) == 'S':
            array_E['B'][word1] = 0
            array_E['M'][word1] = -3.14e+100
            array_E['E'][word1] = -3.14e+100
            array_E['S'][word1] = -3.14e+100
        return
    
    #Viterbi算法求测试集最优状态序列
    def Viterbi(sentence,array_pi,array_a,array_b):
        tab = [{}]  #动态规划表
        path = {}
    
        if sentence[0] not in array_b['B']:
            for state in STATES:
                if state == 'S':
                    array_b[state][sentence[0]] = 0
                else:
                    array_b[state][sentence[0]] = -3.14e+100
    
        for state in STATES:
            tab[0][state] = array_pi[state] + array_b[state][sentence[0]]
            # print(tab[0][state])
            #tab[t][state]表示时刻t到达state状态的所有路径中,概率最大路径的概率值
            path[state] = [state]
        for i in range(1,len(sentence)):
            tab.append({})
            new_path = {}
            # if sentence[i] not in array_b['B']:
            #     print(sentence[i-1],sentence[i])
            for state in STATES:
                if state == 'B':
                    array_b[state]['begin'] = 0
                else:
                    array_b[state]['begin'] = -3.14e+100
            for state in STATES:
                if state == 'E':
                    array_b[state]['end'] = 0
                else:
                    array_b[state]['end'] = -3.14e+100
            for state0 in STATES:
                items = []
                # if sentence[i] not in word_set:
                #     array_b[state0][sentence[i]] = -3.14e+100
                # if sentence[i] not in array_b[state0]:
                #     array_b[state0][sentence[i]] = -3.14e+100
                # print(sentence[i] + state0)
                # print(array_b[state0][sentence[i]])
                for state1 in STATES:
                    # if tab[i-1][state1] == -3.14e+100:
                    #     continue
                    # else:
                    if sentence[i] not in array_b[state0]:  #所有在测试集出现但没有在训练集中出现的字符
                        if sentence[i-1] not in array_b[state0]:
                            prob = tab[i - 1][state1] + array_a[state1][state0] + array_b[state0]['end']
                        else:
                            prob = tab[i - 1][state1] + array_a[state1][state0] + array_b[state0]['begin']
                        # print(sentence[i])
                        # prob = tab[i-1][state1] + array_a[state1][state0] + array_b[state0]['other']
                    else:
                        prob = tab[i-1][state1] + array_a[state1][state0] + array_b[state0][sentence[i]]    #计算每个字符对应STATES的概率
    #                     print(prob)
                    items.append((prob,state1))
                # print(sentence[i] + state0)
                # print(array_b[state0][sentence[i]])
                # print(sentence[i])
                # print(items)
                best = max(items)   #bset:(prob,state)
                # print(best)
                tab[i][state0] = best[0]
                # print(tab[i][state0])
                new_path[state0] = path[best[1]] + [state0]
            path = new_path
    
        prob, state = max([(tab[len(sentence) - 1][state], state) for state in STATES])
        return path[state]
    
    #根据状态序列进行分词
    def tag_seg(sentence,tag):
        word_list = []
        start = -1
        started = False
    
        if len(tag) != len(sentence):
            return None
    
        if len(tag) == 1:
            word_list.append(sentence[0])   #语句只有一个字,直接输出
    
        else:
            if tag[-1] == 'B' or tag[-1] == 'M':    #最后一个字状态不是'S'或'E'则修改
                if tag[-2] == 'B' or tag[-2] == 'M':
                    tag[-1] = 'E'
                else:
                    tag[-1] = 'S'
    
    
            for i in range(len(tag)):
                if tag[i] == 'S':
                    if started:
                        started = False
                        word_list.append(sentence[start:i])
                    word_list.append(sentence[i])
                elif tag[i] == 'B':
                    if started:
                        word_list.append(sentence[start:i])
                    start = i
                    started = True
                elif tag[i] == 'E':
                    started = False
                    word = sentence[start:i + 1]
                    word_list.append(word)
                elif tag[i] == 'M':
                    continue
    
        return word_list
    
    
    
    if __name__ == '__main__':
        trainset = open('CTBtrainingset.txt', encoding='utf-8')     #读取训练集
        testset = open('CTBtestingset.txt', encoding='utf-8')       #读取测试集
        # trainlist = []
    
        Init_Array()
    
        for line in trainset:
            line = line.strip()
            # trainlist.append(line)
            line_num += 1
    
            word_list = []
            for k in range(len(line)):
                if line[k] == ' ':continue
                word_list.append(line[k])
            # print(word_list)
            word_set = word_set | set(word_list)    #训练集所有字的集合
    
            line = line.split(' ')
            # print(line)
            line_state = []     #这句话的状态序列
    
            for i in line:
                line_state.extend(get_tag(i))
            # print(line_state)
            array_Pi[line_state[0]] += 1  # array_Pi用于计算初始状态分布概率
    
            for j in range(len(line_state)-1):
                # count_dic[line_state[j]] += 1   #记录每一个状态的出现次数
                array_A[line_state[j]][line_state[j+1]] += 1  #array_A计算状态转移概率
    
            for p in range(len(line_state)):
                count_dic[line_state[p]] += 1  # 记录每一个状态的出现次数
                for state in STATES:
                    if word_list[p] not in array_B[state]:
                        array_B[state][word_list[p]] = 0.0  #保证每个字都在STATES的字典中
                # if word_list[p] not in array_B[line_state[p]]:
                #     # print(word_list[p])
                #     array_B[line_state[p]][word_list[p]] = 0
                # else:
                array_B[line_state[p]][word_list[p]] += 1  # array_B用于计算发射概率
    
        Prob_Array()    #对概率取对数保证精度
    
        print('参数估计结果')
        print('初始状态分布')
        print(array_Pi)
        print('状态转移矩阵')
        print(array_A)
        print('发射矩阵')
        print(array_B)
    
    
        output = ''
    
        for line in testset:
            line = line.strip()
            tag = Viterbi(line, array_Pi, array_A, array_B)
            # print(tag)
            seg = tag_seg(line, tag)
            # print(seg)
            list = ''
            for i in range(len(seg)):
                list = list + seg[i] + ' '
            # print(list)
            output = output + list + '\n'
        print(output)
        outputfile = open('output.txt', mode='w', encoding='utf-8')
        outputfile.write(output)

    参考链接:

    http://www.leexiang.com/hidden-markov-model

    http://www.52nlp.cn/category/hidden-markov-model

    最后如果转载,麻烦留个本文的链接,因为如果读者或我自己发现文章有错误,我会在这里更正,留个本文的链接,防止我暂时的疏漏耽误了他人宝贵的时间。

    展开全文
  • perl实现中文分词 先双向扫描法找出歧义段 再n元语法概率模型消歧 1998年人民日报语料下F1值达94%
  • Java中文分词

    2021-03-08 10:29:24
    虽然是愚人节,但是这个不是愚人节玩笑,最近花了一些时间在MeCab身上,越发喜欢这个来自岛国的开源分词系统,今天花了一些时间训练了一个更适用的模型和词典,打包提供给大家使用,因为数据和词典涉及到一些版权...
  • 使用 dw.py 训练数据 测试数据, 生成结果文件使用 score 根据训练数据,正确分词结果,和我们生成的结果进行评分使用 tail 查看结果文件最后几行的总体评分,另外socre.utf8中还提供了大量的比较结果, 可以用于...
  • 中文分词Java

    2020-12-21 07:20:41
    虽然是愚人节,但是这个不是愚人节玩笑,最近花了一些时间在MeCab身上,越发喜欢这个来自岛国的开源分词系统,今天花了一些时间训练了一个更适用的模型和词典,打包提供给大家使用,因为数据和词典涉及到一些版权...
  • 中文分词评测

    千次阅读 2017-10-17 14:17:14
    中文分词评测4种基于Python第三方库的的中文分词方案的速度和精度。 - jieba https://github.com/fxsjy/jieba - THULAC-Python https://github.com/thunlp/THULAC-Python - pynlpir ...
  • 中文分词评测方法

    2020-04-16 17:11:49
    目录中文分词评测方法步骤参考资料 中文分词评测方法 对于分词,目前有很多开源的程序,包括hanlp、jieba、哈工大分词等。为了确定哪种分词结果比较好,通常有两种方式,一种是调用接口,对特定的句子分词,通过感觉...
  • 干货 | 史上最全中文分词工具整理

    万次阅读 多人点赞 2018-08-25 00:16:06
    中文分词 分词服务接口列表 二.准确率评测: THULAC:与代表性分词软件的性能对比 我们选择LTP-3.2.0、ICTCLAS(2015版)、jieba(C++版)等国内具代表性的分词软件与THULAC做性能比较。我们选择Windows作为...
  • 中文分词应用 生成词典 进入到mmseg的源代码目录后 cd data mmseg -u unigram.txt 在data下边会产生一个文件unigram.txt.uni 这个就是生成的字典 然后把字典改名为uni.lib放在可以读取的目录中即可 cp unigram....
  • perl词典分词

    千次阅读 2011-03-31 16:30:00
    从网上看了一篇perl分词的程序,运行程序后发现,数字全部给分开了,例如,“2010年国家GDP是...”,运行程序后结果为“2 0 1 0 年 国家 G D P 是 ....”,文中“2010”是不应该分开的,我改进了这个程序,...
  • 最近有一个文本分析的需求,因分析系统用的是Perl,而Perl下优秀的中文文本分析包又少,所以调用R处理文本数据。为什么不用Python尽管Python拥有完备的NLP开源包支持,但是理由也很简单——因为Python目前接触不多,...
  • 而Bakeoff则是SIGHAN所主办的国际中文语言处理竞赛,第一届于2003年在日本札幌举行(Bakeoff 2003),第二届于2005年在韩国济州岛举行(Bakeoff 2005), 而2006年在悉尼举行的第三届(Bakeoff 2006)则在前两届的基础上...
  • Elasticsearch7.X 及 IK 中文分词插件安装 一、安装Java并配置 JAVA_HOME 环境变量 由于Elasticsearch是使用Java构建的,所以首先需要安装 Java 8 或更高版本 才能运行。 所有Elasticsearch节点和客户机上都应该...
  • 虽然是愚人节,但是这个不是愚人节玩笑,最近花了一些时间在MeCab身上,越发喜欢这个来自岛国的开源分词系统,今天花了一些时间训练了一个更适用的模型和词典,打包提供给大家使用,因为数据和词典涉及到一些版权...
  • 分词工具作者 |fendouai分词服务接口列表二.准确率评测:THULAC:与代表性分词软件的性能对比我们选择LTP-3.2.0、ICTCLAS(2015版)、jieba(C++版)等国内具代表性的分词软件与THULAC做性能比较。我们选择windows作为...
  • 中文分词工具整理

    千次阅读 2017-07-07 15:41:52
    中文的书写习惯、一词多义等因素,决定了中文分词并不像英文分词那样简单,也使得中文分词成为中文自然语言处理的重要课题之一。 下文的中文分词工具列表是约为14年左右对当时常用中文分词器的一些调研,其中有些...
  • 梁博在线分词pullword的perl客户端,支持直接结果以及一个分词词频的hash。 梁博pullword接口API地址 http://api.pullword.com/ INSTALLATION 安装 To install this module, run the following commands: perl ...
  • Sphinx + Coreseek 实现中文分词搜索

    千次阅读 2016-12-15 08:38:51
    Sphinx + Coreseek 实现中文分词搜索 Sphinx Coreseek 实现中文分词搜索 全文检索 1 全文检索 vs 数据库 2 中文检索 vs 汉化检索 3 自建全文搜索与使用Google等第三方网站提供的站内全文搜索的区别 Sphinx Coreseek...
  • 衡量每种分词的指标,内存消耗、CPU消耗,得到一个在Lucene中比较好的分词版本。 分词源代码介绍 paoding: 庖丁解牛最新版在 https://code.google.com/p/paoding/ 中最多支持Lucene 3.0,且最新提交的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,929
精华内容 771
关键字:

中文分词perl