Die Sprache der Katze
Katzen verbergen ihre Stimmung im Gesicht — aber sie verraten sie im Klang. Du baust die zweistufige Kette aus dem Buch nach: erst die Art des Lauts, dann — trainiert an echten Daten — das Gefühl im Miau.
Kurz gesagt
Was: Du verwandelst Katzenlaute — wie schon Stimme und Pflanzensignal — in Merkmale ihres Klangs und baust zwei kleine Modelle hintereinander. Das erste sortiert die Art des Lauts (Fauchen, Schnurren, Zwitschern, Miau). Das zweite fragt nur beim Miau nach der Stimmung — und lernt sie an einem echten Datensatz mit Hunderten von Miaus.
Der Kern-Gedanke: Es ist dieselbe zweistufige Idee wie „Beti“ und „Kisha“ aus dem Buch. Den leichten Teil — die Art — trainierst du an ein paar eigenen Aufnahmen. Den schweren Teil — das Gefühl im Miau — kann man nicht mit einer Handvoll Beispiele lernen; dafür holst du dir echte Daten von Kaggle.
Du brauchst: den CatMeows-Datensatz von Kaggle, Python mit librosa für die
Klanganalyse und scikit-learn für die beiden Modelle. Optional ein paar eigene Katzen
aufnahmen zum Testen.
Worum es geht
Hund und Pferd tragen ihre Stimmung nach aussen — in Haltung und Gesicht. Die Katze hält sie verborgen. Dafür redet sie mit uns: Das Miauen setzen erwachsene Katzen fast nur gegenüber Menschen ein, untereinander kaum. Wenn wir eine Katze lesen wollen, hören wir also nicht auf das Gesicht, sondern auf den Klang.
Und der Klang wird lesbar wie alles in diesem Buch: Wir machen ein Bild daraus. Ein Spektrogramm zeigt die Frequenzen eines Lautes über die Zeit — und schon greift dieselbe Bilderkennung, die sonst Katze von Hund unterscheidet. Aus einem Fauchen, einem Schnurren, einem Miau werden Zahlen, und aus den Zahlen eine vorsichtige Vermutung.
Bevor du startest
Für die zweite Stufe brauchst du echte Daten. Der frei verfügbare CatMeows-Datensatz enthält 440 Miaus von 21 Katzen, aufgenommen in drei Situationen, die als Gefühls-Etiketten dienen: beim Streicheln (behaglich), in fremder Umgebung allein (verunsichert) und beim Warten aufs Futter (fordernd). Genau diese Situationen wird dein Modell später auseinanderhalten lernen.
Ein bisschen Hintergrund
Zwei Ohren, die nacheinander hören. Im Buch stecken zwei Modelle hintereinander. Das erste, „Beti“, sortiert einen Laut zunächst grob nach seiner Art und liegt dabei in etwa 85 von 100 Fällen richtig. Schon das verrät etwas: Ein Fauchen klingt nach Stress, ein Schnurren nach Behagen. Beim Miau aber bleibt das Gefühl offen — und hier übernimmt das zweite Modell, „Kisha“, das allein auf Miaus spezialisiert ist und mit knapp 92 Prozent glücklich, wütend und traurig unterscheidet. Aus dieser Kette wurde die kleine App CatMotion.
Warum echte Daten für die zweite Stufe? „Ist es überhaupt ein Miau?“ ist klanglich leicht — dafür reichen wenige Beispiele. „Wie fühlt sich dieses Miau an?“ ist viel feiner: Die Unterschiede sind subtil, und ein Modell erkennt sie nur, wenn es viele Miaus vieler Katzen gesehen hat. Genau darum lernt Kisha an Hunderten von Beispielen statt an deiner Handvoll — sonst würde es sich Sicherheit nur einbilden.
Die Daten holen
- Pakete installieren.
pip install librosa scikit-learn numpy soundfile. - CatMeows herunterladen. Von Kaggle:
kaggle.com/datasets/andrewmvd/cat-meow-classification(Zip herunterladen und entpacken). Die Miaus liegen als WAV im Ordnerdataset/. Alternativ dieselben Daten auf Zenodo (Datensatz 4008297). - Die Etiketten verstehen. Jeder Dateiname beginnt mit dem Situations-Buchstaben: B (Brushing / Streicheln), I (Isolation), F (Food / Futter). Die genaue Namensregel steht auf der Dataset-Seite — wirf einen Blick hinein, bevor du weitermachst.
- Optional: eigene Testlaute. Nimm ein paar Miaus deiner eigenen Katze auf
(
test_miau.wav), um das fertige Modell an frischem Material zu prüfen.
Stufe 1 — die Art des Lauts („Beti“)
Die grobe Einteilung ist klanglich leicht — dafür genügen ein paar eigene Aufnahmen je Art. Aus jedem
Laut ziehen wir eine handliche Zahlenreihe: die MFCC, einen kompakten Fingerabdruck des Klangs, den
librosa direkt liefert. Der vollständige Code liegt auf
GitHub.
import librosa
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
def merkmale(datei):
y, sr = librosa.load(datei) # Laut laden
mfcc = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)
# Mittelwert und Streuung ueber die Zeit -> ein Fingerabdruck des Klangs
return np.concatenate([mfcc.mean(axis=1), mfcc.std(axis=1)])
# ein paar eigene Aufnahmen je Art (Art ist klanglich leicht zu trennen)
training = [
("fauchen1.wav", "Fauchen"), ("fauchen2.wav", "Fauchen"),
("schnurren1.wav", "Schnurren"), ("schnurren2.wav", "Schnurren"),
("zwitschern1.wav", "Zwitschern"), ("zwitschern2.wav", "Zwitschern"),
("miau1.wav", "Miau"), ("miau2.wav", "Miau"),
]
X = np.array([merkmale(d) for d, _ in training])
y = [art for _, art in training]
beti = KNeighborsClassifier(n_neighbors=1).fit(X, y) # bei wenig Daten: naechster Nachbar
print("Beti sagt:", beti.predict([merkmale("test_miau.wav")])[0])
Stufe 2 — die Stimmung im Miau („Kisha“)
Jetzt der schwere Teil. Kisha lernt nicht an deinen paar Aufnahmen, sondern an den Hunderten Miaus aus CatMeows. Wir lesen den Ordner ein, holen aus jedem Dateinamen die Situation und trainieren — und, ganz wichtig, wir prüfen ehrlich an zurückgehaltenen Daten, wie gut es wirklich ist.
import glob, os
from sklearn.model_selection import train_test_split
ORDNER = "cat-meow-classification/dataset" # entpacktes Kaggle-Dataset
situation = {"B": "behaglich", "I": "verunsichert", "F": "fordernd"}
X, y = [], []
for datei in glob.glob(os.path.join(ORDNER, "*.wav")):
kennung = os.path.basename(datei)[0].upper() # erster Buchstabe = Situation
if kennung in situation:
X.append(merkmale(datei))
y.append(situation[kennung])
X = np.array(X)
print("gelesen:", len(X), "Miaus")
# ehrlich pruefen: ein Viertel zurueckhalten
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.25,
random_state=0, stratify=y)
kisha = KNeighborsClassifier(n_neighbors=5).fit(Xtr, ytr)
print("Treffer auf ungesehenen Miaus:", round(kisha.score(Xte, yte), 2))
# die volle Kette: erst Art (Beti), dann — nur bei Miau — Stimmung (Kisha)
def deute(datei):
art = beti.predict([merkmale(datei)])[0]
if art == "Miau":
return f"Miau — klingt {kisha.predict([merkmale(datei)])[0]}"
return art
print(deute("test_miau.wav"))
Was du sehen solltest
Kisha trifft auf den ungesehenen Miaus deutlich besser als der Zufall (der läge bei einem Drittel), aber klar unter den 92 Prozent aus dem Buch — ein einfaches KNN auf MFCC ist eben kein feinjustiertes Spezial-Netz. Genau das ist ehrlich: Mit echten Daten wird die Stimmung überhaupt erst lernbar; mit einem schlichten Modell bleibt sie eine gute, aber unsichere Vermutung. Und dein eigenes Test-Miau? Mal trifft Kisha, mal nicht — auch das ist ein Ergebnis.
Arbeitsblatt
Vom Klang zur Vermutung
- Wie hoch ist Kishas Trefferquote auf den zurückgehaltenen Miaus? Wie viel besser als reines Raten (ein Drittel) ist das?
- Welche zwei Situationen verwechselt Kisha am ehesten? Sieh dir ein paar Spektrogramme an — kannst du erahnen, warum sie sich klanglich ähneln?
- Warum trainieren wir Kisha an CatMeows und nicht an deinen eigenen Aufnahmen — Beti aber schon an deinen paar Aufnahmen? Was ist der Unterschied zwischen den beiden Aufgaben?
- Die Etiketten sind Situationen (Streicheln, Isolation, Futter), keine reinen Gefühle. Warum ist das ein ehrlicherer Name — und wo liegt die Grenze dieser Gleichsetzung?
- Das Miau richtet die Katze fast nur an Menschen. Was heisst das für die Frage, ob wir hier „die Katze“ lesen — oder etwas, das die Katze eigens für uns tut?
Lösung anzeigen
1. Individuell (typisch spürbar über einem Drittel, aber weit unter 90 %). Wichtig ist, die Zahl an der Zufallslinie zu messen: „besser als raten“ ist der Beleg, dass im Klang wirklich etwas über die Situation steckt.
2. Oft verschwimmen „verunsichert“ und „fordernd“, weil beide drängend und angespannt klingen können, während „behaglich“ ruhiger ist. Im Spektrogramm zeigen sich das an Tonhöhe, Länge und Rauigkeit.
3. „Ist es ein Miau?“ ist klanglich leicht — Fauchen, Schnurren und Miau sind sehr verschieden, dafür reichen wenige Beispiele. „Wie fühlt sich das Miau an?“ ist fein und variabel; das lernt ein Modell nur aus vielen Miaus vieler Katzen. Wenige eigene Aufnahmen würden hier nur Sicherheit vortäuschen.
4. Wir wissen sicher, in welcher Situation aufgenommen wurde, nicht sicher, was die Katze dabei fühlt. „Situation“ ist deshalb ehrlicher als „Gefühl“. Die Grenze: Streicheln heisst meist, aber nicht immer Behagen — Situation ist ein guter, aber kein perfekter Stellvertreter fürs Gefühl.
5. Es verschiebt die Frage: Wir lesen weniger einen inneren Zustand als ein an Menschen gerichtetes Kommunikationssignal. Das macht es nicht unecht — aber es ist eine für uns entwickelte Sprache, kein Fenster in die Katzenseele.
Wenn's klemmt
| Problem | Wahrscheinliche Ursache & Lösung |
|---|---|
glob findet keine Dateien | Falscher Ordnerpfad. Prüfe, wohin du entpackt hast, und passe ORDNER an — die WAVs liegen im Unterordner dataset/. |
gelesen: 0 Miaus | Die Dateinamen beginnen anders als erwartet. Sieh dir einen Namen an und passe die Zuordnung in situation an die tatsächlichen Anfangsbuchstaben an. |
| Kisha trifft kaum besser als Zufall | Zu wenige Merkmale. Erhöhe n_mfcc, probiere n_neighbors zwischen 3 und 9, oder ergänze Tonhöhe und Lautstärke (wie in 10.1). |
| Beti verwechselt Zwitschern und Miau | Beide sind hell und kurz. Nimm klarere, längere Beispiele auf oder gib mehr je Art. |
| Sehr langsam | Viele Dateien. Einmal die Merkmale berechnen und in einem Array behalten; optional mit librosa.load(datei, sr=16000) laden. |
Zum Nachdenken
- Immer wird ein Bild daraus: Gesicht, Stimme, Pflanzensignal — und jetzt der Katzenlaut. Sobald ein Signal ein Spektrogramm ist, liest es dieselbe Maschinerie. Ein Babelfisch, viele Arten.
- Die zweistufige Kette ist ein schönes Muster: eine schwere Aufgabe in eine leichte und eine feine zerlegen — und für die feine echte Daten holen, statt sich mit wenigen Beispielen zu täuschen.
- Halte die Grenze: Der gelesene Laut ist ein Ausdruck in einer Situation, kein Beweis eines Gefühls. Richtig eingesetzt — um früh Stress oder Schmerz zu bemerken — ist so ein Leser Fürsorge; leichtfertig gedeutet wird er zur Projektion.
Erweiterung
- Spektrogramme sichtbar machen. Zeichne mit
librosa.display.specshow(librosa.amplitude_to_db(np.abs(librosa.stft(y))))das Bild einzelner Miaus aus den drei Situationen. Siehst du selbst einen Unterschied? - Konfusionsmatrix. Lass dir mit
sklearn.metrics.confusion_matrix(yte, kisha.predict(Xte))zeigen, welche Situationen am häufigsten verwechselt werden. Deckt sich das mit deinem Höreindruck? - Ein echtes Netz. Statt KNN auf MFCC: verwandle jeden Laut in ein Spektrogramm-Bild und trainiere ein kleines Bild-Netz darauf — der Schritt vom Zahlen-Fingerabdruck zur echten Bilderkennung aus Kapitel 3.