Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 最小编辑距离重建_Python_Matrix_Nlp_Dynamic Programming - Fatal编程技术网

Python 最小编辑距离重建

Python 最小编辑距离重建,python,matrix,nlp,dynamic-programming,Python,Matrix,Nlp,Dynamic Programming,我知道在堆栈上和在线上都有类似的答案,但我觉得我遗漏了一些东西。给定下面的代码,我们需要重建导致产生最小编辑距离的事件序列。对于下面的代码,我们需要编写一个输出: Equal, L, L Delete, E Equal, A, A Substitute, D, S Insert, T 编辑:使用我的(部分正确的)解决方案更新代码 下面是代码,以及我的部分解决方案。例如,它适用于我被给予(“lead”->“last”),但不适用于下面的示例(“hint”->“isnt”)。我怀疑这是因为第一个字

我知道在堆栈上和在线上都有类似的答案,但我觉得我遗漏了一些东西。给定下面的代码,我们需要重建导致产生最小编辑距离的事件序列。对于下面的代码,我们需要编写一个输出:

Equal, L, L
Delete, E
Equal, A, A
Substitute, D, S
Insert, T
编辑:使用我的(部分正确的)解决方案更新代码

下面是代码,以及我的部分解决方案。例如,它适用于我被给予(“lead”->“last”),但不适用于下面的示例(“hint”->“isnt”)。我怀疑这是因为第一个字符是相等的,这会使我的代码失效。任何正确方向的提示或指针都将非常棒

def printMatrix(M):
        for row in M:
                print row
        print

def med(s, t):  
        k = len(s) + 1
        l = len(t) + 1

        M = [[0 for i in range(k)] for j in range(l)]
        MTrace = [["" for i in range(k)] for j in range(l)]

        M[0][0] = 0


        for i in xrange(0, k):
                M[i][0] = i
                MTrace[i][0] = s[i-1]

        for j in xrange(0, l):
                M[0][j] = j
                MTrace[0][j] = t[j-1]

        MTrace[0][0] = "DONE"

        for i in xrange(1, k):
                for j in xrange(1, l):

                        sub = 1
                        sub_op = "sub"
                        if s[i-1] == t[j-1]:
                                # equality
                                sub = 0
                                sub_op = "eq"


                        # deletion
                        min_value = M[i-1][j] + 1
                        op = "del"
                        if min_value > M[i][j-1] + 1:
                                # insertion
                                min_value = M[i][j-1] + 1
                                op = "ins"
                        if min_value > M[i-1][j-1] + sub:
                                # substitution
                                min_value = M[i-1][j-1] + sub
                                op = sub_op


                        M[i][j] = min_value
                        MTrace[i][j] = op                        

        print "final Matrix"
        printMatrix(M)
        printMatrix(MTrace)

############ MY PARTIAL SOLUTION

        def array_append(array,x,y):
            ops_string = MTrace[x][y]
            if ops_string == 'ins':
                array.append(("Insert",MTrace[0][y]))
            elif ops_string == 'sub':
                array.append(("Substitute",MTrace[x][0],MTrace[0][y]))
            elif ops_string == 'eq':
                array.append(("Equal",MTrace[x][0],MTrace[0][y]))
            elif ops_string == 'del':
                array.append(("Delete",MTrace[x][0]))


        i = len(s)
        j = len(t)

        ops_array = []
        base = M[i][j]
        array_append(ops_array,i,j)


        while MTrace[i][j] != "DONE":
            base = M[i][j]
            local_min = min(M[i][j-1],M[i-1][j],M[i-1][j-1])
            if base == local_min:
                i = i - 1
                j = j - 1
                array_append(ops_array,i,j)
            elif M[i][j-1] < M[i-1][j]:
                j = j -1
                array_append(ops_array,i,j)
            elif M[i-1][j] < M[i][j-1]:
                i = i - 1
                array_append(ops_array,i,j)
            else:
                i = i - 1
                j = j - 1
                array_append(ops_array,i,j)

        print ops_array
#########

        return M[k-1][l-1]      

print med('lead', 'last')
def打印矩阵(M):
对于以M为单位的行:
打印行
打印
def med(s,t):
k=透镜+1
l=len(t)+1
M=[[0代表范围(k)中的i]代表范围(l)中的j]
MTrace=[[“”表示范围(k)中的i]表示范围(l)中的j]
M[0][0]=0
对于x范围内的i(0,k):
M[i][0]=i
MTrace[i][0]=s[i-1]
对于X范围内的j(0,l):
M[0][j]=j
MTrace[0][j]=t[j-1]
MTrace[0][0]=“完成”
对于x范围内的i(1,k):
对于X范围内的j(1,l):
sub=1
sub_op=“sub”
如果s[i-1]==t[j-1]:
#平等
sub=0
sub_op=“eq”
#删除
最小值=M[i-1][j]+1
op=“del”
如果最小值>M[i][j-1]+1:
#插入
最小值=M[i][j-1]+1
op=“ins”
如果最小值>M[i-1][j-1]+sub:
#替代品
最小值=M[i-1][j-1]+sub
op=sub_op
M[i][j]=最小值
MTrace[i][j]=op
打印“最终矩阵”
打印矩阵(M)
打印矩阵(MTrace)
############我的偏解
def array_append(数组,x,y):
ops_string=MTrace[x][y]
如果ops_字符串=='ins':
array.append((“Insert”,MTrace[0][y]))
elif ops_string==“sub”:
array.append((“替换”,MTrace[x][0],MTrace[0][y]))
elif ops_字符串=='eq':
array.append((“Equal”,MTrace[x][0],MTrace[0][y]))
elif ops_string==“del”:
array.append((“Delete”,MTrace[x][0]))
i=len(s)
j=len(t)
ops_数组=[]
基数=M[i][j]
数组附加(操作数组,i,j)
而MTrace[i][j]!=“完成”:
基数=M[i][j]
局部_min=min(M[i][j-1],M[i-1][j],M[i-1][j-1])
如果基==局部最小值:
i=i-1
j=j-1
数组附加(操作数组,i,j)
elif M[i][j-1]
我建议您看看该模块。这可能会让你有很长的路要走:

>>> import Levenshtein
>>> Levenshtein.editops('LEAD','LAST')
[('replace', 1, 1), ('replace', 2, 2), ('replace', 3, 3)]

您可以处理编辑操作的输出以创建详细的指令。

我认为,在这种情况下,更深入地理解算法非常重要。我将引导您完成算法的基本步骤,并向您展示所需数据如何在最终生成的矩阵中“编码”,而不是给您一些伪代码。当然,如果您不需要使用自己的算法,那么您显然应该使用其他人的算法,例如

大局 在我看来,这就像是。基本思想是计算“附近”前缀之间的距离,取最小值,然后计算当前字符串对与该前缀之间的距离。例如,假设您有两个字符串
'i'
'h'
。让我们沿着矩阵的垂直轴和水平轴进行布局,如下所示:

  _ h
_ 0 1
i 1 1
这里,
'
表示一个空字符串,矩阵中的每个单元格对应一个编辑序列,该序列将输入(
'
'i'
)转换为输出(
'
'h'

从空字符串到长度为L的任何字符串的距离为L(需要插入L)。长度为L的任何字符串到空字符串的距离也是L(需要删除L)。这包括第一行和第一列中的值,它们只是增量

在此基础上,您可以通过从左上角、左上角和左上角的值中取最小值并添加一个值来计算任何位置的值,或者,如果字符串中该点的字母相同,则取左上角的值不变。对于上表中
(1,1)
处的值,在
(0,0)
处的最小值是
0
,因此
(1,1)
处的值是
1
,这是从
'i'
'h'
的最小编辑距离(一次替换)。所以一般来说,最小编辑距离总是在矩阵的右下角

现在让我们做另一个,比较
is
hi
。这里,矩阵中的每个单元格都对应一个编辑序列,该序列将输入(
'
'i'
,或
'is'
)转换为输出(
'
'h'
,或
'hi'

我们首先放大矩阵,使用
#
作为p
  _ h i
_ 0 1 2
i 1 1 #
s 2 # #
  _ h i
_ 0 1 2
i 1 1 #
s 2 2 #
  _ h i
_ 0 1 2
i 1 1 1
s 2 2 #
  _ h i
_ 0 1 2
i 1 1 1
s 2 2 2
  _ h i n t
_ 0 1 2 3 4
i 1 1 1 2 3
s 2 2 2 2 3
n 3 3 3 2 3
t 4 4 4 3 2
(4, 4) -> (3, 3) -> (2, 2) -> (1, 2) -> (0, 1) -> (0, 0)
(4, 4) -> (3, 3) -> (2, 2) -> (1, 1) -> (0, 0)
(0, 0) -> (0, 1) -> (1, 2) -> (2, 2) -> (3, 3) -> (4, 4)
(0, 0) -> (1, 1) -> (2, 2) -> (3, 3) -> (4, 4)
Insert, h
Equal, i, i
Delete, s
Equal, n, n
Equal, t, t
isnt   (No change)
hisnt  (Insertion)
hisnt  (No change)
hint   (Deletion)
hint   (No change)
hint   (No change)
    [TestMethod]
    public void TestEditDistance()
    {
        var expected = new[]
            {
                Move.Delete, 
                Move.Substitute, 
                Move.Match, 
                Move.Match, 
                Move.Match, 
                Move.Match, 
                Move.Match, 
                Move.Insert,
                Move.Substitute, 
                Move.Match, 
                Move.Substitute, 
                Move.Match, 
                Move.Match, 
                Move.Match, 
                Move.Match
            };
        Assert.IsTrue(expected.SequenceEqual(new EditDistanceCalculator().CalcEditDistance("thou-shalt-not", "you-should-not")));

        var calc = new EditDistanceCalculator(3, 1, 1);
        var edit = calc.CalcEditDistance("democrat", "republican");
        Console.WriteLine(string.Join(",", edit));
        Assert.AreEqual(3, edit.Count(m => m == Move.Match)); //eca
    }