Praktischer KI-Kurs
Was ist KI?
Agent: Etwas, das wahrnimmt und in einer Umgebung handelt
- Sensoren → Umgebung → Aktuatoren
- Hat ein Ziel, das es zu erreichen versucht
Beispiele:
- Staubsaugerroboter: Sensoren (Schmutz, Stoß), Aktuatoren (Räder), Ziel (reinigen)
- Schach-KI: Sensoren (Brett), Aktuatoren (Züge), Ziel (Matt)
- Selbstfahrendes Auto: Sensoren (Kameras), Aktuatoren (Lenkung), Ziel (Ziel erreichen)
Problemformulierung
5 Komponenten eines Suchproblems:
- Anfangszustand - wo wir starten
- Aktionen - was wir tun können
- Übergangsmodell - Ergebnis von Aktionen
- Zieltest - sind wir fertig?
- Pfadkosten - wie teuer? (optional)
Beispiel: Labyrinth-Navigation
Problem-Definition:
- Anfangszustand: (0, 0) - oben links
- Aktionen:
- Übergang: bewegen, wenn keine Wand
- Zieltest: (5, 5) erreicht?
- Kosten: Anzahl Schritte
Zustandsraum = Graph
- Knoten = Zustände
- Kanten = Aktionen
- Suche erkundet diesen Graph
Alle vom Anfangszustand erreichbaren Zustände
Breitensuche (BFS)
Idee: Erkunde Distanz k vor k+1
Algorithmus:
- Warteschlange ← [anfangszustand]
- Solange Warteschlange nicht leer:
- Entferne vordersten
- Wenn Ziel → fertig!
- Füge Nachbarn hinten hinzu
- Markiere besucht
Datenstruktur: Warteschlange (FIFO)
BFS-Eigenschaften
✓ Vollständig: Findet immer Lösung ✓ Optimal: Findet kürzesten Pfad (ungewichtet) ✗ Speicher: O(b^d) - hoher Speicher!
- Zeit: O(b^d)
- b = Verzweigungsfaktor
- d = Tiefe der Lösung
Tiefensuche (DFS)
Idee: Gehe tief vor Alternativen erkunden
Algorithmus:
- Stapel ← [anfangszustand]
- Solange Stapel nicht leer:
- Entferne obersten
- Wenn Ziel → fertig!
- Füge Nachbarn oben hinzu
- Markiere besucht
Datenstruktur: Stapel (LIFO)
DFS-Eigenschaften
✗ Vollständig: Nein (unendliche Schleifen) ✗ Optimal: Nein (findet einen Pfad) ✓ Speicher: O(bd) - wenig Speicher!
- Zeit: O(b^m)
- m = maximale Tiefe
BFS vs DFS
| BFS | DFS | |
|---|---|---|
| Struktur | Warteschlange | Stapel |
| Vollständig? | Ja | Nein |
| Optimal? | Ja | Nein |
| Speicher | O(b^d) | O(bd) |
| Verwenden wenn | Kürzester Pfad | Tiefe Lösung |
Wichtige Implementierungs-Details
Immer besucht verfolgen:
besucht = set()
besucht.add(zustand)2
Pfad rekonstruieren mit vorgaenger-Dict:
vorgaenger = {zustand: vorheriger_zustand}
# Rückwärts von Ziel zu Start2
Modul 2: Informierte Suche
Sitzungen 3-4
Einschränkung uninformierter Suche
Problem: Erkundet blind!
- Kein Wissen über Ziel-Position
- Verschwendet Zeit in falschen Richtungen
- Ineffizient für große Räume
Lösung: Verwende Domänenwissen
Heuristische Funktionen
h(n) = geschätzte Kosten von n zum Ziel
- Domänenspezifisches Wissen
- Leitet Suche zum Ziel
- Nie perfekt, nur Schätzung
Gitter-Pfadfindungs-Heuristiken
Manhattan-Distanz:
h(n) = |x_ziel - x_aktuell| + |y_ziel - y_aktuell|- Für 4-Richtungs-Bewegung
- Immer zulässig
Euklidische Distanz:
h(n) = √[(x_ziel - x_aktuell)² + (y_ziel - y_aktuell)²]- Für diagonale Bewegung
- Luftlinien-Distanz
8-Puzzle-Heuristiken
Falsch platzierte Steine:
- Zähle Steine in falscher Position
- Einfach aber schwach
Manhattan-Distanz:
- Summe der Distanzen, die jeder Stein bewegen muss
- Stärker (informierter)
Gierige Best-First-Suche
Idee: Expandiere immer Knoten am nächsten zum Ziel (niedrigstes h)
Algorithmus:
- Prioritätswarteschlange geordnet nach h(n)
- Expandiere niedrigstes h zuerst
✓ Schnell ✗ Nicht vollständig ✗ Nicht optimal (ignoriert bisherige Kosten!)
A*-Suchalgorithmus
Idee: Balanciere bisherige Kosten + geschätzte verbleibende
f(n) = g(n) + h(n)
- g(n) = tatsächliche Kosten von Start zu n
- h(n) = geschätzte Kosten von n zu Ziel
- f(n) = geschätzte Gesamtkosten durch n
A*-Algorithmus
Prioritätswarteschlange geordnet nach f(n) = g(n) + h(n)
- Expandiere niedrigstes f(n)
- Aktualisiere g-Werte für Nachbarn
- Füge zur Warteschlange mit neuem f hinzu
- Stoppe wenn Ziel expandiert
Zulässige Heuristiken
h(n) ≤ wahre_kosten(n, ziel)
Nie überschätzen!
Beispiele: ✓ Manhattan-Distanz (4-Richtungen) ✓ Euklidische Distanz ✓ Luftlinien-Distanz ✗ 2 × Manhattan (überschätzt!)
Wichtig: Wenn h zulässig → A* optimal!
Warum A* optimal ist
Bei zulässiger Heuristik:
- A* findet immer kürzesten Pfad
- Übersieht nie bessere Lösung
- Expandiert Knoten in Best-First-Reihenfolge
Algorithmen-Vergleich
| BFS | DFS | Gierig | A* | |
|---|---|---|---|---|
| Vollständig | ✓ | ✗ | ✗ | ✓ |
| Optimal | ✓* | ✗ | ✗ | ✓** |
| Geschwindigkeit | Langsam | Schnell | Schnell | Mittel |
* gleiche Kosten | ** zulässiges h
Modul 3: Spielbäume
Sitzungen 5-6
Adversariale Suche
Neue Herausforderung: Gegner handelt gegen uns!
- Zwei Spieler mit gegensätzlichen Zielen
- Kann Gegner nicht kontrollieren
- Muss ihre Züge antizipieren
Fokus: Deterministisch, perfekte-Info, Nullsummen-Spiele
Beispiele: Tic-Tac-Toe, Schach, Vier Gewinnt
Spielbäume
Baum repräsentiert alle Zugfolgen
- Knoten = Spielzustände
- Kanten = mögliche Züge
- Schichten wechseln zwischen Spielern
- Blätter = terminale Zustände (Sieg/Niederlage/Unentschieden)
Problem: Exponentielles Wachstum!
- Tic-Tac-Toe: ~5.000 Knoten ✓
- Schach: ~10^120 Spiele ✗
Minimax-Algorithmus
Annehmen beide spielen optimal
- MAX-Spieler: will höchste Punktzahl (wir)
- MIN-Spieler: will niedrigste Punktzahl (Gegner)
Nutzen:
- MAX gewinnt: +1
- MIN gewinnt: -1
- Unentschieden: 0
Minimax-Logik
Wenn terminal:
return nutzen(zustand)
Wenn MAX am Zug:
return max der Kinder
Wenn MIN am Zug:
return min der Kinder2
3
4
5
6
7
8
Werte propagieren aufwärts im Baum
Minimax-Beispiel
MAX
/ \
MIN MIN
/ \ / \
3 12 8 2
MIN: min(3,12)=3 min(8,2)=2
MAX: max(3,2) = 32
3
4
5
6
7
8
MAX wählt linken Zweig
Minimax-Eigenschaften
✓ Vollständig: Ja (endlicher Baum) ✓ Optimal: Ja (gegen optimalen Gegner) ✗ Geschwindigkeit: O(b^m) - zu langsam!
- b = Verzweigungsfaktor
- m = max Tiefe
Brauchen: Intelligentere Suche!
Alpha-Beta-Pruning
Idee: Erkunde Zweige nicht, die Ergebnis nicht beeinflussen können
Verfolge zwei Werte:
- α = bestes was MAX garantieren kann
- β = bestes was MIN garantieren kann
Pruning wenn:
- MAX: Wert ≥ β (MIN erlaubt nicht)
- MIN: Wert ≤ α (MAX erlaubt nicht)
Alpha-Beta-Beispiel
MAX (α=-∞, β=+∞)
/ \
MIN MIN
/ \ / \
3 12 2 ?
Nach Finden von 3: β=3
Beim Finden von 2: 2≤α
→ PRUNING! (Erkunde ? nicht)2
3
4
5
6
7
8
9
Alpha-Beta-Effektivität
Bester Fall: O(b^(m/2))
- Verdoppelt effektive Suchtiefe!
- Minimax Tiefe 4 → Alpha-Beta Tiefe 8
Hängt von Zugreihenfolge ab:
- Beste Züge zuerst → mehr Pruning
- Zufällige Reihenfolge → weniger Pruning
Bewertungsfunktionen
Problem: Kann nicht bis zum Ende in komplexen Spielen suchen
Lösung: Schätze Positionswert
Schach-Beispiel:
bewertung = 9×Damen + 5×Türme + 3×Läufer
+ 3×Springer + 1×Bauern
(Material-Differenz)2
3
Besser: Füge Position, Mobilität, König-Sicherheit hinzu
Tiefenlimitierte Suche
Alpha-Beta + Bewertungsfunktion:
- Suche bis feste Tiefe
- Bewerte nicht-terminale Positionen
- Wähle besten Zug nach Schätzung
Abwägung:
- Tiefer = besser aber langsamer
- Typisch: 6-12 Halbzüge in Spielen
Iterative Vertiefung
Suche progressiv tiefer:
Tiefe 1: 0.001s
Tiefe 2: 0.01s
Tiefe 3: 0.1s
Tiefe 4: 1s ← Zeitlimit2
3
4
Verwende Tiefe-3-Ergebnis
✓ Immer Zug bereit ✓ Bessere Zugreihenfolge ✓ Minimaler Overhead
Zusammenfassung: Suchalgorithmen
Uninformiert:
- BFS: optimal, hoher Speicher
- DFS: niedriger Speicher, nicht optimal
Informiert:
- A*: optimal mit zulässigem h
Spielen:
- Minimax: optimal gegen optimal
- Alpha-Beta: schneller durch Pruning
Wichtigste Erkenntnisse
- Heuristiken leiten Suche effizient
- Zulässigkeit sichert Optimalität
- Minimax nimmt optimalen Gegner an
- Alpha-Beta pruned nutzlose Zweige
- Bewertungsfunktionen schätzen nicht-terminale Zustände
- Tiefenlimitierung macht große Spiele handhabbar
Nächstes: Grid World Battle-Projekt
Wende diese Konzepte an:
- Pfadfindung (A*)
- Entscheidungsfindung
- Gegner-Modellierung
- Ressourcen-Management
Lasst uns KI-Agenten bauen!