# snsg **Repository Path**: jempson/snsg ## Basic Information - **Project Name**: snsg - **Description**: 这是一个无监督训练文本词库分词 - **Primary Language**: Python - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 8 - **Created**: 2018-03-01 - **Last Updated**: 2021-11-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # **SNSG** [![tyoui](https://github.com/zhangwei0530/logo/blob/master/logo/photolog.png?raw=true)](http://www.tyoui.cn) [![](https://github.com/zhangwei0530/logo/blob/master/logo/logo.png?raw=true)](http://www.tyoui.cn) ## 这是一个无监督训练文本词库与分词 [![](https://img.shields.io/badge/DL-train-yellow.svg)]() [![](https://img.shields.io/badge/Python-3.6-green.svg)]() [![](https://img.shields.io/badge/BlogWeb-Tyoui-bule.svg)](http://www.tyoui.cn) [![](https://img.shields.io/badge/Email-tyoui@tyoui.cn-red.svg)]() ## 训练代码(文本是UTF-8格式) import snsg if __name__ == '__main__': s = snsg.SNSG(file_name="C:\\Users\\User\\Desktop\\1.txt") s.read() s.split() s.handle() data = s.filter() for key, value in data: print('关键字:' + key, '次数:' + str(value[0]), '词频:' + str(value[1]), '凝聚度:' + str(value[2]), '自由度:' + str(value[3])) ## 接口参数 file_name, file_encoding='utf-8-sig', split_num=4, seq=0.001, cond=50, free=0.5 """ 初始化参数 :param file_name: 读取的文件 :param file_encoding: 文本编码 :param split_num: 匹配个数 :param seq: 关键字出现的频率 :param cond: 凝固程度 :param free: 自由程度 """ ![](https://github.com/zhangwei0530/logo/blob/master/photo/snsg1.png?raw=true) ## 爬虫的新闻数据一部分截图(大概100M纯文本) ![](https://github.com/zhangwei0530/logo/blob/master/photo/snsg2.png?raw=true) ## 训练政治新闻后的结果 ![](https://github.com/zhangwei0530/logo/blob/master/photo/snsg.png?raw=true) ## 核心原理 要想从一段文本中抽出词来,我们的第一个问题就是,怎样的文本片段才算一个词?大家想到的第一个标准或许是, 看这个文本片段出现的次数是否足够多。我们可以把所有出现频数超过某个阈值的片段提取出来,作为该语料中的词汇输出。 不过,光是出现频数高还不够,一个经常出现的文本片段有可能不是一个词,而是多个词构成的词组。如果“的电影”出现了 389 次, “电影院”只出现了 175 次,然而我们却更倾向于把“电影院”当作一个词,因为直觉上看,“电影”和“院”凝固得更紧一些。 为了证明“电影院”一词的内部凝固程度确实很高,我们可以计算一下,如果“电影”和“院”真的是各自独立地在文本中随机出现, 它俩正好拼到一起的概率会有多小。在整个 2400 万字的数据中,“电影”一共出现了 2774 次,出现的概率约为 0.000113 。“院”字则出现了 4797 次,出现的概率约为 0.0001969 。如果两者之间真的毫无关系,它们恰好 拼在了一起的概率就应该是 0.000113 × 0.0001969 ,约为 2.223 × 10-8 次方。但事实上,“电影院”在语 料中一共出现了 175 次,出现概率约为 7.183 × 10-6 次方,是预测值的 300 多倍。类似地,统计可得“的”字 的出现概率约为 0.0166 ,因而“的”和“电影”随机组合到了一起的理论概率值为 0.0166 × 0.000113 ,约为 1.875 × 10-6 ,这与“的电影”出现的真实概率很接近——真实概率约为 1.6 × 10-5 次方,是预测值的 8.5 倍。计算结果表明,“电影院”更可能是一个有意义的搭配,而“的电影”则更像是“的”和“电影”这两个成分偶然拼到一 起的。 当然,作为一个无知识库的抽词程序,我们并不知道“电影院”是“电影”加“院”得来的,也并不知道“的电影”是“的”加 上“电影”得来的。错误的切分方法会过高地估计该片段的凝合程度。如果我们把“电影院”看作是“电”加“影院”所得, 由此得到的凝合程度会更高一些。因此,为了算出一个文本片段的凝合程度,我们需要枚举它的凝合方式——这个文本 片段是由哪两部分组合而来的。令 p(x) 为文本片段 x 在整个语料中出现的概率,那么我们定义“电影院”的凝合程 度就是 p(电影院) 与 p(电) · p(影院) 比值和 p(电影院) 与 p(电影) · p(院) 的比值中的较小值, “的电影”的凝合程度则是 p(的电影) 分别除以 p(的) · p(电影) 和 p(的电) · p(影) 所得的商的较小值。 光看文本片段内部的凝合程度还不够,我们还需要从整体来看它在外部的表现。考虑“被子”和“辈子”这两个片段。 我们可以说“买被子”、“盖被子”、“进被子”、“好被子”、“这被子”等等,在“被子”前面加各种字;但“辈子”的用 法却非常固定,除了“一辈子”、“这辈子”、“上辈子”、“下辈子”,基本上“辈子”前面不能加别的字了。“辈子”这个 文本片段左边可以出现的字太有限,以至于直觉上我们可能会认为,“辈子”并不单独成词,真正成词的其实 是“一辈子”、“这辈子”之类的整体。可见,文本片段的自由运用程度也是判断它是否成词的重要标准。如果一个文 本片段能够算作一个词的话,它应该能够灵活地出现在各种不同的环境中,具有非常丰富的左邻字集合和右邻字集合。 “信息熵”是一个非常神奇的概念,它能够反映知道一个事件的结果后平均会给你带来多大的信息量。如果某个结果的 发生概率为 p ,当你知道它确实发生了,你得到的信息量就被定义为 – log(p) 。 p 越小,你得到的信息量就 越大。如果一颗骰子的六个面分别是 1 、 1 、 1 、 2 、 2 、 3 ,那么你知道了投掷的结果是 1 时可能并 不会那么吃惊,它给你带来的信息量是 – log(1/2) ,约为 0.693 。知道投掷结果是 2 ,给你带来的信息量 则是 – log(1/3) ≈ 1.0986 。知道投掷结果是 3 ,给你带来的信息量则有 – log(1/6) ≈ 1.79 。但 是,你只有 1/2 的机会得到 0.693 的信息量,只有 1/3 的机会得到 1.0986 的信息量,只有 1/6 的机会 得到 1.79 的信息量,因而平均情况下你会得到 0.693/2 + 1.0986/3 + 1.79/6 ≈ 1.0114 的信息量。 这个 1.0114 就是那颗骰子的信息熵。现在,假如某颗骰子有 100 个面,其中 99 个面都是 1 ,只有一个面 上写的 2 。知道骰子的抛掷结果是 2 会给你带来一个巨大无比的信息量,它等于 – log(1/100) ,约为 4.605 ;但你只有百分之一的概率获取到这么大的信息量,其他情况下你只能得到 – log(99/100) ≈ 0.01005 的信息量。平均情况下,你只能获得 0.056 的信息量,这就是这颗骰子的信息熵。再考虑一个最极端的情况: 如果一颗骰子的六个面都是 1 ,投掷它不会给你带来任何信息,它的信息熵为 – log(1) = 0 。什么时候信息 熵会更大呢?换句话说,发生了怎样的事件之后,你最想问一下它的结果如何?直觉上看,当然就是那些结果最不确 定的事件。没错,信息熵直观地反映了一个事件的结果有多么的随机。 ### 详细请参考文章 http://www.matrix67.com/blog/archives/5044 注:参考文章。感谢楼主提供灵感