d8a80f6272
이름만 다른(표기 변형) [[위키링크]]를 대상 문서의 canonical 제목으로 치환해 끊겼던 1,200개 링크를 연결. 제목/파일명 정규화 일치만 적용하고 별칭 매칭은 과병합 위험으로 제외(애매성 가드). 원본은 _link_reconcile_backup/ 에 백업. 도구: Datacollect/scripts/link_reconcile_apply.mjs Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
249 lines
7.5 KiB
Markdown
249 lines
7.5 KiB
Markdown
---
|
|
id: wiki-2026-0508-heuristics
|
|
title: Heuristics
|
|
category: 10_Wiki/Topics
|
|
status: verified
|
|
canonical_id: self
|
|
aliases: [heuristics, rule of thumb, Kahneman, biases, mental shortcut, fast and frugal]
|
|
duplicate_of: none
|
|
source_trust_level: A
|
|
confidence_score: 0.94
|
|
verification_status: applied
|
|
tags: [decision-making, heuristics, kahneman, gigerenzer, biases, ai-search]
|
|
raw_sources: []
|
|
last_reinforced: 2026-05-10
|
|
github_commit: pending
|
|
tech_stack:
|
|
language: Decision Theory / AI
|
|
applicable_to: [Decision Support, AI Search, UX]
|
|
---
|
|
|
|
# Heuristics
|
|
|
|
## 매 한 줄
|
|
> **"매 fast 의 의 의 'good enough' rule"**. Tversky & Kahneman (heuristics & biases) ↔ Gigerenzer (fast and frugal). 매 AI: 매 A* heuristic, 매 game tree pruning. 매 cognitive: 매 availability, anchoring, representativeness. 매 modern LLM 의 의 의 heuristic-like.
|
|
|
|
## 매 핵심
|
|
|
|
### 매 cognitive heuristics (Kahneman)
|
|
- **Availability**: 매 easily recalled = more frequent.
|
|
- **Anchoring**: 매 first number bias.
|
|
- **Representativeness**: 매 stereotype-based.
|
|
- **Affect**: 매 emotional shortcut.
|
|
|
|
### 매 fast and frugal (Gigerenzer)
|
|
- **Take-the-best**: 매 single most valid cue.
|
|
- **Tallying**: 매 count positive cues.
|
|
- **Recognition**: 매 known = better.
|
|
|
|
### 매 AI
|
|
- **A* heuristic**: 매 admissible (lower bound).
|
|
- **Alpha-beta pruning**: 매 game tree.
|
|
- **Greedy**.
|
|
- **Beam search**: 매 LLM decoding.
|
|
|
|
### 매 응용
|
|
1. **AI search / planning**.
|
|
2. **Decision support**.
|
|
3. **UX defaults**.
|
|
4. **Risk assessment**.
|
|
5. **Medical triage**.
|
|
|
|
## 💻 패턴
|
|
|
|
### A* heuristic (admissible)
|
|
```python
|
|
import heapq
|
|
|
|
def a_star(start, goal, neighbors_fn, heuristic_fn):
|
|
"""매 heuristic: estimate cost to goal (lower bound)."""
|
|
open_set = [(0 + heuristic_fn(start, goal), 0, start, [start])]
|
|
visited = set()
|
|
|
|
while open_set:
|
|
f, g, node, path = heapq.heappop(open_set)
|
|
if node == goal: return path
|
|
if node in visited: continue
|
|
visited.add(node)
|
|
|
|
for nb, cost in neighbors_fn(node):
|
|
if nb not in visited:
|
|
new_g = g + cost
|
|
new_f = new_g + heuristic_fn(nb, goal)
|
|
heapq.heappush(open_set, (new_f, new_g, nb, path + [nb]))
|
|
return None
|
|
|
|
# 매 example: Manhattan distance for grid
|
|
def manhattan(a, b):
|
|
return abs(a[0] - b[0]) + abs(a[1] - b[1])
|
|
```
|
|
|
|
### Alpha-beta pruning
|
|
```python
|
|
def alphabeta(node, depth, alpha, beta, maximizing):
|
|
if depth == 0 or is_terminal(node): return evaluate(node)
|
|
|
|
if maximizing:
|
|
v = -float('inf')
|
|
for child in children(node):
|
|
v = max(v, alphabeta(child, depth-1, alpha, beta, False))
|
|
alpha = max(alpha, v)
|
|
if alpha >= beta: break # 매 prune
|
|
return v
|
|
else:
|
|
v = float('inf')
|
|
for child in children(node):
|
|
v = min(v, alphabeta(child, depth-1, alpha, beta, True))
|
|
beta = min(beta, v)
|
|
if alpha >= beta: break
|
|
return v
|
|
```
|
|
|
|
### Take-the-best (Gigerenzer)
|
|
```python
|
|
def take_the_best(cues, ordered_by_validity, options):
|
|
"""매 매 single most valid cue 의 의 의 의 decide."""
|
|
for cue in ordered_by_validity:
|
|
a_val = cues[options[0]][cue]
|
|
b_val = cues[options[1]][cue]
|
|
if a_val != b_val:
|
|
return options[0] if a_val > b_val else options[1]
|
|
return options[0] # 매 tie: arbitrary
|
|
```
|
|
|
|
### Greedy (knapsack value/weight)
|
|
```python
|
|
def greedy_knapsack(items, capacity):
|
|
items = sorted(items, key=lambda i: i.value / i.weight, reverse=True)
|
|
chosen = []
|
|
remaining = capacity
|
|
for item in items:
|
|
if item.weight <= remaining:
|
|
chosen.append(item); remaining -= item.weight
|
|
return chosen
|
|
```
|
|
|
|
### Beam search (LLM decoding)
|
|
```python
|
|
def beam_search(model, prompt, beam_width=5, max_len=50):
|
|
beams = [(0, prompt)] # 매 (log_prob, sequence)
|
|
for _ in range(max_len):
|
|
candidates = []
|
|
for log_p, seq in beams:
|
|
next_logits = model(seq)
|
|
top_k = next_logits.topk(beam_width)
|
|
for tok, p in zip(top_k.indices, top_k.values.log_softmax(-1)):
|
|
candidates.append((log_p + p.item(), seq + [tok]))
|
|
beams = sorted(candidates, key=lambda x: x[0], reverse=True)[:beam_width]
|
|
return beams[0][1]
|
|
```
|
|
|
|
### Anchoring effect (detect)
|
|
```python
|
|
def anchoring_check(estimates, anchor_provided):
|
|
"""매 매 anchor 의 매 estimate 의 의 magnitude."""
|
|
if not anchor_provided: return None
|
|
median_est = np.median(estimates)
|
|
distance_from_anchor = abs(median_est - anchor_provided)
|
|
return distance_from_anchor < 0.3 * abs(median_est) # 매 within 30%
|
|
```
|
|
|
|
### Availability heuristic (debiasing)
|
|
```python
|
|
def availability_debias(memory_prevalence, base_rate_data):
|
|
"""매 'easily recalled' 의 의 의 = 매 frequent 의 X."""
|
|
return {
|
|
'memory_estimate': memory_prevalence,
|
|
'actual_base_rate': base_rate_data,
|
|
'correction_factor': base_rate_data / memory_prevalence,
|
|
}
|
|
```
|
|
|
|
### Recognition heuristic
|
|
```python
|
|
def recognition_heuristic(option_a, option_b, recognized_set):
|
|
a_known = option_a in recognized_set
|
|
b_known = option_b in recognized_set
|
|
if a_known and not b_known: return option_a
|
|
if b_known and not a_known: return option_b
|
|
return None # 매 both known or both unknown
|
|
```
|
|
|
|
### Triage (medical, simple)
|
|
```python
|
|
def triage(vitals):
|
|
if vitals.unconscious: return 'red'
|
|
if vitals.systolic_bp < 90: return 'red'
|
|
if vitals.respiratory_rate > 30: return 'red'
|
|
if vitals.glucose < 60: return 'red'
|
|
if vitals.pain > 7: return 'orange'
|
|
return 'green'
|
|
```
|
|
|
|
### Heuristic evaluation (UX, Nielsen)
|
|
```python
|
|
NIELSEN_HEURISTICS = [
|
|
'visibility_of_system_status',
|
|
'match_real_world',
|
|
'user_control_freedom',
|
|
'consistency_standards',
|
|
'error_prevention',
|
|
'recognition_over_recall',
|
|
'flexibility_efficiency',
|
|
'aesthetic_minimalist',
|
|
'help_recovery',
|
|
'help_documentation',
|
|
]
|
|
|
|
def usability_audit(interface):
|
|
return {h: evaluate(interface, h) for h in NIELSEN_HEURISTICS}
|
|
```
|
|
|
|
### LLM-as-heuristic
|
|
```python
|
|
def llm_decision(options, criteria, llm):
|
|
prompt = f"""Apply heuristic: {criteria}.
|
|
Options: {options}.
|
|
Pick best option (single). Output JSON: {{ choice: ..., reason: ... }}"""
|
|
return json.loads(llm.generate(prompt))
|
|
```
|
|
|
|
## 매 결정 기준
|
|
| 상황 | Approach |
|
|
|---|---|
|
|
| Path planning | A* + admissible heuristic |
|
|
| Game tree | Alpha-beta |
|
|
| Quick decision | Take-the-best |
|
|
| Knapsack-like | Greedy (approximation) |
|
|
| LLM decoding | Beam search / nucleus |
|
|
| UX | Nielsen heuristics |
|
|
| Medical | Triage rules |
|
|
|
|
**기본값**: 매 admissible heuristic 의 always prefer (A*) + 매 fast-and-frugal in time pressure + 매 LLM 의 modern heuristic substitute.
|
|
|
|
## 🔗 Graph
|
|
- 부모: [[Decision-Making]]
|
|
- 변형: [[Heuristics|Heuristic-Search]] · [[Cognitive Bias]]
|
|
- Adjacent: [[Foundation-Models]]
|
|
|
|
## 🤖 LLM 활용
|
|
**언제**: 매 fast decision. 매 search. 매 default rule.
|
|
**언제 X**: 매 high-stakes precision needed.
|
|
|
|
## ❌ 안티패턴
|
|
- **Inadmissible heuristic in A***: 매 wrong path.
|
|
- **Heuristic for high-stakes**: 매 systematic bias.
|
|
- **Over-trust availability**: 매 base rate ignore.
|
|
- **Anchoring without awareness**: 매 manipulated.
|
|
|
|
## 🧪 검증 / 중복
|
|
- Verified (Tversky & Kahneman, Gigerenzer, Russell & Norvig AI).
|
|
- 신뢰도 A.
|
|
|
|
## 🕓 Changelog
|
|
| 날짜 | 변경 |
|
|
|---|---|
|
|
| 2026-04-26 | Auto |
|
|
| 2026-05-08 | Phase 1 |
|
|
| 2026-05-10 | Manual cleanup — heuristics + 매 A*/alpha-beta/take-the-best/Nielsen code |
|