精华内容
下载资源
问答
  • 该库是对目前市面上已有开源中文聊天语料的搜集和系统化整理工作 该库搜集了包含 - chatterbot - 豆瓣多轮 - PTT八卦语料 - 青云语料 - 电视剧对白语料 - 贴吧论坛回帖语料 - 微博语料 - 小黄鸡语料 ...
  • 长期做NLP研究,经常需将语料处理成特殊格式,这个模块经常用到,每次都要去查。。。。。今天有时间,一次性,整理出中文的所有的方法的解释和例子,方便自己查阅,同时分享出来供大家参考 好了废话不说了… 整数...

    目的

    长期做NLP研究,经常需将语料处理成特殊的格式,这个模块经常用到,每次都要去查。。。。。今天有时间,一次性,整理出中文的所有的方法的解释和例子,方便自己查阅,同时分享出来供大家参考
    好了废话不说了…

    整数领域

    random.randrange(start,stop[,step])

    作用

    range(start,stop,step),随机选择一个元素(注意:实际上没有创建一个range object.)

    例子
    #例子1
    print(random.randrange(5))
    #例子2
    r_1=random.randrange(0,6,2)
    r_2=random.randrange(1,6,2)
    print("r_1",r_1)
    print("r_2",r_2)
    
    

    输出:

    0
    r_1:  0
    r_2:  1
    

    random.randint(a, b)

    作用

    在区间[a,b]中随机的返回一个整数

    例子
    #例子1
    print("在[0,5]之间随机的选取一个整数: ",random.randint(0,5))
    

    输出:

    在[0,5]之间随机的选取一个整数:  1
    

    序列领域

    random.choice(seq)

    作用

    在一个 非空的序列(注意序列的结构不能是字典) 中随机选取一个元素

    例子
    seq_list=[1,3,45,67,88,1]
    seq_dict={"1":1,"2":2,"3":3,"4":4}
    seq_tuple=(1,34,56,7,8,9)
    seq_other=[seq_list,seq_dict,seq_tuple]
    
    
    print("在一个list中随机的选择一个元素: ",random.choice(seq_list))
    print("在一个tuple中随机的选择一个元素: ",random.choice(seq_tuple))
    print("在一个嵌套的序列中随机的选择一个元素: ",random.choice(seq_other))
    
    #会报错,是因为字典的特殊存储结构
    try:
        print("在一个dict中随机的选择一个元素: ",random.choice(seq_dict))
    except Exception:
        print("当序列是词典是出错")
    

    输出:

    在一个list中随机的选择一个元素:  67
    在一个tuple中随机的选择一个元素:  8
    在一个嵌套的序列中随机的选择一个元素:  (1, 34, 56, 7, 8, 9)
    当序列是词典是出错
    

    *random.choices(population, weights=None, , cum_weights=None, k=1)

    作用
    • 以有放回的方式 从populaition(注意:不能是字典类型的序列)随机抽取K个元素
    • 若指定weights(权重序列),根据相对权重进行选择。同时len(weights)必须等于len(population)
    • 若给出了一个cum_weights(累计权重序列),根据累计权重进行选择。权重cum_weights=[10,5,30,5]等权重[10,15,45,50]。
    • 若上述weights 和cum_weights都未指定,则以等概率取样
    • weights 和cum_weights 最多只能有一个赋值
    • 这个函数在python3.6版本中才有
    例子
    seq_list=[1,3,45,67,88,1111]
    weights_list=[100000000,1,1,1,1,1]
    
    seq_dict={"1":1,"2":2,"3":3,"4":4}
    weights_dict=[10000000,1,1,1]
    
    seq_tuple=(1,34,56,7,8,9)
    weights_tuple=[10000000,1,1,1,1,1]
    
    seq_other=[seq_list,seq_dict,seq_tuple]
    weights_other=[10000000,1,1]
    
    print("list: \n",seq_list)
    print("权重: \n",weights_list)
    print("在一个list中有放回的等概率的选择20个元素: \n",random.choices(seq_list,k=20))
    print("在一个list中有放回的根据权重选择20个元素: \n",random.choices(seq_list,weights=weights_list,k=20))
    
    print("\n\n")
    print("tuple: \n",seq_tuple)
    print("权重: \n",weights_tuple)
    print("在一个tuple中有放回的等概率的选择20个元素: \n",random.choices(seq_tuple,k=20))
    print("在一个tuple中有放回的根据权重选择20个元素: \n",random.choices(seq_tuple,weights=weights_tuple,k=20))
    
    print("\n\n")
    print("other: \n",seq_other)
    print("权重: \n",weights_other)
    print("在一个嵌套的序列中有放回的等概率的选择20个元素: ",random.choices(seq_other,k=20))
    print("在一个嵌套的序列中有放回的根据权重选择选择20个元素: ",random.choices(seq_other,weights=weights_other,k=20))
    
    #会报错,是因为字典的特殊存储结构
    try:
        print("在一个dict中随机的选择一个元素: ",random.choices(seq_dict,k=1))
    except Exception:
        print("当序列是词典是出错")
    

    输出:

    list: 
     [1, 3, 45, 67, 88, 1111]
    权重: 
     [100000000, 1, 1, 1, 1, 1]
    在一个list中有放回的等概率的选择20个元素: 
     [67, 45, 88, 1111, 67, 45, 67, 1, 3, 88, 45, 3, 88, 45, 45, 88, 3, 45, 1, 67]
    在一个list中有放回的根据权重选择20个元素: 
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
     
    tuple: 
     (1, 34, 56, 7, 8, 9)
    权重: 
     [10000000, 1, 1, 1, 1, 1]
    在一个tuple中有放回的等概率的选择20个元素: 
     [9, 8, 56, 8, 34, 56, 9, 34, 56, 56, 1, 34, 56, 9, 8, 34, 8, 8, 34, 34]
    在一个tuple中有放回的根据权重选择20个元素: 
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
    other: 
     [[1, 3, 45, 67, 88, 1111], {'1': 1, '2': 2, '3': 3, '4': 4}, (1, 34, 56, 7, 8, 9)]
    权重: 
     [10000000, 1, 1]
    在一个嵌套的序列中有放回的等概率的选择20个元素:  [[1, 3, 45, 67, 88, 1111], {'1': 1, '2': 2, '3': 3, '4': 4}, {'1': 1, '2': 2, '3': 3, '4': 4}, (1, 34, 56, 7, 8, 9), [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], (1, 34, 56, 7, 8, 9), {'1': 1, '2': 2, '3': 3, '4': 4}, [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], {'1': 1, '2': 2, '3': 3, '4': 4}, [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], (1, 34, 56, 7, 8, 9), [1, 3, 45, 67, 88, 1111], {'1': 1, '2': 2, '3': 3, '4': 4}, {'1': 1, '2': 2, '3': 3, '4': 4}]
    在一个嵌套的序列中有放回的根据权重选择选择20个元素:  [[1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111], [1, 3, 45, 67, 88, 1111]]
    当序列是词典是出错
    
    ​
    

    random.shuffle(x[, random])

    作用

    随机打乱序列X

    • x 不能是词典:词典本身就是无序的(详情,请了解字典的存储结构)
    • x不能是tuple(元组的元素不能修改。)
    • 注意:是在原序列上进行打乱的
    例子
    seq_list=[1,3,45,67,88,1111]
    seq_dict={"1":1,"2":2,"3":3,"4":4}
    seq_tuple=(1,34,56,7,8,9)
    seq_other=[seq_list,seq_dict,seq_tuple]
    
    print("list: ",seq_list)
    random.shuffle(seq_list)
    print("打乱list序列: ",seq_list)
    
    
    print("\n\n")
    print("other: ",seq_other)
    random.shuffle(seq_other)
    print("打乱嵌套的序列: ",seq_other)
    
    
    #会报错
    try:
        random.shuffle(seq_tuple)
    except Exception:
        print("打乱tuple序列失败,原因是:元组的元素不能修改")
    
    
    
    #会报错,是因为字典的特殊存储结构
    try:
        random.shuffle(seq_dict)
    except Exception:
        print("当序列是词典是出错")
    

    输出:

    list:  [1, 3, 45, 67, 88, 1111]
    打乱list序列:  [67, 1, 45, 3, 88, 1111]
    
    
    other:  [[67, 1, 45, 3, 88, 1111], {'1': 1, '2': 2, '3': 3, '4': 4}, (1, 34, 56, 7, 8, 9)]
    打乱嵌套的序列:  [(1, 34, 56, 7, 8, 9), [67, 1, 45, 3, 88, 1111], {'1': 1, '2': 2, '3': 3, '4': 4}]
    
    
    打乱tuple序列失败,原因是:元组的元素不能修改
    当序列是词典是出错
    

    random.sample(population, k)

    作用

    返回从population中以 不放回抽取方式 选择k个元素

    • 注意:不改变原序列
    • Population必须是一个序列 or 集合 。For dicts, use list(d)[选择的是 key]
    例子
    seq_list=[1,3,45,67,88,1111]
    seq_dict={"1":1,"2":2,"3":3,"4":4}
    seq_tuple=(1,34,56,7,8,9)
    seq_other=[seq_list,seq_dict,seq_tuple]
    
    
    print("list: ",seq_list)
    print("从list序列抽取3个: ",random.sample(seq_list,3))
    print("\n")
    
    
    print("tuple: ",seq_tuple)
    print("从tuple序列抽取3个: ",random.sample(seq_tuple,3))
    print("\n")
    
    
    
    print("other: ",seq_other)
    print("从嵌套序列抽取3个: ",random.sample(seq_other,2))
    print("\n")
    
    
    
    print("dict: ",seq_dict)
    try:
        print("从dict序列抽取3个: ",random.sample(seq_dict,3))
    except Exception:
        print("直接使用词典会报错")
        print("从dict序列抽取3个key: ",random.sample(list(seq_dict),3))
        
    
    

    输出:

    list:  [1, 3, 45, 67, 88, 1111]
    从list序列抽取3个:  [1, 88, 3]
    
    tuple:  (1, 34, 56, 7, 8, 9)
    从tuple序列抽取3个:  [1, 9, 7]
    
    other:  [[1, 3, 45, 67, 88, 1111], {'1': 1, '2': 2, '3': 3, '4': 4}, (1, 34, 56, 7, 8, 9)]
    从嵌套序列抽取3个:  [{'1': 1, '2': 2, '3': 3, '4': 4}, (1, 34, 56, 7, 8, 9)]
    
    dict:  {'1': 1, '2': 2, '3': 3, '4': 4}
    直接使用词典会报错
    从dict序列抽取3个key:  ['4', '1', '2']
    

    产生真实的分布Real-valued distributions

    random.random()

    作用

    在[0.0,1.0)产生一个zfloat类型的数

    例子
    print(random.random())
    

    输出:

    0.05863293760200872
    

    不常用的函数这里就不讲解了,有兴趣的同学点击自己看哈
    random.uniform(a, b)
    random.triangular(low, high, mode)
    random.normalvariate(mu, sigma)

    展开全文
  • 大纲 中文分词概念与分类 常用分词(规则分词、统计分词、混合分词)技术介绍 开源中文分词工具-Jieba ...一种机械分词方法,主要通过维护词典,切分语句时,将语句中每个字符串与词表中词逐一匹配

    大纲

    • 中文分词的概念与分类

    • 常用分词(规则分词、统计分词、混合分词)技术介绍

    • 开源中文分词工具-Jieba

    • 实战分词之高频词提取


    3.1 中文分词简介

    1. 规则分词

      最早兴起,主要通过人工设立词库,按照一定方式进行匹配切分,实现简单高效,但对新词难以处理;

    2. 统计分词

      能较好应对新词发现场景,但是太过于依赖于语料质量;

    3. 混合分词

      规则分词与统计分词的结合体;


    3.2 规则分词

    • 定义

      一种机械分词方法,主要通过维护词典,切分语句时,将语句中的每个字符串与词表中的词逐一匹配,找到则切分,否则不切分;

    • 分类

      • 正向最大匹配法(Maximum Match Method,MM法)
      1. 基本思想

        假定分词词典中最长词有ii个汉字字符,则用被处理文档的当前字符串中的前ii个字作为匹配字段,查找字典;

      2. 算法描述

        • 从左向右取待切分汉语句的mm个字符作为匹配字段,mm是机器词典中最长词条的字符数;
        • 查找机器词典并进行匹配。匹配成功则将匹配字段作为一个词切分出来,匹配失败则将匹配字段的最后一个字去掉,剩下的字符串作为新的匹配字段,进行再匹配,一直重复上述过程指导切分出所有词;
      • 逆向最大匹配法(Reverse Maximum Match Method,RMM法)
      1. 基本原理

        从被处理文档末端开始匹配扫描,每次取末端的ii个字符作为匹配字段,匹配事变则去掉匹配字段最前一个字,继续匹配;

      • 双向最大匹配(Bi-direction Matching Method)
      1. 基本原理

        将正向最大匹配法和逆向最大匹配法得到的分词结果进行比较,庵后按照最大匹配原则,选取词数切分最少的作为结果;

    • 相关代码

    1. 正向最大匹配
    	
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @version : 1.0
    # @Time    : 2019-8-25 15:27
    # @Author  : cunyu
    # @Email   : cunyu1024@foxmail.com
    # @Site    : https://cunyu1943.github.io
    # @File    : mm.py
    # @Software: PyCharm
    # @Desc    : 正向最大匹配分词
    
    train_data = './data/train.txt'  # 训练语料
    test_data = './data/test.txt'  # 测试语料
    result_data = './data/test_sc_zhengxiang.txt'  # 生成结果
    
    
    def get_dic(train_data):  # 读取文本返回列表
        with open(train_data, 'r', encoding='utf-8', ) as f:
            try:
                file_content = f.read().split()
            finally:
                f.close()
        chars = list(set(file_content))
        return chars
    
    
    def MM(test_data, result_data, dic):
        # 词的最大长度
        max_length = 5
    
        h = open(result_data, 'w', encoding='utf-8', )
        with open(test_data, 'r', encoding='utf-8', ) as f:
            lines = f.readlines()
    
        for line in lines:  # 分别对每行进行正向最大匹配处理
            max_length = 5
            my_list = []
            len_hang = len(line)
            while len_hang > 0:
                tryWord = line[0:max_length]
                while tryWord not in dic:
                    if len(tryWord) == 1:
                        break
                    tryWord = tryWord[0:len(tryWord) - 1]
                my_list.append(tryWord)
                line = line[len(tryWord):]
                len_hang = len(line)
    
            for t in my_list:  # 将分词结果写入生成文件
                if t == '\n':
                    h.write('\n')
                else:
                    print(t)
                    h.write(t + "  ")
        h.close()
    
    
    if __name__ == '__main__':
        print('读入词典')
        dic = get_dic(train_data)
        print('开始匹配')
        MM(test_data, result_data, dic)
    
    
    1. 逆向最大匹配
    
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @version : 1.0
    # @Time    : 2019-8-25 15:36
    # @Author  : cunyu
    # @Email   : cunyu1024@foxmail.com
    # @Site    : https://cunyu1943.github.io
    # @File    : rmm.py
    # @Software: PyCharm
    # @Desc    : 逆向最大匹配法
    
    train_data = './data/train.txt'
    test_data = './data/test.txt'
    result_data = './data/test_sc.txt'
    
    
    def get_dic(train_data):
        with open(train_data, 'r', encoding='utf-8', ) as f:
            try:
                file_content = f.read().split()
            finally:
                f.close()
        chars = list(set(file_content))
        return chars
    
    def RMM(test_data,result_data,dic):
        max_length = 5
    
        h = open(result_data, 'w', encoding='utf-8', )
        with open(test_data, 'r', encoding='utf-8', ) as f:
            lines = f.readlines()
    
        for line in lines:
            my_stack = []
            len_hang = len(line)
            while len_hang > 0:
                tryWord = line[-max_length:]
                while tryWord not in dic:
                    if len(tryWord) == 1:
                        break
                    tryWord = tryWord[1:]
                my_stack.append(tryWord)
                line = line[0:len(line) - len(tryWord)]
                len_hang = len(line)
    
            while len(my_stack):
                t = my_stack.pop()
                if t == '\n':
                    h.write('\n')
                else:
                    print(t)
                    h.write(t + "  ")
    
        h.close()
    
    
    if __name__ == '__main__':
        print('获取字典')
        dic = get_dic(train_data)
        print('开始匹配……')
        RMM(test_data,result_data,dic)
    

    3.3 统计分词

    • 主要操作

      • 建立统计语言模型;
      • 对句子进行单词划分,然后对划分结果进行概率计算,获得概率最大额分词方式,常用统计学习算法有隐含马尔可夫(HMM)、条件随机场(CRF)等;
    • n元条件概率

    P(wiwi(n1),,wi1)=count(wi(n1),,wi1,wi)count(wi(n1),,wi1)P(w_i|w_{i-(n-1)},…,w_{i-1})=\frac{count(w_{i-(n-1)},…,w_{i-1},w_i)}{count(w_{i-(n-1)},…,w_{i-1})}

    其中,count(wi(n1),,wi1)count(w_{i-(n-1)},…,w_{i-1})表示词wi(n1),,wi1w_{i-(n-1)},…,w_{i-1}在语料库中出现的总次数;

    • HMM模型

      将分词作为字在字串中的序列标注任务来实现。基本思路:每个字在构造一个特定的词语时都占据着一个确定的构词位置(即词位),规定每个字最多有四个构词位置:B(词首)、M(词中)、E(词尾)、S(单独成词);

    1. 数学理论

      假设用λ=λ1λ2λn\lambda=\lambda _1 \lambda_2 …\lambda_n代表输入的句子,nn表示句子长度,λi\lambda_i表示字,o=o1o2ono=o_1o_2…o_n表示输出的标签,则理想输出为:

    max=maxP(o=o1o2onλ=λ1λ2λn)=P(o1λ1)P(o2λ2)P(onλn)max = maxP(o=o_1o_2…o_n|\lambda=\lambda _1 \lambda_2 …\lambda_n)=P(o_1|\lambda_1)P(o_2|\lambda_2)…P(o_n|\lambda_n)

    在这个算法中,求解结果的常用方法是Veterbi算法,这是一种动态规划算法,核心是:如果最终的最优路径经过某个节点oio_i,则从初始节点到oi1o_{i-1}点的路径必然也是一个最优路径,因为每个节点oio_i只会影响前后两个P(oi1oi)P(o_{i-1}|o_i)P(oioi+1)P(o_i|o_{i+1})

    1. Python实现
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @version : 1.0
    # @Time    : 2019-8-27 15:42
    # @Author  : cunyu
    # @Email   : cunyu1024@foxmail.com
    # @Site    : https://cunyu1943.github.io
    # @File    : HMM_model.py
    # @Software: PyCharm
    # @Desc    : HMM模型分词
    
    import os
    import pickle
    
    
    class HMM(object):
        def __init__(self):
            import os
    
            # 主要是用于存取算法中间结果,不用每次都训练模型
            self.model_file = './data/models/hmm_model.pkl'
    
            # 状态值集合
            self.state_list = ['B', 'M', 'E', 'S']
            # 参数加载,用于判断是否需要重新加载model_file
            self.load_para = False
    
        # 用于加载已计算的中间结果,当需要重新训练时,需初始化清空结果
        def try_load_model(self, trained):
            if trained:
                import pickle
                with open(self.model_file, 'rb') as f:
                    self.A_dic = pickle.load(f)
                    self.B_dic = pickle.load(f)
                    self.Pi_dic = pickle.load(f)
                    self.load_para = True
    
            else:
                # 状态转移概率(状态->状态的条件概率)
                self.A_dic = {}
                # 发射概率(状态->词语的条件概率)
                self.B_dic = {}
                # 状态的初始概率
                self.Pi_dic = {}
                self.load_para = False
    
        # 计算转移概率、发射概率以及初始概率
        def train(self, path):
    
            # 重置几个概率矩阵
            self.try_load_model(False)
    
            # 统计状态出现次数,求p(o)
            Count_dic = {}
    
            # 初始化参数
            def init_parameters():
                for state in self.state_list:
                    self.A_dic[state] = {s: 0.0 for s in self.state_list}
                    self.Pi_dic[state] = 0.0
                    self.B_dic[state] = {}
    
                    Count_dic[state] = 0
    
            def makeLabel(text):
                out_text = []
                if len(text) == 1:
                    out_text.append('S')
                else:
                    out_text += ['B'] + ['M'] * (len(text) - 2) + ['E']
    
                return out_text
    
            init_parameters()
            line_num = -1
            # 观察者集合,主要是字以及标点等
            words = set()
            with open(path, encoding='utf8') as f:
                for line in f:
                    line_num += 1
                    print(line)
    
                    line = line.strip()
                    if not line:
                        continue
    
                    word_list = [i for i in line if i != ' ']
                    words |= set(word_list)  # 更新字的集合
    
                    linelist = line.split()
    
                    line_state = []
                    for w in linelist:
                        line_state.extend(makeLabel(w))
    
                    assert len(word_list) == len(line_state)
    
                    for k, v in enumerate(line_state):
                        Count_dic[v] += 1
                        if k == 0:
                            self.Pi_dic[v] += 1  # 每个句子的第一个字的状态,用于计算初始状态概率
                        else:
                            self.A_dic[line_state[k - 1]][v] += 1  # 计算转移概率
                            self.B_dic[line_state[k]][word_list[k]] = \
                                self.B_dic[line_state[k]].get(word_list[k], 0) + 1.0  # 计算发射概率
    
            self.Pi_dic = {k: v * 1.0 / line_num for k, v in self.Pi_dic.items()}
            self.A_dic = {k: {k1: v1 / Count_dic[k] for k1, v1 in v.items()}
                          for k, v in self.A_dic.items()}
            # 加1平滑
            self.B_dic = {k: {k1: (v1 + 1) / Count_dic[k] for k1, v1 in v.items()}
                          for k, v in self.B_dic.items()}
            # 序列化
            import pickle
            with open(self.model_file, 'wb') as f:
                pickle.dump(self.A_dic, f)
                pickle.dump(self.B_dic, f)
                pickle.dump(self.Pi_dic, f)
    
            return self
    
        def viterbi(self, text, states, start_p, trans_p, emit_p):
            V = [{}]
            path = {}
            for y in states:
                V[0][y] = start_p[y] * emit_p[y].get(text[0], 0)
                path[y] = [y]
            for t in range(1, len(text)):
                V.append({})
                newpath = {}
    
                # 检验训练的发射概率矩阵中是否有该字
                neverSeen = text[t] not in emit_p['S'].keys() and \
                            text[t] not in emit_p['M'].keys() and \
                            text[t] not in emit_p['E'].keys() and \
                            text[t] not in emit_p['B'].keys()
                for y in states:
                    emitP = emit_p[y].get(text[t], 0) if not neverSeen else 1.0  # 设置未知字单独成词
                    (prob, state) = max(
                        [(V[t - 1][y0] * trans_p[y0].get(y, 0) *
                          emitP, y0)
                         for y0 in states if V[t - 1][y0] > 0])
                    V[t][y] = prob
                    newpath[y] = path[state] + [y]
                path = newpath
    
            if emit_p['M'].get(text[-1], 0) > emit_p['S'].get(text[-1], 0):
                (prob, state) = max([(V[len(text) - 1][y], y) for y in ('E', 'M')])
            else:
                (prob, state) = max([(V[len(text) - 1][y], y) for y in states])
    
            return (prob, path[state])
    
        def cut(self, text):
            import os
            if not self.load_para:
                self.try_load_model(os.path.exists(self.model_file))
            prob, pos_list = self.viterbi(text, self.state_list, self.Pi_dic, self.A_dic, self.B_dic)
            begin, next = 0, 0
            for i, char in enumerate(text):
                pos = pos_list[i]
                if pos == 'B':
                    begin = i
                elif pos == 'E':
                    yield text[begin: i + 1]
                    next = i + 1
                elif pos == 'S':
                    yield char
                    next = i + 1
            if next < len(text):
                yield text[next:]
    
    if __name__ == '__main__':
        hmm = HMM()
        hmm.train('./data/trainCorpus.txt_utf8')
        print('训练完成')
        text = input('输入一个句子:')
        result = hmm.cut(text)
        print(str(list(result)))
    
    • 其他统计分词算法

      • 条件随机场(CRF)
      • 神经网络分词算法(CNN、LSTM)

    3.5 中文分词工具——Jieba

    • 使用Jieba的优点

      • 社区活跃
      • 功能丰富
      • 使用简单
      • 提供多种编程语言实现
    • 官网地址

    • 简介

      结合基于规则和统计的两类方法,首先基于前缀词典(指词典中的词按照前缀包含的顺序排列)进行词图扫描,从而形成一种层级包含结构。这样可以快速构建包含全部可能分词结果的有向无环图,图中包含多条分词路径,有向指全部路径都始于第一个字、止于最后一个字,而无环则指节点间不构成闭环。基于标注语料,使用动态规划方法找出最大概率路径并将其作为最终分词结果。而对于OOV,则使用基于汉字成词的HMM模型,采用Viterbi算法进行推导。

    • 三种分词模式

      • 精确模式:试图将句子最精确的切分,适合文本分析;
      • 全模式:将句子中所有可以成词的词语都扫描出来,速度快,但存在歧义问题;
      • 搜索引擎模式:在精确模式的基础上,多长词再切分,提高召回率,适用于搜索引擎分词;
    
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @version : 1.0
    # @Time    : 2019-8-26 21:33
    # @Author  : cunyu
    # @Email   : cunyu1024@foxmail.com
    # @Site    : https://cunyu1943.github.io
    # @File    : jieba_demo.py
    # @Software: PyCharm
    # @Desc    : jieba简单使用
    
    # 三种模式对比
    
    import jieba
    sent = '中文分词是文本处理中不可获取的一步!'
    
    seg_list = jieba.cut(sent,cut_all=True)
    print('全模式: ', '/'.join(seg_list))
    
    seg_list = jieba.cut(sent,cut_all=False)
    print('精确模式: ', '/'.join(seg_list))
    
    seg_list = jieba.cut_for_search(sent)
    print('搜索引擎模式: ', '/'.join(seg_list))
    

    三种模式结果

    • 高频词提取

      高频词指文档中出现频率较高且非无用的词语,在一定程度上代表了文档的焦点所在,主要有以下干扰:

      • 标点符号
      • 停用词
    
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @version : 1.0
    # @Time    : 2019-8-27 9:16
    # @Author  : cunyu
    # @Email   : cunyu1024@foxmail.com
    # @Site    : https://cunyu1943.github.io
    # @File    : keyWords.py
    # @Software: PyCharm
    # @Desc    : 关键词抽取
    
    import glob
    import random
    import jieba
    
    # 读取文件
    def get_content(path):
        with open(path, 'r', encoding='gbk', errors='ignore') as f:
            content = ''
            for l in f:
                l = l.strip()
                content += l
            return content
    
    # 获取高频词
    def get_TF(words, topK=10):
        tf_dic = {}
        for w in words:
            tf_dic[w] = tf_dic.get(w, 0) + 1
        return sorted(tf_dic.items(), key=lambda x: x[1], reverse=True)[:topK]
    
    # 加载停用词
    def stop_words(path):
        with open(path) as f:
            return [l.strip() for l in f]
    
    # 分词
    def main(path,stop_words_path):
    
        files = glob.glob(path)
        corpus = [get_content(x) for x in files[:5]]
        # 随机产生一个随机数(小于总的长度)个样本,然后对这几个样本进行提取高频词操作
        sample_inxs = random.randint(0, len(corpus))
        for sample_inx in range(sample_inxs):
            split_words = [x for x in jieba.cut(corpus[sample_inx]) if x not in stop_words(stop_words_path)]
            print('样本之一:' + corpus[sample_inx])
            print('样本分词效果:' + '/ '.join(split_words))
            print('样本的topK(10)词:' + str(get_TF(split_words)))
    
    if __name__ == '__main__':
        path = './data/news/C000010/*.txt'
        stop_words_path='./data/stop_words.utf8'
        main(path, stop_words_path)
    
    展开全文
  • Python实现中文的word2vec

    千次阅读 2019-01-08 17:09:26
    第一种方法是去网上下载相关语料,我这里有一份复旦大学中文文本分类时用的语料模型,分为训练集和测试集两部分,约220M,包括了常用的中文词汇。训练文本的大小直接决定了算法的训练效果,如果你有更合适的语料库...

    1、语料相关说明


    第一种方法是去网上下载相关语料,我这里有一份复旦大学中文文本分类时用的语料模型,分为训练集测试集两部分,约220M,包括了常用的中文词汇。训练文本的大小直接决定了算法的训练效果,如果你有更合适的语料库可以用自己的。

    2、中文训练语料的处理

    首先去网下载相关的语料文本,然后将其打开后另存为,注意选utf-8编码格式。

    文本文件准备好,现在开始用python对此txt文档进行处理。

    # 此函数作用是对初始语料进行分词处理后,作为训练模型的语料
    def cut_txt(old_file):
        import jieba
        global cut_file     # 分词之后保存的文件名
        cut_file = old_file + '_cut.txt'
    
        try:
            fi = open(old_file, 'r', encoding='utf-8')
        except BaseException as e:  # 因BaseException是所有错误的基类,用它可以获得所有错误类型
            print(Exception, ":", e)    # 追踪错误详细信息
    
        text = fi.read()  # 获取文本内容
        new_text = jieba.cut(text, cut_all=False)  # 精确模式
        str_out = ' '.join(new_text).replace(',', '').replace('。', '').replace('?', '').replace('!', '') \
            .replace('“', '').replace('”', '').replace(':', '').replace('…', '').replace('(', '').replace(')', '') \
            .replace('—', '').replace('《', '').replace('》', '').replace('、', '').replace('‘', '') \
            .replace('’', '')     # 去掉标点符号
        fo = open(cut_file, 'w', encoding='utf-8')
        fo.write(str_out)

    注意open中必须指明编码方式,否则就会报错;上面的函数若要单独运行,须要更改old_file变量为原文件名。

    3、训练模型

    准备好训练语料(注意训练语料文件越大越好,越大最后的训练效果越好),之后就开始写训练模型了,训练模型的代码如下所示:

    def model_train(train_file_name, save_model_file):  # model_file_name为训练语料的路径,save_model为保存模型名
        from gensim.models import word2vec
        import gensim
        import logging
        # 模型训练,生成词向量
        logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
        sentences = word2vec.Text8Corpus(train_file_name)  # 加载语料
        model = gensim.models.Word2Vec(sentences, size=200)  # 训练skip-gram模型; 默认window=5
        model.save(save_model_file)
        model.wv.save_word2vec_format(save_model_name + ".bin", binary=True)   # 以二进制类型保存模型以便重用

    训练后的模型用普通方式和二进制方式进行保存,以便下次直接使用,避免每次训练耗费大量时间。

    4、word2vec模型调用

    两个功能都以函数方式实现了,现在准备编写主函数代码,在主函数中负责调用各个方法实现预处理和模型训练,以此做后面的相关计算。

    from gensim.models import word2vec
    import os
    import gensim
    
    # if not os.path.exists(cut_file):    # 判断文件是否存在,参考:https://www.cnblogs.com/jhao/p/7243043.html
    cut_txt('复旦大学文本分类语料训练集.txt')  # 须注意文件必须先另存为utf-8编码格式
    
    save_model_name = '复旦大学文本分类语料训练集.model'
    if not os.path.exists(save_model_name):     # 判断文件是否存在
        model_train(cut_file, save_model_name)
    else:
        print('此训练模型已经存在,不用再次训练')
    
    # 加载已训练好的模型
    model_1 = word2vec.Word2Vec.load(save_model_name)
    # 计算两个词的相似度/相关程度
    y1 = model_1.similarity("新闻", "热度")
    print(u"新闻和热度的相似度为:", y1)
    print("-------------------------------\n")
    
    # 计算某个词的相关词列表
    y2 = model_1.most_similar("校园", topn=10)  # 10个最相关的
    print(u"和校园最相关的词有:\n")
    for item in y2:
        print(item[0], item[1])
    print("-------------------------------\n")

    最终的结果一定程序上还是取决于分词的准确率,使用jieba分词时可以针对性的加入用户自定义词典(jieba.load_userdict(“userDict.txt”) # 加载用户自定义词典),可以提高对人名,地名等未登陆词的识别效果,提高分词性能。

    展开全文
  • 中文word2vecpython实现

    万次阅读 多人点赞 2018-01-27 10:44:23
    第一种方法是去网上下载相关语料,我这里有一个英文语料模型点我下载,它适合于使用word2vec英文训练的语料,约96M,包括常用的英文词汇。 而由于中文语料比较少,暂时也是写前期代码测试,就去网上下载了《倚天...

    1、语料相关说明

    第一种方法是去网上下载相关语料,我这里有一个英文语料模型点我下载,它适合于使用word2vec英文训练的语料,约96M,包括常用的英文词汇。

    而由于中文语料比较少,暂时也是写前期代码测试,就去网上下载了《倚天屠龙记》小说全集,为txt格式,作为训练文本,此文件较小,不能达到很好的训练效果。

    2、中文训练语料的处理

    首先去网上下载了这本小说,然后将其打开后另存为,注意选utf-8编码格式。
    这里写图片描述
    文本文件准备好,现在开始用python对此txt文档进行处理。

    # 此函数作用是对初始语料进行分词处理后,作为训练模型的语料
    def cut_txt(old_file):
        import jieba
        global cut_file     # 分词之后保存的文件名
        cut_file = old_file + '_cut.txt'
    
        try:
            fi = open(old_file, 'r', encoding='utf-8')
        except BaseException as e:  # 因BaseException是所有错误的基类,用它可以获得所有错误类型
            print(Exception, ":", e)    # 追踪错误详细信息
    
        text = fi.read()  # 获取文本内容
        new_text = jieba.cut(text, cut_all=False)  # 精确模式
        str_out = ' '.join(new_text).replace(',', '').replace('。', '').replace('?', '').replace('!', '') \
            .replace('“', '').replace('”', '').replace(':', '').replace('…', '').replace('(', '').replace(')', '') \
            .replace('—', '').replace('《', '').replace('》', '').replace('、', '').replace('‘', '') \
            .replace('’', '')     # 去掉标点符号
        fo = open(cut_file, 'w', encoding='utf-8')
        fo.write(str_out)

    注意open中必须指明编码方式,否则就会报错;上面的函数若要单独运行,须要更改old_file变量为原文件名。

    3、训练模型

    准备好训练语料(注意训练语料文件越大越好,越大最后的训练效果越好),之后就开始写训练模型了,训练模型的代码如下所示:

    def model_train(train_file_name, save_model_file):  # model_file_name为训练语料的路径,save_model为保存模型名
        from gensim.models import word2vec
        import gensim
        import logging
        # 模型训练,生成词向量
        logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
        sentences = word2vec.Text8Corpus(train_file_name)  # 加载语料
        model = gensim.models.Word2Vec(sentences, size=200)  # 训练skip-gram模型; 默认window=5
        model.save(save_model_file)
        model.wv.save_word2vec_format(save_model_name + ".bin", binary=True)   # 以二进制类型保存模型以便重用

    训练后的模型用普通方式和二进制方式进行保存,以便下次直接使用,避免每次训练耗费大量时间。

    4、word2vec模型调用

    两个功能都以函数方式实现了,现在准备编写主函数代码,在主函数中负责调用各个方法实现预处理和模型训练,以此做后面的相关计算。

    from gensim.models import word2vec
    import os
    import gensim
    
    # if not os.path.exists(cut_file):    # 判断文件是否存在,参考:https://www.cnblogs.com/jhao/p/7243043.html
    cut_txt('倚天屠龙记.txt')  # 须注意文件必须先另存为utf-8编码格式
    
    save_model_name = '倚天屠龙记.model'
    if not os.path.exists(save_model_name):     # 判断文件是否存在
        model_train(cut_file, save_model_name)
    else:
        print('此训练模型已经存在,不用再次训练')
    
    # 加载已训练好的模型
    model_1 = word2vec.Word2Vec.load(save_model_name)
    # 计算两个词的相似度/相关程度
    y1 = model_1.similarity("赵敏", "韦一笑")
    print(u"赵敏和韦一笑的相似度为:", y1)
    print("-------------------------------\n")
    
    # 计算某个词的相关词列表
    y2 = model_1.most_similar("张三丰", topn=10)  # 10个最相关的
    print(u"和张三丰最相关的词有:\n")
    for item in y2:
        print(item[0], item[1])
    print("-------------------------------\n")

    最后的运行结果如下所示:
    这里写图片描述
    最终的结果一定程序上还是取决于分词的准确率,使用jieba分词时可以针对性的加入用户自定义词典(jieba.load_userdict(“userDict.txt”) # 加载用户自定义词典),可以提高对人名,地名等未登陆词的识别效果,提高分词性能。

    如有问题,欢迎留言指出,共同进步。

    展开全文
  • 必须采用一些方法将中文语句划分为单词序列才能进一步处理, 这一划分步骤即是所谓的中文分词。 主流中文分词方法包括基于规则的分词,基于大规模语料库的统计学习方法以及在实践中应用最多的规则与统计综合方法。 ...
  • 中文分词评测常用的语料上进行实验对比结果表明,基于LSTM网络模型的方法能得到比当前传统机器学习方法更好的性能;采用六词位标注并加入预先训练的字嵌入向量能够取得相对最好的分词性能;而且利用GPU可以大大...
  • 必须采用一些方法将中文语句划分为单词序列才能进一步处理, 这一划分步骤即是所谓的中文分词。 主流中文分词方法包括基于规则的分词,基于大规模语料库的统计学习方法以及在实践中应用最多的规则与统计综合方法。 ...
  • 常用的有:正向最大匹配,逆向最大匹配,最少切分法。实际应用中,将机械分词作为初分手段,利用语言信息提高切分准确率 基于词频度统计的分词方法(基于统计) 相邻的字同时出现的次数越多,越有可能构成一个词语...
  • 更好的中文近义词:聊天机器人、智能问答工具包。 synonyms可以用于自然语言理解的很多任务:文本对齐,推荐算法,相似度计算,语义偏移,关键字提取,概念提取,自动摘要,搜索引擎等。 Table of Content: ...
  • 情感分析-文本分类-语料及模型、一个拍照做题程序、世界各国大规模人名库、一个利用有趣中文语料库 qingyun 训练出来的中文聊天机器人、中文聊天机器人seqGAN、省市区镇行政区划数据带拼音标注、教育行业新闻语料库...
  • funNLP_fighting41love.tar.gz

    2019-10-20 15:05:11
    + 基于深度学习的中文语音识别系统、笑声检测器、Microsoft多语言数字/单位/如日期时间识别包、中华新华字典数据库及api(包括常用歇后语、成语、词语和汉字)、文档图谱自动生成、SpaCy 中文模型、Common Voice语音...
  • 全拼状态下不需任何引导键,直接输入单词即可输出英文单词的中文释义;拼音状态输入“`”可进入笔画输入,使用横(h)竖(s)撇(p)捺(n)/点(d)折(z),逐个笔画“拼”出汉字。 5.整合了图形化设置工具,以解决小狼毫的...
  • python3利用互信息和左右信息熵的中文分词新词发现 https://github.com/zhanzecheng/Chinese_segment_augment 句子相似度识别 项目地址: https://www.kaggle.com/c/quora-question-pairs 解决方案: word2vec + ...
  • python3利用互信息和左右信息熵的中文分词新词发现 https://github.com/zhanzecheng/Chinese_segment_augment 句子相似度识别 项目地址: https://www.kaggle.com/c/quora-question-pairs 解决方案: word2vec + ...
  • python3利用互信息和左右信息熵的中文分词新词发现 https://github.com/zhanzecheng/Chinese_segment_augment 句子相似度识别 项目地址: https://www.kaggle.com/c/quora-question-pairs 解决方案: word2vec + ...
  • 删除文本中异常字符,主要保留汉字、常用的标点,单位计算符号,字母数字等 ⭐⭐⭐ 4.文件读写工具 功能 函数 描述 星级 按行读取文件 read_file_by_iter 以迭代器形式方便按行读取文件,节省内存,...
  • PaddlePaddle 提供了丰富计算单元,使得用户可以采用模块化的方法解决各种学习问题。在此Repo中,我们展示了如何用 PaddlePaddle来解决常见机器学习任务,提供若干种不同易学易用神经网络模型。PaddlePaddle...
  • Macropodus是一个以Albert+BiLSTM+CRF网络架构为基础,用大规模中文语料训练自然语言处理工具包。将提供中文分词、词性标注、命名实体识别、关键词抽取、文本摘要、新词发现、文本相似度、计算器、数字转换、拼音...

空空如也

空空如也

1 2
收藏数 25
精华内容 10
关键字:

常用的中文语料处理方法