Praxis · Grundlagen

Ein Weltmodell von Hand:
49 Pixel, 8 Zahlen, ein Traum.

20. August 2026 · Lesezeit ca. 14 Minuten

Ein Agent sieht 49 Graupixel, lernt daraus die Regeln seiner Umgebung und plant anschließend in seiner eigenen Vorstellung, statt die Umgebung zu fragen. Ich habe das in einer Python-Datei gebaut, ohne PyTorch, ohne GPU, nur mit der Standardbibliothek. Der interessanteste Messwert kam heraus, als das gelernte Modell besser plante als die echte Welt.

Woher die Zahlen stammen. Alle Messwerte in diesem Beitrag stammen aus meinen eigenen Läufen des Projekts. Alles ist gesät, zwei Läufe liefern dieselben Zahlen. Ein vollständiger Durchlauf dauert auf meinem Rechner 2 Minuten 12 Sekunden, davon 96 Sekunden für den Autoencoder.

Was ein Weltmodell ist

Ein Agent, der lernen soll, probiert normalerweise in der Umgebung herum. Jeder Versuch kostet einen echten Schritt. Ein Weltmodell verschiebt das Probieren nach innen: Der Agent lernt aus seinen bisherigen Beobachtungen eine Nachbildung der Umgebung und spielt Handlungsfolgen darin durch, bevor er sich in der Wirklichkeit bewegt. Ha und Schmidhuber haben das 2018 unter dem Namen World Models populär gemacht, Hafner et al. 2020 mit Dream to Control auf richtige Aufgaben gebracht.

Die veröffentlichten Arbeiten arbeiten mit VAEs, rekurrenten Netzen und mehreren GPU-Tagen. Ich wollte wissen, welcher Teil davon das eigentliche Prinzip trägt, und habe die kleinste Fassung gebaut, die noch funktioniert. Kein Framework, keine Bibliothek, eine Datei mit rund 900 Zeilen. Das Ziel war Durchschaubarkeit, nicht Produktionsreife: Jede Zahl im Ergebnis lässt sich auf eine Zeile Code zurückführen.

Die Welt

Ein Raum aus 7×7 Feldern. # ist Wand, Z das Ziel, o der Agent:

#######
#..#..#
#..#..#
#..o..#
#.##..#
#....Z#
#######

Vier Aktionen, eine Belohnung von 1 auf dem Zielfeld, sonst nichts. Der Agent bekommt nie eine Koordinate zu sehen. Seine gesamte Wahrnehmung sind diese 49 Felder als Grauwerte: Wand 1,0, Ziel 0,6, er selbst 0,3, freies Feld 0. Wo er steht, wo die Wände sind und wo es Belohnung gibt, muss das Modell aus Bildern herausziehen.

Die Datenlage ist knapp, und das mit Absicht. Gesammelt wird mit einer Zufallspolitik, die in 94 Episoden 38-mal das Ziel erreicht. Von 3000 aufgezeichneten Übergängen tragen 1,3 Prozent überhaupt eine Belohnung. Mit dieser Ausbeute muss das Modell auskommen, so wie in echten Anwendungen auch.

Schritt 1: Sammeln

Der Agent läuft zufällig durch den Raum, und jeder Übergang wird mitgeschrieben: Bild vorher, Aktion, Bild nachher, Belohnung, Endsignal. Das ist der ganze Schritt. Er dauert Sekunden und ist der einzige Moment, in dem die echte Umgebung noch gebraucht wird.

python weltmodell.py sammeln       # 3000 Übergänge -> daten.json

Schritt 2: Sehen

Autoencoder

49 Pixel durch 8 Zahlen pressen und zurück

Encoder 49 → 24 → 8 (tanh) · Decoder 8 → 24 → 49 (tanh, sigmoid) · 16 Epochen, Adam, Lernrate 0,01

Der Trick ist der Engpass. Wer 49 Pixel durch 8 Zahlen schicken und danach rekonstruieren muss, kann nichts abspeichern, er muss zusammenfassen. Die Karte ist immer dieselbe, veränderlich ist nur die Agentenposition. Also lernt der Engpass im Kern eine Koordinate. Niemand hat ihm das gesagt.

Die erste Fassung lief 16 Epochen durch und lieferte einen Rekonstruktionsfehler von 0,0015, der nicht mehr fiel. Das sieht nach Konvergenz aus. Tatsächlich war es exakt der Fehler, den man bekommt, wenn man die Wände und das Ziel perfekt malt und den Agenten weglässt: ein Pixel von neunundvierzig, im Mittel unsichtbar. Die Positionsquote lag bei 4 bis 8 Prozent, also schlechter als ein starres Modell, das behauptet, nichts ändere sich.

Die Ursache stand in den Latents:

latent  ['-1.00', '1.00', '-1.00', '-1.00', '1.00', '-1.00', '-1.00', '0.03']

Sieben von acht Zahlen kleben an ±1. In fast jedem Pixel steht immer derselbe Wert, die Wände bewegen sich nie. Diese Konstanten treiben die gewichtete Summe im Encoder so weit ins Positive oder Negative, dass tanh sättigt, und dort ist die Ableitung null. Es kam kein Gradient mehr zurück. Die Lösung ist eine Zeile: das Durchschnittsbild abziehen, bevor der Encoder das Bild sieht. Danach steht im Bild nur noch, was sich tatsächlich ändert. Positionsquote nach 16 Epochen: 100 Prozent.

Die Kennzahl war falsch gewählt. Der Fehler wäre nie aufgefallen, wenn ich nur auf die Verlustkurve geschaut hätte, denn 0,0015 sieht klein aus. Seitdem zählt das Training bei jeder Epoche mit, ob der Agent in der Rekonstruktion auf dem richtigen Feld landet. Das sind zwölf Zeilen und der einzige Grund, warum das Problem sichtbar wurde.
Epoche  5  Rekonstruktionsfehler 0.00146   Agent gefunden 38.3%
Epoche  6  Rekonstruktionsfehler 0.00076   Agent gefunden 85.3%
Epoche  7  Rekonstruktionsfehler 0.00022   Agent gefunden 100.0%

Dieselbe Falle steht in jedem Projekt, in dem ein Durchschnittsmaß über viele Dimensionen als Erfolgskriterium dient. Der Verlust misst, was leicht zu messen ist. Ob er das misst, worauf es ankommt, ist eine getrennte Frage, und sie wird selten gestellt.

Schritt 3: Träumen

Dynamiknetz

Zustand + Aktion → nächster Zustand, Belohnung, Ende

Netz 12 → 32 → 10 (tanh, linear) · 20 Epochen · Belohnung mit Faktor 10 gewichtet

Das eigentliche Weltmodell. Eingabe sind die acht Zahlen aus Schritt 2 plus die Aktion als Vier-Bit-Vektor, Ausgabe der nächste Zustand, die vorhergesagte Belohnung und ob die Episode endet. Die Zielzustände kommen aus dem bereits fertigen Encoder. Das Dynamiknetz sieht kein einziges Pixel.

Dieser Bruch ist der Punkt, an dem Weltmodelle brauchbar werden. Planen kostet danach acht Zahlen statt neunundvierzig, und der Aufwand pro geträumtem Schritt hängt nicht mehr an der Bildgröße. Bei 49 Pixeln ist das eine Fingerübung, bei einem Kamerabild macht es den Unterschied zwischen planbar und nicht planbar.

Eine Kleinigkeit hat mich dabei aufgehalten: Die Belohnung ist in weniger als zwei Prozent der Daten ungleich null. Ohne Gegengewicht lernt das Netz, immer null zu sagen, und liegt damit fast immer richtig. Der Belohnungsanteil im Verlust bekommt deshalb den Faktor 10.

So sieht ein Traum aus. Links die Welt, rechts das, was das Modell sich vorstellt, nachdem es die letzte Beobachtung vor zwei Zügen gesehen hat:

2. rechts  Belohnung echt 0 / getraeumt 0.00
Welt       Traum
#######    #######
#..#..#    #..#..#
#..#..#    #..#..#
#.....#    #.....#
#.##.o#    #.##.o#
#....Z#    #....Z#
#######    #######

Wie weit der Traum trägt

Das Kommando messen gibt dem Modell ein Bild und danach nur noch Aktionen. Gezählt wird, ob der geträumte Agent auf dem richtigen Feld steht. Zum Vergleich läuft das starre Modell mit, das behauptet, nichts ändere sich, also die Latte, die ein Weltmodell reißen kann:

SchrittPosition richtigPixelfehlerStarres Modell
195,0 %0,0001435,0 %
392,7 %0,0002727,1 %
583,6 %0,0005216,9 %
1071,3 %0,0009116,0 %

Der Traum zerfällt langsam, und er zerfällt vorhersehbar. Das ist die Zahl, aus der später der Planungshorizont folgt: Der Agent plant sechs Schritte weit und liest danach wieder die Wirklichkeit ein.

Schritt 4: Planen

Der Planer ist der billigste, der noch funktioniert. Random Shooting mit Model Predictive Control: 100 Aktionsfolgen würfeln, jede im Traum durchspielen, die vorhergesagten Belohnungen mit 0,95 abgezinst aufsummieren, den ersten Zug der besten Folge ausführen und danach neu planen. Das Neuplanen sorgt dafür, dass sich Modellfehler nicht über die ganze Episode aufaddieren.

Zum Vergleich läuft derselbe Planer mit der echten Umgebung als Modell, also mit perfektem Wissen. Ich nenne ihn Orakel, er ist die Obergrenze für dieses Verfahren. Dazu ein Agent ohne Modell, der nur würfelt. 20 Episoden, Abbruch nach 40 Schritten:

HorizontWeltmodellOrakelZufall
38/20, 25,0 Schritte15/20, 17,89/20, 33,1
620/20, 4,5 Schritte19/20, 11,39/20, 33,1
1220/20, 4,5 Schritte20/20, 5,29/20, 33,1

Bei Horizont 6 ist der Träumer besser als die Wirklichkeit. Ein gelerntes Modell kann nicht besser sein als das Original, also habe ich nachgesehen, woher der Vorsprung kommt.

Warum der Träumer das Orakel schlägt

Er kommt von den Feldern, die weiter als sechs Schritte vom Ziel entfernt sind. Dort findet das Orakel in 100 gewürfelten Folgen keine einzige, die das Ziel trifft. Alle Folgen bekommen den Wert 0, der Planer hat nichts zu vergleichen und wählt praktisch zufällig.

Das Weltmodell dagegen halluziniert Belohnungen zwischen 0,00003 und 0,77, und zwar bevorzugt für Folgen, die in die richtige Richtung laufen. Aus einer Belohnung, die nur auf einem einzigen Feld existiert, wird ein Gefälle über den ganzen Raum. Das Kommando warum misst beide Hälften dieser Erklärung nach, auf den drei Feldern jenseits des Horizonts, 30 Wiederholungen, 90 Züge je Planer:

PlanerZug verkürzt den Weg zum Ziel
Weltmodell82,2 %
Orakel46,7 %

Bei Horizont 12, wenn das Orakel die Belohnung selbst findet, holt es auf und zieht mit 20 von 20 gleich. Der Vorsprung des Träumers war also geborgt: Seine Ungenauigkeit wirkte wie ein geformtes Belohnungssignal, das ihm niemand gegeben hat.

Das ist bequem und gefährlich zugleich. Dieselbe Unschärfe kann Belohnungen genauso gut dort erfinden, wo keine sind. Bei Horizont 3 passiert genau das: 8 von 20 Episoden, damit schlechter als reiner Zufall mit 9 von 20. Wer eine solche Zahl in einem Projekt sieht und sich darüber freut, hat noch nicht verstanden, wovon sie kommt. Die Frage nach der Ursache ist mir hier dreimal begegnet und war jedes Mal die Arbeit wert.

Was bewusst fehlt

Das Projekt lässt eine Menge weg, und jede Auslassung hat einen Grund. Wer die Fassung erweitert, fängt hier an:

Was ich mitgenommen habe

Drei Punkte, die sich auf andere Projekte übertragen lassen.

Erstens misst der Verlust selten das, was zählt. Ein Rekonstruktionsfehler von 0,0015 sah nach einem fertigen Modell aus, während der Agent in der Rekonstruktion gar nicht vorkam. Die zwölf Zeilen, die eine fachliche Kennzahl nebenher mitzählen, sind der beste Zeitinvest im ganzen Projekt gewesen.

Zweitens lohnt sich eine dumme Vergleichslinie. Das starre Modell, das behauptet, nichts ändere sich, kostet vier Zeilen und beantwortet die Frage, ob das gelernte Modell überhaupt etwas gelernt hat. Ohne diese 35 Prozent im ersten Schritt hätte ich die kaputte Fassung für funktionierend gehalten.

Drittens ist ein unerwartet gutes Ergebnis ein Grund zum Nachsehen. Der Träumer, der das Orakel schlägt, war der Moment, an dem das Projekt interessant wurde, und er war ein Fehler des Modells, kein Können.

Der ganze Aufbau läuft in 132 Sekunden auf einer CPU durch, in einer Datei, mit der Python-Standardbibliothek. Wer verstehen will, was Weltmodelle tun, braucht dafür weder GPU noch Framework.

Reinforcement Learning oder LLM-Anwendung im Aufbau?

Ich baue KI-Anwendungen für den Produktivbetrieb und schaue dabei besonders auf die Stelle, an der eine Kennzahl gut aussieht und das System trotzdem nicht tut, was es soll. 30 Minuten Erstgespräch, kostenlos.