Verborgene Signale · Begleitseite ← Alle Aktivitäten DE·EN
Kapitel 13 · Pflanzen, die uns lesen · Aktivität 13.2

Pflanzen-Emotionen mit KI

Aus dem Signal wird ein Bild, und ein vortrainiertes Netz liest es: Kann man dem Pflanzensignal ansehen, ob der Mensch daneben gerade glücklich war? Reine Inferenz — du trainierst kein eigenes Netz.

Dauer Doppelstunde Schwierigkeit hoch Gruppe allein oder zu zweit Voll digital S

Kurz gesagt

Was: Du nimmst das rohe Spannungssignal einer Zimmerpflanze und die zeitgleich per Smartwatch gemessene Stimmung des Menschen daneben. Zu jeder Stimmungs-Lesung schneidest du das Pflanzensignal der letzten Minuten heraus, machst — wie überall in diesem Buch — ein Spektrogramm daraus und lässt ein fertig vortrainiertes Netz (ResNet) das Bild lesen. Ein einfaches Nächste-Nachbarn-Verfahren rät daraus die Stimmung.

Der Kern-Gedanke: reine Inferenz. Das tiefe Netz hat längst an Millionen Bildern gelernt — du trainierst es nicht, du benutzt es als fertiges „Auge“. Und dies ist das Skepsis-Kapitel: Du prüfst nüchtern, wie viel — und wie wenig — im Signal wirklich steckt.

Du brauchst: den Datensatz von figshare (31527778) mit plant_raw.csv und predictions.csv, dazu Python mit pandas, scipy, torch/torchvision und scikit-learn.

Worum es geht

Wenn eine Pflanze auf Licht reagiert — reagiert sie auch auf uns? In einer Selbststudie über elf Tage saß ein Mensch an seinem Schreibtisch, einen halben Meter neben einer Tradescantia. Ein einfacher Sensor griff das elektrische Signal der Pflanze ab; gleichzeitig schätzte eine Happimeter-Smartwatch am Handgelenk laufend die Stimmung — glücklich, gestresst, niedergeschlagen. So liegen zwei Spuren nebeneinander: hier das Pflanzensignal, dort die Stimmung des Menschen.

Die Frage ist heikel und darum spannend: Steckt im Pflanzensignal wirklich etwas über den Menschen? Statt es zu glauben, machst du es zum Bild und lässt eine KI schauen — und prüfst dann ehrlich, ob ihre Vermutung besser ist als reines Raten.

Bevor du startest — die Daten

Der Datensatz liegt auf figshare unter der DOI 10.6084/m9.figshare.31527778. Zwei Dateien: plant_raw.csv (Spalten timestamp, voltage — rund 312 000 Messpunkte über elf Tage, etwa eine pro Sekunde) und predictions.csv (die Happimeter-Lesungen mit timestamp und happy, stress, depression, je auf einer Stufe von 0 bis 2). Beide werden über den Zeitstempel verbunden.

Ein bisschen Hintergrund

Wieder ein Bild aus dem Signal. Das Verfahren ist dir vertraut: Ein Signal über der Zeit wird zum Spektrogramm — einem Bild seiner Frequenzen — und dann liest es dieselbe bilderkennende Maschinerie wie Katzenlaut, Stimme und Herzschlag. Neu ist nur: Wir trainieren das Netz nicht selbst, sondern nehmen ein fertiges, das schon an Millionen Bildern gelernt hat, und nutzen seine „Sicht“ als Merkmale. Das ist der Kern von Transfer und Inferenz.

Warum die Pflanze langsam ist. Das Pflanzensignal ändert sich über Sekunden bis Minuten, nicht über Millisekunden. Darum schauen wir pro Stimmungs-Lesung auf ein Fenster von einigen Minuten davor — lang genug, dass die langsamen Rhythmen der Pflanze im Spektrogramm sichtbar werden.

Fenster schneiden und Spektrogramme bauen

Zu jeder Happimeter-Lesung holen wir das Pflanzensignal der letzten drei Minuten, bringen es auf ein gleichmässiges 1-Hz-Raster und machen ein Spektrogramm. Der vollständige Code liegt auf GitHub.

import numpy as np, pandas as pd
from scipy import signal, interpolate

roh  = pd.read_csv("plant_raw.csv",  parse_dates=["timestamp"]).sort_values("timestamp")
mess = pd.read_csv("predictions.csv", parse_dates=["timestamp"])   # Happimeter-Lesungen

EPOCHE = pd.Timestamp("1970-01-01")                              # fester Nullpunkt
t    = ((roh["timestamp"] - EPOCHE) / pd.Timedelta(seconds=1)).to_numpy()   # Sekunden
volt = roh["voltage"].to_numpy()

FENSTER = 180                          # Sekunden Pflanzensignal vor jeder Lesung
GRID    = np.arange(0, FENSTER, 1.0)   # auf 1 Hz vereinheitlichen

def spektrogramm(ende_s):
    m = (t >= ende_s - FENSTER) & (t < ende_s)
    if m.sum() < 120:                  # zu wenige Messpunkte -> ueberspringen
        return None
    w = interpolate.interp1d(t[m] - (ende_s - FENSTER), volt[m],
                             bounds_error=False, fill_value="extrapolate")(GRID)
    w = (w - w.mean()) / (w.std() + 1e-9)          # normieren
    _, _, S = signal.spectrogram(w, fs=1.0, nperseg=32, noverlap=16)
    return np.log1p(S)                             # Bild der langsamen Rhythmen

specs, y = [], []
for _, r in mess.iterrows():
    S = spektrogramm((r["timestamp"] - EPOCHE) / pd.Timedelta(seconds=1))
    if S is not None:
        specs.append(S)
        y.append(int(r["happy"] >= 2))            # 1 = gluecklich, 0 = weniger
y = np.array(y)
print(len(specs), "Fenster  |  gluecklich-Balance:", np.bincount(y))

Das vortrainierte Netz liest — reine Inferenz

Jetzt der Kern: Ein ResNet, vortrainiert auf Millionen Bildern, verwandelt jedes Spektrogramm in einen Merkmalsvektor — seine „Sicht“ des Bildes. Es lernt dabei nichts; wir lassen nur ein schlichtes Nächste-Nachbarn-Verfahren aus diesen Merkmalen die Stimmung erraten.

import torch, torch.nn as nn
from torchvision.models import resnet18, ResNet18_Weights
from PIL import Image
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score

gewichte = ResNet18_Weights.IMAGENET1K_V1        # laedt einmalig die Gewichte (Internet noetig)
netz = resnet18(weights=gewichte); netz.fc = nn.Identity(); netz.eval()
vorbereiten = gewichte.transforms()

def merkmale(S):                                 # Spektrogramm -> Bild -> ResNet-Sicht
    a = (S - S.min()) / (np.ptp(S) + 1e-9)
    bild = Image.fromarray((a * 255).astype("uint8")).convert("RGB").resize((64, 64))
    with torch.no_grad():
        return netz(vorbereiten(bild).unsqueeze(0))[0].numpy()

X = np.array([merkmale(S) for S in specs])       # reine Inferenz: das Netz wird nicht trainiert

zufall  = max(np.bincount(y)) / len(y)
treffer = cross_val_score(KNeighborsClassifier(5), X, y, cv=5).mean()
print("Treffer (5-fach):", round(treffer, 2), " |  Zufallslinie:", round(zufall, 2))

Was du sehen solltest

Für „glücklich“ landet das Verfahren ein Stück über der Zufallslinie — eine schwache, aber echte Spur. Probierst du dasselbe mit stress statt happy, wirst du meist kein Signal über dem Zufall finden. Genau das ist die ehrliche, lehrreiche Doppelantwort: Ja, ein Hauch der menschlichen Stimmung steckt im Pflanzensignal — aber nur ein Hauch, und nicht für jede Emotion. Wer hier grosse Prozente erwartet, hat das Skepsis-Kapitel nicht ernst genommen.

Arbeitsblatt

Echt oder eingebildet?

  1. Wie hoch war deine Trefferquote für „glücklich“, wie hoch die Zufallslinie? Wie gross ist der Abstand wirklich?
  2. Tausche das Ziel auf stress (z. B. stress >= 1). Findest du noch etwas über dem Zufall? Was folgt daraus für die Behauptung „die Pflanze liest Gefühle“?
  3. Das Netz wird nie trainiert — trotzdem entstehen brauchbare Merkmale. Erkläre in einem Satz, wie ein auf Fotos trainiertes Netz einem Pflanzen-Spektrogramm nützen kann.
  4. Die ganze Studie beruht auf einer Person und einer Pflanze über wenige Tage. Nenne zwei Gründe, warum das Ergebnis damit spannend, aber nicht allgemeingültig ist.
  5. Selbst wenn „glücklich“ über dem Zufall liegt: Warum folgt daraus nicht, dass die Pflanze „weiss“ oder „fühlt“, wie es dir geht?
Lösung anzeigen

1. Individuell — typisch ein paar Prozentpunkte über der Zufallslinie (die bei etwa gleicher Klassenaufteilung nahe 0,5 liegt). Wichtig ist, den Abstand ehrlich zu benennen: „über dem Zufall“ ist der Beleg, nicht die absolute Zahl.

2. Meist liegt „stress“ nicht über dem Zufall. Folgerung: Nicht jede Emotion hinterlässt eine lesbare Spur; „die Pflanze liest Gefühle“ ist zu grob. Ehrlich ist: eine schwache Spur für manche Zustände, keine für andere.

3. Das Netz hat gelernt, allgemeine Bildmuster zu erkennen — Kanten, Flächen, Texturen. Ein Spektrogramm ist ein Bild solcher Muster, also liefern die frühen, allgemeinen Schichten des Netzes auch hier brauchbare Merkmale, ohne dass es je ein Pflanzensignal gesehen hat.

4. Eine Person/Pflanze/Zeitspanne kann Eigenheiten haben, die nicht allgemein gelten; ohne viele Menschen und Pflanzen und ohne strenge Kontrolle bleibt es ein Einzelfund. Erst Wiederholung macht daraus eine belastbare Aussage.

5. Gemessen ist eine Korrelation zwischen Stimmung und Signalform — kein Mechanismus und kein Bewusstsein. Die Spur führt vermutlich über den Herzschlag (siehe 17.1) und Duftstoffe, nicht über ein „Verstehen“. Korrelation ist nicht Verstehen.

Wenn's klemmt

ProblemWahrscheinliche Ursache & Lösung
ResNet lädt ewig / Fehler beim LadenDie Gewichte werden einmalig heruntergeladen (Internet nötig). Danach liegen sie im Cache. Bei Firewall: das Modell vorab auf einem Rechner mit Internet laden.
0 FensterZeitstempel passen nicht zusammen. Prüfe, ob sich die Zeiträume von plant_raw.csv und predictions.csv überschneiden; nur überlappende Lesungen liefern ein Fenster.
Sehr unausgewogene KlassenAndere Schwelle wählen (z. B. happy >= 1) oder stratify nutzen, damit beide Klassen ähnlich gross sind.
Treffer genau auf der ZufallslinieEhrliches Ergebnis, kein Fehler — im Signal steckt für dieses Ziel (oft „stress“) einfach nichts Lesbares.
Sehr langsamMerkmale einmal berechnen und in X behalten; kleinere Bildgrösse (z. B. 64×64) genügt.

Zum Nachdenken

Erweiterung

← 13.1 Tag und Nacht 14.1 Die Stimmung des Schwarms →