diff --git a/plans/251016_bayesian_startup_valuation.md b/plans/251016_bayesian_startup_valuation.md index 4acd85d..9646aaf 100644 --- a/plans/251016_bayesian_startup_valuation.md +++ b/plans/251016_bayesian_startup_valuation.md @@ -246,6 +246,229 @@ CREATE TABLE premium_state ( - 자동 시장 반영 - 투자 뉴스 → 자동 업데이트 +### 4.8 포괄적 동적 학습 시스템 + +**현재 문제점**: +- Stage, Industry, K=3, IQR multiplier, Burn-in 10% 등 **하드코딩** +- 임의 경계: seed/pre-A/series A 구분, 공통 태그 3개 +- 새 데이터 → 수동 재학습 필요 + +**해결: 모든 파라미터를 학습 가능하게** + +#### 4.8.1 Feature Engineering + +**Stage → Continuous/Embedding**: +```python +# 현재: categorical split (정보 손실) +if stage == 'seed': + μ = 2.08 +elif stage == 'series A': + μ = 5.0 + +# 개선: learnable encoding +stage_encoding = { + 'seed': 0.0, + 'pre-A': 0.2, + 'series A': 0.4, + 'series B': 0.6 +} +# 또는 embedding: stage → R^d +stage_embedding = learn_embedding(stage, dim=8) +``` + +**Industry → Embedding**: +```python +# 현재: 키워드 매칭 (중복 처리 어려움) +keywords = ['협업툴', 'SaaS', '그룹웨어'] + +# 개선: 태그 embedding +industry_vector = TF-IDF(tags) or Word2Vec(tags) +# 차원: R^d (d=16~64) +``` + +**연속 변수 추가**: +```python +features = [ + N, # 직원 수 + stage_embedding, # Stage (학습됨) + industry_embedding, # Industry (학습됨) + founding_year, # 설립 연도 + total_funding, # 총 투자액 + round_count, # 라운드 수 + location_encoding # 지역 (서울/지방/글로벌) +] +``` + +#### 4.8.2 Hyperparameter Learning + +**자동 최적화 대상**: +```python +learnable_params = { + 'K_min_tags': [2, 3, 4, 5], # 현재 3 고정 + 'IQR_multiplier': [2.0, 2.5, 3.0, 5.0], # 현재 3.0 고정 + 'burn_in_ratio': [0.05, 0.1, 0.15, 0.2], # 현재 0.1 고정 + 'n_iter': [10000, 50000, 100000], # 현재 50000 고정 + 'top_k': [3, 5, 10] # 유사 기업 개수 +} +``` + +**최적화 방법**: +- Cross-validation: 훈련/검증 분리 +- Metric: 실제 투자액 vs 예측 MAPE (Mean Absolute Percentage Error) +- 자동 재최적화: 데이터 100개 추가마다 + +#### 4.8.3 Hierarchical Bayesian Model + +**현재 접근** (데이터 분할): +``` +seed 데이터 115개 → μ_seed = 2.08 +series A 데이터 87개 → μ_A = 5.0 +``` + +**개선 접근** (Hierarchical): +```python +# Level 1: Global +μ_base ~ N(3.0, 5.0) # 전체 평균 + +# Level 2: Stage effect +stage_effect['seed'] ~ N(0, 1.0) +stage_effect['series A'] ~ N(0, 1.0) + +# Level 3: Industry effect +industry_effect[i] ~ N(0, 0.5) + +# Final model +value = N × (μ_base + stage_effect[stage] + industry_effect[industry]) +``` + +**장점**: +- 모든 데이터 (442개) 함께 사용 +- Stage 간 관계 학습 (series A는 seed보다 평균적으로 높다) +- 데이터 적은 stage도 추정 가능 (shrinkage) + +#### 4.8.4 PostgreSQL 스키마 + +```sql +-- 학습된 파라미터 저장 +CREATE TABLE learned_parameters ( + param_name VARCHAR(50), -- stage_effect, industry_effect, K_min_tags 등 + param_value FLOAT, + category VARCHAR(50), -- seed, series A, 협업툴 등 + n_samples INT, + mape FLOAT, -- 검증 오차 + updated_at TIMESTAMP, + PRIMARY KEY (param_name, category) +); + +-- 예시 데이터 +INSERT INTO learned_parameters VALUES + ('μ_base', 3.2, NULL, 442, 0.35, NOW()), + ('stage_effect', -0.45, 'seed', 115, 0.42, NOW()), + ('stage_effect', 0.28, 'series A', 87, 0.31, NOW()), + ('industry_effect', 0.15, '협업툴', 95, 0.38, NOW()), + ('K_min_tags', 3.2, NULL, 442, 0.35, NOW()), + ('IQR_multiplier', 2.8, NULL, 442, 0.35, NOW()); + +-- 투자 데이터 (학습 소스) +CREATE TABLE investment_data ( + company_id VARCHAR, + company_name VARCHAR, + stage VARCHAR, + industry VARCHAR, + employees INT, + investment_amount FLOAT, + founding_year INT, + created_at TIMESTAMP +); +``` + +#### 4.8.5 자동 재학습 트리거 + +**트리거 조건**: +```sql +CREATE OR REPLACE FUNCTION check_retraining() +RETURNS TRIGGER AS $$ +BEGIN + -- 데이터 10개 추가마다 + IF (SELECT COUNT(*) FROM investment_data) % 10 = 0 THEN + PERFORM pg_notify('retrain_model', 'trigger'); + END IF; + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +CREATE TRIGGER investment_insert + AFTER INSERT ON investment_data + FOR EACH ROW + EXECUTE FUNCTION check_retraining(); +``` + +**재학습 플로우**: +``` +새 투자 데이터 입력 + ↓ +PostgreSQL Trigger + ↓ +pg_notify('retrain_model') + ↓ +Python Listener (asyncpg LISTEN) + ↓ +Async Task: + 1. 데이터 로드 (investment_data) + 2. Feature engineering + 3. Hyperparameter optimization (CV) + 4. Hierarchical Bayesian Update + 5. learned_parameters UPDATE + ↓ +다음 가치평가에 자동 적용 +``` + +#### 4.8.6 동적 평가 예시 + +**API 호출**: +```python +valuation = evaluate_startup( + name="NewCo", + N=15, + stage="pre-A", # 경계 모호해도 OK + industry=["AI", "SaaS"], + founding_year=2023 +) +``` + +**내부 동작**: +```python +# 1. PostgreSQL에서 최신 파라미터 로드 +μ_base = get_param('μ_base') # 3.2 +stage_effect = get_param('stage_effect', 'pre-A') # 0.1 +industry_embedding = get_embedding(['AI', 'SaaS']) + +# 2. 예측 +predicted_value_per_emp = ( + μ_base + + stage_effect + + np.dot(industry_embedding, learned_weights) +) + +# 3. 프리미엄 적용 +premium = get_param('μ_premium', stage='pre-A', industry='AI') +final = N × predicted_value_per_emp × premium + +return { + 'valuation': final, + 'base': N × predicted_value_per_emp, + 'premium': premium, + 'params_updated_at': last_update_time, + 'n_samples': total_samples +} +``` + +**장점**: +- 하드코딩 0개 +- 새 stage/industry 자동 지원 +- 데이터 쌓일수록 정확도 ↑ +- 파라미터 근거 명확 (n_samples, mape) + --- ## 5. 시각화 @@ -374,6 +597,12 @@ Robeing: "동적 학습 결과 {μ_premium:.2f}배입니다. - 투자 뉴스 크롤링 → 자동 프리미엄 업데이트 - 교훈: 정적 모델보다 동적 학습이 시장 반영 +### 7.7 임의 경계의 문제 + +- Stage/Industry 범주 분할 → 정보 손실 +- K=3, IQR 3배, Burn-in 10% → 근거 없는 하드코딩 +- 교훈: Categorical → Feature/Embedding, Hyperparameter → Auto-tuning + --- ## 8. 참고 자료