莱文斯坦距离计算(LD levenshtein Distance)

莱文斯坦距离计算(LD levenshtein Distance)

基本理论

莱文斯坦距离用户衡量两个字符串之间的相似度.s(原字符串)和t(目标字符串).莱文斯坦距离被定义为"将字符串s变换为字符串t所需的删除 插入 替换操作的次数

算法原理

该算法的解决是基于动态规划的思想,具体如下:
设 s 的长度为 n,t 的长度为 m。如果 n = 0,则返回 m 并退出;如果 m=0,则返回 n 并退出。否则构建一个数组 d[0…m, 0…n]。
将第0行初始化为 0…n,第0列初始化为0…m。
依次检查 s 的每个字母(i=1…n)。
依次检查 t 的每个字母(j=1…m)。
如果 s[i]=t[j],则 cost=0;如果 s[i]!=t[j],则 cost=1。将 d[i,j] 设置为以下三个值中的最小值:
紧邻当前格上方的格的值加一,即 d[i-1,j]+1
紧邻当前格左方的格的值加一,即 d[i,j-1]+1
当前格左上方的格的值加cost,即 d[i-1,j-1]+cost
重复3-6步直到循环结束。d[n,m]即为莱茵斯坦距离。

为什么:

其实思想就是基于上一个状态的最小距离,推出下一个的最小距离,对于两个数据A,B来说,如何找出他们的上一个状态呢,其实穷举一下就可以了假设当前状态大家都是一个字符A=“a”,B=“a”,那么他们上一个状态有以下3种情况,A="",B=“a”|A=“a”,B=""|A="",B="“对应其实就是 edit(i-1,j)|edit(i,j-1)|edit(i-1,j-1),在表结构对应的位置就是当前位置的上|左|左上,而对于edit(i-1,j)|edit(i,j-1)这两种情况无论怎么样,他们要转换到当前状态至少都要加1的编辑距离。例如A=”",B=“a"变到A=“a”,B=“a” A要增加1个编辑距离。而对于edit(i-1,j-1)如果edit(i,j)中i对应的字符等于j其实是不用增加编辑距离的,例如A=”",B=""到A=“a”,B=“a”,时原本的编辑距离是0,现在还是0,但如果i,j对应的字符不相等,例如A=“ab”,B="ab"到A=“abb”,B=“abc”,其实是从原来的编辑距离是0,变成了1,所以最小编辑距离应该是上一个编辑距离edit(i-1,j-1)+1 。(cost = 1 or 0)

实现代码:

import pandas as pd
import numpy as np



def levenshtein_distance(string1, string2):
    d = pd.DataFrame(np.zeros((len(string1) + 1, len(string2) + 1)).T)
    for i in range(len(string1) + 1):
        d[i][0] = i
    for j in range(len(string2) + 1):
        d[0][j] = j
    for i in range(1, len(string1) + 1):
        for j in range(1, len(string2) + 1):
            cost = 0
            if string1[i-1] != string2[j-1]:
                cost = 1
            if d[i-1][j] < d[i][j-1]:
                mincost = d[i-1][j] + 1
            else:
                mincost = d[i][j-1] + 1  # 替换操作 此时为编辑距离
                mincost = d[i][j-1] + 2  # 次数为类编辑距离 
            if mincost > (d[i - 1][j - 1] + cost):
                mincost = d[i - 1][j - 1] + cost
            # print(i, j, mincost)
            d[i][j] = mincost

    # print(d)
    return d
    
 def levenshtein_ratio(string1, string2):

    i = len(string1)
    j = len(string2)
    ld = levenshtein_distance(string1, string2)[i][j]
    print("ld", ld)
    return 1 - (ld/(i+j))

if __name__ == "__main__":
    s = "abc"
    t = "abbf"
    print(Levenshtein.distance(s, t))
    print("t1\n", levenshtein_distance(s, t))
    print("ratio:", Levenshtein.ratio(s, t))
    print("ld ratio:", levenshtein_ratio(s, t))
    print('\n')
    print("t2\n", levenshtein_distance("bca", "abc"))
    print("ratio:", Levenshtein.ratio("bca", "abc"))
    print("ld ratio:", levenshtein_ratio("bca", "abc"))

你可能感兴趣的:(MachineLearning,机器学习)