Files
2nd/10_Wiki/Topics/Architecture/Experience-Sampling-Method.md
T
2026-05-10 22:08:15 +09:00

212 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: wiki-2026-0508-experience-sampling-method
title: Experience Sampling Method
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [ESM, EMA, Ecological Momentary Assessment, Diary Studies]
duplicate_of: none
source_trust_level: A
confidence_score: 0.9
verification_status: applied
tags: [research-methodology, psychology, ux-research, mobile]
raw_sources: []
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
language: typescript
framework: react-native
---
# Experience Sampling Method
## 매 한 줄
> **"매 retrospection bias 의 in-the-moment self-report 의 replace"**. Experience Sampling Method (ESM, Csikszentmihalyi & Larson 1987) 매 participants 의 day 의 multiple times 의 random/scheduled prompt, 매 current activity/affect/context 의 record. Mobile-era 매 EMA (Ecological Momentary Assessment) 의 generalize — 매 mental health, UX, productivity research 의 gold standard.
## 매 핵심
### 매 Why ESM
- **Retrospection bias**: 매 "지난주 어땠나" 매 peak-end bias, mood-congruent recall 의 distort.
- **Ecological validity**: 매 in-context 매 lab 의 not-replicate.
- **Within-subject variance**: 매 person × situation 의 interaction 의 capture.
### 매 Sampling schedules
- **Signal-contingent**: 매 random beep 매 day 매 6-8 prompts.
- **Interval-contingent**: 매 fixed times (9am/12pm/3pm/6pm).
- **Event-contingent**: 매 specific event (meal, exercise) 의 trigger.
- **Hybrid**: 매 baseline random + event triggers.
### 매 응용
1. Mood / affect tracking (depression, bipolar).
2. Pain studies (chronic pain).
3. UX product research — feature use in-context.
4. Flow state research (Csikszentmihalyi original).
5. LLM agent behavior tracking — analog 매 process.
## 💻 패턴
### Mobile prompt scheduler (React Native)
```typescript
import * as Notifications from 'expo-notifications';
interface ESMConfig {
startHour: number; endHour: number;
promptsPerDay: number;
minIntervalMinutes: number;
}
async function schedulePrompts(cfg: ESMConfig, days = 7) {
const slots = generateRandomSlots(cfg, days);
for (const slot of slots) {
await Notifications.scheduleNotificationAsync({
content: {
title: 'Quick check-in (30s)',
body: 'How are you feeling right now?',
data: { promptId: slot.id, scheduledFor: slot.time.toISOString() },
},
trigger: { date: slot.time },
});
}
}
function generateRandomSlots(cfg: ESMConfig, days: number) {
const slots = [];
for (let d = 0; d < days; d++) {
const dayStart = new Date();
dayStart.setDate(dayStart.getDate() + d);
const windowMs = (cfg.endHour - cfg.startHour) * 3600_000;
const minGap = cfg.minIntervalMinutes * 60_000;
const times: number[] = [];
while (times.length < cfg.promptsPerDay) {
const candidate = Math.random() * windowMs;
if (times.every(t => Math.abs(t - candidate) >= minGap)) {
times.push(candidate);
}
}
times.sort((a, b) => a - b).forEach((offset, i) => {
const t = new Date(dayStart);
t.setHours(cfg.startHour, 0, 0, 0);
t.setTime(t.getTime() + offset);
slots.push({ id: `${d}-${i}`, time: t });
});
}
return slots;
}
```
### Brief response form (PANAS-short, 30s budget)
```typescript
interface ESMResponse {
promptId: string;
respondedAt: Date;
latencyMs: number;
affect: {
valence: number; // -3..+3
arousal: number; // -3..+3
};
activity: string; // dropdown: work | social | rest | exercise | other
social: 'alone' | 'with_others';
freeText?: string;
}
```
### Compliance tracking
```typescript
function complianceMetrics(responses: ESMResponse[], scheduled: number) {
const completed = responses.length;
const onTime = responses.filter(r => r.latencyMs < 15 * 60_000).length;
const meanLatency = responses.reduce((s, r) => s + r.latencyMs, 0) / completed;
return {
completionRate: completed / scheduled, // target > 0.7
onTimeRate: onTime / scheduled, // target > 0.5
meanLatencyMin: meanLatency / 60_000,
};
}
```
### Multilevel analysis (within vs between)
```python
import statsmodels.formula.api as smf
# 매 each row 매 prompt response, 매 participant_id 매 grouping
model = smf.mixedlm(
'valence ~ activity + social + time_of_day',
data=df,
groups=df['participant_id'],
re_formula='~time_of_day',
).fit()
print(model.summary())
# 매 within-person variance (situation) 매 between-person (trait) 의 separate
```
### Sliding-window mood detection
```typescript
function detectMoodEpisode(responses: ESMResponse[], windowDays = 7, threshold = -1.5) {
const sorted = [...responses].sort((a, b) =>
a.respondedAt.getTime() - b.respondedAt.getTime());
const episodes = [];
for (let i = 0; i < sorted.length; i++) {
const start = sorted[i].respondedAt;
const end = new Date(start.getTime() + windowDays * 86400_000);
const window = sorted.filter(r =>
r.respondedAt >= start && r.respondedAt <= end);
if (window.length < 5) continue;
const meanV = window.reduce((s, r) => s + r.affect.valence, 0) / window.length;
if (meanV < threshold) episodes.push({ start, end, meanV, n: window.length });
}
return mergeOverlapping(episodes);
}
```
### Privacy: 매 on-device aggregation
```typescript
// 매 raw responses 매 device 의 stay, 매 weekly summary 만 의 server 의 send
async function uploadWeeklySummary(responses: ESMResponse[]) {
const summary = {
week: getCurrentWeek(),
n: responses.length,
valenceMean: mean(responses.map(r => r.affect.valence)),
valenceStd: std(responses.map(r => r.affect.valence)),
activityHistogram: histogram(responses.map(r => r.activity)),
};
await api.post('/esm/summary', summary);
}
```
## 매 결정 기준
| 상황 | Approach |
|---|---|
| Trait measurement (depression baseline) | 매 ESM unnecessary — 매 single questionnaire 매 fine |
| Within-day variation 의 question | 매 ESM signal-contingent |
| Specific event 매 rare | 매 event-contingent |
| Compliance fragile | 매 prompt count 의 reduce, 매 incentive |
| Privacy-sensitive (clinical) | 매 on-device aggregation 또는 federated |
**기본값**: 매 6-8 prompts/day, 매 14 days, 매 30s response — 매 compliance > 70% 의 target.
## 🔗 Graph
- 부모: [[Research-Methodology]] · [[Psychometrics]]
- 변형: [[Ecological-Momentary-Assessment]] · [[Diary-Study]] · [[Day-Reconstruction]]
- 응용: [[Mood-Tracking-Apps]] · [[UX-Research]] · [[Flow-State]]
- Adjacent: [[Csikszentmihalyi]] · [[Multilevel-Modeling]] · [[Mobile-Sensing]]
## 🤖 LLM 활용
**언제**: 매 in-the-moment subjective state 의 measure. Within-person variance 의 study. Retrospective bias 의 likely.
**언제 X**: 매 stable trait. 매 single-shot decision study. 매 intrusive sampling 매 acceptable 의 X.
## ❌ 안티패턴
- **Too many prompts**: 매 12+/day 매 fatigue → compliance crash.
- **Long forms**: 매 5min response 매 ecological 의 break.
- **Ignoring missing-not-at-random**: 매 prompts during depressive episode 매 skipped — 매 selection bias.
- **Cross-sectional analysis 의 hierarchical data**: 매 multilevel model 의 use, 매 OLS 의 std error 의 underestimate.
## 🧪 검증 / 중복
- Verified (Csikszentmihalyi & Larson 1987 JNMD; Shiffman et al. 2008 Ann Rev Clin Psych).
- 신뢰도 A.
## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — ESM scheduler + analysis + privacy patterns |