Levenstein Distanz und dynamischer Zeitsprung

7

Ich bin mir nicht sicher, wie ich parallel zwischen dem Wagner-Fischer-Algorithmus und dtw algo ziehen soll. In beiden Fällen wollen wir den Abstand jeder Indexkombination (i, j) ermitteln.

In Wagner-Fischer initiieren wir den Abstand durch die Anzahl der Einfügungen, die wir von einer leeren Zeichenfolge zur nächsten machen müssten.

let wagnerFischer (s: string) (t: string) =
   let m, n = s.Length, t.Length
   let d = Array2D.create (m + 1) (n + 1) 0

   for i = 0 to m do d.[i, 0] <- i
   for j = 0 to n do d.[0, j] <- j    

   for j = 1 to n do
       for i = 1 to m do
          d.[i, j] <- List.min [
                           d.[i-1, j  ] + 1; 
                           d.[i  , j-1] + 1; 
                           d.[i-1, j-1] + if s.[i-1] = t.[j-1] then 0 else 1; ]
   printfn "edit matrix \n %A" d 
   d.[m,n]

In der DWT initiieren wir die Grenze bei + unendlich, weil wir keine Zahlen der Sequenz überspringen möchten, sondern immer mit einem anderen Element übereinstimmen möchten.

Was ich nicht sehe, sind die Änderungen zwischen dem DWT und dem WF-Algo, die verhindern, dass die Entfernung auf homogene Weise aktualisiert wird. In der DWT addieren wir systematisch die Kosten, während wir in der WF-Algo diese nicht homögene Funktion für verschiedene Fälle haben

Ich verstehe beide Algo, aber stellen Sie den Zusammenhang zwischen diesen Unterschieden bei der Aktualisierung der Kostenfunktion nicht her. Haben Sie eine Idee, den Unterschied intuitiv zu verstehen?

let sequencebacktrack (s: 'a seq) (t:'a seq) (cost:'a->'a->double) (boundary:int->double)  =
   let m, n = s |> Seq.length, t |> Seq.length
   let d = Array2D.create (m + 1) (n + 1) 0.

   for i = 0 to m do d.[i, 0] <- boundary(i)
   for j = 0 to n do d.[0, j] <- boundary(j)

   t |> Seq.iteri( fun j tj ->
            s |> Seq.iteri( fun i si -> 
                        d.[1+i, 1+j] <- cost tj si + List.min [d.[1+i-1, 1+j  ]; 
                                                               d.[1+i  , 1+j-1]; 
                                                               d.[1+i-1, 1+j-1]; ] ))
   printfn "edit matrix \n %A" d 
   d.[m,n]
//does not work
let wagnerFischer2 (s: string) (t: string) =
   sequencebacktrack s t (fun a b -> if a = b then 0. else 1.) (id >> double)

let b = wagnerFischer2 "ll" "la"
nicolas
quelle
2
Sie könnten Ihre Frage verbessern, indem Sie den Quellcode entfernen (ein Link reicht aus). Stattdessen sollten Sie die Unterschiede zwischen den beiden Algorithmen deutlicher hervorheben. Verwenden sie dieselbe Rekursion, verarbeiten die Tabelle jedoch in einer anderen Reihenfolge? Ist nur die Initialisierung anders? Niemand möchte den Quellcode analysieren. Machen Sie auch klar, was beide Algorithmen berechnen, die Levenstein-Distanz, richtig?
A.Schulz
1
DWT = DTW? Ich bin mit "Dynamic Time Warp" nicht vertraut. Können Sie bitte auf eine einleitende Referenz verweisen?
Raphael
1
(Referenz) David Sankoff, Joseph Kruskal: Zeitverzerrungen, String-Bearbeitungen und Makromoleküle: Theorie und Praxis des Sequenzvergleichs. 1983, Neuauflage 1999.
Hendrik

Antworten:

5

Es gibt tatsächlich eine ganze Reihe verwandter Algorithmen. Im modernen Kontext glaube ich, dass "Zeitverzerrung" als Sequenzausrichtung bezeichnet wird . Je nachdem, ob Sie komplette Saiten oder optimale Teilzeichenfolgen zusammenbringen möchten, erhalten Sie Needleman-Wunsch und Smith-Waterman .

In Ihrem letzteren Algorithmus scheinen die Kosten zu variieren, dh man kann unterschiedliche Kosten für das Löschen und Einfügen eines Zeichens sowie für das Ändern von Zeichen zuschreiben. Ihr erster Algorithmus scheint diese Kosten für alle drei möglichen Änderungen auf zu setzen.1

Hendrik Jan.
quelle