文本词语挖掘

|导语 现在社交网络和视频网站发展都非常迅猛,参与人数非常多,每日UGC(用户原创内容)量非常可观。也因此爆炸性新闻和流行词语也频频出现。不同的社交圈内,由于话题性的不同,其新词分布也不同,若直接引入搜狗等输入法的新词,会造成新词污染。因此,往往需要基于自营社交圈的语料库做新词发现,才能实现更精确的文本语义分析。

算法解析

假设你有一次看到A(男生)和B(女生)两人在街上一起肩并肩地行走,你会觉得两个人应该互相认识(凝固度还比较低);如果两个人牵着手,有说有笑,你可认为两个人很熟悉但还不一定是伴侣,也可能是兄妹吧(凝固度有提高,但是还不够高);如果在你犹豫的时候,两个人相互拥抱,这两个人可能也不算上是伴侣(因为你就只看了一次,自由度太低)。如果,在接下来的一个月内,你经常在不同的地方和时间(情景很多,说明双方比较自由,没有其他伴侣的束缚)看到过两个人亲密接触,这个时候,你基本上有百分九十以上的把握认定二人是伴侣关系。

是的,新词发现的整个判定方式和上面是一致的。你需要从凝固度和自由度两个角度考虑你通过一元分词的相邻词组合而成的“新词”是否是语境中真正的一个词。

算法三大属性

1 凝固度

凝固度是指一个新词单独出现的频次很高,远高于其组合词的概率之和。

假设是二元组词,词A和词B单独出现的概率分别是P(A)和P(B),假设这两个词是独立词,则两个词同时出现的概率为P(A)*P(B)。如果这两个词不是独立的,则两个词同时出现的条件概率会大于P(A)*P(B),即P(C) >>P(A)*P(B)。一般远大于,量级设定为1000倍。

2 自由度

文本片段的自由运用程度也是判断它是否成词的重要标准。如果一个文本片段能够算作一个词的话,它应该能够灵活地出现在各种不同的环境中,具有非常丰富的左邻字集合和右邻字集合。

左(或右)邻接字频 / 词频 > 0.2。说明左(或右)邻接有其他词和该词经常同时出现,往往邻接词比该词更有代表性。比如“欧丽格”

3 新词IDF

IDF表征了新词在文档中出现的次数,如果出现的频次越高,说明这个词在不同的环境中出现的概率更高(这个和自由度有相似性)。IDF在论坛中提取新词具有特定的意义,表征了新词在不同帖子中的认同度。一般IDF越高,说明其倍认可度越高,越有可能是新词。[但是如果IDF非常高,反而代表这个词非常普通,不一定必要进入到新词库,尤其是为了防止造成新词污染,影响词的原子性。

例如: “中国”

假设 一篇文章10000字,其中“中” 出现的词频为 100次,“国”出现的词频为200次,“中国”出现的词频是50次

0.005[中国的概率] >> 0.01[中的概率] * 0.02[国的概率] = 0.0002

例如:“是中国人”

“是中国”中, “是”则为 “中国”的左邻接字

假设“是中国”出现的词频是2次 “中国”的出现的词频是50次

2/50 = 0.04 不大于 0.2

“中国人”同理计算右邻接字自由度

代码实现

import numpy as np
import pandas as pd
import re,datetime
from numpy import log, min

# today = datetime.datetime.now()
# print(today)

f = open('word.txt', 'r')  # 读取文章
s = f.read()  # 读取为一个字符串

# 定义要去掉的标点字
drop_dict = [u',', u',', u'\n', u'。', u'、', u':', u'(', u')', u'(', u')', u'[', u']', u'.', u',', u' ', u'\u3000', u'”' , u'“' , u'?', u'?',
             u'!', u'‘', u'’', u'…',u'》',u'《',u'-',u'>',u'■',u'●',u'』',u'『',u'>',u';',u'&', u' ',u'—']
for i in drop_dict:  # 去掉标点字
    s = s.replace(i, '')

# 为了方便调用,自定义了一个正则表达式的词典
myre = {2: '(..)', 3: '(...)', 4: '(....)', 5: '(.....)', 6: '(......)', 7: '(.......)', 8: '(........)'}

min_count = 10  # 录取词语大于出现次数
min_support = 30  # 录取词语最低支持度,1代表着随机组合
min_s = 2  # 录取词语最低信息熵,越大说明越有可能独立成词
max_sep = 8  # 候选词语的最大字数
t = []  # 保存结果用。

t.append(pd.Series(list(s)).value_counts())  # 逐字统计
tsum = t[0].sum()  # 统计总字数
print(u'共%s个字...' % tsum)

rt = []  # 保存结果用

for m in range(2, max_sep + 1):
    print(u'正在生成%s字词...' % m)
    t.append([])

    for i in range(m):  # 生成所有可能的m字词
        t[m - 1] = t[m - 1] + re.findall(myre[m], s[i:])
    t[m - 1] = pd.Series(t[m - 1]).value_counts()  # 逐词统计
    t[m - 1] = t[m - 1][t[m - 1] > min_count]  # 最小次数筛选
    tt = t[m - 1][:]

    for k in range(m - 1):
        qq = np.array(list(map(lambda ms: tsum * t[m - 1][ms] / t[m - 2 - k][ms[:m - 1 - k]] / t[k][ms[m - 1 - k:]],
                               tt.index))) > min_support  # 最小支持度筛选。
        tt = tt[qq]

    rt.append(tt.index)


def cal_S(sl):  # 信息熵计算函数
    return -((sl / sl.sum()).apply(log) * sl / sl.sum()).sum()




for i in range(2, max_sep + 1):
    print(u'正在进行%s字词的最大熵筛选(%s)...' % (i, len(rt[i - 2])))
    pp = []  # 保存所有的左右邻结果
    for j in range(i):
        pp = pp + re.findall('(.)%s(.)' % myre[i], s[j:])
    pp = pd.DataFrame(pp).set_index(1).sort_index()  # 先排序,这个很重要,可以加快检索速度
    index = np.sort(np.intersect1d(rt[i - 2], pp.index))  # 作交集
    # 下面两句分别是左邻和右邻信息熵筛选
    index = index[np.array(list(map(lambda s: cal_S(pd.Series(pp[0][s]).value_counts()), index))) > min_s]
    rt[i - 2] = index[np.array(list(map(lambda s: cal_S(pd.Series(pp[2][s]).value_counts()), index))) > min_s]


# 下面都是输出前处理
for i in range(len(rt)):
    t[i + 1] = t[i + 1][rt[i]]
    t[i + 1].sort_values(ascending=False)

# # 保存结果并输出
pd.DataFrame(pd.concat(t[1:])).to_csv('all_data_word5.txt', header=False)

today = datetime.datetime.now()
print(today)

代码结果

原文链接:https://kexue.fm/archives/3491

编辑于

算法

1 篇文章1 人订阅

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏PPV课数据科学社区

“数学之美”系列二:谈谈中文分词

谈谈中文分词 --- 统计语言模型在中文处理中的一个应用 上回我们谈到利用统计语言模型进行语言处理,由于模型是建立在词的基础上的,对于中日韩等语言,首先...

2883
来自专栏木子昭的博客

《进击的虫师》爬取豆瓣电影海报(Top250)

有人想学一点编程, 但是一直没有找到感兴趣的切入点,可以简单的爬虫入手! 几十行代码, 轻松爬取豆瓣Top250电影数据,即刻体会编程的乐趣... ? ...

4484
来自专栏龙行天下CSIEM

科学瞎想系列之七十七 齿槽转矩是个神马鬼

【图片部分来自网络如有侵权敬请邮箱联系。欢迎原文转发到朋友圈,未经许可的媒体平台谢绝转载,如需转载或合作请邮件联系。联系邮箱laolicsiem@126.co...

931
来自专栏日常学python

看我如何用Python来分析《斗破苍穹》

近期根据小说《斗破苍穹》改编的同名电视剧正在热映,本文对《斗破苍穹》进行文本分析,分为两部分,首先爬取豆瓣影评进行简单分析,随后对于原创小说文本中的人物进行详细...

712
来自专栏Albert陈凯

算法与数据结构algorithm

算法与数据结构 《Data structures》 介绍:高级数据结构大全,基本算法:二叉树等 《基于用户投票的排名算法(一):Delicious和Hacker...

2915
来自专栏大数据文摘

AI不仅能画画,还能编和弦了:谷歌这几年取得了哪些艺术成就?

1534
来自专栏新智元

从“London”出发,8步搞定自然语言处理(Python代码)

【新智元导读】自然语言处理是AI的一个子领域,从人们日常沟通所用的非结构化文本信息中提取结构化数据,以便计算机理解。本文用通俗易懂的语言深入浅出的介绍了自然语言...

582
来自专栏专知

【干货】台大李宏毅两个小时带你纵览自然语言处理和语音内容机器理解,附全程视频PPT下载

【导读】李宏毅11月25日在Dosudo硅谷工程师读书会上两个办小时的演讲。 在这次演讲中李宏毅老师以语音机器理解为例纵览自然语言处理各种最新技术。李宏毅老师演...

9885
来自专栏AzMark

3天破9亿!上万条评论解读《西虹市首富》是否值得一看

作者介绍:徐麟,目前就职于上海唯品会产品技术中心,哥大统计数据狗,从事数据挖掘&分析工作,喜欢用R&Python玩一些不一样的数据

1463
来自专栏IT派

大吉大利,今晚如何用 Python 解锁“吃鸡”的正确姿势

大吉大利,今晚吃鸡~ 今天跟朋友玩了几把吃鸡,经历了各种死法,还被嘲笑说论女生吃鸡的100种死法,比如被拳头抡死、跳伞落到房顶边缘摔死 、把吃鸡玩成飞车被车技秀...

762

扫码关注云+社区