上篇主要梳理了基于关键词来识别变体词的一些方法,这篇重点在于实现变体词的生成上的一些方法细节。
首先,我们需要有一个算法,可以计算两个字的相似度,然后,我们基于变体字的相似度来建模,为什么是基于字呢?首先,变体词是多个变体字的组合,大部分变体词无法成词(组成词语的概率很低),这种情况下,基于我们常规的分词工具是很难正确地把他切分出来,比如下面的例子:
结巴分词结果:我/可以/加/你/的/薇/信/吗/? 正确分词结果:我/可以/加/你/的/薇信/吗/?其次,在文本信息审核的场景中,变体词生成的目的是基于一定的规则来对某些敏感词进行包装,来逃避过滤系统的审查,基于字来进行组合生成往往可以覆盖更多的组合,提高召回率。
按照前文所讲的方法:
对关键词进行拆解成字,对每个字建立关联网络(结合拼音相似度,字形相似度,字频,共同出度,共同入度构建关联边的权重),譬如,【微】字 可以生成【薇】,【徽】等,【信】 可以生成 【亻言】,【亻訁】等对生成的关键字进行组合,就可以生成【薇亻言】,【徽亻訁】等变体词,依据排列组合,会生成 a * b * c…数量的变体词,(a, b, c 表示每个组成关键词的字生成的变体字数目)具体实践中,我们运用了字形相似度,语音相似度,以及上下文相似度构建变体字的生成模型。并设定各个权重以及 阈值,进行变体词的组合生成。
汉字,作为世界上仅存的几种象形文字之一,有着和世界主流使用的拉丁语系截然不同的表现形式。拉丁文字作为一种拼音文字,在于表音,即文字形态表示了它的发音。而象形文字,则是表意文字,一个汉字本身,便表达了它所隐含的意思。 对于这个问题,一种朴素的思想,便是首先将汉字转化成一组的字母数字的序列,而这个转化所用到的hash算法必须能够将该汉字的字形特征保留下来。利用这样的转化,我们便将汉字字形的相似度问题,变成了两组字母数字序列的相似度问题。而这正是传统相似度匹配算法的强项。
我们的目的是找到一种汉字到编码的映射关系同时还能保留汉字的字形特征呢,这里,有一个四角码的编码算法可以解决这个问题。
四角编码的汉字检字法来实现这样的算法。四角算法是由王云五于1925年发明,这种编码方式根据汉字所含的单笔或复笔对汉字进行编号,取汉字的左上角,右上角,左下角以及右下角四个角的笔形,将汉字转化成最多五位的阿拉伯数字。关于四角号码的编码方式,并非本文的重点,感兴趣的读者,可以访问站点:http://baike.baidu.com/view/67253.htm?fr=aladdin 以了解更多信息。
通过将汉字转化成四角编码,再对四角编码的相似度进行计算,便可以得出两个汉字在字形上的相似程度。比如: 徽 - 2824 微 - 2824 这两个字的四角编码完全一致,而这两个字的字形也是很相似的。 然而四角编码也有其自身的问题,由于只取汉字的四角笔形,有些外形截然不同的汉字,因为四角结构相同,也拥有同样的四角编码。 举例说明: 量 - 6010 日 - 6010
所以,在四角编码的基础上,我们也加入了结构相似度(单一结构,左右结构,向下结构,左右结构,…),
可以写爬虫上结构查询链接 爬取对应内容,笔画相似度,综合进行计算 大概是:
# 0.4 * 四角相似度 + 0.3 * 笔画相似度 + 0.3 * 结构相似度 所有相似度都进行了归一化 0.4 * sijiao_code_sim(a,b) + 0.3 * strokes_num_sim(a,b) + 0.3 * struct_sim(a,b)这里的权重设置大家可以在工作中进行微调,这里我只是给一个演示。 综上,基于这个模型,我们就可以判断两个字的字形相似度了。 效果如下:
微 徽 0.829411764706 达 凯 0.225【微】和 【徽】的字形相似度达到了0.82, 但是【达】 和 【凯】就只有0.225, 还是符合期望的。
在语音相似度的计算方面,我们最开始想到的是基于拼音的编辑距离这一种思路,但是这个是不合理的,基于编辑距离的算法虽然可以一定程度上来表征两个拼音的相似度,但是却弱化了拼音所含有的比如声母和韵母这些信息。 下面介绍一个将声母韵母映射到字符的方法 用三个字符来表示一个汉字的读音: 第一位,是韵母位,通过简单的替代规则,将汉字的韵母部分映射到一个字符位。汉字的拼音中一共有24种韵母,其中部分为了后期计算目的,采用相同的字符来替代,以下是一张完整的匹配表:
我们对于an和ang,所使用的是同一种转化,目的便是为了再后期计算相似度的时候,将这种差异弱化。
第二位是声母位,同样的,也是利用一张替换表来将声母转换成字符:
第三位是声调位,表示四个声调 这样,就可以完成对拼音的转码,比较两个编码的相似度,就可以得到两个语音的相似度了。
或者,我们可以对读音近似的声母或者韵母维护一个映射表,便于在比较的时候查找映射关系,下图表示的是读音接近的声母或者韵母,读音相似的声母或者韵母可以在你进行语音相似度计算的时候给予一定加分。 如下图:
1 n l 2 l n 3 an ang 4 ang an 5 en eng 6 eng en 7 in ing 8 ing in 9 z zh 10 zh z 11 c ch 12 ch c 13 s sh 14 sh s 15 zh z 16 z zh 17 h g 18 g h 19 r l 20 l r 21 h w 22 w h 23 ei ui 24 ui ei上下文相似度,我们采用了char 级别的word2vec 即基于字的字向量, word2vec 可以看成是对于词表征学习,这里,我们对单个字进行表征学习,得到字向量,由于word2vec是学习的上下文到字的关系,所有,这种表征也可以认为是字的上下文的表征,两个字的字向量相似度,可以理解为两个字的上下文的相似度,我们用余弦相似度来计算两个向量之间的相似度 ,比如下面的例子:
您 [-0.28212646 0.43997204 -0.14741544 -0.49779999 -0.3045463 -0.02506022 1.46738672 0.55004889 1.08153665 -0.95514721 -1.11543608 -0.7564469 0.26575103 -0.79899824 -0.6336357 -0.22165367 0.30508438 0.51844716 -1.5655539 0.23785743 0.51214266 0.36013752 -1.92374432 0.56445408 -1.89895403 -0.61975962 1.84077835 1.09475625 -1.26757193 -0.24422407 0.81092846 2.1201725 0.72087884 0.66134083 1.39566183 0.92219985 0.75198483 -0.81814706 2.08854318 -0.53482115 0.75422382 0.25408059 0.5397104 0.15585403 -1.68189943 -0.15282738 0.94399124 -0.50126714 0.20012827 1.04889572 -0.31238881 0.36360955 0.5666706 -1.76381207 -0.07195765 0.33728388 -1.45689464 -1.42888248 -2.73988867 -0.36748099 1.00372493 2.11279178 -0.05676143 0.06905891 1.1735481 -0.09207518 -0.3572244 -1.28235662 -0.81183326 -0.54922819 0.58972377 1.46196055 -1.90159023 -1.24671388 0.20891149 0.97977585 2.02965879 -0.90073782 -0.4353902 1.84080458 -1.45479691 1.68460441 0.35632136 0.32696143 -0.83454508 -1.01666665 -1.0688535 0.46793419 0.17012806 -0.02928532 -0.34112716 -0.3369118 0.0247614 0.88394713 -0.36711413 -1.94277298 0.66214651 1.86682606 0.74104279 1.00784481] 你 [-1.74210298 0.27980745 -1.8341527 -1.66875982 -0.15934299 -0.82237691 0.98693097 -0.94083858 -0.01493859 -1.33691931 -0.82567811 -1.47123039 -0.40029699 -0.88372868 -0.06267058 0.5276565 -0.24367696 -0.08511459 -0.26037151 0.38780862 0.48129258 1.46434903 -1.55039108 -0.05691601 0.79519665 -1.49613678 0.69732237 0.39740315 -3.56778526 -1.45964611 0.29013771 1.88702655 0.20149691 -1.12064481 -0.06347585 -0.08697937 -0.23133473 -0.05028496 1.18464255 -1.0285728 -0.65479171 0.84930605 -1.43254888 -0.08186711 -1.13612378 2.09099388 -0.16534413 0.16576864 0.70801824 0.24148147 1.46831727 1.35163593 0.4976922 -0.52558732 -0.54664528 -1.13439965 -2.45574045 -0.34252024 -1.77293146 -0.58472925 -1.67340338 1.95280874 -2.02391267 0.7385686 0.35265663 1.35309052 -0.07064502 -0.79282701 -1.40726244 -0.22519769 1.14157903 -0.74147052 0.33884728 -1.33394825 -0.68762374 0.80799878 1.20788956 -0.62801659 -2.43817687 2.2570281 -0.29828027 -0.91494125 0.91147298 -0.49235961 -1.63211787 -0.99274009 1.30053198 -1.32980514 1.34227896 -1.38714659 -1.98865664 0.87581593 1.54487026 -0.07472751 -1.41451836 -0.76830268 -0.76483279 3.45483184 0.16658254 0.61983395] 您 你 0.730525478472【您】和【你】含义相近,出现的上下文也接近,所以,字向量的余弦相似度也比较高。
拆字,比如【信】字可以拆成【亻】和 【言】两个字,拆字也会大量的出现在变体词中,我们在网上爬了拆字的映射关系 网址:https://chaizi.51240.com/, 本地维护一个字典,用以识别一些常用汉字的拆分变体
上文提到了字形相似度,语音相似度,以及拆字,我们给每个相似度设定了一个权重,考虑到语音相似度是变体词生成的重要来源,我们给予与语音相似度的权重会偏大一点。我们也设置了一个阈值,相似度查过阈值的字,可以作为变体字。变体词就是变体字的一个组合,比较简单,就不介绍了。 大致效果是这样的,我要生成 【微信】的变体词,得到的结果如下(一部分):
维亻言 威信 威欣 威锌 威亻言 微欣 微锌 微亻言 蔚信 蔚欣 蔚锌 蔚亻言 薇信 偎欣 偎锌 偎亻言 猥信 猥欣 猥锌 猥亻言 痿信 痿欣 痿锌 痿亻言 微信 微欣 微锌 微亻言匹配算法就是基于有限状态自动机的文本匹配算法,匹配到的变体词,我们称之为疑似变体词,需要结合词在规范文本的出现的频率来进行校验,就是前文提到的贝叶斯检验方法,也可以基于词向量分析和上下围的相似度进行检验,在这里,最好离线的去维护一个变体词的词频词典,这样可以提高效率。 效果如下:
我要加你的薇亻言, 我要加你的薇信, 我要加你的威信 威信 => 微信 薇信 => 微信 薇亻言 => 微信文本介绍的变体词生成方法仅仅只是考虑了语音相似度,字形相似度,字向量等特征,虽然这种方式的变体词占据了绝大部分变体词,而且在文本过滤的场景中会有比较好的效果,但是这种方法针对一些基于人物映射、特定事件、历史和背景,以及知识产生的变体词,就无能为力了,这个是一个后期需要优化的方向。 后面第三篇,将会梳理下变体词识别的一些新的技术展望。