WEBVTT

00:05.310 --> 00:11.210
Okay, dann machen wir weiter mit Grundlagen der automatischen

00:11.210 --> 00:12.070
Spracherkennung.

00:13.530 --> 00:17.490
Wir hatten letztes Jahr, letztes Mal uns noch ein bisschen angeschaut,

00:17.870 --> 00:21.090
wie die Vorverarbeitung funktioniert, wie so typische

00:21.090 --> 00:22.830
Vorverarbeitungen aussehen.

00:24.230 --> 00:29.850
Und dann noch allgemein, was gab es so für Fragestellungen aus dem

00:29.850 --> 00:32.670
Bereich der Musterklassifikation.

00:34.010 --> 00:38.610
Und waren stehen geblieben, als es darum geht, dass man jetzt mit den

00:38.610 --> 00:42.230
Werkzeugen, die wir bisher haben, Spracherkennung wirklich als eine

00:42.230 --> 00:46.990
Art Musterklassifikationsproblem auffassen kann und schon mal so

00:46.990 --> 00:52.370
einfache Musterklassifikationsansätze verwenden kann, um zumindest zum

00:52.370 --> 00:55.230
Beispiel einzelne Worte erkennen zu können.

00:55.610 --> 01:00.270
Und die Idee dahinter ist halt, dass man mit dieser Folge von

01:00.270 --> 01:04.450
Merkmalsvektoren, die man bekommt aus der Vorverarbeitung, also Folge

01:04.450 --> 01:07.350
von Kepstralvektoren zum Beispiel oder auch Folge von

01:07.350 --> 01:09.830
Spektralvektoren, arbeiten kann.

01:10.290 --> 01:14.330
Und die Idee ist, dass man jetzt eine Distanz zwischen dieser einen

01:14.330 --> 01:16.390
Matrix und der anderen Matrix findet.

01:17.610 --> 01:20.690
Und die Idee ist, ich habe für jedes Wort, das ich erkennen möchte,

01:20.790 --> 01:24.030
habe ich ein Referenzmuster, das prototypisch für dieses Wort steht.

01:24.350 --> 01:27.530
Und wenn ich eine neue Aufnahme bekomme, berechne ich die

01:27.530 --> 01:31.870
Vorverarbeitung und für jedes Wort rechne ich die Distanz aus in

01:31.870 --> 01:34.470
meinem Vokabular an Worten, die ich erkennen kann.

01:34.830 --> 01:39.170
Und da, wo die Distanz am geringsten ist, das Wort ist dasjenige, das

01:39.170 --> 01:41.810
ich erkennen möchte.

01:43.890 --> 01:47.890
Allgemein, so eine Aufnahme nennt man eine Äußerung oder im Englischen

01:47.890 --> 01:48.790
utterance.

01:49.350 --> 01:52.450
Das kann ein Wort sein, das kann eine Sequenz von Worten sein, etc.

01:53.390 --> 01:56.370
Angenommen, bei uns ist es erstmal nur ein Wort.

01:59.770 --> 02:05.670
Jetzt ist die Frage, wie berechne ich die Distanz zwischen diesen zwei

02:05.670 --> 02:10.090
Matrizen, zwischen diesen beiden Folgen von Referenzvektoren?

02:13.210 --> 02:17.390
Offensichtlich wichtig ist die zeitliche Reihenfolge.

02:17.830 --> 02:23.770
Also, wenn ich zwei solche Muster habe, dann sind zwar die irgendwie

02:23.770 --> 02:30.030
ähnlich, aber offensichtlich sind sie nicht dasselbe Muster, weil sie

02:30.030 --> 02:34.650
hier in der Mitte von der Zeitreihenfolge her vertauscht sind.

02:35.090 --> 02:39.450
Das heißt, bei dieser Berechnung der Distanz muss ich darauf achten,

02:39.950 --> 02:43.590
dass ich die Reihenfolge der Vektoren, wie sie vorkommen, halt mit in

02:43.590 --> 02:46.270
die Distanzberechnung mit reinziehe.

02:47.310 --> 02:52.470
Und dann kann ich mir die einzelnen Vektoren jeweils paarweise

02:52.470 --> 02:53.230
anschauen.

02:53.230 --> 02:57.530
Und so der erste naive Ansatz, den man dann halt verfolgt hat und den

02:57.530 --> 03:02.490
man sich machen könnte, ist, okay, ich gehe halt Referenzmuster und

03:02.490 --> 03:08.690
aufnahme Zeitschritt für Zeitschritt ab und vergleiche immer paarweise

03:08.690 --> 03:10.110
die beiden Vektoren.

03:10.410 --> 03:14.350
Die ersten beiden Vektoren vergleiche ich miteinander, berechne ich

03:14.350 --> 03:18.650
eine Distanz, gibt es normalerweise so eklidische Distanz, zum

03:18.650 --> 03:22.570
Beispiel Standarddistanz so in mehrdimensionalen Vektoren, und

03:22.570 --> 03:25.610
summiere die Einzeldistanzen, die ich bei diesem paarweisen Vergleich

03:25.610 --> 03:27.130
habe, auf.

03:27.990 --> 03:31.670
Und dann sage ich, okay, ich entscheide mich für das Referenzwort, wo

03:31.670 --> 03:35.550
diese aufsummierte Distanz entsprechend am kleinsten ist.

03:38.510 --> 03:45.670
Was ist ein offensichtliches Problem dieses etwas naiven Ansatzes?

03:46.430 --> 03:49.450
Womit kommt er offensichtlich nicht zurecht?

03:51.090 --> 03:55.350
Wovon ich eigentlich ausgehen dürfte, wenn ich so Audioaufnahmen habe

03:55.350 --> 03:55.950
von Wörtern.

03:56.390 --> 03:56.610
Genau.

03:57.410 --> 04:00.830
Im Prinzip, und jetzt nochmal einen Schritt zurück und noch einfacher,

04:01.250 --> 04:02.850
meine, wovon geht dieser Ansatz aus?

04:02.930 --> 04:05.810
Ich sage immer, erster Zeitschritt wird mit dem ersten verglichen,

04:05.890 --> 04:08.690
zweiter mit dem zweiten, letzter mit dem letzten verglichen.

04:09.030 --> 04:11.410
Was ist also das erste, die erste Annahme, die gemacht wird?

04:11.770 --> 04:16.950
Die erste Annahme, die gemacht wird, ist, dass die gleich lang sind.

04:16.950 --> 04:20.790
Also erstmal dieser naive Ansatz, das erste, wo es schon scheitert

04:20.790 --> 04:23.950
ist, die sind nicht notwendigerweise gleich lang, die Aufnahmen.

04:24.450 --> 04:30.170
Also dieses Verfahren geht erstmal davon aus, dass das Ganze gleich

04:30.170 --> 04:30.750
lang ist.

04:31.210 --> 04:34.910
Und dann geht es auch davon aus, dass sozusagen das Sprechtempo immer

04:34.910 --> 04:35.550
gleich ist.

04:36.650 --> 04:38.950
Gut, wenn das Sprechtempo immer gleich ist und dasselbe Wort

04:38.950 --> 04:42.130
gesprochen wird, dann sind sie wenigstens halbwegs gleich lang.

04:42.630 --> 04:46.210
Aber das Sprechtempo kann ja auch innerhalb dessen, während gesprochen

04:46.210 --> 04:47.310
wird, auch variieren.

04:47.990 --> 04:51.010
Und das sind alles Probleme, die ich jetzt bei diesem naiven Ansatz

04:51.010 --> 04:52.250
nicht lösen konnte.

04:56.910 --> 05:05.190
Deswegen hat man dann angefangen zu überlegen, wie kann ich zum

05:05.190 --> 05:09.190
Beispiel für unterschiedliche Sprechgeschwindigkeit oder

05:09.190 --> 05:13.050
unterschiedliche Längen von Aufnahmen kompensieren.

05:13.050 --> 05:14.250
Was kann ich damit machen?

05:14.930 --> 05:18.190
Wenn ich schneller spreche als in der Referenzaufnahme, bekomme ich

05:18.190 --> 05:21.150
halt weniger Vektoren für die gleiche Zeit.

05:21.290 --> 05:24.890
Umgekehrt, wenn ich langsamer spreche, bekomme ich halt mehr Vektoren

05:24.890 --> 05:27.470
für das gleiche Wort in gleicher Zeit.

05:28.170 --> 05:31.070
Und selbst wenn die Anzahl der Vektoren gleich ist, kann es sein, dass

05:31.070 --> 05:35.850
es halt innen drin zeitlich irgendwie schwankt.

05:36.250 --> 05:38.750
Also das ist so ein typisches Beispiel.

05:38.750 --> 05:41.750
Das sieht man auf beiden Projektoren eigentlich schlecht.

05:43.750 --> 05:49.130
Wenn man hinguckt, dann wird das wohl die gleiche Aufnahme sein.

05:49.870 --> 05:53.530
Die da ist ein bisschen kürzer als die da.

05:54.090 --> 05:57.650
Und man sieht schon, der Teil hier, der ist da ein bisschen länger

05:57.650 --> 05:58.210
gezogen.

05:59.010 --> 06:04.550
Und der Teil hier, der ist hier kürzer und da länger gezogen.

06:04.550 --> 06:09.490
Das heißt, hier hat er langsamer gesprochen und da schneller und hier

06:09.490 --> 06:11.670
hat er schneller gesprochen und da langsamer.

06:12.390 --> 06:13.770
Also genau umgekehrt jeweils.

06:14.250 --> 06:15.690
Obwohl dasselbe gesagt wurde.

06:18.250 --> 06:19.950
Spontane Sprache ist nun mal so.

06:20.090 --> 06:23.070
Man kann es auch einsetzen, um irgendwelche Sachen zu betonen etc.

06:23.830 --> 06:25.710
Was macht man jetzt als erstes?

06:26.610 --> 06:30.610
Gut, man legt sich halt nicht mehr statisch fest und sagt, der erste

06:30.610 --> 06:34.390
Vektor muss immer mit dem ersten Vektor verglichen werden, sondern es

06:34.390 --> 06:40.790
sollen geeignete Vektoren miteinander verglichen werden.

06:43.230 --> 06:47.190
Dieses rausfinden, was sind geeignete Vektoren, da braucht man ein

06:47.190 --> 06:47.950
paar Einschränkungen.

06:48.810 --> 06:50.910
Die eine Einschränkung ist halt die Monotonie.

06:51.310 --> 06:56.930
Ich will also nicht, dass ich Zuordnungen von den Vektoren zulasse,

06:57.010 --> 06:59.930
die ich miteinander vergleiche, die halt zu Umordnungen führen würden.

06:59.930 --> 07:04.370
Es muss also sichergestellt sein, dass ich immer in der Zeit

07:04.370 --> 07:07.830
vorangehe, aber nie in der Zeit zurückgehe, wenn ich Vektoren

07:07.830 --> 07:08.970
miteinander vergleiche.

07:09.330 --> 07:12.470
Wenn ich also in dem einen den dritten mit dem fünften Vektor

07:12.470 --> 07:15.750
verglichen habe, dann darf ich nicht als nächstes den vierten mit dem

07:15.750 --> 07:18.910
vierten Vektor vergleichen, sondern dann muss mindestens der sechste

07:18.910 --> 07:19.910
Vektor kommen.

07:19.990 --> 07:22.930
Ich muss also irgendwie entweder stehen bleiben oder in der Zeit

07:22.930 --> 07:24.430
vorangehen.

07:25.930 --> 07:30.150
Die ersten Ideen, die man da gemacht hatte, ist, okay, ich habe

07:30.150 --> 07:33.210
Aufnahmen unterschiedlicher Länge, dann nummiere ich halt auf Länge.

07:34.730 --> 07:37.310
Nummieren kann ich, indem ich zum Beispiel immer auf die kürzeste

07:37.310 --> 07:39.250
Äußerung nummiere.

07:39.790 --> 07:44.170
Dann kann ich mir halt Vektoren zwischendurch weglassen.

07:44.290 --> 07:48.410
Muss ich halt gucken, immer den Endenvektor muss ich halt weglassen.

07:48.530 --> 07:51.770
Unter Umständen, da ich halt nicht kontinuierlich bin, muss ich halt

07:51.770 --> 07:54.250
solche Sachen machen, jeden zweiten, jeden dritten, jeden zweiten,

07:54.370 --> 07:57.250
jeden dritten, jeden zweiten, jeden dritten Vektor oder jeden zweiten,

07:57.450 --> 07:59.050
jeden zweiten, jeden dritten Vektor, jeden zweiten.

07:59.270 --> 08:02.270
Da muss ich also irgendein Verfahren finden, dass ich halt Vektoren

08:02.270 --> 08:05.670
weglasse, um die längere auf genau die Länge der kürzeren zu bekommen.

08:07.830 --> 08:11.470
Kann man zum Beispiel noch komplizierter machen, dass ich halt nicht

08:11.470 --> 08:15.550
einfach weglasse, sondern dass ich zum Beispiel mehrere Vektoren dann

08:15.550 --> 08:19.150
gewichtet zusammenfasse zu einem neuen Vektor, so dass die richtige

08:19.150 --> 08:21.130
Anzahl der Vektoren rauskommt.

08:22.110 --> 08:24.610
Umgekehrt kann ich auch genauso mir vorstellen, dass ich auf die

08:24.610 --> 08:25.630
längere Aufnahme nummiere.

08:26.470 --> 08:29.770
Dann muss ich halt in der kürzeren irgendwie Vektoren hinzufügen.

08:30.210 --> 08:34.310
Ich kann zum Beispiel Vektoren duplizieren oder ich kann auch zum

08:34.310 --> 08:38.030
Beispiel mit irgendwelchen Interpolationsverfahren zwischen zwei

08:38.030 --> 08:39.950
Vektoren einen neuen Vektor einfügen.

08:40.650 --> 08:44.290
Kann man auch sich beliebig komplizierte Verfahren vorstellen, um dann

08:44.290 --> 08:49.550
eine schöne glatte Interpolation zu bekommen, um halt letztendlich die

08:49.550 --> 08:51.510
Auflösung der Aufnahme zu verbessern.

08:52.010 --> 08:54.850
Wenn das gemacht ist, kann man eine lineare Zuordnung machen.

08:55.590 --> 08:59.250
Hat natürlich das Problem, dass ich immer noch nicht diese

08:59.250 --> 09:02.690
unterschiedlichen Sprechgeschwindigkeiten hinbekomme.

09:03.010 --> 09:06.390
Das funktioniert nur dann, wenn halt die eine Aufnahme konstant

09:06.390 --> 09:09.890
langsamer gesprochen wurde als die andere Aufnahme oder konstant

09:09.890 --> 09:10.990
schneller gesprochen wurde.

09:10.990 --> 09:17.990
Aber wenn ich jetzt, was mal rauskommt bei der entweder Extrapolieren

09:17.990 --> 09:23.110
auf die lange oder Kürzen auf die kürzeste Aufnahme, das ist dann

09:23.110 --> 09:26.770
immer noch so eine lineare Zuordnung dieser Vektoren irgendwie

09:26.770 --> 09:30.630
zueinander, der dann aufgebohrten Vektoren.

09:30.790 --> 09:34.390
Was aber passiert ist, wie hier in dem Beispiel, dass man halt mal

09:34.390 --> 09:37.690
schneller und mal langsamer spricht und dann vielleicht auch noch so

09:37.690 --> 09:38.450
Sondereffekte.

09:38.450 --> 09:40.750
Da hat man mal ein bisschen mehr Stille, bevor es losgeht.

09:40.850 --> 09:42.970
Da hat man ein bisschen weniger Stille, bevor es losgeht.

09:43.530 --> 09:48.050
Das heißt, was man idealerweise hätte, ist, dass Vektoren hier oben

09:48.050 --> 09:52.310
auf andere Vektoren hier unten abgebildet werden und dass das mal

09:52.310 --> 09:56.690
aufgespreizt wird und mal kleiner gemacht wird.

09:56.770 --> 09:59.490
Also hier wird es aufgespreizt, hier wird es aufgespreizt, hier wird

09:59.490 --> 10:02.350
es ein bisschen kleiner gemacht, hier ist es ungefähr gleich und da

10:02.350 --> 10:04.370
wird es wieder ein bisschen kleiner gemacht.

10:04.370 --> 10:08.730
Dass ich also den Effekt, dass ich hin und wieder variierende, während

10:08.730 --> 10:14.410
des Sprechens variierende Geschwindigkeiten habe, dass ich die

10:14.410 --> 10:17.470
geeignet zuordne.

10:18.210 --> 10:23.230
Das heißt, was am Ende herauskommt ist, dass man, wenn man zwei

10:23.230 --> 10:28.790
Aufnahmen hat, man irgendwie eine geeignete Abbildung machen muss.

10:29.470 --> 10:32.610
Finden muss dieser Vektoren auf einen anderen Vektor.

10:32.610 --> 10:39.170
Diese Abbildung ist nicht bijektiv, sie muss auch nicht injektiv sein

10:39.170 --> 10:42.710
und sie muss auch nicht sujektiv sein, sondern die muss damit umgehen

10:42.710 --> 10:45.450
können, dass halt das eine kann länger sein, das andere kann kürzer

10:45.450 --> 10:49.330
sein und dann diese unterschiedlichen Geschwindigkeiten machen will.

10:51.510 --> 10:54.410
Das Ganze ist also, wenn man jetzt in den Grundbegriffen der

10:54.410 --> 10:55.770
Informatik denkt, eine Relation.

10:55.770 --> 11:00.030
Ich brauche also lauter solche Tupe, die mir den i-ten Vektor in der

11:00.030 --> 11:05.290
einen Aufnahme auf den j-ten Vektor in der anderen Aufnahme abbildet.

11:09.690 --> 11:16.430
Da es sein kann, dass mehrere x auch auf dasselbe y abgebildet werden,

11:16.890 --> 11:20.310
oder auch ein x auf mehrere y, ist das Ganze auch keine Abbildung,

11:20.490 --> 11:21.830
sondern wirklich eine echte Relation.

11:21.990 --> 11:26.210
Sie ist zwar links total, muss aber nicht notwendigerweise rechts

11:26.210 --> 11:27.010
eindeutig sein.

11:30.390 --> 11:34.090
Plus, wenn man das sozusagen zulässt, dass man auch noch bestimmte

11:34.090 --> 11:38.890
Dinge überspringt und wenn man jetzt sagt, überspringen ist nicht eine

11:38.890 --> 11:42.190
Abbildung auf irgendwie ein Sonderzeichen, sondern der fällt halt

11:42.190 --> 11:44.890
völlig raus aus der Relation, dann wird es auch nicht mal mehr eine

11:44.890 --> 11:48.250
links totale Relation, sondern dann ist es wirklich eine ganz freie,

11:48.670 --> 11:50.650
beliebige Relation, mit der wir da umgehen.

11:51.590 --> 11:55.090
Und dieses Verfahren nennt man Time Warping.

11:55.090 --> 11:58.410
Time Warping deshalb, weil in der Vorstellung, so wie wir schon

11:58.410 --> 12:01.690
Frequenzachsen skaliert haben, logarithmisch skaliert haben oder mit

12:01.690 --> 12:06.190
der Mail-Skala skaliert haben, skalieren wir hier die Zeitachsen.

12:06.550 --> 12:10.550
Weil die Indizes in den Folgen entsprechen halt der Zeit und ich warpe

12:10.550 --> 12:15.990
halt die Zeit in dem Referenzwort und die Zeit in dem Hypothesenwort,

12:16.110 --> 12:19.310
in der Aufnahme, die ich klassifizieren möchte, die warpe ich halt so

12:19.310 --> 12:22.110
zusammen, dass es hinterher passt.

12:22.710 --> 12:27.650
Und man stellt dann das Ergebnis, welchen Vektor ich mit welchem

12:27.650 --> 12:31.550
vergleiche, in der Regel als so einen kleinen Pfad da, überall wo uns

12:31.550 --> 12:34.590
schwarzer Punkt ist, werden zwei Vektoren aneinander zugeordnet.

12:36.110 --> 12:39.450
Hier zum Beispiel, so wir gucken, da ist der siebte, da ist der

12:39.450 --> 12:42.830
sechste, genau, da sind so Sprünge drin, dieser sechste Vektor zum

12:42.830 --> 12:46.170
Beispiel, der wird nichts zugeordnet, der kann auch mal übersprungen

12:46.170 --> 12:48.850
werden, das heißt, da sind dann so Lücken drin und dann bekomme ich

12:48.850 --> 12:52.490
hier so einen Pfad, das ist der dynamische Time Warping Pfad.

12:53.730 --> 12:58.350
Und an jedem schwarzen Punkt kann ich halt eine Distanz berechnen und

12:58.350 --> 13:01.750
dann summiere ich die Distanz entlang dieses Pfades aus auf und

13:01.750 --> 13:08.210
bekomme da meinen Score, wie nahe sich diese beiden Aufnahmen an den

13:08.210 --> 13:12.070
jeweiligen Achsen sind, welche Distanz sie haben.

13:14.290 --> 13:17.490
Also die Pfade, die Distanzen werden aufsummiert.

13:18.630 --> 13:21.270
Jetzt ist immer noch die Frage, wo kriege ich den Pfad her?

13:21.970 --> 13:25.250
Für welchen Pfad entscheide ich mich?

13:25.370 --> 13:29.270
Und da ist die Idee, dass ich mich unter allen möglichen Pfaden, die

13:29.270 --> 13:32.810
ich habe, zwischen zwei Äußerungen, mich für den Pfad entscheide, der

13:32.810 --> 13:34.130
die kleinste Distanz hat.

13:34.750 --> 13:38.050
Weil ich davon ausgehe, dass halt ähnliche Teile sollen sich ähnlich

13:38.050 --> 13:41.690
sein, das heißt, wenn ich also einen Pfad finde, der so einen Time

13:41.690 --> 13:46.710
Warping macht, der die kleinste Distanz am Ende hat, dann sollte das

13:46.710 --> 13:51.210
bitteschön der Pfad sein, der auch diesem Warping am besten

13:51.210 --> 13:51.790
entspricht.

13:53.430 --> 14:00.190
Es stellt sich eine wichtige Frage, wenn ich sowas berechne, was mache

14:00.190 --> 14:02.490
ich, wenn ich hier so eine Lücke drin habe?

14:03.230 --> 14:06.490
Und wenn ich so eine Lücke drin habe, dass irgendwas nicht auf

14:06.490 --> 14:09.990
irgendwas anderes abgebildet wird, dann muss ich das auch irgendwie

14:09.990 --> 14:10.910
bestrafen können.

14:10.910 --> 14:14.010
Weil ansonsten kann ich immer sagen, ich habe immer eine Distanz von

14:14.010 --> 14:16.250
0, wenn ich einfach nichts auf nichts abbilde.

14:16.470 --> 14:18.150
Das will ich natürlich nicht haben.

14:20.030 --> 14:25.150
Und dieses Finden dieses kleinsten Pfades ist im Prinzip dasselbe wie

14:25.150 --> 14:29.490
das Finden einer minimalen Editierdistanz beim Berechnen der

14:29.490 --> 14:30.210
Wortfehlerrate.

14:30.790 --> 14:36.850
Bei der Wortfehlerrate hatte ich zwei Zeichenfolgen, die Wörter sind x

14:36.850 --> 14:37.830
i und y i.

14:37.830 --> 14:43.490
Ich hatte drei mögliche Editierschritte und konnte dann, habe mich

14:43.490 --> 14:47.470
halt dann interessiert, was ist der kleinste, die kleinste Folge von

14:47.470 --> 14:51.890
Editierschritten, um aus der einen Wortfolge die andere zu machen und

14:51.890 --> 14:55.750
hatte dann eine Möglichkeit, mit Hilfe von dynamischem Programmieren

14:55.750 --> 14:59.370
herauszufinden, was ist jetzt diese kleinstmögliche Folge von

14:59.370 --> 15:02.130
Editierschritten, um das zu machen.

15:02.690 --> 15:05.130
Jetzt habe ich hier...

15:08.270 --> 15:12.310
Erinnerung, also das Finden der minimalen Editierdistanz war halt mit

15:12.310 --> 15:13.650
dynamischem Programmieren.

15:15.010 --> 15:19.330
Wie gesagt, kennen Sie aus der Vorlesung Softwaretechnik, kennen Sie

15:19.330 --> 15:21.850
zum Beispiel auch aus Operations Research.

15:22.090 --> 15:26.010
Die Grundidee beim dynamischen Programmieren ist immer, dass ich

15:26.010 --> 15:30.130
kürzere Teilprobleme ausrechne, ich speichere die Zwischenergebnisse

15:30.130 --> 15:35.070
ab und mache dann das Teilproblem einen Schritt länger und rechne dann

15:35.070 --> 15:39.170
das Neue aus, basierend auf den Zwischenergebnissen, ohne dass ich

15:39.170 --> 15:41.930
alle möglichen Folgen immer berechnen muss.

15:43.690 --> 15:46.910
Und das hatten wir halt dargestellt, das hatte ich immer an der Tafel

15:46.910 --> 15:50.530
gemacht, macht man mit so einer Matrix, dass man also seine Folgen

15:50.530 --> 15:54.610
immer an die Achsen dieser Matrix schreibt und dann geht man die

15:54.610 --> 16:00.110
Spalten dieser Matrix durch und füllt halt die einzelnen Zellen dieser

16:00.110 --> 16:01.170
Matrix immer auf.

16:01.550 --> 16:04.550
Und bei der minimalen Editierdistanz war es halt so, dass wenn ich den

16:04.550 --> 16:10.090
Wert reinschreiben wollte in so eine Matrixzelle ij, dann konnte ich

16:10.090 --> 16:15.130
das tun, indem ich geschaut habe, was ist der kleinstmögliche Schritt,

16:15.490 --> 16:19.750
um von entweder der linken, der diagonal unteren oder der unteren

16:19.750 --> 16:21.810
Zelle da reinzukommen.

16:22.250 --> 16:24.230
Hab dann mal ausgerechnet, was sind die Kosten.

16:24.230 --> 16:27.650
Bei dem Diagonalschritt habe ich die Unterscheidung gemacht, stimmen

16:27.650 --> 16:31.590
die beiden Zeichen überein oder mache ich eine Austauschung und die

16:31.590 --> 16:35.370
anderen, der Horizontal- und Vertikalschritt, waren halt sowas wie

16:35.370 --> 16:39.170
Einlöschungen und Einfügungen und Auslöschungen.

16:39.750 --> 16:44.310
Hab Kosten definiert, was kostet mich eine Ersetzung, was kostet mich,

16:44.530 --> 16:49.430
wenn es übereinstimmt, was kostet es mich, wenn ich einfüge, was

16:49.430 --> 16:53.590
kostet es mich, wenn ich lösche und so typische Sachen ist halt, wenn

16:53.590 --> 16:58.010
die beiden Sachen stimmen, kosten 0, wenn ich austausche, wenn ich

16:58.010 --> 17:00.230
einfüge oder wenn ich lösche, habe ich Kosten 1.

17:00.850 --> 17:04.290
Und hab dann nach dem Pfad gesucht, der mir die mindestens minimalen

17:04.290 --> 17:08.710
Kosten hatte, hab diese Matrix ausgefüllt und das Einzige, was ich

17:08.710 --> 17:13.510
machen musste ist, ich musste mir immer zu jeder neuen Zelle merken,

17:13.950 --> 17:17.410
welches war denn der Schritt, der mich hier in der Zelle zu den

17:17.410 --> 17:21.410
minimalen Kosten geführt hat und wenn ich ganz die Matrix ausgefüllt

17:21.410 --> 17:27.930
hatte, dann kann ich zum Beispiel oben links, oben rechts in der Zelle

17:27.930 --> 17:31.530
nachschauen, was sind die Kosten, die minimalen Kosten und muss mich

17:31.530 --> 17:35.770
dann anhand dieser Rückzeiger zurückhangeln in jeder Zelle, wo bin ich

17:35.770 --> 17:40.090
denn hergekommen und hab dann rückwärts diese Folge aus Operatoren für

17:40.090 --> 17:43.590
das Berechnen der Editierdistanz wieder aufgebaut.

17:46.050 --> 17:49.550
Und genauso ähnlich macht man das halt beim Dynamic Time Warping.

17:50.370 --> 17:55.130
Kann man ähnlich machen, man muss halt nur die Kosten und die

17:55.130 --> 17:57.290
Distanzfunktionen ersetzen.

18:00.150 --> 18:03.930
Beim Dynamic Programming für minimale Editierdistanz gab es

18:03.930 --> 18:07.050
Editierschritte, die gibt es hier jetzt halt nicht mehr.

18:07.050 --> 18:13.770
Stattdessen habe ich dann, ich hatte vorher so Vektoren von einzelnen

18:13.770 --> 18:20.010
Zeichen, jetzt habe ich Folgen von Vektoren von reellen Zahlen und es

18:20.010 --> 18:22.290
gibt nicht mehr diese identischen Vektoren.

18:22.410 --> 18:24.610
Das ist sehr unwahrscheinlich, dass ich zwei identische Vektoren

18:24.610 --> 18:25.030
finde.

18:25.150 --> 18:27.610
Ich finde eher ähnliche und unähnliche Wörter.

18:29.070 --> 18:34.110
Vektoren können nach wie vor ersetzt werden, eingefügt werden oder

18:34.110 --> 18:40.150
gelöscht werden und für das Ersetzen die Kosten, da kann ich einfach

18:40.150 --> 18:44.830
direkt irgendein Distanzmaß zwischen den beiden Vektoren hernehmen.

18:46.030 --> 18:52.010
Zum Beispiel Editierdistanz, zum Beispiel Euclidische Distanz zum

18:52.010 --> 18:54.130
Beispiel auf den Vektoren kann das nehmen.

18:54.210 --> 18:56.850
Wenn die Vektoren gleich sind, habe ich Distanz 0, das ist super und

18:56.850 --> 19:00.390
ansonsten bekomme ich eine immer größer werdende Distanz, je

19:00.390 --> 19:02.030
unähnlicher die Vektoren sind.

19:02.030 --> 19:06.370
Und für das Einfügen und das Auslöschen, da habe ich jetzt ein

19:06.370 --> 19:12.650
bisschen ein Problem, da muss ich mir geeignet irgendwie beliebig

19:12.650 --> 19:14.930
diese Kosten dafür definieren.

19:15.030 --> 19:19.830
Da muss ich per Hand definieren eine Strafe dafür, wenn ich jetzt

19:19.830 --> 19:24.350
einen Vektor auslasse beziehungsweise einen Vektor einfüge.

19:28.990 --> 19:32.930
Der Algorithmus, der jetzt diesen minimalen Pfad findet, diesen

19:32.930 --> 19:36.130
minimalen Time Warping Pfad, ist genau derselbe dann wie bei der

19:36.130 --> 19:38.130
minimalen Editierdistanz.

19:39.170 --> 19:42.310
Das einzige, was ich jetzt noch machen kann, ich kann unter Umständen

19:42.310 --> 19:45.710
mir noch neue Arten von Schritten einfügen, wenn ich zum Beispiel

19:45.710 --> 19:51.650
nicht nur einen Vektor auf einmal auslöschen will, sondern was ist,

19:51.710 --> 19:54.870
wenn ich zum Beispiel zwei Vektoren auf einmal auslöschen will und so

19:54.870 --> 19:55.690
weiter und so fort.

19:55.890 --> 19:58.670
Da kann man dann noch ein paar Spielarten machen, aber so in seiner

19:58.670 --> 20:03.810
Grundform kann man sagen, ist genauso wie minimale Editierdistanz, nur

20:03.810 --> 20:07.490
dass ich halt die Kosten für Einfügen und Löschen irgendwie anders

20:07.490 --> 20:09.430
definieren muss, geeignet definieren muss.

20:09.490 --> 20:12.230
Da muss ich halt rumprobieren, bis es passt einigermaßen.

20:13.550 --> 20:17.390
Und dass ich halt nicht mehr die Entscheidung treffe, zwei Vektoren,

20:17.490 --> 20:20.330
die ich aufeinander abbilde, passen die oder sind die unterschiedlich,

20:20.430 --> 20:22.870
sondern das ersetze durch so eine kontinuierliche Distanz.

20:25.570 --> 20:28.750
Wie gesagt, bei der minimalen Editierdistanz habe ich immer diesen

20:28.750 --> 20:29.270
Dreierschritt.

20:29.270 --> 20:32.390
Ich kann diagonal gehen, von rechts kommen, von unten kommen.

20:32.990 --> 20:36.570
Jetzt kann ich mir beim DTW das Ganze komplizierter überlegen.

20:37.210 --> 20:41.210
Das Einzige ist, dass ich so ein paar Einschränkungen machen will.

20:41.790 --> 20:45.790
Was ich nicht möchte zum Beispiel ist sowas hier, dass ich rückwärts

20:45.790 --> 20:46.530
in der Zeit gehe.

20:46.630 --> 20:47.610
Das hatten wir schon gesagt.

20:48.050 --> 20:49.270
Das darf ich nicht zulassen.

20:50.150 --> 20:53.910
Was ich auch nicht möchte ist zum Beispiel, dass ich so große Sprünge

20:53.910 --> 20:57.430
mache, dass ich also zu viel auslösche.

20:57.570 --> 21:00.310
Sondern auch wenn ich unterschiedliche Sprechgeschwindigkeiten habe,

21:00.730 --> 21:04.610
wenn es dasselbe ist, sollte der Pfad zumindest so irgendwo in der

21:04.610 --> 21:05.830
Nähe der Diagonalen liegen.

21:05.990 --> 21:09.370
Wenn der zu weit von der Diagonalen abweicht, dann ist das eher

21:09.370 --> 21:09.990
unwahrscheinlich.

21:10.190 --> 21:13.490
Also es ist sehr unwahrscheinlich, dass ich mal den Anfang ganz

21:13.490 --> 21:16.750
schnell spreche und dann in der anderen Aufnahme den Anfang ganz

21:16.750 --> 21:17.590
langsam spreche.

21:18.410 --> 21:22.550
Schneller und langsamer, ja, aber irgendwie in vernünftigen, intuitiv

21:22.550 --> 21:23.550
machbaren Grenzen.

21:25.210 --> 21:29.090
Am Anfang und am Ende sollte ich nicht zu viel auslassen.

21:29.230 --> 21:32.030
Dahinter steckt die Idee, dass ich möglichst mein Audio immer so

21:32.030 --> 21:35.090
segmentiere, dass ich am Anfang und am Ende nicht zu viel Stille habe,

21:35.650 --> 21:40.110
sondern die sollten am Anfang ungefähr gleich anfangen und sie sollten

21:40.110 --> 21:41.170
ungefähr gleich enden.

21:41.290 --> 21:46.510
Das heißt also Anfangs- und Endpunkt sollte nicht zu weit wegliegen

21:46.510 --> 21:50.090
von der obersten rechten Zelle beziehungsweise von der untersten

21:50.090 --> 21:50.710
linken Zelle.

21:52.330 --> 21:56.350
Und ich hätte gerne, dass der Pfad mehr oder minder glatt verläuft.

21:56.470 --> 22:00.270
Also ich will es vermeiden, dass ich solche zu steilen Anteile habe.

22:00.430 --> 22:03.410
Ich meine, der Extremfall ist der hier, dass ich einen echten Sprung

22:03.410 --> 22:07.530
mache, aber auch sowas, dass ich hier einen sehr, sehr steilen Pfad

22:07.530 --> 22:12.730
habe oder einen teilweise sehr, sehr glatten Pfad, dann hinterher ist

22:12.730 --> 22:14.790
eher unwahrscheinlich, dass das richtig ist.

22:14.850 --> 22:16.310
Das möchte ich doch eher vermeiden.

22:16.550 --> 22:19.370
Also angenommen, wir machen jetzt Einzelworterkennung.

22:19.370 --> 22:20.750
Ich spreche halt Wörter.

22:21.130 --> 22:21.670
Städtenamen.

22:22.450 --> 22:24.790
Und habe immer Aufnahmen von Städtenamen.

22:25.130 --> 22:29.990
Ich meine, so ein einzelner Vektor deckt einen Bereich von 16

22:29.990 --> 22:32.630
Millisekunden ab und alle 10 Millisekunden bekomme ich einen neuen

22:32.630 --> 22:33.050
Vektor.

22:33.470 --> 22:36.850
Das heißt also Pi mal Daumen, ein Vektor ungefähr 10 Millisekunden,

22:37.430 --> 22:38.570
die er abdeckt.

22:39.250 --> 22:42.110
Dann bekomme ich auch, wenn ich jetzt nochmal zwei Sekunden lang

22:42.110 --> 22:44.010
spreche, schon relativ viele Vektoren.

22:44.690 --> 22:48.790
Und wenn ich das Audio ordentlich schneide mit geeigneten Verfahren,

22:48.790 --> 22:52.710
dass ich also nicht zu viel Stille am Anfang und am Ende habe, dann

22:52.710 --> 22:56.770
dürfte zum Beispiel der Anfang und das Ende nicht stark abweichen.

22:56.850 --> 23:01.450
Weil das Einzige, warum ich nicht den ersten auf den ersten Vektor

23:01.450 --> 23:04.330
abbilde und nicht den letzten Vektor auf den letzten Vektor abbilde,

23:04.450 --> 23:07.790
ist, wenn dahinter noch was kommt, was jetzt nichts mehr mit zu tun

23:07.790 --> 23:09.070
hat und wenn vorher was nicht kommt.

23:09.570 --> 23:10.530
Das ist also das Erste.

23:11.250 --> 23:16.250
Und dann hier, diese Glättigkeit hängt natürlich ein bisschen von den

23:16.250 --> 23:16.850
Daten ab.

23:16.850 --> 23:19.670
Aber, meine, sowas ist schon extrem.

23:19.830 --> 23:22.410
Wenn man also sich anschaut, das ist das gesamte Wort.

23:23.450 --> 23:28.610
Dann wird hier, wenn ich das mache, heißt das nichts anderes, als dass

23:28.610 --> 23:33.910
80, 90 Prozent des Wortes in den ersten 10 Prozent der Aufnahme

23:33.910 --> 23:38.030
gesprochen wurden und die restlichen 10 Prozent werden dann in den

23:38.030 --> 23:40.990
restlichen 90 Prozent der Aufnahme gesprochen.

23:41.370 --> 23:42.810
Also schon extrem.

23:42.810 --> 23:46.910
Also selbst wenn ich jetzt, sagen wir mal, eine Silbe dehne, dass das

23:46.910 --> 23:49.690
das gesamte Wort dann so aussieht, ist eher unwahrscheinlich.

23:51.050 --> 23:54.070
Das sind schon sehr starke Extremfälle.

23:57.210 --> 24:00.010
Und dementsprechend haben halt unterschiedliche Forscher

24:02.870 --> 24:07.510
unterschiedliche Muster für mögliche Übergänge vorgeschlagen, die dann

24:07.510 --> 24:10.670
halt Einfluss darauf haben, wie glatt so etwas aussieht.

24:10.670 --> 24:15.670
So, der Standardfall ist dieser symmetrische, dieses symmetrische

24:15.670 --> 24:16.030
Muster.

24:16.870 --> 24:20.210
Das hat erstmal als solches noch keine Einschränkungen in dem Sinne,

24:20.610 --> 24:24.310
als dass ich da beliebig viele Auslassungen und Einfügungen machen

24:24.310 --> 24:24.530
kann.

24:24.610 --> 24:26.670
Das ist das gleiche wie dann bei der Editierdistanz.

24:27.550 --> 24:30.930
Dann gibt es manchmal so komische Muster, dass ich also diesen,

24:31.910 --> 24:34.670
entweder so einen Editierdistanzschritt machen kann, oder ich kann

24:34.670 --> 24:38.670
nochmal so einen Doppelschritt machen, dass ich hier diagonal und hoch

24:38.670 --> 24:38.910
gehe.

24:38.910 --> 24:45.430
Der Herr Barkes hat sozusagen zugelassen, dass man ein oder zwei, also

24:45.430 --> 24:48.950
dass man nicht dieses auslöscht, sondern dass man diesen extrem

24:48.950 --> 24:50.270
diagonalen Schritt macht.

24:50.990 --> 24:54.370
Dann der Herr Itakura hat halt gesagt, okay, ich darf halt nicht

24:54.370 --> 24:58.330
zweimal hintereinander so einen Auslöschungsschritt machen.

24:58.910 --> 25:00.290
Dann gibt es manchmal solche Dinge.

25:00.690 --> 25:03.330
Und manchmal fängt man auch noch an zu gewichten, weil man ist ja

25:03.330 --> 25:04.370
relativ frei.

25:04.550 --> 25:08.430
Man darf ja die Strafen für Auslöschungen und Einfügungen wählen, wie

25:08.430 --> 25:12.970
man will, dass man halt manche Schritte, so

25:12.970 --> 25:18.390
Auslöschungseinführungsschritte halt stärker bestraft, als andere

25:18.390 --> 25:20.570
Auslöschungs - oder Einführungsschritte.

25:24.810 --> 25:30.330
Man kann das auch mit globalen Einschränkungen reden, arbeiten.

25:31.070 --> 25:34.230
Also man kann zum Beispiel sagen, okay, ich möchte halt das Anfang und

25:34.230 --> 25:35.870
Ende immer aufeinander abgebildet werden.

25:35.870 --> 25:40.690
Und ansonsten soll ich mich irgendwo in der Nähe der Diagonalen

25:40.690 --> 25:41.350
aufhalten.

25:41.850 --> 25:46.090
Und dann kann man anfangen, mit so Geraden zu arbeiten, die man da

25:46.090 --> 25:50.110
halt reinlegt, dass ich halt so erstmal den Bereich begrenze, dann da

25:50.110 --> 25:53.490
hinten den Bereich begrenze und das spiegle ich nach oben noch und

25:53.490 --> 25:57.230
sage dann, meine Pfade, die gültig sind, die sollen alle irgendwie in

25:57.230 --> 26:00.130
diesem schraffierten Bereich liegen.

26:00.830 --> 26:04.470
Wenn man solche Einschränkungen einführt, hat das halt auch den

26:04.470 --> 26:06.150
Folter, dass das die Rechenzeit verringert.

26:06.390 --> 26:08.950
Weil ich muss nicht mehr die ganzen Matrix ausfüllen, weil die nicht

26:08.950 --> 26:12.210
mehr gültig ist, sondern ich muss nur noch den Bereich der Matrix

26:12.210 --> 26:16.770
ausfüllen, der da entsprechend schraffiert ist.

26:17.270 --> 26:21.670
Das heißt, das ist der einzige Bereich der Matrix, den ich ausfüllen

26:21.670 --> 26:21.950
muss.

26:24.890 --> 26:29.670
Wie gesagt, je nachdem, was man da macht, hat man halt das Problem,

26:29.670 --> 26:33.830
klar, Stille führt zu diesen eckigen Stücken.

26:33.990 --> 26:36.810
Wenn ich mittendrin Stille habe, dann führt das darin, dass ich eben

26:36.810 --> 26:38.750
diese großen Sprünge habe.

26:39.430 --> 26:43.230
Und jetzt muss ich halt mir überlegen, was will ich maximal an Stille,

26:43.310 --> 26:44.650
an solchen Sprüngen zulassen.

26:46.110 --> 26:48.750
Ansonsten, wenn das halt passiert, mache ich halt eventuell einen

26:48.750 --> 26:49.030
Fehler.

26:51.110 --> 26:56.090
Und wenn die Aufnahmen von der Länge her zu stark abweichen und ich

26:56.090 --> 27:03.110
diese schraffierte Flächen nur zulasse, dann kann es halt passieren,

27:03.290 --> 27:05.890
dass der eigentliche Pfad, den ich gerne hätte, außerhalb dieser

27:05.890 --> 27:10.570
Flächen verläuft und dass ich dann den korrekten Pfad halt nicht mehr

27:10.570 --> 27:11.270
finde.

27:16.900 --> 27:19.660
Andererseits kann ich damit halt beschleunigen.

27:20.100 --> 27:24.940
Also Matrix ausfüllen ist sowas wie O von n² und Anzahl der Schritte

27:24.940 --> 27:27.200
mal Anzahl der Schritte pro Zelle.

27:27.200 --> 27:32.540
Wenn ich konstante Fensterbreite mache, rund um die Diagonale lege,

27:32.860 --> 27:35.900
dann habe ich jetzt plötzlich nur noch sowas wie O von n Schritte.

27:36.480 --> 27:43.620
Das macht dann in der Praxis gegebenenfalls schon einen Unterschied.

27:44.620 --> 27:49.160
Jetzt kann man statt so einer konstanten Fensterbreite auch sich immer

27:49.160 --> 27:54.820
wieder lokal neu, wenn man expandiert hat, überlegen, okay, wie suche

27:54.820 --> 27:57.940
ich weiter ab, basierend auf dem, was ich bisher so als Optimum

27:57.940 --> 27:58.720
gefunden habe.

27:59.320 --> 28:01.040
Und das nennt man dann die Strahlsuche.

28:01.740 --> 28:05.540
Bei der Strahlsuche guckt man halt, man geht ja immer spaltenweise

28:05.540 --> 28:09.420
durch, schaut man immer, okay, was ist jetzt aktuell in dieser Spalte

28:09.420 --> 28:11.500
den kleinsten Wert, den ich habe.

28:12.000 --> 28:20.320
Und ausgehend davon expandiere ich dann nur noch Werte, die nicht

28:20.320 --> 28:23.600
sonderlich viel schlechter sind als der aktuell beste Wert.

28:23.820 --> 28:27.180
Und diese Werte expandiere ich zum Beispiel nur.

28:27.820 --> 28:31.300
Das sorgt halt dafür, dass ich auch wieder nur so eine konstante

28:31.300 --> 28:33.960
Fensterbreite habe, die ich absuche.

28:34.160 --> 28:37.280
Aber ich lege nicht fest, dass die auf der Diagonalen sein muss,

28:37.740 --> 28:41.740
sondern die kann halt von der Diagonalen irgendwie abweichen und hängt

28:41.740 --> 28:45.040
dann davon ab, wo sich im Augenblick mein Optimum befindet.

28:45.040 --> 28:51.640
Die Art und Weise kann ich halt auch die Rechenzeit runterbringen und

28:51.640 --> 28:55.560
gleichzeitig mich so ein bisschen an die Daten anpassen, um zu

28:55.560 --> 29:01.900
schauen, dass ich halt irgendwie mich von den Daten leiten lasse, was

29:01.900 --> 29:06.200
so die Form des Pfades, den ich hinterher herausbekomme, angeht.

29:06.740 --> 29:10.060
Das garantiert mir natürlich auch nicht, dass ich den kürzesten Pfad

29:10.060 --> 29:16.140
finde, aber ich kann immerhin einen guten Pfad finden in annehmbarer

29:16.140 --> 29:16.840
Rechenzeit.

29:17.300 --> 29:21.120
Wenn es jetzt darum geht, festzulegen, wie mache ich dann dieses

29:21.120 --> 29:21.500
Strahl?

29:21.600 --> 29:25.540
Also wie betrachte ich ausgehend von dem aktuell Besten in der

29:25.540 --> 29:30.880
aktuellen Spalte, welche anderen Felder betrachte ich denn noch?

29:30.980 --> 29:33.920
Expandiere ich denn noch mit den zulässigen Schritten, die mir

29:33.920 --> 29:37.220
vorgegeben sind durch mein DTW-Schrittmuster?

29:37.220 --> 29:40.680
Dann gibt es im Prinzip zwei Varianten.

29:41.000 --> 29:44.460
Das eine ist die relative Strahlbreite und das andere ist die absolute

29:44.460 --> 29:45.260
Strahlbreite.

29:45.740 --> 29:49.140
Bei der relativen Strahlbreite sagt man halt, ich schaue mir alle

29:49.140 --> 29:54.500
Felder an, die nicht mehr als n Prozent schlechter sind, als das, was

29:54.500 --> 29:55.540
ich im Augenblick habe.

29:56.400 --> 29:59.600
Und bei der absoluten Strahlbreite sagt man, ich schaue mir nur die

29:59.600 --> 30:04.200
Felder an, die maximal n absolut schlechter sind, als der aktuell

30:04.200 --> 30:05.840
beste Wert.

30:08.380 --> 30:12.500
Oder ich kann das Ganze dann noch kombinieren mit so einer Obergrenze,

30:12.660 --> 30:16.640
so einem Cap, dass ich sage, alle die, die mir der relative oder der

30:16.640 --> 30:23.180
absolute Strahl vorgeben, aber maximal 20 oder maximal 10.

30:24.280 --> 30:27.260
Und auf die Art und Weise hat man zumindest eine Obergrenze, der

30:27.260 --> 30:31.880
Anzahl der Zellen, die man ausfüllen muss in jedem Zeitschritt.

30:32.620 --> 30:36.700
Und gleichzeitig, wenn irgendwie die Daten vorgeben, okay, man kann

30:36.700 --> 30:39.800
auch schärfer entscheiden, oder es scheint so, dass man schärfer

30:39.800 --> 30:42.660
entscheiden könnte, dann kann ich auch noch schneller sein als das,

30:42.720 --> 30:45.340
was mir maximal durch diese Obergrenze vorgegeben wird.

30:47.600 --> 30:51.200
Dann muss man sich noch ein bisschen überlegen, was gibt es so an

30:51.200 --> 30:54.420
Möglichkeiten, an Distanzen zwischen diesen beiden Vektoren, die aus

30:54.420 --> 30:56.400
der Vorverarbeitung rausgepurzelt sind.

30:56.940 --> 30:59.200
Wie gesagt, das Einfachste, was man kennt, ist sowas wie eine

30:59.200 --> 31:00.200
euclidische Distanz.

31:01.720 --> 31:04.640
Noch einfacher wäre sowas wie eine City-Block-Metrik, wird gerne in

31:04.640 --> 31:06.980
den Wirtschaftswissenschaften verwendet.

31:07.520 --> 31:11.260
Oder es gibt auch zum Beispiel sowas wie die Mahanalobes-Distanz.

31:11.780 --> 31:17.180
Wenn ich also zwei mehrdimensionale Vektoren X und Y habe, und ich tue

31:17.180 --> 31:21.940
so, als seien die das Ergebnis eines Zufallsprozesses gewesen, und

31:21.940 --> 31:26.440
diese Zufallsvariable habe gerade eine Varianz, beziehungsweise eine

31:26.440 --> 31:34.580
Kovarianz S, dann kann ich sowas ausrechnen wie die Wurzel aus Distanz

31:34.580 --> 31:41.040
X -Y mal dem Inversen der Kovarianzmatrix mal X-Y wieder der Distanz.

31:45.320 --> 31:50.380
Falls jetzt hier S die Einheitsmatrix wäre, also falls ich keine

31:50.380 --> 31:53.560
Kovarianzen habe, sondern nur eine Varianz innerhalb der jeweiligen

31:53.560 --> 31:58.840
Dimension, aber die nicht irgendwie zusammenhängt mit den Varianzen in

31:58.840 --> 32:02.460
der anderen Dimension, dann kommt halt gerade wieder die euklidische

32:02.460 --> 32:03.260
Distanz heraus.

32:03.440 --> 32:07.740
Wenn ich jetzt hier diese Kovarianzmatrix einfüge, kann ich halt auch

32:07.740 --> 32:14.380
solche Effekte berücksichtigen, dass ich so gewisse Varianzen habe, wo

32:14.380 --> 32:18.640
das bei den einzelnen Dimensionen in ihrer Varianz miteinander

32:18.640 --> 32:19.360
zusammenhängt.

32:20.280 --> 32:23.560
Und das hier ist etwas, das Sie alle im Prinzip mehr oder weniger

32:23.560 --> 32:24.940
schon so gesehen haben.

32:25.360 --> 32:29.060
Das ist nämlich das Gleiche wie bei der Multivariaten-Gauss

32:29.060 --> 32:29.640
-Verteilung.

32:30.240 --> 32:33.940
Das ist mehr oder minder das, was oben im Exponenten steht.

32:34.620 --> 32:37.160
Da ist halt keine Wurzel dabei.

32:37.840 --> 32:41.520
Was aber dabei ist, dass dann einer der beiden Vektoren wird halt zum

32:41.520 --> 32:42.320
Mittelwertsvektor.

32:43.060 --> 32:47.660
Und wenn ich halt dann den Wert eines Vektors X einer Multivariaten

32:47.660 --> 32:51.440
-Gauss -Verteilung auswerte, dann rechne ich im Prinzip

32:51.440 --> 32:57.240
Normierungsfaktor 1 durch Wurzel 2 Pi n d und dann noch ein bisschen

32:57.240 --> 33:02.920
Determinant in der Kovarianzmatrix rein, mal e hoch, mal analoges

33:02.920 --> 33:06.640
Distanz zum Mittelwertsvektor dieser Multivariaten-Gauss-Glocke.

33:07.620 --> 33:11.120
Das sind so typische Distanzmaße, die man verwenden kann.

33:11.120 --> 33:13.920
Und man kann einfach auf den Daten ausprobieren, was funktioniert am

33:13.920 --> 33:14.260
besten.

33:14.700 --> 33:17.120
Und dann wird man halt manchmal rausfinden, manchmal das eine,

33:17.300 --> 33:17.940
manchmal das andere.

33:19.540 --> 33:24.260
Wenn ich jetzt dieses Verfahren des DTWs mal einordnen möchte in

33:24.260 --> 33:28.780
dieses Klassifikationsschema, das wir letzte Woche geschaut haben.

33:29.520 --> 33:33.340
Ist so was DTW als Klassifikationsverfahren, ist das ein überwachtes

33:33.340 --> 33:34.940
oder ist es ein unüberwachtes Verfahren?

33:39.970 --> 33:44.930
Es ist ein überwachtes, weil wir haben Referenzmuster und vergleichen

33:44.930 --> 33:47.930
halt die Distanz zu diesen Referenzmustern und diese Referenzmuster

33:47.930 --> 33:51.950
haben halt das Wort, für das sie stehen, als Label mit dabei.

33:52.850 --> 33:56.570
Ist das Ganze parametrisch oder nicht parametrisch?

33:57.270 --> 34:00.150
Und wenn es parametrisch oder nicht parametrisch heißt, das erste, was

34:00.150 --> 34:03.330
man dann denken muss, dann muss man sich die Frage stellen, ist das

34:03.330 --> 34:08.710
Ganze ein statistisches oder nicht statistisches Verfahren?

34:09.470 --> 34:12.550
Und dann ist es parametrisch oder nicht parametrisch?

34:16.440 --> 34:19.500
Ist es ein statistisches oder nicht statistisches Verfahren?

34:22.910 --> 34:24.610
Wäre es für nicht statistisch?

34:26.510 --> 34:28.630
Wer ist für statistisch?

34:30.830 --> 34:32.790
Ein paar, die zögern.

34:33.710 --> 34:36.650
Wenn statistisch, wäre parametrisch oder nicht parametrisch?

34:41.000 --> 34:42.020
Wer ist für parametrisch?

34:42.880 --> 34:44.200
Wer ist für nicht parametrisch?

34:44.920 --> 34:48.420
Das ist eine gemeine Frage, das kommt drauf an.

34:48.420 --> 34:52.140
Wenn man also erstmal so drauf guckt, sind es ja eigentlich erstmal

34:52.140 --> 34:52.920
Distanzen.

34:53.580 --> 34:55.240
Da ist erstmal noch keine Wahrscheinlichkeit.

34:56.140 --> 35:00.760
Nur wenn ich darauf gucke und ich schon weiß, das hängt irgendwie mit

35:00.760 --> 35:04.940
Gaussglocken zusammen, dann kann ich mir vorstellen, dass ich mir ja

35:04.940 --> 35:09.540
auch Distanzmaße definieren kann, die letztendlich mit

35:09.540 --> 35:11.440
Wahrscheinlichkeitsverteilungen zusammenhängen.

35:12.000 --> 35:16.280
Dass ich sozusagen mir eine Wahrscheinlichkeit berechnen kann, wie

35:16.280 --> 35:20.620
wahrscheinlich ist es denn, dass wenn ich zwei Vektoren habe, wie

35:20.620 --> 35:23.100
wahrscheinlich ist es denn, dass die aufeinander abgebildet werden.

35:24.080 --> 35:26.320
Und wenn ich so eine Wahrscheinlichkeit modellieren kann, dann kann

35:26.320 --> 35:29.980
ich die natürlich als Distanzmaß verwenden und kann die in meinem DTW

35:29.980 --> 35:30.540
reinstecken.

35:31.120 --> 35:33.960
Und je nachdem, wie ich jetzt diese Wahrscheinlichkeit modelliere,

35:34.140 --> 35:38.580
dass zwei Vektoren aufeinander abgebildet werden, kann ich das halt

35:38.580 --> 35:40.460
parametrisch oder nicht parametrisch machen.

35:41.160 --> 35:45.060
Das heißt, ob es jetzt parametrisch oder nicht parametrisch ist,

35:45.060 --> 35:49.000
statistisch oder nicht statistisch ist, das hängt jetzt ganz stark

35:49.000 --> 35:51.940
davon ab, was für ein Distanzmaß verwende ich.

35:52.580 --> 35:55.140
Und das Interessante ist, wenn man das jetzt aus der Geschichte her

35:55.140 --> 35:57.720
betrachtet, man hat halt angefangen bei der Spracherkennung mit diesem

35:57.720 --> 36:03.260
DTW -Verfahren und hat sich immer wieder aufgehängt an dem Problem,

36:03.620 --> 36:06.140
ich weiß ja nicht, welchen Vektor ich auf welchem anderen Vektor

36:06.140 --> 36:06.600
abbilde.

36:07.260 --> 36:10.540
Ich weiß nicht, wie lange so ein Wort ausgesprochen wird, wenn ich

36:10.540 --> 36:13.780
Wortfolgen erkenne, ich weiß nicht, wo Wortgrenzen sind.

36:13.780 --> 36:17.700
Da ist man immer wieder daran gestoßen, dass das offensichtlich das

36:17.700 --> 36:19.300
wichtige Problem ist.

36:19.840 --> 36:22.640
Und je mehr man daran gearbeitet hat, desto mehr ist man dazu

36:22.640 --> 36:26.800
übergegangen, von diesen Distanzen hinwegzugehen zu eigentlichen

36:26.800 --> 36:30.380
echten Wahrscheinlichkeiten, bis man dann irgendwann wirklich den

36:30.380 --> 36:33.560
Schritt gemacht hat, dass man weggegangen ist von diesen sturen

36:33.560 --> 36:36.960
Mustervergleichen hin zu einem rein statistischen Verfahren.

36:37.520 --> 36:40.180
Das war nicht so etwas, wo sich einer hingesetzt hat und gesagt hat,

36:40.320 --> 36:43.060
jetzt überlege ich mir mal, wie ich das grundsätzlich mache, mache ich

36:43.060 --> 36:46.260
es grundsätzlich statistisch oder nicht statistisch, sondern man hat

36:46.260 --> 36:48.440
halt damit mal angefangen und hat weitergearbeitet und

36:48.440 --> 36:51.040
weitergearbeitet und weitergearbeitet und es wurde halt immer

36:51.040 --> 36:53.960
statistischer, statistischer, bis man hinterher irgendwie bei den ganz

36:53.960 --> 36:56.460
statistischen Verfahren angekommen ist.

36:59.000 --> 37:02.420
Gut, also für einzelne Wörter fassen wir zusammen, wenn ich jetzt

37:02.420 --> 37:06.820
Einzelworterkennung machen möchte mit so einem DTW, ganz einfach nur

37:06.820 --> 37:10.540
basierend auf der Vorverarbeitung, die bei dem Wort rauskommt, da muss

37:10.540 --> 37:13.720
ich halt für jedes Wort in meinem Vokabular, das ich möchte erkennen

37:13.720 --> 37:18.420
können, ein Referenzmuster abspeichern und dann wird immer paarweise

37:18.420 --> 37:24.620
per DTW die Distanz zwischen Referenzmuster und Aufnahme ausgerechnet

37:25.840 --> 37:31.680
und ich erkenne das, wo die Distanz nach dem DTW am kleinsten ist.

37:32.920 --> 37:35.060
Jetzt kann ich das Ganze noch komplizierter machen.

37:35.180 --> 37:37.260
Jetzt kann ich sagen, okay, ich habe für jedes Wort in meinem

37:37.260 --> 37:41.140
Vokabular nicht ein Referenzmuster, sondern mehrere Referenzmuster.

37:41.720 --> 37:44.260
Jetzt gucke ich halt immer noch, was ist das Kleinste zwischen

37:44.260 --> 37:48.260
Referenzmuster und Aufnahme und dann zu welchem Referenzmuster gehört

37:48.260 --> 37:51.760
denn das Wort und es können halt mehrere Referenzmuster zu dem Wort

37:51.760 --> 37:52.100
gehören.

37:52.760 --> 37:55.240
Oder wenn ich es halt scheue, dass ich dadurch, sagen wir mal, wenn

37:55.240 --> 37:58.900
ich fünf Referenzmuster pro Wort habe, dann habe ich auch fünfmal so

37:58.900 --> 38:01.900
viel Rechenaufwand, weil ich gegen fünfmal so viele Referenzmuster

38:01.900 --> 38:02.580
vergleichen muss.

38:02.660 --> 38:04.360
Ich muss fünfmal so viele Daten sammeln.

38:04.360 --> 38:05.720
Gut, das muss ich halt.

38:05.820 --> 38:10.620
Aber was ist, wenn ich diesen Rechenaufwand fünfmal mehr verhindern

38:10.620 --> 38:12.000
möchte, vermeiden möchte?

38:12.400 --> 38:14.200
Da könnte man sich natürlich auch vorstellen, dass man irgendwie

38:14.200 --> 38:17.740
Mittelwerte zwischen Referenzmustern berechnet.

38:18.600 --> 38:21.820
Wie kann ich so einen Mittelwert zwischen Referenzmustern berechnen?

38:21.900 --> 38:24.160
Weil die sind ja unter Umständen unterschiedlich lang und

38:24.160 --> 38:25.280
unterschiedliche Geschwindigkeit.

38:25.700 --> 38:28.280
Da muss ich halt zwischen allen Referenzmustern halt ein DTW

38:28.280 --> 38:31.880
ausrechnen und dann wird die halt... dann habe ich eine Zuordnung der

38:31.880 --> 38:34.380
Vektoren zueinander und dann kann ich immer vektorweise einen

38:34.380 --> 38:36.940
Mittelwert bilden und dann kommen immer mehr Referenzmuster dazu.

38:37.440 --> 38:39.280
Das ist zum Beispiel eine Art und Weise, wie man so einen Mittelwert

38:39.280 --> 38:40.720
bilden kann.

38:42.080 --> 38:45.220
Und dann kann ich mir halt zig Variationen ausdenken.

38:45.340 --> 38:48.600
Okay, wenn ich halt mehrere Referenzmuster pro Wort habe, entweder ich

38:48.600 --> 38:52.080
entscheide mich immer für das nächstgelegene oder für jedes Wort

38:52.080 --> 38:55.160
berechne ich den Durchschnitt der Distanzen für alle Referenzmuster

38:55.160 --> 38:58.940
und entscheide mich dann da für das Wort, wo halt dieser Durchschnitt

38:58.940 --> 39:03.540
dieser Distanzen am kleinsten ist oder ich, wie gesagt, gucke halt nur

39:03.540 --> 39:05.780
das am nahesten gelegene Referenzmuster.

39:06.540 --> 39:09.460
Oder ich kann halt sowas machen, dass ich die Varianz aus den

39:09.460 --> 39:13.700
Referenzmustern zu einem Wort berechne und dann kann ich zum Beispiel

39:13.700 --> 39:19.000
mit einer Mahanalobes-Distanz mir wieder eine Distanz zwischen dem

39:19.000 --> 39:23.060
normalen Muster und den allen Referenzmustern, die zu einem Wort

39:23.060 --> 39:24.680
gehören, berechnen.

39:27.160 --> 39:31.940
Wenn ich ein sehr kleines Vokabular habe und wenn die Spracherkennung

39:31.940 --> 39:35.420
sprecherabhängig ist und ich nur ganz wenig Rechenressourcen zur

39:35.420 --> 39:39.680
Verfügung habe, dann ist das nach wie vor ein sinnvolles Vorgehen.

39:41.940 --> 39:47.140
Zum Beispiel hatten wir, also früher, als Sie alle noch nicht geboren

39:47.140 --> 39:50.060
waren und ich noch mit so einem Handy durch die Gegend gelaufen bin

39:50.060 --> 39:53.320
und so weiter und so fort und alles früher besser war, da war das

39:53.320 --> 39:57.320
durchaus ein übliches Verfahren, um zum Beispiel Spracherkennung auf

39:57.320 --> 39:58.160
einem Handy zu machen.

39:58.260 --> 40:02.160
Da gab es halt die Handys, wo man halt per Worteingabe wählen konnte.

40:02.320 --> 40:06.880
Da hat man halt gesagt, ruf Willi an und dann hat er halt Willi

40:06.880 --> 40:09.520
erkannt mithilfe so eines Mustervergleiches.

40:09.600 --> 40:13.340
Da musste man halt vorher dreimal für den Kontakt im Wörterbuch halt

40:13.340 --> 40:13.940
Willi sagen.

40:14.080 --> 40:15.200
Dann hat er halt Willi aufgenommen.

40:15.320 --> 40:18.260
Wenn ich das nächste gesagte Mal Willi gerufen habe, dann hat er halt

40:18.260 --> 40:21.980
das Wort aus dem Telefonbuch gewählt.

40:22.680 --> 40:24.720
Das sind halt ein paar Dutzend Wörter, die ich da vielleicht

40:24.720 --> 40:26.620
reingesprochen habe von unterschiedlichen Namen.

40:27.200 --> 40:31.200
Das ist relativ einfach dann zu machen.

40:31.500 --> 40:36.180
Aber die Handys, die hatten halt auch keine große Rechenkapazität.

40:36.320 --> 40:37.460
Das hat nicht so gut funktioniert.

40:38.380 --> 40:41.900
Das ist aber durchaus auch heute noch sinnvoll in den glorreichen

40:41.900 --> 40:45.500
Zeiten des Hochleistungsrechners in der Tasche.

40:46.260 --> 40:51.240
Wir hatten jetzt vor kurzem eine Bachelorarbeit.

40:51.380 --> 40:53.340
Das war so vor anderthalb Jahren.

40:53.820 --> 40:56.060
Da hat er das für einen Raspberry Pi gemacht.

40:56.880 --> 41:00.520
Und da, wenn man jetzt so naiv auf dem Raspberry Pi programmiert und

41:00.520 --> 41:04.140
das Ganze soll in Echtzeit laufen und so weiter und so fort, dann

41:04.140 --> 41:07.300
kommt man mit den aktuellen modernen Verfahren nicht wirklich weit.

41:07.760 --> 41:11.340
Und seine Idee war halt, er hätte gerne, dass sein Raspberry Pi auf

41:11.340 --> 41:13.760
akustische Signale reagiert.

41:13.760 --> 41:15.200
Das war jetzt nicht unbedingt Sprache.

41:15.380 --> 41:18.940
Es konnten solche Sachen sein, wie es läutet an der Tür oder die

41:18.940 --> 41:22.340
Mikrowelle piepst oder das Telefon läutet, weil er hatte halt gerne

41:22.340 --> 41:23.560
Computerspiele gespielt.

41:23.700 --> 41:26.900
Und wenn er dann das Headset auf hatte und mittendrin in irgendeinem

41:26.900 --> 41:30.540
Massaker war und der Pizzabote hat geklingelt, dann wollte er bitte

41:30.540 --> 41:33.980
von seinem Raspberry Pi nachrichtigt werden, dass es gerade an der Tür

41:33.980 --> 41:35.940
geklingelt hat und er doch bitte aufmachen möge.

41:38.580 --> 41:41.780
Und der ist zwar schon relativ leistungsstark, aber wenn man jetzt

41:41.780 --> 41:45.960
nochmal kontinuierlich solche akustischen Events klassifizieren muss,

41:46.300 --> 41:48.080
dann hat es dafür nicht ganz ausgereicht.

41:48.440 --> 41:52.480
Dann war, nachdem man die Vorverarbeitung so erstmal naiv durchgeführt

41:52.480 --> 41:55.520
hatte, so eine spektrumsbasierte Vorverarbeitung, so mit

41:55.520 --> 41:58.680
Kurzzeitspektrananalyse und man will das Ganze in Echtzeit machen,

41:58.760 --> 42:01.100
dann war nicht mehr viel Rechenzeit übrig, die man zur Verfügung

42:01.100 --> 42:05.140
hatte, nachdem die Vorverarbeitung schon durchgelaufen war.

42:05.360 --> 42:08.340
Und dann konnte er halt nicht mit so ganz komplizierten Verfahren, wie

42:08.340 --> 42:10.760
wir sie dann bei der Spracherkennung verwenden, ankommen, sondern dann

42:10.760 --> 42:14.020
hat er angefangen, mit solchen Sachen wieder rumzuexperimentieren,

42:14.180 --> 42:17.540
Varianten davon, und hat das damit eigentlich ganz gut hinbekommen.

42:18.020 --> 42:21.620
Das heißt auch, wenn das Ganze eigentlich Historie ist, behalten Sie

42:21.620 --> 42:24.600
es im Hintergrund, zum einen als Motivation dafür, wie wir es wirklich

42:24.600 --> 42:29.380
machen, zum anderen, wenn Sie irgendwas Embedded machen, kann es sein,

42:29.460 --> 42:32.120
dass Sie dann auch trotzdem nochmal in der heutigen Zeit in eine

42:32.120 --> 42:35.240
Situation kommen, wo Sie nicht genügend Rechenzeit zur Verfügung

42:35.240 --> 42:39.260
haben, aber wenn die Spracherkennungsaufgabe klein genug und leicht

42:39.260 --> 42:42.820
genug ist, können Sie immer noch zur Not mit solchen Dingen da was

42:42.820 --> 42:43.100
machen.

42:45.000 --> 42:48.560
Jetzt ist die Frage, was machen wir denn, wenn wir nicht nur ein

42:48.560 --> 42:52.200
einzelnes Wort oder eine einzelne Phrase erkennen wollen, sondern was

42:52.200 --> 42:55.400
ist, wenn wir beliebige Sequenzen von Wörtern erkennen wollen?

42:56.440 --> 43:01.340
Und wenn man beliebige Sequenzen von Wörtern erkennen will, hat man

43:01.340 --> 43:07.920
dieses Dynamic Time Warping erweitert zum Algorithmus, zum Prinzip des

43:07.920 --> 43:10.760
sogenannten One-Stage Dynamic Programming.

43:12.560 --> 43:19.280
Und die Idee ist, dass man solche DTW-Fade von einzelnen erkannten

43:19.280 --> 43:23.520
Wörtern verknüpft mit neuen DTW-Faden.

43:24.360 --> 43:29.020
Die Idee ist also, dass wann immer ich mit einem Wort fertig bin, wenn

43:29.020 --> 43:32.780
ich also in so einem Endzustand eines Wortes bin, dann ist als

43:32.780 --> 43:37.440
nächster möglicher Übergang auch der, dass ich in den Anfang eines

43:37.440 --> 43:39.720
neuen Wortes reinspringen kann.

43:40.560 --> 43:41.920
Und das macht man halt so.

43:43.160 --> 43:47.040
Unten auf der Achse sind nach wie vor die Referenzvektoren meiner

43:47.040 --> 43:52.600
Aufnahme und auf der vertikalen Achse kommt erst die Referenzvektoren

43:52.600 --> 43:56.040
des ersten Wortes, dann dicker fetter Strich, dann kommen die

43:56.040 --> 43:59.240
Referenzvektoren des zweiten Wortes, dicker fetter Strich,

43:59.360 --> 44:01.040
Referenzvektoren des dritten Wortes.

44:01.040 --> 44:05.320
Und innerhalb so eines Wortes habe ich halt das typische DTW

44:05.320 --> 44:09.420
-Übergangsmuster und wenn ich am Ende eines Wortes bin, also das hier

44:09.420 --> 44:13.320
ist der Endzustand eines Wortes, dann kann ich auch noch normal

44:13.320 --> 44:15.940
weitermachen, dann heißt das einfach nur, dass ich jetzt halt noch

44:15.940 --> 44:21.480
mehr Vektoren aus der Aufnahme zum Beispiel lösche oder ich kann halt

44:21.480 --> 44:26.800
den Sprung machen hin zu dem Anfangszustand eines neuen Wortes.

44:26.800 --> 44:31.260
Man kann sagen, okay, als zusätzlichen Schritt lasse ich zu, dass ich

44:31.260 --> 44:32.540
jetzt ein neues Wort anfange.

44:33.380 --> 44:36.080
Und solche Schritte, die jetzt hier zum Beispiel normalerweise

44:36.080 --> 44:39.120
senkrecht über so dicke Linien gehen, die lasse ich halt nicht zu, das

44:39.120 --> 44:39.860
darf halt nicht sein.

44:41.400 --> 44:44.920
Das sind halt sozusagen diese imaginären Wortgrenzen, wo ich die Fade

44:44.920 --> 44:46.540
innerhalb eines Wortes mal rechne.

44:49.200 --> 44:53.140
Das Ganze sieht dann also, kann man sich so vorstellen, hier ist jetzt

44:53.140 --> 44:57.540
mal eingezeichnet in schwarz nur der beste Pfad, der hinterher

44:57.540 --> 44:58.480
herausgekommen ist.

44:58.860 --> 45:02.040
Da hat sich halt herausgestellt, also parallel hat man immer die

45:02.040 --> 45:07.360
gesamten Spalten innerhalb dieser Kästchen ausgefüllt und irgendwann

45:07.360 --> 45:12.040
war man halt beim Wort B und wenn ich hier oben in der Zeile ankomme,

45:12.160 --> 45:14.920
das heißt, das ist also sozusagen der Endzustand, der letzte

45:14.920 --> 45:19.020
Referenzvektor eines Referenzwortes B, dann darf ich da anfangen,

45:19.540 --> 45:23.220
entweder in neue Wörter zu springen oder halt noch horizontal an

45:23.220 --> 45:24.360
dieser schwarzen Linie weiter.

45:24.720 --> 45:28.380
Und dann war halt der beste Pfad der, der erst dieses Wort B hatte und

45:28.380 --> 45:32.140
der dann nach oben nach D gesprungen ist, dann war der beste Pfad

45:32.140 --> 45:35.400
halt, das D weiterzumachen, dann ist er wieder zurück an den Anfang

45:35.400 --> 45:38.620
des Ds gesprungen, dann war wieder da der beste Pfad bis zum D-Ende,

45:39.100 --> 45:41.940
dann ist er runter bis zum A gesprungen und da war es halt das Beste,

45:42.380 --> 45:44.180
nachdem das A fertig war, das B aufzubauen.

45:45.340 --> 45:48.720
Trotzdem, man rechnet, wenn man jetzt nicht irgendwie Suchraum

45:48.720 --> 45:53.080
einschränkt, immer alle möglichen Pfade ab, indem man halt stur diese

45:53.080 --> 45:56.280
Matrix ausfüllt und sich für jede Zelle halt merkt, wo bin ich

45:56.280 --> 46:02.020
hergekommen, wo hätte ich herkommen können und für solche Zellen heißt

46:02.020 --> 46:05.820
es dann halt immer, ich dürfte auch von hier kommen, ich dürfte von da

46:05.820 --> 46:07.140
kommen und ich dürfte von da kommen.

46:07.620 --> 46:11.280
Das ist der neue Schritt, den man bei den DTW-Schritten jetzt halt

46:11.280 --> 46:15.380
zusätzlich zulässt und dann rechnet man ganz stur sein DTW aus.

46:15.980 --> 46:19.640
Man lässt nicht den Schritt zu, dass man halt hier über die dicken

46:19.640 --> 46:23.940
schwarzen Linien einfach so rüber gehen darf, da darf man nur drüber

46:23.940 --> 46:26.700
gehen, wenn man sozusagen am Endwort ist.

46:27.880 --> 46:33.160
Also ich darf nicht irgendwie, wenn ich zum Beispiel hier angekommen

46:33.160 --> 46:35.680
bin, dann darf ich nicht senkrecht nach da oben, weil dann wäre ich

46:35.680 --> 46:46.100
hier im Endzustand, also nach da dürfte ich nicht, ich dürfte

46:46.100 --> 46:50.000
sozusagen nur nach diagonal springen, aber nicht genau senkrecht nach

46:50.000 --> 46:50.280
oben.

46:52.900 --> 46:56.720
Und kann halt auf diese Art und Weise Spracherkennung machen für

46:56.720 --> 46:57.560
beliebige Wörter.

46:58.240 --> 47:03.160
Und das Schöne ist halt, ich mache keinerlei Annahmen darüber, wo denn

47:03.160 --> 47:06.740
jetzt bitte schön diese Grenzen der Wörter liegen.

47:07.760 --> 47:09.720
Das ist diese Beschriftung, die sehe ich nicht.

47:10.260 --> 47:14.600
Diese Beschriftung sehe ich erst, wenn der Pfad fertig ist.

47:15.040 --> 47:18.360
Erst wenn ich weiß, wo habe ich die Wortübergänge gemacht, dann kann

47:18.360 --> 47:22.200
ich die rote Linie einzeichnen und weiß, da sind meine Wortgrenzen.

47:22.680 --> 47:25.360
Wenn ich anfange, diesen Pfad zu rechnen, habe ich da unten nur eine

47:25.360 --> 47:26.200
Folge von Vektoren.

47:26.840 --> 47:29.800
Ich mache also keinerlei Annahme darüber, wo die Wortgrenzen sind,

47:29.800 --> 47:35.280
sondern die Wortgrenzen fallen ganz so nebenbei implizit ab, wenn ich

47:35.280 --> 47:37.780
das One-Stage-Dynamic-Programming durchrechne.

47:38.380 --> 47:42.200
Und das war insofern revolutionär, weil das Erste, was man gemacht

47:42.200 --> 47:46.100
hatte, ist, okay, DTW für Einzelworterkennung, jetzt will ich ganze

47:46.100 --> 47:50.720
Wortfolgen erkennen, also unterteile ich das klassisch Informatik.

47:51.480 --> 47:54.740
Erstes Problem Wortgrenzen finden, zweites Problem, wenn ich die

47:54.740 --> 47:58.460
Wortgrenzen gefunden habe, welches Wort ist denn innerhalb der Grenze.

47:58.460 --> 48:00.400
Das funktioniert nicht gut.

48:00.740 --> 48:02.540
Das funktioniert ganz und gar nicht gut.

48:03.280 --> 48:06.220
Das hat ganz schlechte Ergebnisse gebracht und als man dann

48:06.220 --> 48:10.200
übergegangen ist, diese Wortgrenzen implizit zu finden anhand der

48:10.200 --> 48:13.660
Distanzmaße, dann ist es halt angefangen, besser zu werden.

48:16.400 --> 48:20.320
Wenn man das jetzt alles noch formal schön hinschreiben möchte, muss

48:20.320 --> 48:25.260
man halt da an dieser Distanz zwischen den Iden und dem J-Vektor halt

48:25.260 --> 48:30.240
noch ein bisschen rumfummeln, indem man halt jetzt noch einen Index

48:30.240 --> 48:36.880
dafür einfügt, zu welchem Wort gehört denn jetzt der J-Referenzvektor.

48:37.420 --> 48:41.020
Und dann bekomme ich halt Zustandsfolgen, die mir halt zusätzlich noch

48:41.020 --> 48:46.740
sagen, im alten Frame, welche werden denn zugeordnet und zu welchem

48:46.740 --> 48:48.880
Wort wird das Ganze denn zugeordnet.

48:48.980 --> 48:52.260
Und dann suche ich nach wie vor wieder den Pfad mit der kleinsten

48:52.260 --> 48:54.420
aufsummierten Distanz.

48:58.580 --> 49:00.780
Okay, hier hatte ich jetzt noch eine Verständnisfrage, jetzt muss ich

49:00.780 --> 49:01.740
selber gucken.

49:02.700 --> 49:04.040
Wo ist da das Problem?

49:04.680 --> 49:07.000
Also die Zustandsfolge, die ich habe, ist halt,

49:12.080 --> 49:13.080
Wort zu welchem...

49:13.960 --> 49:21.520
Also das ist immer die Distanz dieses Trupels, bestehend aus Frame I,

49:22.220 --> 49:29.980
Frame J und K, für den elten schwarzen Punkt auf meinem DTW-Pfad.

49:31.220 --> 49:37.380
Und diesem elten Punkt wird halt immer noch zugeordnet ein Wort K.

49:37.540 --> 49:41.180
Also für jeden elten Punkt weiß ich, aus welchem Wort kommt denn der

49:41.180 --> 49:42.040
Referenzvektor.

49:45.580 --> 49:48.180
Frage ist also hier, warum ist L ungleich N?

49:48.300 --> 49:52.640
Und die gleiche Frage kann man halt auch stellen beim DTW.

49:53.360 --> 49:59.100
Wenn also L der Index ist für das wievielte Paar, wo ich eine Distanz

49:59.100 --> 50:00.120
ausgerechnet habe.

50:00.680 --> 50:05.560
Warum ist also L nicht gleich Anzahl der Frames N, die ich in meiner

50:05.560 --> 50:08.920
Beispielaufnahme habe?

50:10.260 --> 50:14.560
Es liegt halt daran, der Pfad kann halt mal auslöschen oder einfügen.

50:15.160 --> 50:19.740
Das heißt, wenn der Pfad genau linear gehen würde, und die wären alle

50:19.740 --> 50:22.280
beide gleich gelangt, dann hätte ich natürlich genauso viele Punkte

50:22.280 --> 50:25.560
auf dem Pfad, wo ich so ein paarweisen Vergleich zugenommen habe, wie

50:25.560 --> 50:27.400
ich Vektoren habe.

50:27.780 --> 50:30.320
Wenn ich es jetzt aber zulasse, dass ich auslösche oder dass ich

50:30.320 --> 50:36.300
einfüge, dann wird der Pfad halt länger als die Anzahl der Frames, die

50:36.300 --> 50:39.840
ich unten habe, beziehungsweise er kann auch kürzer werden als die

50:39.840 --> 50:41.520
Anfangs der Frames.

50:42.520 --> 50:46.800
Und man muss jetzt halt gucken, man hat jetzt an der Stelle halt zwei

50:46.800 --> 50:49.580
unterschiedliche Arten von Übergängen.

50:49.680 --> 50:54.480
Ich habe halt den Übergang innerhalb eines Referenzmusters und ich

50:54.480 --> 50:57.420
habe diesen Übergang an der Wortgrenze, den ich nur machen kann, wenn

50:57.420 --> 51:03.240
ich im letzten Vektor eines Referenzwortes bin und darf dann halt in

51:03.240 --> 51:07.220
ganz viele andere übergehen, nämlich in aller Startzellen eines

51:07.220 --> 51:10.620
anderen Wortes bei der Referenz.

51:13.560 --> 51:17.780
Und das kann ich halt mit dynamischen oder anderen Mustern machen und

51:17.780 --> 51:21.740
dann kann ich halt diese akkumulierten Distanzen halt berechnen und

51:21.740 --> 51:25.320
kann halt den Wert in jeder Zelle neu ausrechnen und muss nur

51:25.320 --> 51:30.060
berücksichtigen, dass wenn es der Anfangszustand oder die Anfangszeile

51:30.060 --> 51:33.480
eines Wortes ist, dass ich dann auch von irgendwelchen Endzuständen

51:33.480 --> 51:34.440
hätte herkommen können.

51:36.240 --> 51:41.020
Wenn man jetzt anschaut, wenn ich da jetzt die optimale Lösung

51:41.020 --> 51:43.780
ausrechne, dann hat das einen relativ hohen Aufwand.

51:44.180 --> 51:48.500
Also ich muss sehr viele solcher Matrizen ausrechnen, also die Matrix

51:48.500 --> 51:52.820
ausrechnen und n mal m mal Anzahl Schritte in der Zelle, meistens

51:52.820 --> 51:54.280
konstant, also n mal m.

51:55.280 --> 52:02.520
Und dann das Ganze noch maximal wie viele... und das dann noch k mal.

52:03.020 --> 52:06.280
Das heißt, ich suche mir also, wenn m die Anzahl der Referenzvektoren

52:06.280 --> 52:08.780
ist, wenn ich es jetzt im Okalkül abschätzen will, gucke ich, welches

52:08.780 --> 52:11.720
Referenzwort hat die meisten Frames.

52:11.820 --> 52:19.560
Das ist mein mkmax und dann ist der Aufwand also n o mal mkmax mal k.

52:21.700 --> 52:25.700
Das ist halt irgendwas kubisches, mehr oder weniger.

52:28.380 --> 52:33.060
In der Praxis ist es ein bisschen weniger, weil Wortübergang ist halt

52:33.060 --> 52:36.040
nicht immer zu jedem Zeitpunkt möglich, sondern Wortübergang ist immer

52:36.040 --> 52:38.640
noch möglich, wenn ich ans Ende reinkomme.

52:38.740 --> 52:41.620
Das heißt, die Anzahl der Übergänge variiert, je nachdem, ob ich mich

52:41.620 --> 52:44.700
innerhalb des Wortes befinde oder jetzt an der Wortgrenze.

52:45.680 --> 52:50.380
Aber man kann jetzt auch anfangen, dass man das Ganze beschleunigt.

52:51.080 --> 52:56.100
Wenn ich dieses Übergangsmuster bei der DTW-Matrix simpel halte, wenn

52:56.100 --> 52:56.680
ich also z.B.

52:56.820 --> 52:59.640
dieses, was ich als symmetrisch bezeichnet habe, wie bei der minimalen

52:59.640 --> 53:00.400
Editierdistanz.

53:00.760 --> 53:03.300
Ich kann nach oben gehen, ich kann waagerecht gehen oder ich kann

53:03.300 --> 53:04.160
diagonal gehen.

53:04.940 --> 53:09.520
Wenn ich nur so ein einfaches Muster habe, dann brauche ich z.B., wenn

53:09.520 --> 53:13.600
ich jetzt Speicher reduzieren möchte, nicht die gesamte Matrix im

53:13.600 --> 53:14.300
Speicher halten.

53:14.800 --> 53:18.380
Die Matrix kann ja als solches auch relativ groß werden.

53:19.680 --> 53:22.700
Anzahl der Referenzworte und wenn ich jetzt großes Vokabular habe,

53:23.140 --> 53:25.900
kann das eine sehr große Matrix werden, kann sehr viel Speicher

53:25.900 --> 53:26.260
brauchen.

53:27.880 --> 53:36.400
Um die aktuelle Matrix berechnen zu können, muss ich ja nur auf die

53:36.400 --> 53:38.340
vorhergehende Spalte zurückgreifen.

53:40.220 --> 53:43.480
Weil alles, was ich in der neuen Spalte ausrechne, alles, was ich

53:43.480 --> 53:48.780
brauche, ist nur den aktuellen Frame, die Referenzframes auf der

53:48.780 --> 53:53.440
waagerechten Liste und die Spalte vom Zeitpunkt vorher.

53:54.120 --> 53:56.360
Mehr brauche ich nicht, um die neue Spalte auszurechnen.

53:56.740 --> 53:59.880
Das heißt, alle Spalten, die davor waren, die vorvorletzte und so

53:59.880 --> 54:02.020
weiter, die brauche ich eigentlich gar nicht mehr im Speicher zu

54:02.020 --> 54:02.180
halten.

54:02.260 --> 54:03.500
Die interessiert mich überhaupt nicht mehr.

54:03.500 --> 54:07.340
Das heißt, ich kann erstmal das reduzieren darauf, dass ich immer nur

54:07.340 --> 54:11.540
zwei Spalten dieser ganz großen Matrix im Speicher halte.

54:12.000 --> 54:15.020
Das Einzige, was ich natürlich beachten muss, gut, ich muss mir die

54:15.020 --> 54:16.740
Rückzeiger, muss ich mir merken.

54:17.460 --> 54:21.420
Aber auch da ist es so, beim OneStage Dynamic Programming, muss ich

54:21.420 --> 54:23.880
mir ja nicht alle Rückzeiger merken.

54:25.500 --> 54:26.380
Warum nicht?

54:27.100 --> 54:31.140
Naja, mich interessiert ja beim OneStage, also beim DTW, brauche ich

54:31.140 --> 54:34.060
mir eigentlich gar keine Rückzeiger zu merken, weil mich interessiert

54:34.060 --> 54:36.260
ja nicht, welcher Frame wurde auf welchen abgebildet, mich

54:36.260 --> 54:37.400
interessiert nur die Distanz.

54:37.840 --> 54:39.140
Da kann ich mir die Rückzeiger schenken.

54:39.960 --> 54:43.040
Beim OneStage Dynamic Programming will ich jetzt also Wortfolgen

54:43.040 --> 54:43.460
erkennen.

54:44.200 --> 54:48.820
Und da interessiert mich ja jetzt nicht, in welcher, welcher Frame

54:48.820 --> 54:52.480
wurde auf welchem abgebildet, sondern mich interessiert nur noch, wann

54:52.480 --> 54:55.340
wurde ein Wortübergang gemacht auf dem DTW-Fort.

54:55.740 --> 54:57.400
Und nur das muss ich mir merken.

54:57.520 --> 55:00.820
Ich muss mir nur merken, wenn ich einen Wortübergang mache, das muss

55:00.820 --> 55:04.740
ich mir abspeichern und diese, das sind die einzigen Rückzeiger, die

55:04.740 --> 55:08.200
ich mir dann vom Ende her merken muss und das kann ich so als so eine

55:08.200 --> 55:10.480
Linked List mir hinschreiben.

55:10.600 --> 55:13.040
Da brauche ich dann nicht so eine ganz große Matrix, sondern eine viel

55:13.040 --> 55:18.300
kürzere Linked Listen für jeder einzelne Wert in der aktuellen Spalte,

55:18.740 --> 55:21.500
der mir halt sagt, von welchen Wörtern bin ich denn vorher mal

55:21.500 --> 55:21.860
gekommen.

55:22.700 --> 55:26.740
Und wenn halt so ein Wort nur alle 10 Frames kommt, dann spare ich da

55:26.740 --> 55:30.140
ein Zehntel halt der Rückzeiger, die ich theoretisch haben könnte,

55:30.140 --> 55:32.480
oder sogar noch mehr entsprechend ein.

55:33.280 --> 55:38.760
Und wenn ich jetzt wirklich nur diese Dreiersache habe, dann kann ich

55:38.760 --> 55:41.780
das Ganze auf die Spitze treiben, weil dann reicht mir nur eine

55:41.780 --> 55:42.240
Spalte.

55:42.740 --> 55:46.960
Weil die Spalte, die rechne ich von unten aus und wenn ich also den

55:46.960 --> 55:53.600
unteren Wert ersetze, dann kann ich mir den löschen, dann muss ich mir

55:53.600 --> 55:58.640
nur noch den im Speicher sozusagen halten, was war der unterste, der

55:58.640 --> 56:03.160
vorletzte Wert und alles, was da drunter war, das kann ich vergessen.

56:03.840 --> 56:05.580
Alles, was links war, kann ich auch vergessen.

56:05.700 --> 56:09.980
Das heißt, wenn ich es also geschickt anstelle, reicht es, wenn ich

56:09.980 --> 56:13.740
diese Spalte von oben nach unten ausfülle.

56:14.600 --> 56:17.840
Weil dann überschreibe ich nichts, weil es ich nicht nochmal brauche,

56:17.920 --> 56:21.020
weil ich halt von oben nicht runtergehen kann.

56:21.460 --> 56:24.780
Das heißt also, wenn ich es geschickt anstelle, reicht es sogar, wenn

56:24.780 --> 56:29.420
ich nur eine Spalte von dieser OneStage Dynamic Programming im

56:29.420 --> 56:37.540
Speicher bereite und mir halt diese Rückzeiger als so eine verlinkte

56:37.540 --> 56:42.660
Liste jeweils abspeichere.

56:48.910 --> 56:52.210
Was man dann gemacht hat, als nächstes festgestellt hat, ist, dass man

56:52.210 --> 56:57.150
Probleme damit bekommt, dass man ja keinerlei Wissen darüber

56:57.150 --> 57:01.850
einfließen lässt, welche Wortfolgen sind überhaupt zulässig in einer

57:01.850 --> 57:02.870
Sprache oder nicht.

57:03.850 --> 57:07.250
Wenn ich jetzt die Rechenzeit einschränken will und gleichzeitig

57:07.250 --> 57:10.130
robuster werden will gegen Fehler, die ich mache, wenn ich jetzt

57:10.130 --> 57:14.850
diesen kürzesten Pfad berechne, dann kann ich ja zusätzliches Wissen

57:14.850 --> 57:19.150
mit hinzunehmen, dass es Wortfolgen gibt, die sind zulässig oder

57:19.150 --> 57:22.810
zumindest wahrscheinlich und dass es Wortfolgen gibt, die wird es nie

57:22.810 --> 57:23.610
im Leben geben.

57:24.290 --> 57:27.450
Wenn wir zurückdenken, wir hatten ja mal so eine Auflistung gemacht,

57:27.450 --> 57:32.890
so unterschiedliche Arten von Spracherkennung an der Art der Sprache

57:32.890 --> 57:33.590
festgemacht.

57:33.850 --> 57:37.610
Und da gab es halt so Einzelworterkennung, künstliche Sprachen, wo ich

57:37.610 --> 57:40.910
halt irgendeine Grammatik vorgebe oder natürliche Sprachen.

57:41.390 --> 57:43.750
Wenn ich jetzt, sagen wir mal, zumindest irgendeine Grammatik

57:43.750 --> 57:46.950
vorgegeben habe, die mir Muster vorgibt, was ich gesprochen werden

57:46.950 --> 57:50.910
darf und was nicht, dann gibt es jetzt eine relativ einfache Art und

57:50.910 --> 57:54.450
Weise, das in dieses One-Stage-Dynamic-Programming mit reinzubringen.

57:54.450 --> 57:59.250
Die Idee ist nämlich, dass ich mir für jedes neue Wort, in das ich

57:59.250 --> 58:04.290
reingehen kann, abspeichere nur noch eine Liste von erlaubten

58:04.290 --> 58:07.770
Vorgängerwörtern, die mir halt meine künstliche Sprache, meine

58:07.770 --> 58:08.990
Grammatik vorgegeben hat.

58:09.410 --> 58:14.570
Das heißt, ich rechne also nicht mehr aus, von jedem möglichen Wort in

58:14.570 --> 58:17.550
meinem Vokabular kann ich jetzt in den Anfang des Wortes reingehen,

58:17.870 --> 58:21.910
sondern ich schränke das ein auf nur noch eine Liste von erlaubten

58:21.910 --> 58:22.510
Vorgängern.

58:22.510 --> 58:26.010
Nennen wir sie halt p von k, die Menge der erlaubten Vorgänger für das

58:26.010 --> 58:26.610
k -te Wort.

58:30.730 --> 58:33.850
Manchmal hätte man es gerne ein bisschen komplizierter, manchmal hätte

58:33.850 --> 58:37.390
man gerne, dass man da irgendwie so eine Art von Zustand drin hat.

58:37.990 --> 58:43.210
Wenn ich also im Zustand so und so bin, ist das die Menge der

58:43.210 --> 58:46.010
erlaubten Vorgänger, wenn ich in einem anderen Zustand bin, ist das

58:46.010 --> 58:48.590
die Menge der erlaubten Vorgänger, wenn ich den Übergang mache,

58:49.110 --> 58:50.590
wechsle ich irgendwie den Zustand.

58:50.590 --> 58:54.450
Wenn man da jetzt nicht sozusagen einen zusätzlichen Zustandsautomaten

58:54.450 --> 58:57.930
dahinter bauen möchte, der mir halt vorgibt, was ist jetzt die Menge

58:57.930 --> 59:01.470
der erlaubten Vorgänger, kann man das zum Beispiel so machen, indem

59:01.470 --> 59:05.110
man halt Wörter im Vokabular dann so lange dupliziert und die halt mit

59:05.110 --> 59:11.490
irgendwelchen zusätzlichen Zeichen annotiert, dann solche Pseudowörter

59:11.490 --> 59:15.090
daraus macht, bis ich dann wieder meinen gesamten Zustandsautomaten

59:15.090 --> 59:21.250
ausgerollt habe und kann dann damit relativ granular steuern, welche

59:21.250 --> 59:27.090
Wortfolgen sind jetzt zumindest so auf lokaler Ebene zulässig.

59:28.830 --> 59:32.370
Wie gesagt, das hat man alles eine Weile gemacht und hat halt

59:32.370 --> 59:36.450
festgestellt, ja, man ist zwar schon relativ inflexibel, in welche

59:36.450 --> 59:41.450
Vektoren man aufeinander zuordnen kann, die Distanzmaße sind trotzdem

59:41.450 --> 59:42.710
noch relativ starr.

59:43.670 --> 59:48.550
Bei den Möglichkeiten dieser syntaktischen Einschränkungen ist man

59:48.550 --> 59:53.090
relativ primitiv, das könnte man deutlich besser machen und man würde

59:53.090 --> 59:57.830
halt gerne noch viel flexibler sein in dieser Zuordnung von den

59:57.830 --> 01:00:00.390
Vektoren und in der Distanzberechnung von den Vektoren.

01:00:00.890 --> 01:00:03.610
Und ist halt darauf gekommen, es ist besser, wenn man das Ganze mit

01:00:03.610 --> 01:00:05.410
Wahrscheinlichkeiten macht.

01:00:06.170 --> 01:00:09.790
Und wenn man dann halt so mit Wahrscheinlichkeiten arbeitet, ist das

01:00:09.790 --> 01:00:12.330
Erste, worauf man häufig stößt, halt die Gauss-Verteilung.

01:00:12.330 --> 01:00:17.350
Weil sie sich halt für natürliche Prozesse ganz gut eignet, weil wenn

01:00:17.350 --> 01:00:21.150
man in der Natur irgendwelche Prozesse beobachtet, sind die meistens

01:00:21.150 --> 01:00:24.470
oder häufig so ungefähr Gauss-verteilt.

01:00:25.270 --> 01:00:28.690
Und wenn ich jetzt eine Gauss-Verteilung über einen eindimensionalen

01:00:28.690 --> 01:00:32.390
Wert habe, dann wird die halt parametrisiert über einen Mittelwert µ

01:00:32.390 --> 01:00:35.390
und die Varianz bzw.

01:00:37.070 --> 01:00:38.990
Standardabweichung Sigma-Quadrat bzw.

01:00:39.270 --> 01:00:44.630
Varianz Sigma-Quadrat.

01:00:45.250 --> 01:00:49.010
Das sind die beiden Parameter, die ich bei so einer eindimensionalen

01:00:49.010 --> 01:00:50.070
Gauss -Verteilung habe.

01:00:51.050 --> 01:00:56.490
Die muss ich halt irgendwie geeignet wählen oder geeignet schätzen und

01:00:56.490 --> 01:00:58.730
kann damit dann so eine Gauss-Glocke machen.

01:01:01.090 --> 01:01:06.930
Jeder kennt noch aus der Schule diese einfachen Formeln, wenn ich halt

01:01:06.930 --> 01:01:11.630
Daten habe, die von einer Gauss-Glocke hervorgebracht wurden, also von

01:01:11.630 --> 01:01:16.130
denen ich ausgehe, diese Folge von Datenpunkten, die ist verteilt

01:01:16.130 --> 01:01:19.850
unter einer Gauss-Verteilung, dann kann ich aus diesen Daten einfach

01:01:19.850 --> 01:01:23.850
den Mittelwert und die Varianz schätzen.

01:01:24.070 --> 01:01:27.590
Mittelwert ist einfach das arithmetische Mittel der einzelnen Werte,

01:01:28.190 --> 01:01:29.610
deswegen auch der Name Mittelwert.

01:01:29.970 --> 01:01:34.130
Und die Varianz ist dann eben die durchschnittliche Abweichung der

01:01:34.130 --> 01:01:40.810
einzelnen Werte vom Mittelwert, und zwar der Durchschnitt der

01:01:40.810 --> 01:01:44.050
quadrierten Abweichung der einzelnen Werte vom Mittelwert.

01:01:44.910 --> 01:01:48.510
Und dann gibt es halt vor der Gauss-Verteilung noch so einen

01:01:48.510 --> 01:01:52.610
Nummierungspaktor, dieses 1 durch Wurzel 2 Pi Sigma Quadrat, das dient

01:01:52.610 --> 01:01:57.190
einfach dafür, dass die Gauss-Glocke, die ich habe, so nummiert wird,

01:01:57.310 --> 01:02:00.070
dass die Fläche unter dieser Gauss-Glocke halt immer 1 ist.

01:02:00.070 --> 01:02:03.630
Weil halt eine Dichtefunktion, muss halt das Integral über die

01:02:03.630 --> 01:02:07.930
Dichtefunktion muss halt gerade 1 ergeben, qua Definition.

01:02:12.910 --> 01:02:15.030
Was letztendlich die Varianz macht?

01:02:15.230 --> 01:02:18.370
Die Varianz macht nichts anderes, als dass es die Gauss-Glocke breiter

01:02:18.370 --> 01:02:20.050
oder schmaler macht.

01:02:20.670 --> 01:02:22.590
Aber in der Höhe ändert sich halt nichts.

01:02:23.010 --> 01:02:25.990
Und deswegen muss man dann halt mit diesem Nummierungsfaktor die

01:02:25.990 --> 01:02:28.710
Fläche unter der Gauss-Glocke wieder nummieren.

01:02:28.710 --> 01:02:31.310
Durch den Nummierungsfaktor macht man sozusagen die Höhe der Gauss

01:02:31.310 --> 01:02:34.210
-Glocke wieder kleiner, wenn ich sie breiter mache, damit halt die

01:02:34.210 --> 01:02:35.510
Fläche nach wie vor 1 ist.

01:02:35.970 --> 01:02:38.990
Und über den Mittelwert verschiebe ich halt, wo ist der höchste Punkt

01:02:38.990 --> 01:02:40.970
der Gauss-Glocke.

01:02:41.250 --> 01:02:42.350
Verschiebe ich halt hin und her.

01:02:42.770 --> 01:02:45.250
Haben Sie alles schon in kognitive Systeme gesehen.

01:02:46.150 --> 01:02:49.790
Und das Gleiche gibt es halt auch für mehrdimensionale Vektoren.

01:02:49.950 --> 01:02:53.410
Wenn ich jetzt also nicht mehr einen Wert aus den reellen Zahlen habe,

01:02:53.410 --> 01:03:01.490
sondern ich habe einen Wert aus einem Vektorraum der reellen Zahlen,

01:03:01.590 --> 01:03:07.390
aus dem r hoch d, r hoch n, dann wird aus meinem Mittelwert ein

01:03:07.390 --> 01:03:12.510
Mittelwertsvektor, der genauso dimensional ist wie mein Vektor aus dem

01:03:12.510 --> 01:03:13.090
r hoch d.

01:03:14.050 --> 01:03:19.130
Und aus der Varianz wird so eine sogenannte Kovarianzmatrix Sigma.

01:03:19.130 --> 01:03:23.170
Und die invertiere ich und dann rechne ich hier oben dieses Minus

01:03:23.170 --> 01:03:26.190
-einhalb und so weiter und sofort aus.

01:03:26.790 --> 01:03:29.550
Und dann sehen Sie schon, wenn Sie da jetzt einfach das Minus-einhalb

01:03:29.550 --> 01:03:32.690
mal vergessen würden und daraus die Wurzel ziehen, dann hätten Sie

01:03:32.690 --> 01:03:36.590
gerade die Mahler-Lobis-Distanz zwischen dem Vektor, für den Sie den

01:03:36.590 --> 01:03:42.030
Wert der Gauss-Glocke berechnen wollen und dem Mittelwertsvektor der

01:03:42.030 --> 01:03:42.570
Gauss -Glocke.

01:03:43.270 --> 01:03:47.490
Und diese Parameter kann man jetzt auch wieder entsprechend schätzen.

01:03:47.490 --> 01:03:50.310
Für den Mittelwertsvektor ist das relativ einfach.

01:03:50.450 --> 01:03:56.930
Das ist einfach das komponentenweise arithmetische Mittel der Vektoren

01:03:56.930 --> 01:03:59.750
in den Trainingsdaten.

01:04:01.110 --> 01:04:04.290
Die Kovarianzmatrix ist halt eine Matrix und da wird es jetzt ein

01:04:04.290 --> 01:04:05.470
bisschen komplizierter.

01:04:06.050 --> 01:04:08.350
Das ist erstmal die erste Frage, was heißt das überhaupt?

01:04:09.970 --> 01:04:12.290
Kovarianzmatrizen, wie ist die aufgebaut?

01:04:12.290 --> 01:04:16.130
Die ist so aufgebaut, wenn ich mir die Diagonale anschaue.

01:04:16.530 --> 01:04:20.590
Die Werte auf der Diagonalen ist einfach die Varianz der

01:04:20.590 --> 01:04:24.950
Trainingsdaten in dieser jeweiligen Dimension, wo ich mich halt gerade

01:04:24.950 --> 01:04:28.230
auf der Diagonalen befinde.

01:04:28.870 --> 01:04:34.910
Und die anderen Werte beschreiben halt, wie stark variiert diese eine

01:04:34.910 --> 01:04:40.670
Dimension in Zusammenhang mit der anderen Dimension.

01:04:40.670 --> 01:04:50.730
Und das macht man einfach, indem ich die Varianz ausrechne in der

01:04:50.730 --> 01:04:55.010
einen Dimension und das Ganze multipliziere mit der Varianz

01:04:55.010 --> 01:04:57.530
ausgerechnet in der anderen Dimension und davon wieder den

01:04:57.530 --> 01:05:00.550
Erwartungswert entsprechend bilde.

01:05:00.810 --> 01:05:05.070
Und das gibt mir dann die sogenannte Kovarianzmatrix.

01:05:05.070 --> 01:05:08.670
Dadurch, dass halt die Multiplikation kommutativ ist, ist die

01:05:08.670 --> 01:05:13.870
Kovarianzmatrix demnach automatisch auch symmetrisch um die Diagonale

01:05:13.870 --> 01:05:14.430
drumherum.

01:05:16.410 --> 01:05:21.830
Die einzelnen Werte auf der Diagonalen, also diese Werte in der

01:05:21.830 --> 01:05:26.090
Kovarianzmatrix auf der Diagonalen, müssen für eine normale, für eine

01:05:26.090 --> 01:05:29.390
echte Normalverteilung auch echt größer 0 sein.

01:05:30.050 --> 01:05:30.370
Warum?

01:05:30.510 --> 01:05:31.690
Wie kann man sich das vorstellen?

01:05:31.690 --> 01:05:36.510
Wenn wir jetzt mal alle anderen Werte ignorieren und uns nur anschauen

01:05:36.510 --> 01:05:41.410
die Werte auf der Diagonalen und mal so tun als seien alle anderen

01:05:41.410 --> 01:05:48.850
Werte 0, kann durchaus sein, dann ist das so, dass ich statt einer

01:05:48.850 --> 01:05:55.050
Gauss -Glocke so eine Art, naja, Ellipsoiden bekomme, der mir wo die

01:05:55.050 --> 01:05:58.950
Varianzen dieser Gauss-Glocke dann angegeben werden in den jeweiligen

01:05:58.950 --> 01:05:59.870
Dimensionen.

01:05:59.870 --> 01:06:02.690
Und wenn ich das jetzt projizieren würde auf die jeweiligen

01:06:02.690 --> 01:06:05.470
Dimensionen, würde ich halt wieder so eine Gauss-Glocke bekommen.

01:06:05.590 --> 01:06:09.310
Und wenn das bedeuten würde, dass also in einer Dimension die Varianz

01:06:09.310 --> 01:06:13.030
0 wäre, dann wäre das eine Gauss-Glocke, die komplett zusammengedrückt

01:06:13.030 --> 01:06:13.430
wäre.

01:06:14.110 --> 01:06:17.810
Das würde bedeuten, Varianz 0 in dieser einen Dimension.

01:06:18.690 --> 01:06:19.510
Und das geht halt nicht.

01:06:19.830 --> 01:06:22.350
Also so eine Gauss-Glocke, wenn die halt komplett zusammengedrückt

01:06:22.350 --> 01:06:25.510
wird, dann kriege ich da halt so eine Singularität raus und dann ist

01:06:25.510 --> 01:06:29.110
das eben keine echte Normalverteilung mehr.

01:06:30.610 --> 01:06:35.130
Wenn das halt so ein, ja, singulärer Fall ist, wo das halt wirklich

01:06:35.130 --> 01:06:39.850
die Varianz komplett zusammengedrückt wird, dann kann der Wert sogar 0

01:06:39.850 --> 01:06:40.210
werden.

01:06:41.050 --> 01:06:42.750
Kleiner als 0 kann er halt nie werden.

01:06:43.810 --> 01:06:48.030
So eine, wie gesagt, ist symmetrisch wegen der Kommutativität der

01:06:48.030 --> 01:06:48.910
Multiplikation.

01:06:49.330 --> 01:06:52.150
Das Ganze ist positiv semidefinit.

01:06:52.590 --> 01:06:56.450
Und wenn man es irgendwie darstellen möchte, zumindest so im

01:06:56.450 --> 01:06:59.090
dreidimensionalen Raum, dann stellt man das meistens als so einen

01:06:59.090 --> 01:07:05.490
Ellipsoiden her, wobei der Ellipsoid sozusagen immer das Einfache der,

01:07:05.630 --> 01:07:10.250
naja, Standardabweichung der Kovarianz in dieser Dimension dann

01:07:10.250 --> 01:07:10.790
darstellt.

01:07:12.250 --> 01:07:17.570
Und wenn jetzt halt alle anderen Werte außer der Diagonale 0 sind,

01:07:17.570 --> 01:07:22.690
dann heißt das, dass diese Achsen dieses Ellipsoiden, wo ich da

01:07:22.690 --> 01:07:32.790
sozusagen Werte gleicher Größe in dieser Multivariaten-Gaussglocke

01:07:32.790 --> 01:07:38.210
darstelle, zum Beispiel halt einmal Standardabweichung, für welche

01:07:38.210 --> 01:07:42.150
Vektoren ist also der Wert immer einmal Standardabweichung sozusagen

01:07:42.150 --> 01:07:44.450
als multidimensional dargestellt,

01:07:47.730 --> 01:07:51.490
wenn also die Werte außerhalb der Diagonalen alle 0 sind, dann sind

01:07:51.490 --> 01:07:55.930
diese Achsen dieses Ellipsoiden gerade parallel zu den Achsen meines

01:07:55.930 --> 01:07:57.270
Koordinatensystems.

01:07:57.710 --> 01:08:01.090
Das heißt, mit so ein bisschen Fantasie kann man sich auch vorstellen,

01:08:01.270 --> 01:08:05.830
dass das, was diese Anteile außerhalb der Diagonalen machen, dass das

01:08:05.830 --> 01:08:10.850
vorgibt, wie jetzt dieser Ellipsoid, wie die Achsen dieses Ellipsoiden

01:08:10.850 --> 01:08:13.270
im Koordinatensystem rotiert werden.

01:08:13.270 --> 01:08:15.450
Da kann man sich so ein bisschen das vorstellen.

01:08:15.570 --> 01:08:18.530
Man kennt vielleicht noch so diese Rotationskästchen, die man mal

01:08:18.530 --> 01:08:19.090
gesehen hat.

01:08:19.650 --> 01:08:23.750
Dann kann man da so einen Zusammenhang erkennen, zu wie ich solche

01:08:23.750 --> 01:08:28.170
Dinge im Raum rotieren kann mit solchen Rotationskästchen und was da

01:08:28.170 --> 01:08:30.710
in dieser Kovarianzmatrix passiert.

01:08:34.850 --> 01:08:38.690
Meine Schätzen der Kovarianzmatrix ist dann halt auch relativ einfach.

01:08:38.830 --> 01:08:41.830
Ich kann die halt komponentenweise schätzen, indem ich halt hier

01:08:41.830 --> 01:08:43.370
einfach Erwartungswerte ausrechne.

01:08:43.450 --> 01:08:47.350
Also erst der Erwartungswert in der Dimension, sprich Mittelwerte in

01:08:47.350 --> 01:08:51.930
der Dimension ausrechnen, dann die Abweichung von dem Erwartungswert,

01:08:51.930 --> 01:08:55.830
das jeweils miteinander multipliziere und darüber dann nochmal den

01:08:55.830 --> 01:08:59.650
Erwartungswert über alle Datenpunkte in der jeweiligen Dimension oder

01:08:59.650 --> 01:09:03.470
in dem jeweiligen Paar von Dimensionen, Dimensionen i und Dimensionen

01:09:03.470 --> 01:09:05.210
j miteinander ausrechne.

01:09:07.310 --> 01:09:13.110
Jetzt sind viele Prozesse in der Natur so ungefähr Gauss verteilt,

01:09:13.630 --> 01:09:16.250
aber meistens sieht es doch ein bisschen anders aus als

01:09:16.250 --> 01:09:17.170
Gaussverteilung.

01:09:17.170 --> 01:09:21.010
Und Sprache als solche ist nicht so richtig wirklich schön Gauss

01:09:21.010 --> 01:09:21.450
verteilt.

01:09:22.190 --> 01:09:24.690
Also wenn ich mir so anschaue, was aus der Vorverarbeitung

01:09:24.690 --> 01:09:29.170
herauskommt, dann folgt das nicht zu einer schönen Gaussverteilung,

01:09:29.330 --> 01:09:35.630
sondern ist das irgendwie ein beliebig geformter

01:09:35.630 --> 01:09:36.770
Wahrscheinlichkeitsprozess.

01:09:36.770 --> 01:09:41.070
Und damit man jetzt in der Lage ist, beliebig geformte

01:09:41.070 --> 01:09:49.150
Dichtefunktionen darstellen zu können, erweitert man halt die einzelne

01:09:49.150 --> 01:09:52.710
Gaussverteilung auf eine Summe von Gaussverteilungen.

01:09:53.550 --> 01:09:55.890
Das nennt man dann Gaussmischverteilung.

01:09:56.050 --> 01:09:59.290
Ich bilde jetzt die gewichtete Summe aus unterschiedlichen

01:09:59.290 --> 01:10:02.410
Gaussglocken und jede Gaussglocke hat halt seinen eigenen

01:10:02.410 --> 01:10:05.090
Mittelwertsvektor und seine eigene Kovarianzmatrix.

01:10:05.870 --> 01:10:09.430
Die kriegen dann jeweils ein eigenes Gewicht und summiere die auf.

01:10:09.430 --> 01:10:13.390
Die Gewichte müssen halt zwischen 0 und 1 liegen und müssen halt in

01:10:13.390 --> 01:10:14.430
der Summe 1 ergeben.

01:10:15.890 --> 01:10:19.230
Und dann ist das, was herauskommt bei dieser gewichteten Summe, auch

01:10:19.230 --> 01:10:20.550
wieder eine Dichtefunktion.

01:10:23.090 --> 01:10:25.550
Warum macht man das so in dieser Form?

01:10:25.830 --> 01:10:29.730
Man macht das deshalb so in dieser Form, und das ist eben gerade das

01:10:29.730 --> 01:10:36.730
Schöne daran, dass wenn ich eine beliebig geformte Dichtefunktion

01:10:36.730 --> 01:10:45.690
beliebig genau annähern möchte, also ich gebe mir vor einen Wert, der

01:10:45.690 --> 01:10:48.950
der maximale Fehler sein soll, den ich bei der Approximation dieser

01:10:48.950 --> 01:10:53.590
beliebigen Dichteverteilung mache, gebe mir also diesen maximalen

01:10:53.590 --> 01:10:58.790
Fehler vor und möchte jetzt diese Dichtefunktion annähern, dann reicht

01:10:58.790 --> 01:11:02.070
eine endliche Anzahl von Gaussglocken aus in einer

01:11:02.070 --> 01:11:06.510
Gaussmischverteilung, um so eine Annäherung zu bekommen, die beliebig

01:11:06.510 --> 01:11:07.290
genau ist.

01:11:08.530 --> 01:11:14.290
Das heißt, ich kann damit also sehr gut verschiedene beliebige

01:11:14.290 --> 01:11:17.630
Wahrscheinlichkeitsdichtefunktionen approximieren.

01:11:18.850 --> 01:11:24.270
Das Einzige, wodurch ich ausgebremst werde bei der Approximation, ist

01:11:24.270 --> 01:11:26.530
halt die Anzahl der verfügbaren Trainingsdaten.

01:11:27.230 --> 01:11:33.170
Je mehr Gaussglocken ich halt hinzunehme in die Mixtur, desto mehr

01:11:33.170 --> 01:11:36.510
Parameter habe ich, desto mehr Trainingsdaten bräuchte ich halt, um

01:11:36.510 --> 01:11:38.990
die Parameter robust und zuverlässig schätzen zu können.

01:11:38.990 --> 01:11:42.770
Wenn ich jetzt aber beliebig viele Trainingsdaten habe, dann kann ich

01:11:42.770 --> 01:11:48.950
jede Dichtefunktion beliebig genau durch so eine Gaussmischverteilung

01:11:48.950 --> 01:11:51.230
entsprechend approximieren.

01:11:53.470 --> 01:11:57.530
Um jetzt Parameter zu sparen, weil Parameter sind immer kostbar und

01:11:57.530 --> 01:12:01.970
Rechenzeit ist kostbar und so weiter und so fort, arbeitet man häufig

01:12:01.970 --> 01:12:05.630
mit Gaussglocken mit diagonalen Kovarianzmatrixen.

01:12:05.630 --> 01:12:08.930
Ich spare halt dadurch sehr viele Parameter ein in der

01:12:08.930 --> 01:12:11.110
Kovarianzmatrix.

01:12:11.990 --> 01:12:16.510
Plus das Rechnen wird deutlich einfacher.

01:12:19.720 --> 01:12:25.860
Und das andere, was man macht, ist, dass man häufig nicht mit den

01:12:25.860 --> 01:12:29.960
tatsächlichen Wahrscheinlichkeitswerten arbeitet, sondern man arbeitet

01:12:29.960 --> 01:12:31.700
häufig im logarithmischen Bereich.

01:12:31.700 --> 01:12:35.860
Der Vorteil ist halt, der Logarithmus zu streng monotone Funktion,

01:12:36.440 --> 01:12:40.100
also alles, was im ursprünglichen Wahrscheinlichkeitsbereich den

01:12:40.100 --> 01:12:43.700
maximalen Wert hat, wird auch im logarithmischen Bereich den maximalen

01:12:43.700 --> 01:12:44.220
Wert haben.

01:12:45.060 --> 01:12:50.000
Angenommen, ich habe jetzt nur eine Gaussmixtur und da werfe ich den

01:12:50.000 --> 01:12:50.900
Logarithmus drauf.

01:12:51.280 --> 01:12:55.940
Dann wird durch das Anwenden des Logarithmuses diese E-Funktion

01:12:55.940 --> 01:12:56.700
eliminiert.

01:12:57.240 --> 01:13:01.420
Und was mehr oder minder übrig bleibt, ist nur noch die Mahaner-Lobes

01:13:01.420 --> 01:13:01.860
-Distanz.

01:13:01.860 --> 01:13:04.900
Den Numierungsfaktor kann ich wegwerfen, der ist konstant.

01:13:05.560 --> 01:13:11.440
Und oben bleibt nur noch die Mahaner-Lobes-Distanz stehen.

01:13:12.420 --> 01:13:16.120
Und jetzt muss ich statt dieser teuren E-Funktion im Rechner nur noch

01:13:16.120 --> 01:13:20.780
die Mahaner-Lobes-Distanz ausrechnen und das sind am Ende Quadrate und

01:13:20.780 --> 01:13:25.300
Summen und Differenzen, die ich einfach darstellen muss.

01:13:25.300 --> 01:13:28.660
Und auch die Wurzel kann ich letztendlich weglassen, weil die Wurzel

01:13:28.660 --> 01:13:32.400
in so positiven ist halt auch eine monotone Funktion, bringt mir halt

01:13:32.400 --> 01:13:32.860
auch nichts.

01:13:33.660 --> 01:13:37.580
Das heißt, wenn ich also nur eine Gaussglocke habe, kann ich sehr viel

01:13:37.580 --> 01:13:40.220
Rechenzeit sparen, indem ich nicht frage, was ist die höchste

01:13:40.220 --> 01:13:44.480
Wahrscheinlichkeit, sondern was ist die höchste logarithmierte

01:13:44.480 --> 01:13:48.980
Wahrscheinlichkeit oder was ist die logarithmierte Wahrscheinlichkeit

01:13:48.980 --> 01:13:51.140
von diesem Wert bei der Gaussglocke.

01:13:52.300 --> 01:13:54.440
Das funktioniert bei einzelnen Gaussglocken.

01:13:55.000 --> 01:13:58.500
Wenn ich das auf Gaussmixtur-Verteilungen anwende, stehe ich in der

01:13:58.500 --> 01:14:02.420
Wiese, weil Logarithmus auf eine Summe ist halt nichts, kann ich nicht

01:14:02.420 --> 01:14:02.920
reinziehen.

01:14:03.240 --> 01:14:07.300
Dann habe ich ein Problem, da muss ich mir dann wieder andere Tricks

01:14:07.300 --> 01:14:11.720
einfallen lassen, um trotzdem Rechenzeit einzusparen und trotzdem

01:14:11.720 --> 01:14:13.360
damit zurecht zu kommen.

01:14:14.000 --> 01:14:17.240
Und da geht man dann hin, dass man wirklich teilweise sehr krude

01:14:17.240 --> 01:14:18.620
Approximationen macht.

01:14:19.000 --> 01:14:23.040
Dass man dann sagt, okay, ich suche mir erstmal die Gaussglocke raus,

01:14:23.700 --> 01:14:27.980
zu der der Wert, den ich in die Gaussmixtur reinstecke, am nächsten

01:14:27.980 --> 01:14:28.280
ist.

01:14:28.420 --> 01:14:31.620
Also aus den 15 Gaussglocken, die ich in meiner Mixtur habe, suche ich

01:14:31.620 --> 01:14:33.360
diejenige raus, die am nächsten liegt.

01:14:33.960 --> 01:14:35.640
Das mache ich mit der Mahler-Lobes-Distanz.

01:14:35.740 --> 01:14:36.860
Die gibt mir halt gerade vor.

01:14:37.480 --> 01:14:41.920
Dann noch gewichtet mit dem Gewicht.

01:14:42.000 --> 01:14:43.560
Das Gewicht kann ich ignorieren.

01:14:43.700 --> 01:14:46.580
Ich gucke also anhand der Mahler-Lobes-Distanzen, welche Gaussglocke

01:14:46.580 --> 01:14:48.360
ist diejenige, die am nächsten liegt.

01:14:48.360 --> 01:14:50.360
Dann muss ich noch keine E-Funktion ausführen.

01:14:51.020 --> 01:14:55.120
Und dann tue ich so, als würden alle anderen Gaussglocken so weit weg

01:14:55.120 --> 01:14:57.880
liegen, dass sie keinen signifikanten Beitrag mehr liefern zu der

01:14:57.880 --> 01:14:59.120
gesamten Summe.

01:14:59.140 --> 01:15:01.820
Was glücklicherweise in der Praxis häufig der Fall ist.

01:15:02.420 --> 01:15:05.500
Und komme dann damit aus, dass ich dann sozusagen nur noch eine

01:15:05.500 --> 01:15:08.720
Gaussglocke auswerte im logarithmischen Bereich.

01:15:09.040 --> 01:15:11.400
Das heißt, da muss ich dann die E-Funktion auch wieder nicht

01:15:11.400 --> 01:15:12.960
auswerten.

01:15:14.060 --> 01:15:15.520
Ich mache natürlich einen Fehler.

01:15:15.860 --> 01:15:18.640
Alle anderen Gaussglocken in der Mixtur tue ich so, als sei da der

01:15:18.640 --> 01:15:19.120
Wert 0.

01:15:19.420 --> 01:15:20.400
Ist er natürlich nicht.

01:15:20.500 --> 01:15:22.460
Das ist das, was mir hinterher fehlt in der Summe.

01:15:23.060 --> 01:15:24.260
Aber dafür bin ich halt schneller.

01:15:24.880 --> 01:15:28.600
Und wenn ich Glück habe und meine Daten halt gemütlich und gutmütig

01:15:28.600 --> 01:15:34.440
verteilt sind, dann ist das Ergebnis, die Approximation, hoffentlich

01:15:34.440 --> 01:15:36.940
gut genug, um vernünftig klassifizieren zu können.

01:15:39.740 --> 01:15:45.200
Manchmal möchte man auch wegkommen von diesem Rechnen im

01:15:45.200 --> 01:15:46.040
Kontinuierlichen.

01:15:46.440 --> 01:15:49.480
Dass man also mit kontinuierlichen Merkmalsvektoren rechnet und dann

01:15:49.480 --> 01:15:52.460
muss ich kontinuierliche Mixturverteilungen ausrechnen.

01:15:53.160 --> 01:15:57.040
Manchmal möchte man auch Rechenzeit dadurch sparen, dass ich zum

01:15:57.040 --> 01:15:58.440
Beispiel Sachen vorberechne.

01:15:59.300 --> 01:16:04.820
Also angenommen, statt beliebige Vektoren reeller Zahlen würde ich aus

01:16:04.820 --> 01:16:08.200
der Vorverarbeitung nur noch eine endliche Menge von Vektoren

01:16:08.200 --> 01:16:08.840
rausbekommen.

01:16:08.960 --> 01:16:12.860
Ich weiß, es wird einer von 3000 Vektoren sein, der aus der

01:16:12.860 --> 01:16:14.140
Vorverarbeitung rausfällt.

01:16:14.140 --> 01:16:17.220
Und ich habe so eine Gauss-Mixtur, die ich dann hinterher berechnen

01:16:17.220 --> 01:16:19.780
will auf den Vektoren aus der Vorverarbeitung.

01:16:20.320 --> 01:16:25.120
Dann brauche ich nur 3000 Mal irgendwann mal im Vorfeld diese Gauss

01:16:25.120 --> 01:16:29.720
-Mixtur auszurechnen, speichere das in der Tabelle ab und später, wenn

01:16:29.720 --> 01:16:32.980
ich halt wissen will, was ist der Wert der Gauss-Mixtur für einen von

01:16:32.980 --> 01:16:36.560
diesen 3000 Vektoren, die da rauskommen, gucke ich einfach nur noch in

01:16:36.560 --> 01:16:37.340
der Tabelle nach.

01:16:37.340 --> 01:16:38.840
Spare ich sehr viel Rechenzeit.

01:16:39.700 --> 01:16:42.520
Jetzt ist es natürlich so, ich weiß natürlich nicht, was für Vektoren

01:16:42.520 --> 01:16:43.880
aus der Vorverarbeitung rauskommen.

01:16:43.960 --> 01:16:45.440
Das können beliebige Vektoren sein.

01:16:46.120 --> 01:16:49.520
Und dann arbeitet man halt damit, dass man halt diese Vektoren

01:16:49.520 --> 01:16:50.240
quantisiert.

01:16:50.240 --> 01:16:54.560
Genauso wie ich bei der Digitalisierung aus dem kontinuierlichen

01:16:54.560 --> 01:17:01.440
Signal ein diskretes Signal mache, indem ich Zeit diskret mache und

01:17:01.440 --> 01:17:04.740
dann in den Werten die einzelnen kontinuierlichen Werte auf

01:17:04.740 --> 01:17:08.780
Quantisierungsstufen drücke, kann ich jetzt meine

01:17:08.780 --> 01:17:13.320
Vorverarbeitungsvektoren auch auf Quantisierungsstufen drücken, die

01:17:13.320 --> 01:17:19.660
jetzt halt Vektoren im n-dimensionalen Raum sind.

01:17:20.240 --> 01:17:24.680
Oder Bereiche, Unterbereiche in diesem n-dimensionalen Raum.

01:17:25.300 --> 01:17:29.320
Alles, was da reinfällt, wird halt auf einen Vektor, einen

01:17:29.320 --> 01:17:31.000
Prototypvektor abgebildet.

01:17:36.060 --> 01:17:39.160
Und wie gesagt, dann kann ich das Ganze vorberechnen und kann Ganze

01:17:39.160 --> 01:17:41.240
nur noch in der Tabelle nachrechnen.

01:17:41.700 --> 01:17:44.640
Das ist besonders dann interessant, wenn ich halt mit Geräten arbeite,

01:17:44.720 --> 01:17:46.080
die wenig Rechenkraft haben.

01:17:47.460 --> 01:17:51.540
Mobiltelefone, PDAs, Embedded Systeme, wo ich halt so viel Speicher

01:17:51.540 --> 01:17:54.200
habe, dass ich diese Tabellen abspeichern kann, aber halt wenig

01:17:54.200 --> 01:17:58.340
Rechenkraft und mir diese ganze Auswertung der E-Funktion sparen.

01:17:59.140 --> 01:18:01.300
Und E-Funktion auswerten ist wirklich ekelhaft.

01:18:02.100 --> 01:18:03.880
Das kostet den Rechner viel Zeit.

01:18:03.980 --> 01:18:07.000
Da muss ich so Taylor Series, Approximation, irgendwas in der Richtung

01:18:07.000 --> 01:18:07.280
machen.

01:18:07.420 --> 01:18:10.260
Anders kann ich die E-Funktion nicht vernünftig ausrechnen.

01:18:12.320 --> 01:18:17.700
Das einzige Problem dabei ist, zurzeit ändert sich das ganze Spiel,

01:18:18.180 --> 01:18:22.280
weil man von diesen Verwendungen von Gauss-Glocken wegkommt und

01:18:22.280 --> 01:18:24.420
plötzlich anfängt, neuronale Netze zu verwenden.

01:18:25.280 --> 01:18:29.160
Und da ist halt die Frage, funktioniert das immer noch?

01:18:29.520 --> 01:18:31.900
Und das ist etwas, was wir noch nicht so richtig wissen.

01:18:32.040 --> 01:18:33.160
Da gibt es erste Arbeiten.

01:18:33.580 --> 01:18:36.480
Da haben wir zurzeit zum Beispiel eine Masterarbeit laufen, die mal

01:18:36.480 --> 01:18:39.400
schaut, was ist, wenn ich jetzt Vektorquantisierung mache und das zum

01:18:39.400 --> 01:18:42.720
Beispiel mit neuronalen Netzen kombiniere, damit ich nicht mal

01:18:42.720 --> 01:18:44.180
neuronale Netze ausrechnen muss.

01:18:45.520 --> 01:18:50.100
Also bei Vektorquantisierung ist halt die Herausforderung, ich brauche

01:18:50.100 --> 01:18:54.560
so geeignete Repräsentanten, auf die ich quantisiere.

01:18:55.220 --> 01:18:58.180
Bei der Quantisierung, bei der Digitalisierung hatten wir gesagt,

01:18:58.760 --> 01:19:00.840
naja, man kann das zum Beispiel gleichverteilt machen.

01:19:00.840 --> 01:19:03.300
Ich habe einen bestimmten Wertebereich, der wird gleichverteilt

01:19:03.300 --> 01:19:06.000
aufgeteilt und quantisiere gleichverteilt.

01:19:06.440 --> 01:19:10.460
Dann hatte man schon gesehen, ja, bei menschlicher Sprache, Auflösung

01:19:10.460 --> 01:19:12.580
der Lautstärken ist unterschiedlich stark beim Menschen,

01:19:12.700 --> 01:19:16.120
unterschiedlicher Dynamikumfang und so weiter und so fort, kann ich

01:19:16.120 --> 01:19:19.860
zum Beispiel auch gut quantisieren, indem ich unterschiedlich große

01:19:19.860 --> 01:19:21.160
Quantisierungsstufen habe.

01:19:21.160 --> 01:19:25.040
Da kann man sich das sozusagen ableiten aus dem Wissen darüber, wie

01:19:25.040 --> 01:19:27.680
wir Menschen hören und was wir gut hören und was wir schlecht hören,

01:19:28.060 --> 01:19:30.700
dass man dann eine andere Art von besser geeigneten

01:19:30.700 --> 01:19:33.000
Quantisierungsstufen hat.

01:19:33.000 --> 01:19:36.960
Und jetzt hier bei der Vorverarbeitung im n-dimensionalen Raum habe

01:19:36.960 --> 01:19:42.260
ich allgemein das Problem, dass ich eine sehr unscharfe Begrenzung

01:19:42.260 --> 01:19:44.740
habe, was den Raum angeht.

01:19:44.880 --> 01:19:50.320
Also wenn ich sage, ich habe jetzt hier kontinuierliche Werte, das

01:19:50.320 --> 01:19:57.840
sind reelle Zahlen von Minus ganz, ganz groß bis Plus ganz, ganz groß,

01:19:57.920 --> 01:20:02.260
was auch immer mir der IEEE Double Floats Standard dahergibt, dann ist

01:20:02.260 --> 01:20:03.500
das ein sehr großer Bereich.

01:20:05.120 --> 01:20:08.140
Den kann ich natürlich jetzt auch gleichverteilt aufteilen in so

01:20:08.140 --> 01:20:12.640
kleine Kästchen oder halt was auch immer das ist im n-dimensionalen.

01:20:14.220 --> 01:20:17.340
Nur wenn ich mir dann meine Daten anschaue, wird es so sein, dass es

01:20:17.340 --> 01:20:20.760
da viele Bereiche gibt im Vektorraum, da wird es Daten geben und da

01:20:20.760 --> 01:20:23.520
gibt es viele Bereiche, da wird nie irgendwie so ein Wert mal

01:20:23.520 --> 01:20:24.740
vorkommen.

01:20:25.940 --> 01:20:29.800
Das heißt also, so eine gleichverteilte Aufteilung ist nicht unbedingt

01:20:29.800 --> 01:20:30.620
ideal.

01:20:32.120 --> 01:20:34.420
Und was ich außerdem gerne hätte, ist, ich habe hier so

01:20:34.420 --> 01:20:37.040
Trainingsdaten, die stehen dafür, ich möchte natürlich möglichst

01:20:37.040 --> 01:20:39.380
geringen Quantisierungsfehler machen.

01:20:40.480 --> 01:20:43.740
Das heißt, es wäre schön, wenn ich weiß, wie viele

01:20:43.740 --> 01:20:46.860
Quantisierungsstufen ich hinterher maximal haben will und wenn ich

01:20:46.860 --> 01:20:50.860
Trainingsdaten gegeben habe, wenn ich ein Verfahren herfinden kann,

01:20:51.440 --> 01:20:56.280
das mir Prototypvektoren, Quantisierungsstufen letztendlich findet,

01:20:56.420 --> 01:20:59.860
Quantisierungsstufen repräsentiert durch so einen Prototypvektor,

01:21:00.360 --> 01:21:03.580
sodass der Quantisierungsfehler, den ich hinterher mache, wenn ich

01:21:03.580 --> 01:21:06.780
neue Daten quantisiere, möglichst klein wird.

01:21:08.020 --> 01:21:10.940
Und wenn man sich das mal anschauen will, was passiert bei so einer

01:21:10.940 --> 01:21:14.800
Vektorquantisierung, dann kann man sich das sehr schön anschauen, wenn

01:21:14.800 --> 01:21:20.580
man jetzt für die Zuordnung beliebiger Vektor auf einen Referenzvektor

01:21:20.580 --> 01:21:23.680
mit der euclidischen Distanz arbeitet.

01:21:24.140 --> 01:21:26.520
Wenn man also sagt, okay, hier habe ich einen neuen Vektor, den will

01:21:26.520 --> 01:21:30.120
ich quantisieren, ich schaue, welcher Referenzvektor liegt am nächsten

01:21:30.120 --> 01:21:34.360
dran unter der euclidischen Distanz, auf den wird er zugeordnet.

01:21:34.360 --> 01:21:38.880
Und wenn man sich das mal im Zweidimensionalen aufzeichnet, hier die

01:21:38.880 --> 01:21:43.380
Kreise sind immer solche Referenzvektoren, und man sich anschaut,

01:21:43.500 --> 01:21:46.580
welche Fläche, welche Vektoren werden denn jetzt immer auf diese

01:21:46.580 --> 01:21:51.560
Referenzvektoren gemäß euclidischer Distanz zugeordnet, dann sieht man

01:21:51.560 --> 01:21:55.620
halt, dass der Raum so zerfällt in solche Flächen, die durch solche

01:21:55.620 --> 01:21:58.200
Strecken dort abgegrenzt werden.

01:21:58.200 --> 01:22:03.020
Das ist also alles, was innerhalb dieser Fläche liegt, die durch diese

01:22:03.020 --> 01:22:08.700
Linien begrenzt ist, das ist das, was am nächsten dran liegt an diesem

01:22:08.700 --> 01:22:10.000
Referenzvektor.

01:22:10.860 --> 01:22:13.640
Und dann zerfällt das schön in diese Bereiche, die durch diese schönen

01:22:13.640 --> 01:22:16.820
geraden Linien abgetrennt sind, und sowas nennt man dann entsprechend

01:22:16.820 --> 01:22:20.900
ein Vor- und Neudiagramm, beziehungsweise diese einzelnen Regionen

01:22:20.900 --> 01:22:24.360
innerhalb, die immer zu einem Referenzvektor gehören, sind dann halt

01:22:24.360 --> 01:22:26.380
die entsprechenden Vor- und Neuregionen.

01:22:30.520 --> 01:22:34.640
Kann einem manchmal schon ein bisschen Kopfschmerzen bereiten, wenn

01:22:34.640 --> 01:22:38.140
man jetzt nur eine euclidische Distanz nimmt, weil wenn man sich jetzt

01:22:38.140 --> 01:22:44.020
das Bild hier anschaut, ich habe irgendwo solche Referenzvektoren drin

01:22:44.020 --> 01:22:47.660
liegen, die spannen diese Vor- und Neuregionen auf, und jetzt will ich

01:22:47.660 --> 01:22:50.840
dieses X klassifizieren.

01:22:51.520 --> 01:22:56.480
Und wenn man jetzt sich das Bild anschaut, wo würde man als Mensch das

01:22:56.480 --> 01:22:58.260
X eher hinstecken?

01:22:59.000 --> 01:23:02.300
Würde man sagen, das X, das scheint irgendwie da oben links

01:23:02.300 --> 01:23:06.780
hinzugehören, oder scheint das X eher zu dem zu gehören, was da so

01:23:06.780 --> 01:23:07.720
weiter rechts liegt?

01:23:07.720 --> 01:23:11.500
Man würde halt so denken, naja, die links da, die sind alle irgendwie

01:23:11.500 --> 01:23:15.380
kompakt, die liegen dicht beieinander, und die anderen, die liegen

01:23:15.380 --> 01:23:19.760
halt so schön weit auseinander entfernt, und dieses X, das liegt nicht

01:23:19.760 --> 01:23:23.660
so richtig schön kompakt bei diesem oberen Cluster, das liegt viel

01:23:23.660 --> 01:23:24.840
weiter da rechts.

01:23:24.840 --> 01:23:27.800
Deswegen könnte man eigentlich sagen, naja, wenn ich das nur so sehe,

01:23:28.160 --> 01:23:31.200
hätte ich gedacht, das gehört vielleicht eher zu dem Ding oder zu dem

01:23:31.200 --> 01:23:34.900
Ding, aber nicht unbedingt zu einem von diesen Vektoren, weil dazu ist

01:23:34.900 --> 01:23:37.500
er viel zu weit entfernt von diesen dicht beieinander liegenden

01:23:37.500 --> 01:23:38.700
Vektoren.

01:23:39.740 --> 01:23:43.400
Und sowas kann man dann halt zum Beispiel in den Griff bekommen, indem

01:23:43.400 --> 01:23:47.900
man statt der euclidischen Distanz sowas wie eine Distanz nimmt, wo

01:23:47.900 --> 01:23:50.940
die Varianz mit dabei ist.

01:23:51.360 --> 01:23:54.700
Und das ist eben gerade die Mahana-Lobis-Distanz, das ist genau das,

01:23:54.840 --> 01:23:59.680
was sie macht, sie berücksichtigt die Varianz der Daten, die zu einem

01:23:59.680 --> 01:24:01.740
Referenzvektor gehören, irgendwie dazu.

01:24:03.140 --> 01:24:07.680
Das Problem ist halt, damit ich diese Varianz schätzen kann, brauche

01:24:07.680 --> 01:24:11.900
ich irgendwie Trainingsdaten, wo gelabelt ist, dieser Vektor gehört zu

01:24:11.900 --> 01:24:14.780
diesem Referenzvektor, der soll dazu geordnet werden.

01:24:15.660 --> 01:24:18.340
Wenn ich das habe, dann kann ich auf Trainingsdaten so eine Varianz,

01:24:18.460 --> 01:24:22.660
so eine Streuung berechnen und kann dann zum Beispiel eine Mahana

01:24:22.660 --> 01:24:24.000
-Lobis -Distanz ausrechnen.

01:24:26.680 --> 01:24:32.220
Und was dann passiert ist, dass aus diesen Linien, die mir da im Vor-

01:24:32.220 --> 01:24:36.680
und Neudiagramm aufgespannt werden, kriege ich jetzt sozusagen diese

01:24:36.680 --> 01:24:43.140
Schnitte von Gaussglocken, die jetzt halt runterprojiziert werden, im

01:24:43.140 --> 01:24:46.060
mehrdimensionalen Bereich kollidieren dann irgendwann diese

01:24:46.060 --> 01:24:47.520
Ellipsoiden miteinander.

01:24:47.520 --> 01:24:53.800
Und dann bekomme ich so Kurven, die halt diese Grenzflächen angeben,

01:24:53.920 --> 01:25:00.340
die halt entweder so Hyperblen ähnlich aussehen oder so geschnittene

01:25:00.340 --> 01:25:02.440
Hyperblen irgendwie miteinander darstellen.

01:25:02.880 --> 01:25:07.560
Und die berücksichtigen gerade dann eben so diese Varianzen mit.

01:25:08.940 --> 01:25:13.180
Die Frage ist natürlich, was jetzt überhaupt bleibt.

01:25:13.460 --> 01:25:17.080
Wo kriege ich überhaupt jetzt solche vernünftigen Vektoren her?

01:25:19.540 --> 01:25:22.620
Plus, wenn ich jetzt Varianzen schätzen will, brauche ich die

01:25:22.620 --> 01:25:23.660
handgelabelten Daten.

01:25:23.760 --> 01:25:25.060
Das habe ich in der Regel nicht.

01:25:26.000 --> 01:25:30.700
Wo kriege ich jetzt überhaupt solche Referenzvektoren mal her, die

01:25:30.700 --> 01:25:32.940
irgendwie halbwegs vernünftig das machen können?

01:25:32.940 --> 01:25:37.160
Und das ist wieder dieses, wo finde ich Referenzvektoren, die ich für

01:25:37.160 --> 01:25:39.000
die Vektorquantisierung verwenden kann?

01:25:39.520 --> 01:25:42.760
Das kann man wiederum als Musterklassifikationsproblem auffassen.

01:25:43.300 --> 01:25:49.660
Indem man sagt, wir geben eine Menge von Vektoren x, von denen ich

01:25:49.660 --> 01:25:54.420
weiß, die sollen zu einer Stufe, zu einer Quantisierungsstufe

01:25:54.420 --> 01:25:55.280
zugeordnet werden.

01:25:55.760 --> 01:25:59.340
Was ist denn bitteschön der Referenzvektor, der jetzt zu dieser Menge

01:25:59.340 --> 01:26:06.760
x von Vektoren x gehört, die jetzt zu dieser Referenzstufe hinzugefügt

01:26:06.760 --> 01:26:06.980
werden?

01:26:07.560 --> 01:26:10.380
Jetzt kann man sagen, naja, wenn man nur einen Referenzvektor

01:26:10.380 --> 01:26:14.600
betrachtet, kann man zum Beispiel sowas wie den Durchschnitt bilden.

01:26:15.420 --> 01:26:18.040
Das Problem ist, die Daten, die man bekommt, die sind nicht immer so

01:26:18.040 --> 01:26:18.960
schön theoretisch.

01:26:19.040 --> 01:26:20.560
Da können Ausreißer drin sein.

01:26:20.560 --> 01:26:24.300
Die Sachen, die jetzt gerade nicht so schön passend sind.

01:26:24.860 --> 01:26:27.000
Und die können, wenn ich mir so eine simple Durchschnittsbildung

01:26:27.000 --> 01:26:32.240
mache, ganz schnell das Ganze verderben.

01:26:32.340 --> 01:26:35.960
Da kann ich dann ganz schnell meinen einen Prototypvektor irgendwo in

01:26:35.960 --> 01:26:38.240
der Region reinschieben, wo er nicht hingehört.

01:26:38.760 --> 01:26:41.640
Dagegen kann ich ein bisschen robuster werden, indem ich pro

01:26:41.640 --> 01:26:45.320
Quantisierungsstufe nicht einen Referenzvektor nehme, sondern zum

01:26:45.320 --> 01:26:49.120
Beispiel mehrere Referenzvektoren pro Quantisierungsstufe.

01:26:49.120 --> 01:26:53.140
Und kann dann zum Beispiel hinterher sagen, okay, wenn ich mehrere

01:26:53.140 --> 01:27:02.100
solcher Referenzvektoren habe, dann kann ich die robuster dazuordnen,

01:27:02.200 --> 01:27:04.340
wenn da ein Ausreißer dabei ist, ist nicht so schlimm.

01:27:05.720 --> 01:27:08.920
Jetzt dieses Zuordnenvektor, den man gefunden hat auf

01:27:08.920 --> 01:27:12.280
Quantisierungsstufe, kann man zum Beispiel schön mit k-nächste

01:27:12.280 --> 01:27:12.920
Nachbarn machen.

01:27:14.420 --> 01:27:17.200
Angenommen, ich habe jetzt für jeden Quantisierungsindex, für jede

01:27:17.200 --> 01:27:20.140
Quantisierungsstufe, habe ich mehrere solcher Referenzvektoren.

01:27:21.080 --> 01:27:26.720
Für einen neuen Wert x berechne ich halt, was sind die k-am-nächsten

01:27:26.720 --> 01:27:29.420
-gelegenen Prototypvektoren.

01:27:30.240 --> 01:27:33.680
Unter denen zähle ich dann aus, welches ist die Quantisierungsstufe,

01:27:33.740 --> 01:27:37.580
die am häufigsten vertreten ist und für die entscheide ich mich dann.

01:27:38.320 --> 01:27:44.460
Was ist, wenn es nicht eindeutig festgelegt ist, wenn da so eine Patte

01:27:44.460 --> 01:27:49.700
ist zwischen mehreren Quantisierungsstufen, dann kann man zum Beispiel

01:27:49.700 --> 01:27:52.960
die nehmen, wo zum Beispiel die kumulierte Distanz am geringsten ist

01:27:52.960 --> 01:27:54.240
und so weiter und so fort.

01:27:55.980 --> 01:28:00.960
Das ist also eine schöne Anwendung von k-nächster Nachbar.

01:28:00.960 --> 01:28:04.140
Wenn man halt so Vektorquantisierungen macht, wird der k-nächster

01:28:04.140 --> 01:28:08.380
Nachbar oft häufig gemacht und da lohnt es sich dann darüber

01:28:08.380 --> 01:28:10.680
nachzudenken, wie kann ich das Ganze schneller machen.

01:28:11.940 --> 01:28:20.640
Häufig in der Praxis hat man halt viele Referenzvektoren pro Klasse,

01:28:20.860 --> 01:28:25.740
also das kann sein, dass wenn ich so 16.000, 24.000, also ganz viele

01:28:25.740 --> 01:28:29.060
Referenzvektoren pro Klasse, plus ich kann sehr viele Klassen haben,

01:28:29.220 --> 01:28:32.780
also so Größenordnung 10 hoch 4, 10 hoch 5, der Merkmalsraum ist

01:28:32.780 --> 01:28:34.020
relativ hochdimensional.

01:28:35.580 --> 01:28:40.040
Das heißt, dieses Ausrechnen der Distanzen, wenn das jetzt eine

01:28:40.040 --> 01:28:43.460
Manalobes Distanz ist oder irgendwas kompliziertes, das kann extrem

01:28:43.460 --> 01:28:44.740
groß werden.

01:28:45.080 --> 01:28:48.400
Ich muss dann also immer paarweise zu jedem Referenzvektor die Distanz

01:28:48.400 --> 01:28:55.260
ausrechnen und dann die fünf nächsten finden und dann muss ich das

01:28:55.260 --> 01:28:55.540
machen.

01:28:56.000 --> 01:28:59.540
Und das ist jetzt, und das muss ich das für alle ausrechnen und dann

01:28:59.540 --> 01:29:01.420
sieht man schon, das sind sehr, sehr viele Distanzen, die ich

01:29:01.420 --> 01:29:02.080
ausrechnen muss.

01:29:03.060 --> 01:29:07.800
Einfache Hausaufgabe für zu Hause, was wäre eine einfache Möglichkeit,

01:29:08.300 --> 01:29:13.660
das zu beschleunigen und zwar so, dass das immer noch das korrekte

01:29:13.660 --> 01:29:14.660
Ergebnis rauskommt.

01:29:15.220 --> 01:29:19.400
Also wie kann ich etwa, kann ich das beschleunigen und kriege immer

01:29:19.400 --> 01:29:22.980
noch das korrekte Ergebnis raus und da gilt jetzt immer noch der alte

01:29:22.980 --> 01:29:26.140
Leersatz, wenn ich beschleunige, aber immer noch das korrekte Ergebnis

01:29:26.140 --> 01:29:29.320
rausbekommen will, dann ist mir die Beschleunigung nicht garantiert.

01:29:29.820 --> 01:29:33.140
Dann kann es schneller sein, aber im schlimmsten Fall läuft es genauso

01:29:33.140 --> 01:29:34.860
langsam, wie es vorher gelaufen ist.

01:29:35.380 --> 01:29:39.800
Aber was wäre so eine typische Sache, die man da machen könnte, um so

01:29:39.800 --> 01:29:44.920
eine nicht garantierte Beschleunigung, aber ein garantiert korrektes

01:29:44.920 --> 01:29:46.240
Ergebnis zu bekommen.

01:29:47.860 --> 01:29:53.000
Antwort darauf rate ich dann dementsprechend nächste Woche und damit

01:29:53.000 --> 01:29:53.820
machen wir Schluss für heute.

