Wir machen weiter.
Wir legen los mit automatischer Spracherkennung und bei den Problemen,
dass wir bekommen, wenn wir jetzt Sprachmodelle in die Suche mit
reinnehmen.
Jetzt habe ich ungünstigerweise natürlich das Buch, aus dem ich es
abschreiben würde, vergessen.
Das heißt, ich muss mich jetzt auf mein löchriges Gedächtnis
verlassen, ob ich das heilig hinkriege.
Den einfachen Fall hatten wir uns ja letztes Mal schon angeschaut.
Angenommen, ich habe so ein Vokabular und damit es jetzt
übersichtlicher wird, dass da immer HMMs hinter jedem Wort dahinter
stecken.
Also wir hatten letztes Mal schon
angefangen.
Wenn wir jetzt diese Vokabularwörter A1 bis N haben und wir wollen
jetzt Sprachmodell reinnehmen, dann macht man halt so einen
Sammelzustand.
Eine Möglichkeit, das geschickt zu machen, ist so ein Sammelzustand,
so ein Startzustand mit so Nullübergängen, an denen die
Unigrammwahrscheinlichkeit zum Beispiel von dem Wort rangeschrieben
wird.
Und nach jedem Wort gehe ich wieder mit so einem Nullübergang, wo
nichts passiert, in den Startzustand.
Auf die Art und Weise kann ich jetzt ein Unigrammsprachmodell mit
reinbauen in den Suchraum.
Und das hier sind halt immer die HMM-Zustände und dann wird das halt
immer weiter expandiert nach den Regeln.
Jetzt, was passiert, wenn ich jetzt Migrammwahrscheinlichkeiten habe?
Das kann man sich ein bisschen zurückerinnern, wenn man mal mit so
endlichen Automaten etc.
agiert hat.
Da hatte man ja immer, dass man durch Vermehren der Zustände mal sowas
wie Gedächtnis, Speicher, Memory implementieren konnte.
Und da brauchen wir jetzt halt mehr Zustände, um den Speicher zu
implementieren.
Wir müssen uns also sozusagen merken, ich war jetzt in einem Zustand,
wo vorher ein Wort war und damit es jetzt übersichtlicher wird,
beschränken wir uns mal nur auf den Ausschnitt, der sich um ein Wort
kümmert.
Ich bin also irgendwie aus dem Wort 1 Startzustand gehabt, bin in das
Wort 1 übergegangen und jetzt gehe ich in ein zweites Wort über.
Nennen wir es VI.
Dann habe ich hier erstmal noch den Übergang von der
Unigrammwahrscheinlichkeit, weil ich bin am Anfang.
Und dann, wenn ich in das Wort VI, also hier habe ich V1 und wenn ich
dann in das Wort VI übergehe, dann muss ich hier halt die
Wahrscheinlichkeit drauf multiplizieren, dass ich nach VI gehe und
nach vorher in V1.
Und dann bin ich im Wort VI und wenn ich dann in irgendein beliebiges
anderes Wort übergehe, also hier haben wir V1, V2 bis VN.
Wenn ich in ein beliebiges Wort PI übergehe, hier steht dann halt
entsprechend, äh VI übergehe, hier steht dann VI, dass ich vorher im
Wort V2 war.
Und wenn ich jetzt von hier aus wieder in ein Wort reingehe, zum
Beispiel nach V2, dann muss ich hier halt die Wahrscheinlichkeit
dranschreiben, dass ich jetzt in das Wort V2 gehe und vorher im Wort
VI war.
Das heißt, ich habe hier deutlich mehr Übergänge, weil ich immer einen
Speicher brauche.
Okay, ich war in einem Wort, gehe jetzt in ein neues Wort über.
Ich kann nicht mehr über diesen Sammelstartzustand gehen, sondern muss
immer dann direkt in das neue Wort reingehen und mir merken, okay, ich
komme vom Wort VI und gehe jetzt in das Wort V2.
Die Anzahl der Zustände bleibt im Großen und Ganzen gleich, das ist
immer noch die Größe des Vokabulars, aber die Anzahl der Übergänge
wird halt mehr, weil ich halt nicht von hier VI wieder in den
Startzustand reingehe, weil wenn ich in einem Startzustand bin,
vergesse ich, von welchem Wort ich komme und kann halt nur beim
Übergang in ein Wort eine Unigrammwahrscheinlichkeit drauf tun,
sondern ich muss dann, wenn ich jetzt reingehe in so ein Wort, ich
komme von einem VI, schreibe dann die Bigrammwahrscheinlichkeit rein,
indem ich hier reinschreibe, in welches neue Wort gehe ich über.
Und dann habe ich halt von jedem Wort aus so viele Übergänge, wie es
Wörter in meinem Vokabular gibt.
Es ist also deutlich mehr Übergänge.
Und wenn ich das Ganze jetzt zum Beispiel mit Trigramm mache, dann
wird es richtig unangenehm.
Dann brauche ich nämlich Zustände, die mir sich merken, was waren die
letzten zwei Worte, in denen ich war.
Dann brauche ich also Zustände, die stehen dafür.
Die letzten beiden Worte, die ich gesehen habe, waren VI, VJ.
Und dann gehe ich über in ein neues Wort, VK, und dann kann ich hier
die Trigrammwahrscheinlichkeit VK, VIJ dran tun.
Das heißt, hier brauche ich quadratisch viele Zustände, also jede
Kombination aus zwei Wörtern aus dem Vokabular.
Und wenn ich jetzt also so einen Übergang mache, dann geht der
natürlich nicht in so einen Zustand VK, sondern ich würde gerne wieder
zurückgehen.
Wenn ich jetzt den Übergang mache, dann muss ich mir sozusagen
überlegen, in welches ist denn jetzt die korrekte Kombination von
Wörtern, in die ich übergehe.
Also wenn ich vorher in VIJ war und erweitere jetzt um das Wort VK,
dann heißt das, ich muss hier in einen Zustand reingehen, der dann
heißt VJVK.
Das heißt, ich habe hier diese quadratisch vielen Zustände und dann
von jedem Zustand aus auch quadratisch viele Übergänge, weil ich kann
von jedem Zustand, der für meine Historie ist, ein bestimmtes Bigramm,
übergehen in jede andere beliebige Historie.
Das heißt, ich habe beim Übergang von Unigramm zu Bigramm die Anzahl
der Zustände gleich, aber die Anzahl der Übergänge ist quadratisch
groß geworden.
Und jetzt habe ich das Problem, dass die Anzahl der Zustände
quadratisch groß geworden ist und die Anzahl der Übergänge ist nochmal
ein Polynom noch höher geworden.
Das heißt, die Anzahl der Zustände steigen mit N-Gramm-Tiefe sozusagen
quadratisch in dem N und exponentiell in dem N, mit N als Exponent und
dann mit N plus 1 Exponent sind dann die Anzahl der Übergänge.
Das heißt, dadurch, dass ich jetzt so ein Sprachmodell reinnehme in
diese Suchnetzwerke, explodiert die Größe.
Und das ganze Ding muss abgesucht werden und muss irgendwie
repräsentiert werden und muss durchgeräumt werden.
Und das heißt also, das Suchnetzwerk wird extrem groß.
Also die Sache ist die, das Netzwerk wird dadurch einfach so groß,
also wenn ich jetzt 4 Gramm mache und das ist heutzutage nicht
unüblich, habe ich halt N hoch 3 dieser Zustände und N hoch 4
Übergänge, dass ich das Netzwerk nicht mehr im Speicher halten kann,
dass ich das Netzwerk zwar implizit repräsentieren kann, aber dass das
Netzwerk trotzdem so groß wird, weil ich hier das Wort, in das ich
sozusagen expandiere, hier das VJ, ja auch als HMM darstelle, wird das
Netzwerk so groß, dass es schwierig ist, dass in erträglicher Zeit
abzusuchen.
Eine Idee ist die Idee, dass man mit sogenannten Mehrpassstrategien
arbeitet.
Das hatte ich schon mal angedeutet.
So eine Möglichkeit wäre, okay, wenn ich halt 3 Gramm nicht anwenden
kann, weil es zu aufwendig ist, dann mache ich halt erstmal eine Suche
mit B Gramm, implizite Strahlsuche, gucke mir an, was ist der
Suchraum, der übrig bleibt, der aktiviert ist und den kann ich nachher
nochmal mit einem Trigramm absuchen, den muss ich sozusagen dann nur
den Teil des kompletten Suchnetzwerkes absuchen, der halt dem
entspricht, was aktiv geworden ist, als ich mit einem B Gramm
Sprachmodell gesucht habe.
Was man aber dann letztendlich wirklich gemacht hat, ist, dass man
sein Kriterium nochmal geändert hat.
Dass man also zurück rangegangen ist an die Fundamentalformel der
Spracherkennung und was letztendlich passiert ist, man hat sich davon
gelöst, dass man für die Berechnung des akustischen Modells immer hier
mal explizit hingenommen ist, die Summe der Wahrscheinlichkeiten der
einzelnen Pfade durch das HMM aufsummiert oder durch die HMMs
hintereinander gesetzt, also die Menge aller möglichen Zustandsfolgen
und deren Wahrscheinlichkeit dann aufsummiert, dass man das weglässt.
Das ist das hier, was letztendlich der Forward-Algorithmus effektiv
berechnet, um p von x gegeben w ausrechnet und das lässt man jetzt
fallen und ersetzt diese Summe durch ein Maximum.
Das heißt, man sucht also nicht mehr nach der Wortfolge, wo dann halt
die Summe über alle Zustandsfolgen, die zu der Wortfolge gehören, beim
akustischen Modell genommen wird, sondern man sucht jetzt nur noch
nach der wahrscheinlichsten Zustandsfolge und multipliziert das Ganze
mit dem Sprachmodell und sagt halt, normalerweise sollte das Problem
so geformt sein und sollte Sprache derart sein, dass die
wahrscheinlichste Wortfolge auch diejenige Wortfolge sein sollte, die
die wahrscheinlichste Zustandsfolge enthält, so dass wenn ich die
wahrscheinlichste Zustandsfolge finde, die Wortfolge, die die
wahrscheinlichste Zustandsfolge entfällt, dass ich sagen kann, das
müsste auch die normalerweise die Wortfolge mit der höchsten
Wahrscheinlichkeit sein.
Die Änderung scheint minimal, sie funktioniert aber wirklich nur
deshalb, weil Spracherkennung als Problem so wohl geformt ist, dass
das eben zutrifft.
Würde ich sowas auf arbiträr geformte Probleme anwenden, könnte ich da
massiv auf die Nase fallen.
Also das kann massiv schief gehen, nur in unserem Fall sind wir in der
glücklichen Position, dass es funktioniert.
Und gleichzeitig schaffe ich es dadurch, massiv an Rechenzeit
einzusparen, weil ich diese ganze HMM-Durchsucherei jedes Mal, wenn
ich hier in den Frame expandiere, muss ich alle möglichen Pfade wie in
der Trellis, muss ich so eine kleine Matrix aufmachen, parallel
expandieren sein lassen kann, sondern es reicht, wenn ich immer nur
Maximum expandiere und dann durch die Beamsearch halt die Sachen weg
prune, die ich nicht brauche und dann spare ich mir jede Menge
Rechenzeit.
Wenn ich das Ganze jetzt implementiere, muss ich im Prinzip das
Gleiche beachten, was ich auch beim Viterbi-Algorithmus rein für HMMs
mache.
Die Zustandsfolge ist ja in Wirklichkeit nicht interessant.
Interessant ist in Wirklichkeit ja nur die Wortfolge.
Das heißt, wenn ich so Buchhaltung mache, welche Zustände besuche ich
denn überhaupt und wie verläuft mein Pfad, dann merke ich mir nicht,
wie sind die Zustände für jeden Frame, sondern ich merke mir immer
nur, was ist eigentlich die Wortfolge.
Und das macht man halt, indem man halt immer die Rückzeiger sich
merkt, wenn ich diesen Übergang bei der Wortfolge mache, aber nicht
die Rückzeiger in der Viterbi-Matrix, die ich innerhalb des Wortes
ausrechne.
Wie gesagt, das Ganze funktioniert dann effektiv oder nur dann
effektiv, wenn man das Ganze wirklich schön kombiniert mit einer
Strahlsuche, damit man diesen Aufwand hier innen drin, der in den HMMs
von den Wörtern stattfindet, möglichst klein hält.
Und die Strahlsuche bei der Viterbi-Suche funktioniert halt deshalb
gut, weil es eben eine zeitsynchrone Suche ist.
Das heißt, beim Pruning aufgrund des Beams vergleiche ich immer Pfade
gleicher Länge und dann sind eben gerade die Wahrscheinlichkeiten der
Pfade gut miteinander vergleichbar, weil halt längere Pfade
tendenziell immer eine kleinere und kleinere und kleinere
Wahrscheinlichkeit bekommen.
Und das ist das, was sich halt durchgesetzt hat als erstmal der
Standard -Suchalgorithmus, die man erstmal im ersten Suchdurchlauf
durchführt.
Und dann, danach schaut man sich an bei der Strahlsuche, welcher
Suchraum wurde denn aktiviert und dann suche ich den nochmal ab mit
stärkeren Modellen, die ich vielleicht dann noch anwenden kann, weil
es ein kleinerer Suchraum ist und mir dann nochmal eine bessere
Hypothese aus dem kleineren Suchraum raussucht.
Und eine typische Anwendung ist immer die Suche dann mithilfe des A
-Sternchen -Algorithmus.
Und da wiederum mit einer besonderen Implementierung von A-Sternchen,
mithilfe eines sogenannten Stack-Decoders.
Und das funktioniert so, dass ich halt einen Stack habe und auf dem
Stack sind alle partiellen Hypothesen, also letztendlich alle Pfade
gleicher Länge, drauf und zwar sortiert nach ihrer Wahrscheinlichkeit,
also höchstwahrscheinlichster Pfad oben und so weiter und so fort.
Und dann expandiere ich immer die Hypothese mit der höchsten
Erfolgswahrscheinlichkeit.
Das heißt also, die Wahrscheinlichkeit, nach der ich die Pfade
sortiere, ist diese Wahrscheinlichkeit, die besteht aus der
tatsächlichen Wahrscheinlichkeit, die ich bisher habe, plus der
Vorhersage anhand meiner Heuristik, wie viele Kosten noch drauf
kommen, wenn ich ganz bis zum Ende gehe.
Und dann habe ich wirklich einen Stack.
Ich hole oben das Höchste raus, expandiere das, bekomme mehrere neue
Pfade durch die Expansion.
Ich kann ja in mehrere Pfade reingehen.
Und die sortiere ich wieder in den Stack rein.
Die tue ich wieder in den Stack rein und zwar so sortiert, dass sie
mit Anwendung der Heuristik dann gemäß ihrer voraussichtlichen
Wahrscheinlichkeit nach besten nach schlechtesten sortiert sind.
Ich hole also immer das Höchste raus, expandiere das, sortiere das
ein.
Und wenn dann nach dem Einsortieren das, was ganz oben auf dem Stack
liegt, ein vollständiger Pfad ist, der es bis zum Ende geschafft hat,
dann ist das mein wahrscheinlichster Pfad, den es überhaupt gibt.
In Klammern unter der Voraussetzung, dass die Heuristik, die ich
verwende, admissible ist, dass ich also meine tatsächlichen Kosten bis
zum Ende immer unterschätze.
Das ist das Schöne beim Stack-Decoder.
Der Stack-Decoder funktioniert asynchron, weil die Schätzung, die ich
habe, ist ja immer eine Schätzung eines Pfades voller Länge.
Sie besteht ja immer aus dem, was ich bisher habe, plus dem, was ich
voraussage.
Und je länger der Pfad jetzt wird, wird der Anteil dessen, was ich
sicher weiß, halt immer größer und der Anteil dessen, den ich
vorhersagen muss, wird immer kleiner.
Deswegen wird die halt auch immer genauer, die Kosten, die werden
immer näher und näher an den tatsächlichen Kosten dran.
Bis dann irgendwann der Pfad komplett ist, dann entspricht er den
tatsächlichen Kosten des kompletten Pfades.
Und wenn dann diese Vorhersage, also meine tatsächlichen Kosten immer
unterschätzt und ich einen vollständigen Pfad habe, der die besten
Kosten hat, die besser sind, die niedriger sind, als die Kosten, die
ich bekomme aus tatsächlich plus unterschätzter Schätzung, dadurch,
dass die Schätzung unterschätzt, kann das nicht mehr besser werden.
Weil dann wäre die Schätzung überschätzt, die Kosten.
Kann das nicht mehr besser werden und dann kann ich mir sicher sein,
dass ich den besten Pfad, den kürzesten Pfad gefunden habe.
Jetzt haben wir an der Sache immer noch die Krux, die wir nicht
beantwortet haben.
Was machen wir mit dieser erwarteten Restbewertung?
Was ist unsere Heuristik?
Wie können wir die voraussagen?
Und das ist für automatische Spracherkennung halt gar nicht so
einfach.
Wir hatten dieses Beispiel Landkarte.
Könnte ich über ein Wegestreckennetz, kann ich halt Luftlinie nehmen
und das ist eine Heuristik, die unterschätzt mir die tatsächlichen
Kosten garantiert.
Kann man garantieren.
Bei uns sind die Kosten jetzt akkumulierte Wahrscheinlichkeiten über
irgendeinen Viterbi-Pfad hinweg.
Zusammen kombiniert mit Sprachmodellwahrscheinlichkeit.
Blöd.
Was kann man machen?
Eine Möglichkeit ist, also Wissen logisch herleiten kann ich es nicht.
Ich kann es versuchen aus den Trainingsdaten zu lernen, so wie ich die
Parameter des HMMs auf Trainingsdaten lerne.
Kann ich versuchen, diese restlichen Kosten, die Schätzung für die
restlichen Kosten auf den Trainingsdaten zu lernen.
Und eine einfache Möglichkeit wäre, dass man sozusagen auf den
Trainingsdaten lernt, was sind so meine typischen Kosten pro Frame.
Und dann gucke ich mir an, was sind denn die minimalen Kosten pro
Frame, die ich auf meinen gesamten Trainingsdaten jemals gesehen habe.
Und wenn ich jetzt davon ausgehe, dass die Trainingsdaten halt
wirklich repräsentativ sind für meine Testdaten, dann könnte ich
sagen, okay, die minimalen Kosten pro Frame, die ich gesehen habe auf
meinen Trainingsdaten, das ist die untere Schranke für das, was es
geben kann pro Frame.
Wie viele Frames ich noch bis zum Ende brauche, das ist etwas, was ich
weiß.
Ich kenne die Länge der Aufnahme.
Ich weiß, wie viele Frames ich brauche.
Und wenn ich dann sage, minimale Kosten, die es überhaupt bei Framen
geben kann, mal Anzahl der Frames, die ich noch bis zum Ende brauche,
das ist dann eine Distanz, die wahrscheinlich meine gesamte
tatsächliche Distanz unterschätzen wird.
Das wäre eine Admissible Heuristik.
Jetzt kann man sich wahrscheinlich vorstellen, dass, sagen wir mal,
diese Spannbreite der Kosten pro Frame über die ganzen Trainingsdaten
relativ groß sein wird.
Und dass die minimalen Kosten pro Frame, die ich sehen werde, sehr,
sehr, sehr, sehr klein sein werden.
Und wenn ich die jetzt ansetze und einfach multipliziere mit der
Anzahl der Frames bis zum Ende, dann werde ich halt meine
tatsächlichen Kosten aller Voraussicht nach unterschätzen.
Allerdings werde ich sie extrem, extrem, extrem, extrem stark
unterschätzen.
Und da haben wir schon gesagt, das ist nicht was, was wir wollen.
Wir wollen zwar unterschätzen, aber wir wollen möglichst nah an den
tatsächlichen Kosten sein, damit wir nicht unnötig Fade expandieren,
die dann hinterher tatsächlich von den Kosten her schlechter werden.
Deswegen ist das zwar eine Admissible, aber eine lausige Heuristik,
die zu sehr schlechter Laufzeit führen wird.
Was man dann machen kann, ist, man kann sagen, okay, ich trenne mich
von dem Glauben oder von dem Wunsch einer Admissible-Heuristik.
Hauptsache, ich finde eine halbwegs vernünftige Heuristik, die zu
schnellerer Laufzeit führt und vielleicht nicht mehr den optimalen Fad
findet, sondern vielleicht nur noch einen guten Fad.
Und da ist eine Möglichkeit gut, da nehme ich zum Beispiel den
Durchschnitt der Framekosten.
Gucke ich mir an, was sind die durchschnittlichen Framekosten und
multipliziere das mit der Anzahl der Frames, die noch bis zum Ende
bleiben.
Und dann habe ich eine Heuristik, die ist zwar nicht mehr Admissible,
aber hoffentlich halbwegs in Ordnung und wird dazu führen, dass ich
zwar nicht mehr den besten Fad, aber hoffentlich noch einen möglichst
guten Fad finde.
Bei der Viterbi-Suche hatten wir eine Strahl-Suche, wo wir den
Suchraum beschränkt haben.
Könnte man sich hier vielleicht auch so etwas vorstellen, dass man
vielleicht den Suchraum beschränken könnte.
Was dafür sprechen würde, wäre, naja, ich kann ja den Stack unten
abschneiden.
Ich limitiere den Stack.
Das ist natürlich gefährlich, weil ich dann Fade bevorzuge, die ich
erst später expandiere, weil ja die Kosten... also je nachdem, wie
stark ich die Kosten, die Kosten stark unterschätze, dann ist es
gefährlich, weil ich dann unter Umständen gute Fade wegwerfe.
Wenn ich eine Heuristik habe, die relativ gut ist, die relativ nah ist
an den tatsächlichen Kosten, dann kann ich den Stack problemlos
abschneiden, weil dann immer der beste Fad oben sein wird.
Wenn ich jetzt so eine mittelmäßige Heuristik habe, kann ich trotzdem
sagen, okay, ich kann den Stack unten ein bisschen abschneiden, muss
nicht mehr alles oben auf dem Stack halten und damit suchen.
In der Praxis bringt es meistens nicht so viel, außer, dass ich ein
bisschen Speicher spare, weil die Wahrscheinlichkeit, dass irgendwas,
was ganz unten auf dem Stack ist, dann noch im Laufe der Zeit nach
oben blubbert, ist eh gering, wenn die Schätzung der Restkosten eh
schon gut ist.
Das heißt also, diese Idee der Suchraumbeschneidung als solches könnte
man zwar machen, funktioniert aber nicht und bringt nicht wirklich
gut.
Funktioniert nicht wirklich gut.
Und das ist auch einer der Gründe, warum Viterbi sich durchgesetzt
hat, weil ich kann den Suchraum nicht beschreiben.
Ich bin davon abhängig, dass ich eine gute Heuristik habe.
Für Spracherkennung habe ich keine Heuristik.
Selbst mit so einer Heuristik wie durchschnittliche Framekosten und so
weiter, ist das Ding einfach noch zu langsam, um damit wirklich
Spracherkennung betreiben zu können.
Und einer der Gründe ist, dass diese Expansion hier am Ende natürlich
brutal teuer ist.
Jedes Mal, wenn ich einen Pfad expandiere und ich gehe aus einem Wort
raus, dann bekomme ich nicht fünf neue Pfade, die ich jetzt in den
Stack einsortieren muss, sondern ich expandiere aus diesem Ding heraus
in V-Quadrat-Anzahl-Vokabular-Quadrat-Zustände.
Das heißt, ich bekomme V-Quadrat-Neue-Pfade und muss die jetzt auch
noch in diesem Stack einsortieren.
Das heißt, mit den Search & Sort muss ich, wenn ich 60.000 Worte
Vokabular habe, 360.000 neue Pfade, wenn ich aus so einem Wort
rausgehe, reinsortieren in den Stack.
Das ist halt langsam.
Das ist ein extrem großer Flaschenhals.
Und da war eine Idee, dass man versuchen kann, diesen Flaschenhals ein
bisschen zu eliminieren, dem ein bisschen zu entgegenzuwirken, indem
man eben nicht alle 360.000 Möglichkeiten einsortiert und dann in den
Stack mitführt, sondern dass man so eine Möglichkeit hat, die einem
auf schnelle Art und Weise, auf einfache, rechnerische einfache Art
und Weise eine Vorhersage macht, in welche Dinger lohnt es sich denn
überhaupt zu expandieren und in welche nicht.
Kann man zum Beispiel machen anhand des Sprachmodells.
Kann man aber auch machen, indem man ein vereinfachtes akustisches
Modell verwendet, indem man irgendwie ein simples akustisches Modell
hat.
Jedes Wort hat nur einen HMM-Zustand.
Und dann rechne ich mal schnell so ein bisschen vor, versuche mal so
ein bisschen abzuschätzen, das was jetzt als nächstes kommt in der
Akustik, passt das überhaupt in das Wort, in das ich jetzt wieder rein
expandiere.
Und wenn es nicht passt, dann expandiere ich nicht rein, dann wird
dieser Pfad halt nicht in den Stack rein sortiert und kann man halt
zum Beispiel ganz gut dann machen.
Oder man kann halt auch solche Sachen sich vorstellen, dass man selbst
Fastmatch macht mit einfachem Sprachmodell, dass man also ein
paralleles Netzwerk mitführt, das nur ein Unigram-Sprachmodell hat und
dann anhand dieses Dings so ein Fastmatch macht, so eine Vorhersage
macht, okay in was lohnt es sich zu expandieren und in was nicht.
Und dann, bevor Auswahl trifft, bevor man dieses Expandieren in dem
großen 3-Gramm-4-Gramm-Grafen macht.
Diese Möglichkeit des Fastmatches ist etwas, das kann ich bei Astern
machen, das könnte ich aber genauso gut auch bei der Viterbi-Suche
machen.
Auch bei der Viterbi-Suche könnte ich mir vorstellen, dass ich so mit
einfachen Modellen schon mal weiter in die Zukunft vorausschaue und
schon mit mehr Informationen wegpune, als nur mit der Information, wie
gut ist denn die Bewertung des Fades aktuell.
Sondern ich kann für alle aktuell aktiven Fade mal 200 Frames in die
Zukunft schauen mit irgendwelchen einfachen Modellen und anhand dessen
zum Beispiel dann auch versuchen, Sachen wegzuprunen, indem ich
genauso mit einem einfachen akustischen Modell oder einem einfachen
Sprachmodell mal ein bisschen vorrechne.
Also Vor- und Nachteile des DECT-Decoders.
Wenn man Glück hat, werden nur wenige Zustände expandiert.
Bei der Spracherkennung haben wir in der Regel gar kein Glück.
Ich muss mir wenig Sorgen machen über diese möglichen
Suchrepräsentationen dieser Historie, ob ich jetzt einen 3-Gramm- oder
4 -Gramm- oder sonst was Sprachmodell habe.
Ich muss mir nur die Regel merken, in was ich expandiere, weil der
gesamte Fade, das einzelne Element auf dem Stack, steht automatisch
für die gesamte Historie, die ich bisher hatte.
Was der Nachteil ist, das kann natürlich unter Umständen vom Speicher
her relativ teuer sein.
DECT-Decoder, wenn ich vernünftige Heuristik habe, findet die optimale
Lösung.
Aber es kann halt unter Umständen sehr lange dauern, weil ich Faden
unterschiedlicher Länge vergleiche.
Und wenn die Heuristik die tatsächlichen Kosten stark unterschätzt,
dann suche ich viel ab, was ich eigentlich gar nicht absuchen möchte.
Man kann sich das auch so vorstellen, was wäre denn eine ideale
Heuristik?
Was wäre denn, wenn ich eine ideale Heuristik hätte?
Wenn ich eine ideale Heuristik berechnen könnte, dann bräuchte ich
auch gar nicht mehr zu suchen.
Das ist ja gerade das Suchproblem.
Die Lösung des Suchproblems ist gleichzeitig die ideale Heuristik.
Das heißt, die Katze beißt sich da in den Schwanz.
Und deswegen werden diese DECT-Decoder häufig halt als zweiter
Suchlauf berechnet, wenn man erstmal den Suchraum verkleinert, ein
bisschen durch absucht mit einer Viterbi-Strahlsuche.
Und das, was übrig bleibt, suche ich dann mit stärkeren Modellen,
größeren M-Gramm-Sprachmodellen, größeren akustischen Modellen und so
weiter ab.
Also wenn es um die Stärke des akustischen Modells geht, wenn man dann
nochmal zurückdenkt an das akustische Modell und an die
kontextabhängige Modellierung mithilfe von Polyphonen und
generalisierten Polyphonen, die wir geclustert haben, kann man sich
auch leicht vorstellen, man kann relativ leicht akustische Modelle
unterschiedlicher Stärke bauen, indem ich entweder kontextunabhängige
akustische Modelle zum Beispiel nehme oder kontextabhängige Modelle,
die nur Triphone sind und komplizierter wird es dann Quintphone.
Und je mehr Zustände ich cluster, desto komplizierter wird da der
Suchraum innerhalb eines Wortes, weil ich mehr Modelle habe, in mehr
Sachen expandieren kann.
Und je länger der Polyphon-Kontext wird, ist das im Prinzip so ähnlich
wie bei dem Sprachmodell, desto komplizierter wird das HMM, das ich
dann innerhalb des Wortes aufbauen und durchsuchen muss.
Und wenn ich also schwache Modelle bauen will, eine geringere N-Gramm
-Historie, geringere Polyphon-Ordnung, weniger Modelle, weniger
geclusterte Modelle, im Extremfall runter zu kontextunabhängigen
Modellen.
Und dann kann ich mit einer Viterbi-Suche schnell mit schwachen
Modellen suchen.
Ich poone nicht so viel, damit schon noch einiges übrig bleibt vom
Suchraum und das, was übrig geblieben ist, ist dann klein genug, dass
ich es dann mit stärkeren Modellen absuche, zum Beispiel mit Hilfe von
so einer A-Sternchen-Suche.
Ja, das sind nochmal die Argumente, halt A-Sternen-Versus-Strahlsuche,
in Klammern meistens Viterbi-Strahlsuche.
Bei der Strahlsuche brauche ich halt diese Heuristik nicht.
Ich kann die Pfade leicht vergleichen, weil sie immer die gleiche
Länge haben.
Und noch ein anderer Faktor, der heutzutage vielleicht interessant
sein könnte, dass ich halt auch mithilfe der parallelen
Implementierung da Geschwindigkeitsvorteile raussuchen kann.
Ein Nachteil bei der Strahlsuche ist halt, dass ich nicht das Optimum
rausbekomme.
Und wie gesagt, in den 80er Jahren tobte halt der Streit, ob jetzt A
-Sternen oder Viterbi und gewonnen hat nominell Viterbi, aber A
-Sternen wird immer noch hinten mit reingenommen.
Gut, jetzt nochmal zusammengefasst, wenn wir jetzt Suche nehmen, was
haben wir bisher gemacht an Optimierungstechniken.
Die wichtigste, wichtigste Optimierungstechnik, die wir jetzt hatten,
war Strahleinführen bei der Strahlsuche, Suchraum beschränken aufgrund
der Scores und wir modifizieren die Fundamentalformel.
Wir suchen nicht mehr nach der besten Wortfolge, wir suchen nach der
besten Zustandsfolge.
Wenn Sie zurückdenken an Grundbegriffe der Informatik, welche anderen
Optimierungstechniken, so generellen Optimierungstechniken bei dem
Entwurf von Algorithmen kennen Sie noch?
Was sind so Standarddinge, die Sie im Studium ständig an den Kopf
geworfen bekommen haben und wo gesagt wurde, hier, wenn Sie den
Algorithmus schneller machen wollen, werfen Sie Drast drauf.
Mir würden da spontan zwei Dinge einfallen, die wir noch nicht gesagt
haben und eine davon wäre etwas, was man hier vielleicht auch ganz gut
anwenden könnte.
Parallelisieren ist immer gut, aber das ist nicht mehr Grundstudium,
das ist dann schon später.
Wir denken jetzt wirklich mal ganz zurück, keine Ahnung, wann ist,
Algorithmen 1 ist zweites Semester?
Okay, noch besser, Algorithmen 1, also Parallelisierung war bestimmt
nicht in Algorithmen 1 das große Thema.
Aber was, da gibt es Standardsachen, auf welchem Prinzip besucht
Quicksort, was ist da das Optimierungsprinzip, ist deshalb schnell,
weil es macht die Weitenkonker, Teile und Herrscher, ist also das eine
Prinzip.
Minimale Editierdistanz ist schnell, weil es macht was?
Es macht nicht die Weitenkonker, sondern es macht DP, dynamische
Programmierung, genau.
Bietet sich jetzt nur dieses Suchproblem bei der Spracherkennung,
bietet sich da Teile und Herrscher an?
Guckt man so drauf, sieht man irgendwas, wie man teilen kann
vielleicht und wie da Teilergebnisse zusammenführen?
Okay, also es ist das nicht, aber bietet... oder?
Genau, also nochmal aufteilen ist irgendwie, scheint... und ich kann
ja auch den Suchraum nicht irgendwie zerschneiden und dann mache ich
halt den kleinen Suchraum, dann den kleinen Suchraum, dann führe ich
es wieder zusammen, da muss ja irgendwo rin und dann, scheint nicht zu
sein.
Okay, also Teile und Herrscher ist es nicht.
Ist da vielleicht was mit dynamischer Programmierung rauszuholen?
Rechnen wir da irgendwo was doppelt und dreifach und vierfach, was wir
vielleicht nicht unbedingt doppelt und dreifach und vierfach berechnen
müssten?
Naja, beim Sprachmodell anscheinend nicht.
Deswegen brauchen wir ja diese fürchterlich vielen Zustände.
Damit war die Sprachmodell-Historie.
Aber ist irgendwas beim akustischen Modell, was wir hier doppelt,
dreifach und sechsfach berechnen, was wir bisher jetzt erstmal so in
der Makrolinse ausgeblendet haben?
Meine Songkästchen hier, da stehen zwar zwei Dinger drin, zwei Worte
drin, aber es steht ja nur dafür, was ist mein Kontext, wo komme ich
her, dass ich jetzt also als letztes J war und vorher war ich in I und
dann gehe ich wieder rein in neues und wenn jetzt vorher J war und am
Ende K, dann steht dieses Kästchen letztendlich dafür, dass ich um das
Wort VK erweitere.
Und davon habe ich jetzt halt hier mehrere Kombinationen, aber jedes
Kästchen steht dafür, dass ich um ein Wort erweitere.
Ich habe aber also Wort-Quadrat-viele-Zustände.
Das heißt also, da werde ich schon mal irgendwas sparen können, weil
da muss ich irgendwas doppelt und dreifach berechnen.
Das ist ja irgendwie doof.
Kann ich machen, dadurch, dass ich das Netz ein bisschen geschickter
anordne, so mit Nullzugängen und so weiter, brauche ich nicht
sämtliche Quadrate, weil ich brauche nur, muss mir nur so Zustände,
Grammatikzustände einführen, die halt kein akustisches Modell
emittieren und dann brauche ich dann hinterher nur noch wieder
Vokabular -viele-Zustände, wo ich das akustische Modell berechnen
muss.
Das ist also das erste, wo offensichtlich Einsparungspotenzial ist.
Und jetzt schaue ich mir mal die Worte an.
Wo können denn die Worte sein?
Worte können so aussehen.
Einfaches kleines Vokabular besteht aus den Worten Cache, Can und
Cake.
Immer so von unten nach oben geschrieben, die Einträge im Vokabular
und dann fange ich halt an, da parallel für die Worte das akustische
Modell zu berechnen.
Und wenn ich mir jetzt Can, Cake und Can anschaue, was ist das Erste,
was mir auffällt?
Die fangen alle mit demselben Phonemen an.
Und Can und Cake fangen sogar mit den beiden selben Phonemen an.
Das heißt, wenn ich da die akustischen Modellwahrscheinlichkeiten
berechne, innerhalb des Wortes, dann ist der Anfang von Can und Cake
100 -prozentig suppiduppig gleich.
Weil ich mache eine zeitsynchrone Suche.
Zu jedem Zeitpunkt gucke ich mir immer den einen und den selben
Merkmalsvektor an.
Und bei Cake ist zumindest für das erste Phonemen, für das K, das eine
und dasselbe.
Da macht es ja wenig Sinn, dass ich diese ganze Berechnung der Gauss
-Mixtur -Modelle für die Emissionen der Zustände und so weiter doppelt
berechne.
Einmal bin ich halt in einem Zustand, da hatte ich halt vorher andere
Sprachmodellwahrscheinlichkeiten und andere Worthistorie und dann bin
ich in einem Zustand, das ist genau derselbe Zustand, ist genau der
gleiche Merkmalsvektor, das Einzige ist, kommt halt eine andere
Sprachmodellwahrscheinlichkeit, die drauf sortiert wird.
Aber ich muss das ja nicht doppelt berechnen.
Ich habe es schon berechnet.
Was ist jetzt die Idee?
Wie kann man sowas machen?
Man braucht ja, wenn man jetzt dynamisches Programmieren anwendet,
immer irgendeine Art, eine Idee, wie ich geschickt Zwischenergebnisse
speichern kann.
Und dann, wenn ich dann was Größeres mache, wie ich das Größere aus
den Zwischenergebnissen berechnen kann, oder das, was in den
Zwischenergebnissen drinsteht, nochmal zu berechnen.
Beim EDT-Distanz mache ich das halt mit der Matrix und diesen
Übergängen und dann sind die Zellen, die speichern halt meine
Zwischenergebnisse und wenn ich dann länger mache, um ein Zeichen,
dann habe ich halt diese Übergänge.
Jetzt, wenn ich hier sowas habe, letztendlich, das sind ja nichts
anderes als Wörter.
Das ist halt ein Wort, die Zeichen, woraus die Wörter bestehen, sind
halt Phoneme.
Und jetzt denken sie zurück, Algorithmik, wahrscheinlich Viertes
Semester Algorithmen 2, irgendwie sowas.
Sie arbeiten mit großen Textmengen und wollen die durchsuchen und
wollen die strukturieren und bestehen aus Wörtern.
Gut, die sind jetzt halt nicht auf Phonemen, die sind auf Graphen
-Ebene, aber verhält sich gleich.
Gibt genauso das Wort Cache und Can.
Die fangen nicht nur beide mit den gleichen, beiden gleich, zwei
gleichen Phonemen an, die fangen auch beide mit den zwei gleichen
Buchstaben an.
Wenn sie da so große Texte haben und die wollten sie irgendwie
geschickt im Speicher organisieren und hinterher nach Zeichenfolgen
durchsuchen, was nehmen sie da für eine Datenstruktur?
Ein Baum ist schon mal gut, aber wir gehen davon, die fangen gleich
an, die hören nicht gleich auf.
Das heißt, ich mache keinen Suffix-Baum, sondern einen Präfix-Baum.
Würde sich halt anbieten, weil die Wörter, die haben alle dasselbe
Präfix.
Also organisiere ich sie in einem Präfix-Baum.
Und nur, dass der Präfix-Baum jetzt halt nicht auf Graphen-Ebene,
sondern auf Phonemen organisiert ist.
Wenn ich mir also jetzt mein Vokabular anschaue, brauche ich nicht die
Liste der Wörter übereinander zu schreiben, sondern ich kann das Ganze
auch als einen Präfix-Baum hinschreiben.
Ich habe halt so viel... streng genommen ist es kein Baum, sondern
streng genommen ist es ein Wald, weil ich habe mehrere Bäume für jedes
Phonem, das ich habe.
Jedes Phonem ist eine Wurzel aller Wörter, die mit diesem Phonem
anfangen.
Und habe dann ganz viele von diesen Bäumen, 50 von diesen Bäumen, die
anfangen und die expandieren alle in die Wörter, die ich ausgehend von
diesem Phonem aufbauen kann.
Das ist ein Baum.
Den kann ich halt so mit so Zeigerlisten und allem möglichen im
Rechner repräsentieren.
Das Einzige, wo ich jetzt aufpassen muss, ist, wenn ich das so mache,
ein ganzes vollständiges Wort kann Präfix eines längeren Wortes sein.
Das heißt, ich muss mir irgendwas überlegen, dass ich markiere, okay,
hier kann auch ein Wort zu Ende sein.
Die einfachste Idee ist okay, alle Knoten in dem Baum, die auch das
Ende eines Wortes sein können, die markiere ich halt.
Dann weiß ich, aus diesem Knoten kann ich jetzt wieder rausschlüpfen
in jeden beliebigen anderen Startknoten, jede beliebige andere Wurzel
aller Bäume.
Oder wenn ich halt in einem Blatt bin, kann ich auch wieder schlüpfen
vorne in einen Startknoten eines jeden anderen Bäumes.
Und das kann dann auch wieder erstmal mein Suchraum sein.
Das Problem mit dem Sprachmodell, das ignorieren wir mal.
Jetzt tun wir mal so, als hätten wir Unigram-Sprachmodelle.
Dieses erste Beispiel.
Dann hätte ich halt da nicht N-Wörter übereinander stehen, in die ich
rein muss, sondern ich habe nur noch 50 Bäume, in die ich parallel
expandiere und dann innerhalb des Bäume habe ich dann einen relativ
deutlich geringeren Verzweigungsgrad, als ich es sonst hatte in der
Summe.
Wenn ich also in einem Zustand bin, ist die Anzahl der möglichen
Nachfolgezustände, ist einfach die Anzahl der verschiedenen Phoneme,
insbesondere wenn ich so einen Wortübergang mache und nicht mehr die
Anzahl der Wörter, die ich habe, so was wie 60.000, 130.000 Wörter.
Oder anders ausgesucht, das sieht dann so aus.
Jetzt ist das große Problem natürlich, was machen wir mit dem
Sprachmodell.
Wenn ich in diesem Suchnetzwerk irgendwo einen Wortübergang mache in
einen neuen Zustand, dann weiß ich, in welches Wort ich reingehe.
Dann weiß ich genau, hier, der Teil gehört jetzt wieder zu dem Wort,
in das ich rein expandiere.
Bei einem Baum weiß ich das nicht.
Bei einem Baum expandiere ich irgendwo in die Wurzel eines Baumes, der
für ganz viele unterschiedliche Wörter steht.
Das heißt, ich weiß nicht, kenne nicht die, das Wort, die
Wortidentität.
Die Wortidentität weiß ich erst dann, wenn ich aus dem Wort wieder
rausgehe, wenn ich es verlasse.
Dann weiß ich, aha, jetzt habe ich den Baum so durchlaufen, um das
Wort Cake zu bilden.
Wenn ich mich nur auf sowas beschränke, wie Bigramme oder auch
Unigramme, dann ist die einfache Lösung, nennt sich Delayed Bigrams.
Angenommen, ich hätte jetzt Unigramme,
dann ist das kein Problem, wenn ich also hier meinen Baum habe, meinen
Präfixbaum, und ich springe hier raus, in eine andere Wurzel wieder
rein, dann mache ich hier halt nicht die Sprachmodell-Unigramm
-Wahrscheinlichkeit dafür, für das Wort, in das ich expandiere,
sondern hier kommt halt die Sprachmodell-Wahrscheinlichkeit drauf von
dem Wort, aus dem ich rauskomme.
Wenn man sich an letzte Woche erinnert, letztes Mal erinnert, da hatte
ich auch ursprünglich die Unigramm-Wahrscheinlichkeiten hinten dran
geschrieben und nicht vorne dran geschrieben, weil letztendlich ist es
egal, ob ich es am Anfang oder am Ende des Wortes drauf mache.
Bei Bigramm ist es letztendlich genau dasselbe.
Ich kann mir merken, sobald ich aus einem Wort raus bin, weiß ich,
okay, jetzt habe ich ein Wort verlassen, und die Bigramm
-Wahrscheinlichkeit kann ich dann drauf multiplizieren, wenn ich das
nächste Mal wieder ein Wort verlasse.
Ich brauche dann halt auch so Grammatikzustände, in denen ich merke,
was war das vorherige Wort, aber ich schiebe das sozusagen nach
hinten, die Entscheidung nach hinten.
Das nennt sich dann Delayed Bigrams.
Wichtig ist halt hier, damit man es gut machen kann, dass ich halt
eindeutige Endzustände verwende, dass ich also sozusagen nicht etwas
habe, okay, hier ist etwas, da kann es entweder in einem Wort
weitergehen oder ich kann ein Wort verlassen, sondern ich dupliziere
jetzt die Zustände.
Wenn ich hier einen Zustand habe, der kann entweder das Ende des
Wortes Cat sein oder das Wort kann noch weitergehen als Cats, dann
dupliziere ich die Systeme.
Warum mache ich das?
Weil es dann einfacher ist zu sagen, okay, jetzt ist das Wort
eindeutig, jetzt kann ich die Verspätete, die Delayed Bigram
-Wahrscheinlichkeit drauf multiplizieren.
Wenn ich sozusagen hier drin wäre, dann weiß ich nicht, kann jetzt das
S noch kommen oder ist es zu Ende?
Wenn ich das so dupliziere, kriege ich es vom Konzept schön her,
sobald ich in dieses T reingehe, kann ich die Delayed Bigram
-Wahrscheinlichkeit drauf multiplizieren und sobald ich in dieses S
reingehe, kann ich die Delayed Bigram-Probability von dem Cats
reintun.
Ich könnte es sogar noch extremer machen.
Wenn jetzt dieses T keine weiteren Nachfolger hat, wie in diesem
Beispiel, sobald ich in dieses T reinkomme, weiß ich, es war Cat,
Sprachmodellwahrscheinlichkeit drauf multiplizieren, sobald ich in
dieses T reinkomme, weiß ich, es war Cats und kann da halt die
Sprachmodellwahrscheinlichkeit für Cats drauf multiplizieren, ohne
dass ich überhaupt in das S schon expandiert habe.
Auf die Art und Weise kann man also versuchen, die Entscheidung
darüber, welches Wort es ist, so früh wie möglich zu treffen, so bald
man es kann und dann die Bigram-Wahrscheinlichkeit oder letztendlich
auch die Trigramm-Wahrscheinlichkeit drauf multiplizieren.
Die Frage ist, bringt das was?
Die Technik ist schon relativ alt, deswegen gibt es eigentlich auch
nur alte Untersuchungen zu der Technik.
Das ist was von 1900...
Entschuldigung, 92, 93, irgendwas so um den Dreh rum.
Vokabular damals, so typische Vokabulargröße waren 12.000 Worte, das
war schon groß und dann hat der Herr Ney einfach mal aufgebaut, wie
ist das, wenn ich so ein volles Netzwerk habe, wie ist das, wenn ich
mit Bäumen arbeite und wie verhält sich das?
Und dann stellt man halt fest, bei dem vollen Vokabular, wenn ich halt
diese Einsparungen mache, die ich durch Backoff und so weiter habe,
einbaue, dann hat er ja sowas wie 100.000 Übergänge von
Nebenübergängen in dem Suchnetzwerk, wenn er das Ganze als Baum
organisiert und mit Delayed Bigrams etc.
arbeitet, ist man bei 43.000 von Nebenübergängen.
Das heißt, das Netz ist einfach durch diese Umorganisation des
Suchvokabulars um den Faktor 2,5 geschrumpft.
Das Schöne ist, dass ich dadurch, dass ich halt jetzt durch dieses
implizierte dynamische Programmieren auch weniger Duplikate oder
Redundanzen ausrechne, die Suchzeit bei gleicher Wortfehlerrate sich
deutlich verschnellert hat um den Faktor 7.
Und wenn man mal ein bisschen übergeschaut hat, wo der
Hauptsuchaufwand war, hat man festgestellt, wenn man in so ein Wort
expandiert, dann muss man, es ist so 80 Prozent des Suchaufwands im
ersten Vernehmen, und danach greift das Pruning wegen der Delayed
Bigrams und natürlich auch wegen des akustischen Modells und Pfade,
die sich nicht lohnen weiter zu verfolgen, kann man rauswerfen.
Das ist halt T1 und das ist halt T2.
Ich gebe halt dem internen anderen Namen.
Ich weiß, der kriegt halt irgendeine ID und ich weiß halt, das eine
ist halt das T, das nicht das Ende des Wortes ist und das andere ist
halt das T, das das Ende des Wortes ist.
Ich meine, ich dupliziere da natürlich wieder Aufwand beim akustischen
Modell.
Da berechne ich plötzlich wieder was doppelt, was ich jetzt halt bei
einer perfekten Präfixorganisation nicht doppelt berechne.
Aber dafür, ich berechne zwar doppelt, kann ich halt früher das
Sprachmodell anwenden.
Und da hat man halt experimentell ausprobiert, ist es wichtiger,
früher das Sprachmodell anzuwenden oder ist es wichtiger zu sparen bei
der Berechnung des akustischen Modells.
Und das war halt eben eine dieser Untersuchungen und der hat halt
rausgefunden, nach den ersten zwei Phonemen greift halt schon das
Poning.
Das heißt, hinterher was doppelt zu berechnen ist eh eher
unwahrscheinlich und viele Worte sind halt auch kurz.
Aber es passiert dann halt nicht so häufig, dass ich diese doppelten
T's überhaupt ausrechne, weil aufgrund allein des akustischen Modells
schon irgendwas vorher weggepront wurde.
Es wird nur eins von den beiden hoffentlich werden.
Ne, das ergibt gerade keinen Sinn.
Dann ist es ja gleich.
Ne, Entschuldigung, ich nehme das zurück, das war Blödsinn.
Sondern es ist tatsächlich so, dass in den meisten Fällen wirklich
schon nach zwei Phonemen, das war auch Englisch, schon sowohl das
akustische, aber auch das Sprachmodell Poning gegriffen haben.
Und der Vorteil halt des Rechenzeitgewinns, dieser Faktor 7, der kommt
daher, dass halt das erste Phonem nicht fünfmal gerechnet werden
musste, sondern nur einmal in dem Baum gerechnet werden musste.
Und wenn man dann hinterher in dieses Suchnetzwerk reinschaut,
kombiniert mit dem Sprachmodell, das waren damals glaube ich auch nur
Bigram -Sprachmodelle, und man schaut, wie sahen denn so die Übergänge
aus, dann hat man halt gesehen, auf der ersten Ebene, die hatten halt
28 Phoneme, da gab es dann halt 28 Phonem-Übergänge.
Dann auf der zweiten Ebene, dadurch, dass ja nicht alle Phonemen
wirklich auf Kombinationsmöglichkeiten im Vokabular vorkamen, waren es
dann sowas wie 300 Übergänge und so weiter und so fort.
Bei Länge 7, Größe gleich 7, waren es dann sowas wie 30.000.
Aber wenn man guckt, wie viele von denen überhaupt während der Suche
besucht werden, also wie viele von denen überhaupt aktiv sind, dann
sieht man, dass sozusagen die Anzahl der aktiven Übergänge mehr oder
minder gleich bleibt während der Suche.
Zum Schluss sogar weiter abfällt, weil halt viele schon vorher
weggepunt werden.
Aber so im Großen und Ganzen, wenn man es mal aufgebaut hat, bleibt
das eine gewisse Zeit lang stabil und wächst nicht so stark, wie die
Anzahl der theoretisch möglichen Aktiven wachsen könnte.
Das heißt also, das Puning, diese Strahlsuche ist da in der Tat sehr
effektiv.
Jetzt ist immer noch das Problem, wir haben uns immer noch so ein
bisschen drum gemogelt, was wir mit Sprachmodellen machen.
Bei Unigram ist es einfach, da habe ich einen Baum und dann gehe ich
immer vorne wieder in die Wurzeln rein und wenn ich aus einem Wort
rausgehe, kann ich die Unigram-Wahrscheinlichkeit darauf
multiplizieren.
Wenn ich das jetzt mit Bigram mache, brauche ich ja wieder meinen
Memory, meinen Speicher, der mir sagt, okay, was ist das aktuelle
Wort, das in meiner Historie steht, wenn ich den Übergang mache.
Da bräuchte man als wieder solche Zustände.
Und die Idee bei den Bäumen ist, dass man da jetzt nicht mit so
aufgeblähten Zuständen arbeitet, sondern dass man Bäume kopiert.
Dass man Bäume nach Bedarf kopiert, wenn ich also aus einem Wort
expandiere, dann hänge ich bei dieser Expansion einmal diesen
Präfixbaum hinten dran.
Das muss man sich dann so vorstellen.
Ich arbeite jetzt einfach mal nur mit einer Wurzel.
Wir haben eine virtuelle Wurzel, die die ganzen 50 Bäume, einen Baum
pro Phonem zusammenfasst.
Und dann sieht das so aus.
Ich habe also meinen ersten Baum, gehe von meinem Start zu, suche
durch mehrere Pfade hier durch diesen Baum so durch.
Und irgendwann komme ich bei einem Pfad, da expandiere ich aus einem
Blatt heraus oder aus einem Zustand heraus, der dem Ende eines Wortes
entspricht.
Und muss mir jetzt, damit ich hinterher vernünftig
Bigramwahrscheinlichkeiten drauf multiplizieren kann, merken, wo komme
ich denn her, was war das erste Wort, aus dem ich heraus expandiert
bin.
Und dann setzt man hier eine Kopie, also ich expandiere hier raus und
setze eine Kopie des Präfixbaums hinten dran.
Und hier, der Pfad, der kommt auch irgendwann am Ende und wenn der aus
dem Wort rausgeht, dann wird hier wieder auch eine komplette Kopie des
Präfixbaums hinten dran gehängt.
Und wenn ich jetzt hier aus so einem Wort rausgehe, dann weiß ich,
weil das die, das ist die Kopie, die zu diesem Wort gehört.
Und an der Stelle weiß ich, das ist jetzt das Wort, ein bestimmtes
Wort.
Das hier sei mal das Wort v i.
Das hier ist das Wort v j.
Und dann weiß ich, wenn ich hier rausgehe und ich mit Bigramm arbeite,
dann muss ich hier die Sprachmodellwahrscheinlichkeit v j gegeben v i
drauf multiplizieren.
Das ist also hier mein Delayed Bigramm an der Stelle.
Und genauso, wenn das hier das Wort v k ist und dann hier suche ich
durch und komme dann irgendwann hier an der Stelle, wo das Wort v l
ist.
Wenn ich dann hier rausgehe, dann muss, kann ich hier dann die
Wahrscheinlichkeit v l gegeben v k drauf multiplizieren.
Und jetzt muss ich gucken, wo gehe ich denn von hier aus hin?
Von hier aus gehe ich jetzt wieder in das Wort j rein.
Das heißt, ich gucke, gibt es hier eine Kopie des Baumes, die bereits
dem Wort v j entspricht?
Wenn ja, springe ich rein.
Also angenommen, ich wäre hier und komme ich hier bei dem Wort v k
raus.
Dann habe ich die Sprachmodellwahrscheinlichkeit, die ich hier drauf
multiplizieren muss, v k gegeben v i.
Und als nächstes, für das nächste Wort wird v k jetzt meine Historie.
Und dann weiß ich, das hier ist ja der Baum, der für die Historie v k
steht.
Das heißt, an der Stelle kann ich dann in diese Kopie reinspringen.
Jetzt kann es natürlich sein, dadurch, dass ich mit Strahlsuche habe
und ich alles expandiere, dass es diese Kopie noch gar nicht gibt.
Wenn es die noch nicht gibt, dann muss ich sie halt erstellen und mir
merken, dass ich jetzt eine Kopie habe, die für Worthistorie v l steht
und da entsprechend reinspringt.
Angenommen, ich mache einen Backoff.
Angenommen, an der Stelle v j gegeben v i gibt es nicht und ich mache
einen Backoff, der sagt, das ist so ungefähr gleich p von v i.
Wenn das jetzt geschickt ist, kommt jetzt dieser Trick zustande, den
ich auch machen kann, wenn ich nicht mit Bäumen arbeite, dass ich halt
hier, dadurch, dass ich jetzt hier nur noch p von v i nehme und danach
meine Historie vergesse, kann ich jetzt hier Abkürzungen einbauen.
Kann ich jetzt hier an andere Stellen, könnte ich unter Umständen da
vorne wieder reinspringen in den Baum.
Wie viele ich von diesen Kopien jetzt brauche, ich meine, die fressen
natürlich Speicher, je mehr von den Kopien ich habe, desto mehr
Speicher brauche, hängt jetzt davon ab, wie gut mein Puning ist.
Aber in der Regel ist gerade das Sprachmodell bei dem Punen
insbesondere sehr effektiv.
Also dadurch, dass halt manche Sprachmodellwahrscheinlichkeiten sehr,
sehr, sehr gering sind, kann ich hier schon an relativ früher Stelle
sagen, okay, brauche ich gar nicht rein zu expandieren.
Wahrscheinlichkeit wird viel zu gering sein und dementsprechend wird
dann die Anzahl der aktiven Kopien der Bäume, die ich haben werde,
sich in der Praxis in einer Größenordnung bewegen, die vollständig
handhabbar ist.
Bleibt noch das leidige Problem der kontextabhängigen Modelle, die wir
halt im Augenblick schon mal so ein bisschen angesprochen haben, aber
auch noch nicht genau gesagt haben.
Wir hatten schon gesehen, wenn wir so HMMs mit kontextabhängigen
Modellen haben, sieht das immer noch aus wie ein HMM, nur dass das HMM
halt komplizierter wird, weil ich hier halt dann so kontextabhängige
Zustände habe.
Dann gibt es halt ein T, das zwischen einem O und einem H steht und da
gibt es ein T, das steht zwischen einem A und einem W und so weiter
und so fort.
Also die Anzahl der Zustände wird halt größer.
Das gleiche passiert leider natürlich auch, wenn ich mit meinem
Vokabular jetzt als Baum organisiere.
Dieser schöne Effekt, den ich hatte, dass ich so bestimmte Sachen halt
mir merken kann und nicht doppelt berechnen kann, der wird dadurch
natürlich zwar nicht zunichte gemacht, aber deutlich abgemildert.
Wenn ich jetzt hier sowas habe wie K, Ken, Cash und so weiter, wenn
ich mir dieses angucke, dann kommt es einmal im Trifon-Kontext K und N
vor.
Da brauche ich dann eine Kopie für.
Dann kommt es einmal im Kontext K und SH vor.
Da brauche ich ein anderes Modell vor, weil da die akustische
Modellwahrscheinlichkeit anders ausgerechnet wird.
Und dann gibt es hier ein E, das kommt zwischen einem K und einem T
vor.
Genauso auf der nächsten Ebene gibt es hier einen N, das kommt
entweder zwischen einem E und einem T vor, oder das ist ein N, das an
der Wortgrenze steht, wo ich wohl nur den linken Kontext kenne, dass A
das links von ihm steht.
Und genauso das T, das kann halt das sein, das zwischen dem E und dem
S steht, oder das kann das sein, das am Ende eines Wortes steht und
vorher kommt dieses E von dem.
Das heißt, da wo ich vorher was eingespart habe, wird es jetzt halt
wieder aufgebläht.
Und was man sich jetzt auch vorstellen kann ist, dass wenn ich das
Ganze jetzt noch mit Wortübergängen kombiniere, dass gerade die
Modellierung mit kontextabhängigen akustischen Modellen an den
Wortgrenzen unangenehm werden kann.
Weil ich jetzt hier in dem Baum, wenn ich mir dieses AE anschaue, da
gibt es halt drei unterschiedliche Kontexte, in denen es vorkommen
kann.
Wenn es am Ende steht, das letzte ist, dann können rechts davon gleich
auf einmal 50 Kontexte auftreten, weil es halt in 50 neue Baumknoten
reingehen kann.
Und dann hat das aber auch einen Einfluss auf die Wurzel, weil hier
das K, da tun wir so, als gäbe es dann keinen, wäre der rechte Kontext
immer gleich, aber was ist mit dem linken Kontext?
Der könnte ja aus 50 anderen Phonemen theoretisch reinkommen.
Das heißt, da müsste ich eigentlich 50 Wurzeln, eine richtige Wurzel
ist nicht mehr, weil eine Wurzel ist eindeutig, aber 50 Startknoten in
diesen Präfixbaum hinein haben.
Und dann wird es ekelhaft.
Das bläht es dann wieder so sehr auf, dass es wieder unhandhabbar wird
im Allgemeinen.
Und was man da macht, ist, dass man da halt einen Kompromiss eingeht
und sagt, ja, kontextabhängige akustische Modierung ist gut und
wichtig und bringt große Gewinne, aber wenn es gerade an die
Wortgrenze geht, dann schränke ich mich ein.
Dann mache ich nicht mehr den vollen, zum Beispiel Quintphon-Kontext,
sondern ich sage, ich gucke maximal ein Phonem in ein neues Wort
hinein.
Oder ich gucke maximal ein Phonem in ein altes Wort hinein.
Und besonders widerlich sind dann halt in dem Fall Wörter, die nur aus
einem Phonem bestehen.
Weil dann habe ich dann 50 mal 50 Möglichkeiten beim Triphon und beim
Quintphon habe ich dann halt 50 mal 50 mal 50 mal 50 mal 50
Möglichkeiten.
Und da sagt man dann unter Umständen im Extremfall, ich pfeife was auf
die kontextabhängige Modellierung, ein Phonem-Wörter werden halt nur
als Monophon modelliert.
Weil den Ärger und zusätzlichen Aufwand ist der Gewinn, den ich
bekommen würde, wenn ich es kontextabhängig modelliere, einfach nicht
wert.
Das ist so etwas, das muss man dann berücksichtigen und da muss man
dann einfach praktische Designentscheidungen treffen, wenn man sowas
implementiert.
Okay, soviel zu den grundlegenden Suchalgorithmen, mit denen ich so
Spracherkennung betreiben kann und suchen kann.
Jetzt gucken wir uns so ein paar Besonderheiten noch an bei der Suche.
Und eine Besonderheit ist die, dass es häufig für viele Anwendungen
ganz praktisch wäre, wenn ich nicht nur die beste Wortsequenz mir
raushole, die wahrscheinlichste Wortsequenz, sondern die besten 10,
die besten 50, die n-wahrscheinlichsten, die n-besten Hypothesen.
Was ist so eine mögliche Anwendung?
Eine mögliche Anwendung ist zum Beispiel, dass ich sage und weiß,
naja, mein Spracherkenner ist nicht perfekt, der macht Fehler.
Und der Benutzer muss hinterher diese Fehler korrigieren, wenn er ein
perfektes Ergebnis haben will.
Zum Beispiel, er will diktieren.
Wie kann man sowas machen?
Naja, wenn ich einen Text diktiere, dann muss der halt hinterher da
reingehen und dann tippen, Zeichen löschen, Zeichen reinfügen, Wörter
löschen, neue Wörter schreiben.
Das ist natürlich aufwendig und zeitintensiv, macht das Ganze nicht
angenehm und kann unter Umständen mehr Zeit kosten, als ich durch das
Diktieren spare.
In Klammern ist auch einer der Gründe, warum für reines Diktieren sich
Spracherkennung nie wirklich auf breiter Front durchgesetzt hat.
Jetzt ist mal eine Idee, naja, dann ändern wir halt die Art und Weise,
wie wir Fehler korrigieren.
Weil wenn ich jetzt zum Beispiel da ein Wort verwechselt habe, dann
ist die Wahrscheinlichkeit doch relativ gut, dass das korrekte Wort,
wenn es denn wenigstens in meinem Vokabular ist, vielleicht eines der
Konkurrenten ist, eines der Wörter ist, die auf den folgenden Plätzen
liegen.
Also das zweitbeste, drittbeste, viertbeste Wort.
Dass einer dieser Follower-Abwörter ist.
Und dann ist halt die Idee, dass ich mir nicht die beste Wortsequenz
nur alleine rausgeben lasse, sondern die besten zehn Wortsequenzen.
Und dann ist hoffentlich das, was korrekt gewesen wäre, darunter.
Und der Benutzer tippt dann zum Beispiel nur auf das falsche Wort
drauf und dann gibt es eine Liste mit den anderen Kandidaten, die es
hätten gewesen sein können.
So ähnlich wie man das bei so einer Rechtschreibkorrektur macht.
Eine Rechtschreibkorrektur in den seltensten Fällen sagt ja auch hier,
das ist das Wort und das setzt es einfach.
Sondern häufig gibt es einem dann hier so eine Liste von möglichen
Kandidaten vor.
Und genauso wird man das dann hier machen und tippt dann nur noch auf
das hoffentlich erscheinende richtige Wort in der Liste von möglichen
Wörtern und spart sich so die Tipperei und macht es so einfacher.
Nur wie gesagt, damit ich das halt machen kann, muss ich halt in der
Lage sein, nicht nur die beste Wortsequenz rauszubekommen, sondern die
zehn wahrscheinlichsten Wortsequenzen.
Und das ist ein bisschen komplizierter, als das so im ersten Fall
klingt.
Je nachdem, ob man jetzt so mit einem Stack-Decoder gearbeitet hat
oder ob man mit einer Zeitsynchron-Viterbi-Suche gearbeitet hat, muss
man das unterschiedlich machen.
Beim Stack-Decoder ist das relativ einfach vom Konzept her, was man
machen muss.
Irgendwann habe ich ja oben auf der obersten Stelle meiner Stacks eine
Hypothese stehen, die einem vollständigen Pfad entspricht und die
beste Bewertung hat.
Dann würde ich normalerweise aufhören.
Was ich jetzt mache, jetzt nehme ich das Ding halt rüber, lege mir das
auf die Seite, im Wissen, das war das Beste.
Dann rutscht halt der ganze Stack einmal nach oben und dann lasse ich
halt weiterlaufen, bis das nächste Mal ein vollständiger Pfad an
oberster Stelle auf dem Stack steht.
Dann wird der wieder runtergenommen und weiterlaufen gelassen.
Und das mache ich so lange, bis ich so viele Hypothesen mir habe
generieren lassen, wie ich haben wollte.
Und die kommen halt dann auch entsprechend in der Reihenfolge ihrer
Wahrscheinlichkeiten raus.
Bei der Zeit-Synchronen Viterbi-Suche muss ich mehr Aufwand treiben.
Bei der Viterbi-Suche ist ja das Wissen darüber, welche Wortsequenz es
ist, nicht wie beim A-Sternchen in dem gesamten Pfad, der auf dem
Stack liegt, explizit kodiert, sondern ähnlich wie beim Viterbi
-Algorithmus für HMM, muss ich mir ja da Rückzeiger merken.
Und wenn ich jetzt so eine Zeit-Synchrone Viterbi-Suche habe, muss ich
aufpassen, weil ich mir ja immer nur die Rückzeiger auf Wortebene
merke und mir auch immer nur den besten Rückzeiger merke, dass ich mir
halt nicht mehr nur den besten Rückzeiger merke, sondern im Extremfall
die N-besten Rückzeiger.
Das heißt, jedes Mal, wenn da ein Wortübergang ist, merke ich mir
nicht mehr, was waren die N-besten, wo ich herkomme, sondern was sind
die N-besten, wo ich herkomme.
Und dann muss ich einen gewissen Aufwand treiben, wenn ich jetzt halt
nicht nur den besten, sondern wissen will, was sind die N-besten, dann
muss ich die sozusagen rückverfolgen unter Berücksichtigung, dass da
teilweise unterschiedliche Worthistorien sind und teilweise dieselben
Worthistorien und mit derselben Worthistorie.
Zu einem Zeitpunkt, die muss ich halt miteinander verschmelzen, weil
ich dann nicht, weil ich wissen muss, das sind nicht mehr
unterschiedliche Pfade, sondern von hier bis zum Anfang ist es immer
ein und derselbe Pfad.
Ich muss sozusagen aus dieser großen Lettice mehr so eine Baumstruktur
machen, damit ich wirklich N-Hypothesen bekomme, die sich nicht
einfach nur in ihrer Bewertung unterscheiden, sondern sich auch
tatsächlich in ihrer Wortfolge, aus der sie bestehen, unterscheiden.
Und auch da, aber das ist ein Problem, das sowohl bei Astern als bei
Viterbi auftauchen kann, muss ich aufpassen, dass ich nicht Hypothesen
mehr generieren lasse, die sich dann nur unterscheiden dadurch, welche
Zeitstempel die Worte in derselben Wortsequenz haben.
Und das ist beim Viterbi-Suche deutlich aufwendiger, das zu machen.
Aber nichtsdestotrotz, wenn ich den Aufwand treibe mit diesem
zusätzlichen Bookkeeping und dem komplizierteren Rückverfolgen, mit
dem Verschmelzen von selben Worthistorien in einen Pfad und
Aufsummieren aller Kosten und Wahrscheinlichkeiten und so weiter, kann
ich das trotzdem machen lassen.
Dann macht man das mal und dann guckt man sich die Wortfolgen an, die
man rausbekommt und dann stellt man fest, dass die einen manchmal
nicht ganz so interessant vorkommen, wie man das möchte.
Also das ist wieder dieses Beispiel von der Hund wedelt mit dem
Schwanz.
Und wenn man sich jetzt anschaut, was sind so die typischen N-Besten
-Ausgaben, die man bei sowas rausbekommt, das ist also wirklich ein
echtes Beispiel, dann hat man da sowas drin, wie das erste ist, der
Hund wedelt mit Herr Stanz, der Hund wedelt mit, der Mund wedelt mit
Herr Stanz, der Mund wedelt mit Herr an und so weiter und so fort.
Mund ist falsch, aber unter den ersten, was sind das, fünf Hypothesen
ist leider doch nicht die dabei, wo es mal ausnahmsweise Hund ist,
statt Mund.
Das, was sich ändert, sind diese kleinen Wörter, die Funktionswörter,
das der, er, ans, ins und so weiter, die ändern sich.
Das heißt, ich habe da immer die Gefahr, dass ich unter Umständen viel
unwichtige Variationen bekomme, während halt falsche inhaltstragende
Wörter sich halt kaum ändern.
Damit ich also da Sachen habe, wo sich dann auch wirklich mal
interessante Änderungen ergeben, muss ich häufig auf sehr große
Wortlisten, N-Besten-Listen greifen.
Der aufmerksame Zuhörer würde sich an der Stelle fragen, ja, aber wie
verträgt sich das denn mit der Idee, die wir da hatten mit, ich tippe
auf das Wort drauf und dann bekomme ich Alternativen angezeigt, wenn
ich da immer drei Alternativen haben will.
Und jetzt aufgepasst,
die Suche, die sucht nicht nach Wörtern an Wortpositionen, die sucht
nach gesamten Wortfolgen.
Das heißt, wenn ich hinterher wissen möchte, welche Alternativen gibt
es denn so an der Wortposition, dann habe ich noch eigentlich das
Problem, ich habe ja gar keine Wortposition.
Wenn ich mir so meine N-Besten-Listen angucke, die können ja auch
unterschiedliche Anzahl an Wörtern haben, dann muss ich überhaupt erst
mal was machen, dass sie sich auf Wortpositionen einigen können.
Und dann brauche ich natürlich relativ viele, damit ich dann an jeder
Wortposition auch genügend Variabilität habe, um aus unterschiedlichen
Wörtern aussuchen zu können.
Das heißt also, wenn ich für jede Wortposition drei Alternativen haben
will, reicht es nicht, die drei besten Wortfolgen zu suchen, sondern
es müssen mehr sein.
Und dadurch, dass gerade die interessanten Worte sich halt weigern,
sich schnell zu ändern, müssen diese N-Besten-Listen für sowas extrem,
extrem, extrem lang sein.
Das können hunderte, tausende alternative Sätze sein, damit ich da
auch wirklich pro Wortposition interessante Variationen zeigen kann
meinem Benutzer.
Und deswegen greift man zu einer etwas anderen Repräsentation.
Man lässt sich dann von dem Spracherkenner nicht einfach eine Liste
von den 100 besten Hypothesen ausgeben, sondern man lässt sich eine
Repräsentation ausgeben, wo diese alternativen Hypothesen als Graph
repräsentiert sind.
Ich kann ja diese N-Besten-Listen hernehmen und daraus einen Graph
machen, der mir alle diese Listen, diese möglichen Wortfolgen enthält.
Man kann sich das vorstellen, dass es insbesondere dann einfach, wenn
ich noch im Kopf behalte, ich weiß ja für jedes Wort seinen Anfangs-
und seinen Endzeitpunkt.
Und das ermöglicht es mir auch, dass selbst wenn solche Wörter
häufiger vorkommen, ich sie zeitlich auch entsprechend in diesem Graph
so anordnen kann, dass jeder Pfad, den ich da durchgehe, dann auch von
der Reihenfolge her der Wörter einer korrekten Wortfolge aus meiner N
-Besten -Liste entsteht.
Und so einen Graph kann ich halt auch mir relativ gut rausdestillieren
aus dem gesamten Suchraum, den ich sichtbar mache.
Wenn ich mir das überlege, bei der Viterbi-Suche mache ich ja einen
bestimmten Suchraum sichtbar.
Letztendlich so ein Netzwerk mache ich sichtbar.
Ein bisschen komplizierter, weil ich ja noch Sprachmodelle und so
weiter.
Aber letztendlich mache ich so ein Modell sichtbar.
Und jetzt kann ich skalieren die Worte, die ich in diesem Netzwerk
drin habe, indem ich einfach noch mal rumdoktere, wie stark prune ich
denn, wie stark schneide ich weg.
Und dann kann ich auf relativ einfache Art und Weise aus der Viterbi
-Suche so einen Graph machen.
Das Einzige, worauf ich achten muss, ist, dass ich hinterher nur die
Pfade übrig behalte, die sichtbar gemacht wurden und die auch
vollständig sind, die also vom ersten akustischen Frame bis ganz zum
letzten akustischen Frame gehen.
Und dann kann ich mir auf die Art und Weise eine sehr kompakte
Repräsentation von den besten Hypothesen, die ich so bei der Suche
gefunden habe, besucht habe, angefasst habe, geben.
Das Erste, wie gesagt, was ich machen kann, ist, ich scheine ja
irgendwie hier so Wortpositionen identifizieren zu können.
Wenn ich weiß, diese eine Pfade ist meine wahrscheinlichste, dann kann
ich gucken, was steht denn so in dem Graphen an ähnlicher Position und
kann das halt als Alternativen dann an dem Benutzer darstellen.
Ich kann mit sowas aber auch deutlich andere interessante Sachen
machen.
Da kommen wir dann sehr bald zu.
An dieser Stelle halt nur nochmal die Zusammenfassung, was haben wir
bisher an Beschleunigungstechniken kennengelernt bei der Suche, damit
das nochmal da ist.
Es sind zwei große Klassen.
Das eine ist, ich versuche die Anzahl der Zustände, die ich besuche,
zu reduzieren.
Durch Puning, durch Mehrpass suchen, Forward-Backward-Suche, durch
dieses Fast Match, dieser Look-Ahead für die Vorhersage, ob ich was
wegschneiden kann oder nicht.
Auch Early Abortion oder sowas kann man da relativ gut mit verwenden,
indem ich halt das Wort abbreche, wenn es unwahrscheinlich ist, dann
rechne ich es nicht mehr zu Ende, ich schneide es weg.
Und auch insbesondere, ich kann dieses Vorausschauen, diesen Fast
Match Look-Ahead machen mit Sprachmodell oder mit akustischem Modell.
Oder ich hatte solche Sachen, wie ich reduziere den Rechenaufwand pro
Zustand.
Da hatte ich dann halt die Parameterkopplung, die Anzahl der Zustände,
die ich klastere.
Je weniger Zustände ich habe, desto kompakter der Baum.
Ich kann was machen bei den Gauss-Mixtur-Modellen, mit Early Abortion,
mit diesen Bucketbox-Intersection-Algorithmen, dass ich diese
Codebücher so in so einer Baumhierarchie anordne und mich dann
entscheide, ob ich wirklich alle auswerten muss oder nicht.
Und diese ganzen Optimierungstechniken fließen jetzt halt in
unterschiedlichen Geschmäckern in das Gesamte, in die gesamte Suche an
ganz unterschiedlichen Stellen mit ein.
Das, was jetzt als nächstes kommt, das lohnt sich nicht, dass ich das
heute noch anfange.
Das machen wir dann ab nächste Woche weiter, dass wir uns dann einmal
zwei Beispiele anschauen für, wie sah der Decoder aus in unserem
Spracherkennungssystem früher, wie sieht er heute aus, und dass wir
uns dann nochmal überlegen, was mache ich falsch bei der
Fundamentalformel und vielleicht können mir ja Wortgrafen helfen, das,
was ich falsch mache, dann besser zu machen, um dann zu sehen, dass
Wortgrafen nicht nur geeignet sind für dieses einfache Beispiel, der
Benutzer korrigiert Fehler, sondern dass die auch essentiell wichtig
sind bei der Berechnung eines anderen Phänomens, das mir dann sehr
hilfreich ist, wenn ich mein Spracherkennungsergebnis noch ein
bisschen besser machen möchte.
Aber das machen wir dann ab nächster Woche.
Dann noch einen schönen Abend.