基于马尔科夫的字符串可读性

文本处理一直是算法学习重要组成,本文对字符串的相似性,可读性做简单记录。

基于马尔科夫的字符串可读性_第1张图片

01 字符串相似性

评价字符串相似度最常见的办法就是:把一个字符串通过插入、删除或替换这样的编辑操作,变成另外一个字符串,所需要的最少编辑次数,这种就是编辑距离(edit distance)度量方法,也称为Levenshtein距离。

hamming 海明距离是编辑距离的一种特殊情况,只计算等长情况下替换操作的编辑次数,只能应用于两个等长字符串间的距离度量。

其他常用的度量方法还有 Jaccard distance、J-W距离(Jaro–Winkler distance)、余弦相似性(cosine similarity)、欧氏距离(Euclidean distance)等。

def domian_similarity():
    str1 = "我的骨骼雪白 也长不出青稞"
    str2 = "雪的日子 我只想到雪中去si"
    # 1. difflib
    seq = difflib.SequenceMatcher(None, str1,str2)
    ratio = seq.ratio()
    print('difflib similarity1: ', ratio)
    # difflib similarity1:  0.14814814814814814

    # difflib 去掉列表中不需要比较的字符
    seq = difflib.SequenceMatcher(lambda x: x in ' 我的雪', str1,str2)
    ratio = seq.ratio()
    print('difflib similarity2: ', ratio)
    # difflib similarity2:  0.0

    # 2. hamming距离,str1和str2长度必须一致,描述两个等长字串之间对应位置上不同字符的个数
    str1 = 'ztcqcffho.com'
    str2 = 'kplzhxzcz.com'
    hamsim = Levenshtein.hamming(str1, str2)
    print('hamming similarity: ', hamsim)
    # hamming similarity:  9

    # 3. 编辑距离,描述由一个字串转化成另一个字串最少的操作次数,在其中的操作包括 插入、删除、替换
    sim = Levenshtein.distance(str1, str2)
    print('Levenshtein similarity: ', sim)
    # Levenshtein similarity:  9

    # 4.计算莱文斯坦比
    ratiosim = Levenshtein.ratio(str1, str2)
    print('Levenshtein.ratio similarity: ', ratiosim)
    # Levenshtein.ratio similarity:  0.46153846153846156

    # 5.计算jaro距离
    jarosim = Levenshtein.jaro(str1, str2)
    print('Levenshtein.jaro similarity: ', jarosim)
    # Levenshtein.jaro similarity:  0.5732600732600731

    # 6. Jaro–Winkler距离
    jaro_winklersim = Levenshtein.jaro_winkler(str1, str2)
    print('Levenshtein.jaro_winkler similarity: ', jaro_winklersim)
    # Levenshtein.jaro_winkler similarity:  0.5732600732600731

    # 字符串处理
    test1 = ['你好', '我是谁']
    test2 = ['你好', 'woshi']
    difflib.SequenceMatcher(a=test1, b=test2).quick_ratio()  # 0.5  # difflib使用时不一定为字符串,但匹配时只有单个元素完全匹配才计入
    difflib.SequenceMatcher(a=test1, b=test2).ratio()  # 0.5
    Levenshtein.distance(','.join(test1), ','.join(test2))  # Levenshtein则需要输入为字符串,匹配时是整体匹配

02 可读性

现实世界中有一类问题具有明显的时序性,比如路口红绿灯、连续几天的天气变化,我们说话的上下文···,隐马尔可夫模型(Hidden Markov Model,HMM)都有很好的应用,以下文文本可读性的算法。

2.1、文本处理

以下文本为模型的训练文本,模型通过学习正常语言规律的文本,获得文本的可读特征。将文本处理成应用算法的数据形式:

基于马尔科夫的字符串可读性_第2张图片

对以上文本做2gram处理,例如 "Well, some hundreds of times."经过2gram处理后为 ['we', 'el', 'll', 'l ', ' s', 'so', 'om', 'me', 'e ', ' h', 'hu', 'un', 'nd', 'dr', 're', 'ed', 'ds', 's ', ' o', 'of', 'f ', ' t', 'ti', 'im', 'me', 'es'] ,全文中'we' 出现15064次。

基于马尔科夫的字符串可读性_第3张图片

计算每种组合的发生概率,log处理后数据如下:

基于马尔科夫的字符串可读性_第4张图片
2.2、转移概率
基于马尔科夫的字符串可读性_第5张图片

例如以下‘ two models ’经2Gram处理后,为9组:
log_prob = log(P('tw')) + log(P('wo')) + log(P('o ')) + log(P(' m')) + log(P('mo')) + log(P('od')) + log(P('de')) + log(P('el')) + log(P('ls')) = -5.2+ -2.5 + -2.2 + -3.4 + -2.2 + -4.1 + -2.0 + -3.4 + -3.9 = -28.9
probably = math.exp(log_prob / 9) = 0.04

如下所示,复合语言可读规律的,概率得分比较高,而不符合可读性的概率得分则比较低。

字符串 转移概率
some long sentence, might suck? 0.084
Project Gutenberg 0.048
How many? I don't know. 0.065
zxcvwerjasc 0.008
nmnjcviburili,<> 0.014
ertrjiloifdfyyoiu 0.006
grty iuewdiivjh 0.013
模型应用

检验域名是否符合可读性的规律
l = ['qwwzlam.ru','rmqsnln.ru','baidu.com','google.com'],显然结果和预想的一样。

基于马尔科夫的字符串可读性_第6张图片

03 参考资料

  • Python 字符串相似性的几种度量方法
  • Gibberish-Detector
    数据标准化处理

你可能感兴趣的:(基于马尔科夫的字符串可读性)