Skip to content

Insights-Engine: Höherwertige statistische Auswertungsmethoden spezifizieren #339

Description

@mpwg

Parent: #334

Ziel

Die bisher geplanten Detektoren sind teilweise zu simpel formuliert, z. B. „Vergleich Schlafdauer vs. persönlicher Median“. Dieses Issue soll die Insight-Engine auf wissenschaftlich robustere, aber weiterhin lokal und nachvollziehbar umsetzbare Verfahren heben.

Die Engine soll nicht nur einfache Mittelwert-/Medianvergleiche nutzen, sondern zeitliche Verläufe, individuelle Unterschiede, Verzögerungseffekte, Unsicherheit und Mehrfachtests berücksichtigen.

Recherche-Erkenntnisse

Wetter und Migräne sind stark individuell

Studien zu Wetter und Migräne zeigen, dass aggregierte Analysen über alle Patient:innen oft keine signifikanten Zusammenhänge finden. Einzelne Subgruppen können aber sehr wohl wetterempfindlich sein. Eine Studie fand in der Gesamtanalyse keine signifikante Wetterassoziation, aber bei einzelnen Personen signifikante Zusammenhänge; etwa 13 % der Teilnehmer:innen zeigten klare Wettersensitivität.

Konsequenz für Symi:

  • Keine globale Aussage wie „Wetter beeinflusst Migräne“.
  • Immer individuell formulieren: „In deinen bisherigen Einträgen …“.
  • Individuelle Modelle sind wichtiger als globale Durchschnittsmuster.

Wetterwerte sollten als Zeitfenster und Veränderungen modelliert werden

In Wetterstudien wurden pro Wettervariable nicht nur der aktuelle Wert, sondern auch Messwerte der letzten 24 Stunden und Differenzen zum Ereigniszeitpunkt analysiert.

Für Symi bedeutet das: Nicht nur „Luftdruck bei Eintrag“, sondern:

  • Wert zum Episodenzeitpunkt
  • Wert 4 h vorher
  • Wert 8 h vorher
  • Wert 12 h vorher
  • Wert 24 h vorher
  • Änderung 4 h → Episode
  • Änderung 8 h → Episode
  • Änderung 12 h → Episode
  • Änderung 24 h → Episode

Das gilt analog für:

  • Temperatur
  • Luftdruck
  • Luftfeuchtigkeit
  • Niederschlag
  • HRV
  • Herzfrequenz
  • Schritte / Aktivität
  • Schlafdefizit über mehrere Tage

Multiple Tests brauchen Kontrolle

Wenn viele Variablen, Zeitfenster und Kategorien getestet werden, entstehen zwangsläufig Zufallstreffer. Die Literatur nutzt daher Korrekturen wie False Discovery Rate (FDR).

Konsequenz für Symi:

  • Jeder Detektor darf nicht isoliert „signifikant“ werden.
  • Die Engine soll pro Lauf eine Liste getesteter Hypothesen sammeln.
  • Danach soll eine FDR-Korrektur oder ein konservatives internes Confidence-Gating angewendet werden.

Zeitreihenmodelle sind besser als einfache Klassifikatoren

Neuere mHealth-Studien zeigen, dass Zeitreihenmodelle deutlich besser abschneiden als klassische ML-Modelle. In einer Studie erreichte ein GRU-D-Zeitreihenmodell für die 24h-Vorhersage eine Test-AUC von ca. 0.84, während klassische Modelle wie Entscheidungsbäume nur ca. 0.59–0.61 erreichten.

Konsequenz für Symi:

  • V1 sollte noch kein komplexes neuronales Modell benötigen.
  • Die Datenstruktur soll aber zeitfensterfähig sein.
  • Später kann ein on-device Zeitreihenmodell ergänzt werden.

Empfohlene Analyse-Architektur für Symi

Stufe 1: Robuste erklärbare Statistik (jetzt umsetzen)

Diese Stufe ersetzt simple Medianvergleiche durch robustere, aber gut testbare Verfahren.

1. Zeitfenster-Feature-Engineering

Für jeden qualifizierten Eintrag wird ein InsightFeatureWindow erzeugt.

Beispiel:

struct InsightFeatureWindow: Equatable, Sendable {
    let episodeID: UUID
    let startedAt: Date
    let outcome: InsightOutcome

    let weather: WeatherFeatureWindow?
    let sleep: SleepFeatureWindow?
    let activity: ActivityFeatureWindow?
    let heart: HeartFeatureWindow?
    let cycle: CycleFeatureWindow?
}
struct WeatherFeatureWindow: Equatable, Sendable {
    let temperatureAtStart: Double?
    let temperature4hBefore: Double?
    let temperature8hBefore: Double?
    let temperature12hBefore: Double?
    let temperature24hBefore: Double?
    let temperatureDelta4h: Double?
    let temperatureDelta8h: Double?
    let temperatureDelta12h: Double?
    let temperatureDelta24h: Double?

    let pressureAtStart: Double?
    let pressure4hBefore: Double?
    let pressure8hBefore: Double?
    let pressure12hBefore: Double?
    let pressure24hBefore: Double?
    let pressureDelta4h: Double?
    let pressureDelta8h: Double?
    let pressureDelta12h: Double?
    let pressureDelta24h: Double?

    let humidityAtStart: Double?
    let humidity4hBefore: Double?
    let humidity8hBefore: Double?
    let humidity12hBefore: Double?
    let humidity24hBefore: Double?
    let humidityDelta4h: Double?
    let humidityDelta8h: Double?
    let humidityDelta12h: Double?
    let humidityDelta24h: Double?
}

2. Matched Case-Control statt simpler Durchschnitt

Für jede Episode („case“) werden vergleichbare Kontrollzeitpunkte („controls“) aus dem gleichen Nutzerverlauf gewählt.

Kontrollen sollten möglichst gleich sein in:

  • Tageszeit / Tagesbereich
  • Wochentag oder Wochenendstatus
  • Saison / Monat
  • vorhandenen Datenquellen

Beispiel:

  • Case: Migräne Dienstag 19:00
  • Controls: andere Dienstag-/Abend-Zeitpunkte ohne Migräne im gleichen Zeitraum

Dann wird geprüft, ob z. B. Schlafdauer, Luftdruckabfall oder HRV beim Case systematisch anders waren als bei Controls.

Vorteile:

  • reduziert Scheinkorrelationen durch Tageszeit
  • reduziert Wochenend-/Saison-Effekte
  • braucht weniger komplexes Modell
  • gut lokal umsetzbar

3. Effektstärke statt nur p-Wert

Ein Insight soll nur sichtbar werden, wenn er praktisch relevant ist.

Pro Kandidat berechnen:

  • effectSize: z. B. Cohen’s d, Odds Ratio oder median difference
  • supportCount: Anzahl betroffener Episoden
  • coverage: Anteil Episoden mit Daten
  • uncertainty: Bootstrap-Konfidenzintervall
  • qValue: FDR-korrigierter Wert oder interner Multiplicity-Score

Beispiel-Entscheidung:

visible = supportCount >= 5
       && coverage >= 0.6
       && abs(effectSize) >= threshold
       && confidenceInterval excludes 0
       && qValue <= 0.10

4. Bootstrapping für Unsicherheit

Für jeden Insight-Kandidaten:

  1. ziehe Episoden/Controls mit Zurücklegen
  2. berechne Effekt erneut
  3. wiederhole 1000x
  4. erzeuge 95%-Konfidenzintervall

Nur wenn das Intervall stabil ist, wird der Insight angezeigt.

5. FDR-Korrektur

Alle Kandidaten eines Engine-Laufs werden gesammelt:

struct InsightHypothesisResult {
    let candidate: InsightCandidate
    let rawPValue: Double?
    let effectSize: Double
    let confidenceInterval: ClosedRange<Double>?
}

Danach:

  • Benjamini-Hochberg-FDR auf alle rawPValue
  • fallback, falls keine echten p-Werte: konservatives Ranking über Effektstärke + Support + Coverage

Stufe 2: Zeitverzögerungen explizit modellieren

Cross-Correlation / Lag-Analyse

Statt nur „Schlafdauer letzte Nacht“:

  • Schlafdauer Lag 0: letzte Nacht
  • Schlafdauer Lag 1: Nacht davor
  • Schlafdauer Lag 2: zwei Nächte davor
  • 3-Tages-Schlafdefizit
  • Varianz der Schlafdauer über 7 Tage

Für Wetter:

  • Luftdruck jetzt
  • Luftdruckabfall 4 h
  • Luftdruckabfall 12 h
  • Luftdruckabfall 24 h
  • Temperaturanstieg 12 h
  • hohe Feuchtigkeit 24 h

Für Aktivität:

  • Schritte am selben Tag
  • Schritte am Vortag
  • 3-Tages-Durchschnitt
  • Abweichung vom persönlichen 14-Tage-Niveau

Ein Insight darf dann z. B. lauten:

In deinen bisherigen Einträgen waren Episoden häufiger, wenn der Luftdruck in den 12 Stunden davor deutlich gefallen ist.

Nicht:

Niedriger Luftdruck ist dein Trigger.


Stufe 3: On-device Forecasting später vorbereiten

Nicht sofort als V1 bauen, aber Architektur vorbereiten:

  • tägliche Feature-Matrix erzeugen
  • Outcome „moderate-to-severe Episode morgen ja/nein“
  • Trainingsfenster 24 h und 72 h
  • Baseline: regularisierte logistische Regression
  • später: Gradient Boosting oder kleines CoreML-Zeitreihenmodell

Wichtig: In der App sollte Forecasting erst aktiviert werden, wenn ausreichend Daten vorhanden sind, z. B. 60–90 Tage mit guter Abdeckung.


Konkrete bessere Methoden pro bisherigem Bereich

Schlaf

Nicht verwenden:

Schlafdauer < persönlicher Median

Besser:

sleepDebt1 = expectedSleep - sleepLastNight
sleepDebt3 = sum(expectedSleep - sleepHours over last 3 nights)
sleepVariability7 = standardDeviation(last 7 nights)
socialJetlag = abs(midSleepWeekend - midSleepWeekday)

Dann matched comparison:

Vergleiche sleepDebt3 bei Episoden mit sleepDebt3 an ähnlichen Kontrolltagen ohne Episode.

Insight nur, wenn:

  • mindestens 5 Episoden mit Schlafdaten
  • mindestens 10 passende Kontrollzeitpunkte
  • Effektgröße praktisch relevant, z. B. sleepDebt3 im Median > 2 h höher
  • Bootstrap-CI stabil

Beispieltext:

Vor deinen Episoden war dein Schlafdefizit über 3 Tage häufiger erhöht als an vergleichbaren Tagen ohne Eintrag.

Wetter

Nicht verwenden:

Temperatur hoch/niedrig im Quartil

Besser:

  • absolute Werte und Veränderungen trennen
  • Richtung nicht vorgeben
  • mehrere Lags testen

Features:

pressureDelta4h
pressureDelta12h
pressureDelta24h
temperatureDelta12h
humidityAtStart
humidityDelta24h

Insight nur, wenn:

  • Effekt in Controls nicht ähnlich häufig ist
  • mehrere nahe Lags konsistent sind, z. B. 8 h und 12 h
  • FDR nach mehreren Wettertests akzeptabel ist

Aktivität

Nicht verwenden:

niedrige Schritte = Muster

Besser:

  • relative Abweichung vom persönlichen Aktivitätsniveau
  • Tageszeit berücksichtigen
  • Vortag und 3-Tage-Niveau berücksichtigen

Features:

stepsSameDayRelativeTo14DayMedian
stepsYesterdayRelativeTo14DayMedian
activityVariance3Days
exerciseMinutes24h

Insight:

An Tagen vor deinen Episoden war deine Aktivität häufiger deutlich unter deinem üblichen Niveau.

Herz / HRV

Nicht verwenden:

HRV unter Median

Besser:

  • HRV z-score gegen persönliches 30-Tage-Niveau
  • Ruhepuls z-score
  • Kombination aus niedriger HRV + erhöhtem Ruhepuls

Features:

hrvZScoreMorning
restingHeartRateZScore
hrvDropFrom7DayAverage
autonomicStressScore = normalized(restingHRIncrease) + normalized(hrvDrop)

Insight:

Vor mehreren Episoden zeigte dein Herz-Kontext ein anderes Muster als sonst: niedrigere HRV und höherer Ruhepuls.

Zyklus

Besser als einfache Phase:

  • Tage relativ zum Beginn der Menstruation
  • Fenster: -3 bis +2 Tage
  • zyklusnormierte Position, falls Länge bekannt
  • Vergleich mit Kontrolltagen derselben Nutzerin

Insight:

Ein Teil deiner Episoden häuft sich im Zeitraum rund um den Beginn der Menstruation.


Akzeptanzkriterien

  • Es gibt ein neues Analysekonzept für robuste, individuelle Insights.
  • Simple Medianvergleiche werden nicht als finale Statistik verwendet.
  • Feature-Windows für 4 h, 8 h, 12 h und 24 h sind spezifiziert.
  • Matched Case-Control-Auswertung ist spezifiziert.
  • Effektstärken und Bootstrap-Konfidenzintervalle sind spezifiziert.
  • Multiple-Testing-Korrektur / FDR ist spezifiziert.
  • Schlafanalyse nutzt Schlafdefizit, 3-Tage-Defizit und Schlafvariabilität.
  • Wetteranalyse nutzt absolute Werte und Änderungen über mehrere Lags.
  • Aktivitätsanalyse nutzt relative Abweichung vom persönlichen Niveau.
  • Herz-/HRV-Analyse nutzt z-scores und kombinierte Stress-Scores.
  • Alle Insight-Texte bleiben nicht-diagnostisch.

Nicht-Ziele

  • Kein medizinischer Ratschlag.
  • Keine Aussage über Ursachen.
  • Kein Servertraining.
  • Kein verpflichtendes ML-Modell in der ersten Umsetzung.

Quellen / Hinweise

  • Wetterstudien zeigen individuelle Subgruppen und schwache bis inkonsistente Effekte in Gesamtpopulationen.
  • Wetteranalysen nutzen Messwerte und Veränderungen in den 24 h vor Ereignissen.
  • Patient-wise Klassifikatoren und Cross-Validation sind wichtig, um Überanpassung zu vermeiden.
  • mHealth-Studien deuten darauf hin, dass Zeitreihenmodelle klassische ML-Modelle deutlich übertreffen können, benötigen aber deutlich mehr Daten und sorgfältige Validierung.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions