Compare commits
52 Commits
v26-shadow
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 920ae7ce38 | |||
| 02f9aea333 | |||
| 15c6313246 | |||
| 1b420a425e | |||
| 55e62d8fe5 | |||
| 21e05148c8 | |||
| e001ce9ab5 | |||
| 9481ad7094 | |||
| 1d4aa36602 | |||
| 5574a3c59d | |||
| 94c7a4481a | |||
| 17ace9bd12 | |||
| 2b87669f41 | |||
| 2507678bc0 | |||
| 2b8dce665f | |||
| b6d64b59bf | |||
| f8599bdb9a | |||
| 4dcc4ced50 | |||
| 70fdc066c7 | |||
| f3362f266c | |||
| 8ce8fa5b94 | |||
| c525b12dfd | |||
| 497b5d8d3b | |||
| 4f7090e2d9 | |||
| 5b5f83c8cf | |||
| bfddcaca7d | |||
| 56d560af08 | |||
| 4bc51cfa99 | |||
| fdb8a5d0f0 | |||
| 22596e69f2 | |||
| f32badbd8f | |||
| 5645b38f20 | |||
| 244d8f5366 | |||
| 9bb8f39bca | |||
| 7a1cf14e2f | |||
| 62c797d299 | |||
| 34cc4a6cbb | |||
| 27e96da31d | |||
| 145a8b336b | |||
| 7a8960edb8 | |||
| 691c52f610 | |||
| bc461429f6 | |||
| a338d02244 | |||
| 1623432039 | |||
| 4c7930e9d2 | |||
| ec463cb927 | |||
| eab95c4e5c | |||
| 9027cc9900 | |||
| 3875f2a512 | |||
| 300dceeb4b | |||
| ad01976fb9 | |||
| 6880eb92f5 |
@@ -11,13 +11,27 @@ jobs:
|
|||||||
- name: Kodu Cek
|
- name: Kodu Cek
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Docker Build
|
- name: Docker Build (Backend)
|
||||||
run: docker build -t iddaai-be:latest .
|
run: docker build -t iddaai-be:latest .
|
||||||
|
|
||||||
- name: Eski Konteyneri Sil
|
- name: Docker Build (AI Engine)
|
||||||
run: docker rm -f iddaai-be || true
|
run: docker build -t iddaai-ai-engine:latest ./ai-engine
|
||||||
|
|
||||||
- name: Yeni Versiyonu Baslat
|
- name: Eski Konteynerleri Sil
|
||||||
|
run: |
|
||||||
|
docker rm -f iddaai-be || true
|
||||||
|
docker rm -f iddaai-ai-engine || true
|
||||||
|
|
||||||
|
- name: AI Engine'i Baslat
|
||||||
|
run: |
|
||||||
|
docker run -d \
|
||||||
|
--name iddaai-ai-engine \
|
||||||
|
--restart unless-stopped \
|
||||||
|
--network iddaai_iddaai-network \
|
||||||
|
-e DATABASE_URL='${{ secrets.DATABASE_URL }}' \
|
||||||
|
iddaai-ai-engine:latest
|
||||||
|
|
||||||
|
- name: Backend'i Baslat
|
||||||
run: |
|
run: |
|
||||||
docker run -d \
|
docker run -d \
|
||||||
--name iddaai-be \
|
--name iddaai-be \
|
||||||
@@ -25,11 +39,21 @@ jobs:
|
|||||||
--network iddaai_iddaai-network \
|
--network iddaai_iddaai-network \
|
||||||
-p 127.0.0.1:1810:3005 \
|
-p 127.0.0.1:1810:3005 \
|
||||||
-e NODE_ENV=production \
|
-e NODE_ENV=production \
|
||||||
-e DATABASE_URL='postgresql://iddaai_user:IddaA1_S4crET!@iddaai-postgres:5432/iddaai_db?schema=public' \
|
-e DATABASE_URL='${{ secrets.DATABASE_URL }}' \
|
||||||
-e REDIS_HOST='iddaai-redis' \
|
-e REDIS_HOST='${{ secrets.REDIS_HOST }}' \
|
||||||
-e REDIS_PORT='6379' \
|
-e REDIS_PORT='${{ secrets.REDIS_PORT }}' \
|
||||||
-e REDIS_PASSWORD='IddaA1_Redis_Pass!' \
|
-e REDIS_PASSWORD='${{ secrets.REDIS_PASSWORD }}' \
|
||||||
-e AI_ENGINE_URL='http://iddaai-ai-engine:8000' \
|
-e AI_ENGINE_URL='http://iddaai-ai-engine:8000' \
|
||||||
-e JWT_SECRET='b7V8jM2wP1L5mQxs2RdfFkAsLpI2oG!w' \
|
-e JWT_SECRET='${{ secrets.JWT_SECRET }}' \
|
||||||
-e JWT_ACCESS_EXPIRATION='1d' \
|
-e JWT_ACCESS_EXPIRATION='1d' \
|
||||||
iddaai-be:latest /bin/sh -c "npx prisma migrate deploy && node dist/src/main.js"
|
iddaai-be:latest /bin/sh -c "npx prisma migrate deploy && node dist/src/main.js"
|
||||||
|
|
||||||
|
- name: Saglik Kontrolu
|
||||||
|
run: |
|
||||||
|
sleep 10
|
||||||
|
echo "=== AI Engine logs ==="
|
||||||
|
docker logs --tail 30 iddaai-ai-engine || true
|
||||||
|
echo "=== Backend logs ==="
|
||||||
|
docker logs --tail 30 iddaai-be || true
|
||||||
|
echo "=== AI Engine health ==="
|
||||||
|
docker exec iddaai-ai-engine python -c "import urllib.request; print(urllib.request.urlopen('http://127.0.0.1:8000/health').read().decode())" || echo "AI engine health check failed"
|
||||||
+12
-3
@@ -21,7 +21,10 @@ venv/
|
|||||||
env/
|
env/
|
||||||
|
|
||||||
# Database / Docker Volumes
|
# Database / Docker Volumes
|
||||||
data/
|
/data/
|
||||||
|
ai-engine/data/**/*.csv
|
||||||
|
ai-engine/data/v26_shadow/
|
||||||
|
ai-engine/data/__pycache__/
|
||||||
postgres-data/
|
postgres-data/
|
||||||
redis-data/
|
redis-data/
|
||||||
|
|
||||||
@@ -42,7 +45,13 @@ uploads/
|
|||||||
public/uploads/
|
public/uploads/
|
||||||
|
|
||||||
# Large Datasets and ML Models
|
# Large Datasets and ML Models
|
||||||
ai-engine/models/
|
ai-engine/models/*
|
||||||
models/
|
!ai-engine/models/*.py
|
||||||
|
!ai-engine/models/v25/
|
||||||
|
!ai-engine/models/v27/
|
||||||
|
!ai-engine/models/basketball_v25/
|
||||||
|
!ai-engine/models/calibration/
|
||||||
|
models/*
|
||||||
|
!models/*.py
|
||||||
colab_export/
|
colab_export/
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -16,7 +16,7 @@ RUN npm ci
|
|||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Generate Prisma client
|
# Generate Prisma client
|
||||||
RUN npx prisma generate
|
RUN DATABASE_URL="postgresql://dummy:dummy@localhost/dummy" npx prisma generate
|
||||||
|
|
||||||
# Build the application
|
# Build the application
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
@@ -38,7 +38,7 @@ RUN apk add --no-cache --virtual .build-deps python3 make g++ cairo-dev pango-de
|
|||||||
|
|
||||||
# Copy Prisma schema and generate client
|
# Copy Prisma schema and generate client
|
||||||
COPY prisma ./prisma
|
COPY prisma ./prisma
|
||||||
RUN npx prisma generate
|
RUN DATABASE_URL="postgresql://dummy:dummy@localhost/dummy" npx prisma generate
|
||||||
|
|
||||||
# Copy built application
|
# Copy built application
|
||||||
COPY --from=builder /app/dist ./dist
|
COPY --from=builder /app/dist ./dist
|
||||||
@@ -47,7 +47,7 @@ COPY --from=builder /app/dist ./dist
|
|||||||
COPY --from=builder /app/src/i18n ./dist/i18n
|
COPY --from=builder /app/src/i18n ./dist/i18n
|
||||||
|
|
||||||
# Copy league filter config files (critical: without these, feeder stores ALL matches)
|
# Copy league filter config files (critical: without these, feeder stores ALL matches)
|
||||||
COPY top_leagues.json basketball_top_leagues.json ./
|
COPY qualified_leagues.json top_leagues.json basketball_top_leagues.json ./
|
||||||
|
|
||||||
# Set environment
|
# Set environment
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import os
|
import os
|
||||||
|
import json
|
||||||
import yaml
|
import yaml
|
||||||
from typing import Dict, Any, Optional
|
from typing import Dict, Any, Optional
|
||||||
|
|
||||||
|
|
||||||
class EnsembleConfig:
|
class EnsembleConfig:
|
||||||
_instance: Optional['EnsembleConfig'] = None
|
_instance: Optional['EnsembleConfig'] = None
|
||||||
_config: Dict[str, Any] = {}
|
_config: Dict[str, Any] = {}
|
||||||
@@ -35,12 +37,79 @@ class EnsembleConfig:
|
|||||||
except (KeyError, TypeError):
|
except (KeyError, TypeError):
|
||||||
return default
|
return default
|
||||||
|
|
||||||
|
|
||||||
# Singleton accessor
|
# Singleton accessor
|
||||||
def get_config() -> EnsembleConfig:
|
def get_config() -> EnsembleConfig:
|
||||||
return EnsembleConfig()
|
return EnsembleConfig()
|
||||||
|
|
||||||
|
|
||||||
|
# ── Market Thresholds Loader ────────────────────────────────────────────
|
||||||
|
|
||||||
|
_market_thresholds_cache: Optional[Dict[str, Any]] = None
|
||||||
|
|
||||||
|
|
||||||
|
def load_market_thresholds() -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
Load market thresholds from JSON config file.
|
||||||
|
Returns the full config dict with 'markets' and 'defaults' keys.
|
||||||
|
Caches after first load for performance.
|
||||||
|
"""
|
||||||
|
global _market_thresholds_cache
|
||||||
|
if _market_thresholds_cache is not None:
|
||||||
|
return _market_thresholds_cache
|
||||||
|
|
||||||
|
config_path = os.path.join(os.path.dirname(__file__), 'market_thresholds.json')
|
||||||
|
try:
|
||||||
|
with open(config_path, 'r', encoding='utf-8') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
_market_thresholds_cache = data
|
||||||
|
print(f"✅ Market thresholds loaded: {len(data.get('markets', {}))} markets (v={data.get('_meta', {}).get('version', '?')})")
|
||||||
|
return data
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Failed to load market thresholds: {e} — using built-in defaults")
|
||||||
|
_market_thresholds_cache = {"markets": {}, "defaults": {
|
||||||
|
"calibration": 0.55,
|
||||||
|
"min_conf": 55.0,
|
||||||
|
"min_play_score": 68.0,
|
||||||
|
"min_edge": 0.02,
|
||||||
|
"odds_band_min_sample": 0.0,
|
||||||
|
"odds_band_min_edge": 0.0,
|
||||||
|
}}
|
||||||
|
return _market_thresholds_cache
|
||||||
|
|
||||||
|
|
||||||
|
def build_threshold_dict(field: str) -> Dict[str, float]:
|
||||||
|
"""
|
||||||
|
Build a flat {market: value} dict for a specific threshold field.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
calibration_map = build_threshold_dict("calibration")
|
||||||
|
# → {"MS": 0.62, "DC": 0.82, ...}
|
||||||
|
"""
|
||||||
|
data = load_market_thresholds()
|
||||||
|
markets = data.get("markets", {})
|
||||||
|
result: Dict[str, float] = {}
|
||||||
|
for market, cfg in markets.items():
|
||||||
|
if field in cfg:
|
||||||
|
result[market] = float(cfg[field])
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def get_threshold_default(field: str) -> float:
|
||||||
|
"""Get the default fallback value for a threshold field."""
|
||||||
|
data = load_market_thresholds()
|
||||||
|
defaults = data.get("defaults", {})
|
||||||
|
return float(defaults.get(field, 0.0))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# Test
|
# Test
|
||||||
cfg = get_config()
|
cfg = get_config()
|
||||||
print(f"Weights: {cfg.get('engine_weights')}")
|
print(f"Weights: {cfg.get('engine_weights')}")
|
||||||
print(f"Team Weight: {cfg.get('engine_weights.team')}")
|
print(f"Team Weight: {cfg.get('engine_weights.team')}")
|
||||||
|
print()
|
||||||
|
print("--- Market Thresholds ---")
|
||||||
|
for field in ["calibration", "min_conf", "min_play_score", "min_edge"]:
|
||||||
|
d = build_threshold_dict(field)
|
||||||
|
print(f"{field}: {d}")
|
||||||
|
print(f"Default calibration: {get_threshold_default('calibration')}")
|
||||||
|
|||||||
@@ -1,3 +1,14 @@
|
|||||||
|
model_ensemble:
|
||||||
|
xgb_weight: 0.50
|
||||||
|
lgb_weight: 0.50
|
||||||
|
temperature: 1.5
|
||||||
|
default_ms_odds:
|
||||||
|
home: 2.65
|
||||||
|
draw: 3.20
|
||||||
|
away: 2.65
|
||||||
|
elo_staleness_days: 14
|
||||||
|
odds_staleness_hours: 48
|
||||||
|
|
||||||
engine_weights:
|
engine_weights:
|
||||||
team: 0.30
|
team: 0.30
|
||||||
player: 0.25
|
player: 0.25
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
{
|
||||||
|
"_meta": {
|
||||||
|
"version": "v34",
|
||||||
|
"description": "Market-specific thresholds for the betting engine pipeline — V34 odds-aware gate fix",
|
||||||
|
"rule": "max_reachable (100 × calibration) MUST be > min_conf + 8",
|
||||||
|
"updated_at": "2026-05-10",
|
||||||
|
"changelog": "V34: Reduced min_edge to realistic levels for odds-aware V25 model. Model output ≈ market-implied, so large EV edges are mathematically impossible."
|
||||||
|
},
|
||||||
|
"markets": {
|
||||||
|
"MS": {
|
||||||
|
"calibration": 0.62,
|
||||||
|
"min_conf": 20.0,
|
||||||
|
"min_play_score": 28.0,
|
||||||
|
"min_edge": 0.005,
|
||||||
|
"odds_band_min_sample": 8.0,
|
||||||
|
"odds_band_min_edge": 0.005
|
||||||
|
},
|
||||||
|
"DC": {
|
||||||
|
"calibration": 0.82,
|
||||||
|
"min_conf": 40.0,
|
||||||
|
"min_play_score": 50.0,
|
||||||
|
"min_edge": 0.003,
|
||||||
|
"odds_band_min_sample": 8.0,
|
||||||
|
"odds_band_min_edge": 0.005
|
||||||
|
},
|
||||||
|
"OU15": {
|
||||||
|
"calibration": 0.84,
|
||||||
|
"min_conf": 45.0,
|
||||||
|
"min_play_score": 50.0,
|
||||||
|
"min_edge": 0.003,
|
||||||
|
"odds_band_min_sample": 8.0,
|
||||||
|
"odds_band_min_edge": 0.005
|
||||||
|
},
|
||||||
|
"OU25": {
|
||||||
|
"calibration": 0.68,
|
||||||
|
"min_conf": 30.0,
|
||||||
|
"min_play_score": 40.0,
|
||||||
|
"min_edge": 0.005,
|
||||||
|
"odds_band_min_sample": 8.0,
|
||||||
|
"odds_band_min_edge": 0.005
|
||||||
|
},
|
||||||
|
"OU35": {
|
||||||
|
"calibration": 0.60,
|
||||||
|
"min_conf": 20.0,
|
||||||
|
"min_play_score": 30.0,
|
||||||
|
"min_edge": 0.008,
|
||||||
|
"odds_band_min_sample": 8.0,
|
||||||
|
"odds_band_min_edge": 0.008
|
||||||
|
},
|
||||||
|
"BTTS": {
|
||||||
|
"calibration": 0.65,
|
||||||
|
"min_conf": 30.0,
|
||||||
|
"min_play_score": 40.0,
|
||||||
|
"min_edge": 0.005,
|
||||||
|
"odds_band_min_sample": 8.0,
|
||||||
|
"odds_band_min_edge": 0.005
|
||||||
|
},
|
||||||
|
"HT": {
|
||||||
|
"calibration": 0.58,
|
||||||
|
"min_conf": 20.0,
|
||||||
|
"min_play_score": 28.0,
|
||||||
|
"min_edge": 0.01,
|
||||||
|
"odds_band_min_sample": 8.0,
|
||||||
|
"odds_band_min_edge": 0.008
|
||||||
|
},
|
||||||
|
"HT_OU05": {
|
||||||
|
"calibration": 0.68,
|
||||||
|
"min_conf": 35.0,
|
||||||
|
"min_play_score": 42.0,
|
||||||
|
"min_edge": 0.005,
|
||||||
|
"odds_band_min_sample": 8.0,
|
||||||
|
"odds_band_min_edge": 0.005
|
||||||
|
},
|
||||||
|
"HT_OU15": {
|
||||||
|
"calibration": 0.60,
|
||||||
|
"min_conf": 25.0,
|
||||||
|
"min_play_score": 32.0,
|
||||||
|
"min_edge": 0.008,
|
||||||
|
"odds_band_min_sample": 8.0,
|
||||||
|
"odds_band_min_edge": 0.008
|
||||||
|
},
|
||||||
|
"OE": {
|
||||||
|
"calibration": 0.62,
|
||||||
|
"min_conf": 35.0,
|
||||||
|
"min_play_score": 32.0,
|
||||||
|
"min_edge": 0.005
|
||||||
|
},
|
||||||
|
"CARDS": {
|
||||||
|
"calibration": 0.58,
|
||||||
|
"min_conf": 30.0,
|
||||||
|
"min_play_score": 35.0,
|
||||||
|
"min_edge": 0.008
|
||||||
|
},
|
||||||
|
"HCAP": {
|
||||||
|
"calibration": 0.56,
|
||||||
|
"min_conf": 25.0,
|
||||||
|
"min_play_score": 30.0,
|
||||||
|
"min_edge": 0.015
|
||||||
|
},
|
||||||
|
"HTFT": {
|
||||||
|
"calibration": 0.45,
|
||||||
|
"min_conf": 10.0,
|
||||||
|
"min_play_score": 18.0,
|
||||||
|
"min_edge": 0.02
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaults": {
|
||||||
|
"calibration": 0.55,
|
||||||
|
"min_conf": 55.0,
|
||||||
|
"min_play_score": 60.0,
|
||||||
|
"min_edge": 0.008,
|
||||||
|
"odds_band_min_sample": 0.0,
|
||||||
|
"odds_band_min_edge": 0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,7 +40,7 @@ class CalculationContext:
|
|||||||
is_surprise: bool = False
|
is_surprise: bool = False
|
||||||
|
|
||||||
# XGBoost Predictions (New)
|
# XGBoost Predictions (New)
|
||||||
xgboost_preds: dict[str, dict[str, Any]] = field(default_factory=dict)
|
xgboost_preds: dict[str, Any] = field(default_factory=dict)
|
||||||
|
|
||||||
|
|
||||||
class BaseCalculator:
|
class BaseCalculator:
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class RecommendationResult:
|
|||||||
|
|
||||||
|
|
||||||
class BetRecommender(BaseCalculator):
|
class BetRecommender(BaseCalculator):
|
||||||
def calculate(self,
|
def calculate(self, # type: ignore[override]
|
||||||
ctx: CalculationContext,
|
ctx: CalculationContext,
|
||||||
ms_res: MatchResultPrediction,
|
ms_res: MatchResultPrediction,
|
||||||
ou_res: OverUnderPrediction,
|
ou_res: OverUnderPrediction,
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class ExpertResult:
|
|||||||
|
|
||||||
|
|
||||||
class ExpertRecommender(BaseCalculator):
|
class ExpertRecommender(BaseCalculator):
|
||||||
def calculate(self,
|
def calculate(self, # type: ignore[override]
|
||||||
ctx: CalculationContext,
|
ctx: CalculationContext,
|
||||||
ms_res: MatchResultPrediction,
|
ms_res: MatchResultPrediction,
|
||||||
ou_res: OverUnderPrediction,
|
ou_res: OverUnderPrediction,
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class HalfTimeCalculator(BaseCalculator):
|
|||||||
return 1.0 if k == 0 else 0.0
|
return 1.0 if k == 0 else 0.0
|
||||||
return (lam ** k) * math.exp(-lam) / math.factorial(k)
|
return (lam ** k) * math.exp(-lam) / math.factorial(k)
|
||||||
|
|
||||||
def calculate(self, ctx: CalculationContext) -> HalfTimePrediction:
|
def calculate(self, ctx: CalculationContext) -> HalfTimePrediction: # type: ignore[override]
|
||||||
team_pred = ctx.team_pred
|
team_pred = ctx.team_pred
|
||||||
odds_pred = ctx.odds_pred
|
odds_pred = ctx.odds_pred
|
||||||
|
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ class MatchResultCalculator(BaseCalculator):
|
|||||||
def _get_engine_winner(self, home_prob: float, draw_prob: float, away_prob: float) -> str:
|
def _get_engine_winner(self, home_prob: float, draw_prob: float, away_prob: float) -> str:
|
||||||
"""Determine which outcome an engine favors."""
|
"""Determine which outcome an engine favors."""
|
||||||
probs = {"1": home_prob, "X": draw_prob, "2": away_prob}
|
probs = {"1": home_prob, "X": draw_prob, "2": away_prob}
|
||||||
return max(probs, key=probs.get)
|
return max(probs, key=probs.__getitem__)
|
||||||
|
|
||||||
def calculate(self, ctx: CalculationContext) -> MatchResultPrediction:
|
def calculate(self, ctx: CalculationContext) -> MatchResultPrediction: # type: ignore[override]
|
||||||
# Weights
|
# Weights
|
||||||
w_team = ctx.weights["team"]
|
w_team = ctx.weights["team"]
|
||||||
w_player = ctx.weights["player"]
|
w_player = ctx.weights["player"]
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class OtherMarketsPrediction:
|
|||||||
|
|
||||||
|
|
||||||
class OtherMarketsCalculator(BaseCalculator):
|
class OtherMarketsCalculator(BaseCalculator):
|
||||||
def calculate(
|
def calculate( # type: ignore[override]
|
||||||
self,
|
self,
|
||||||
ctx: CalculationContext,
|
ctx: CalculationContext,
|
||||||
ms_result: MatchResultPrediction,
|
ms_result: MatchResultPrediction,
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class OverUnderCalculator(BaseCalculator):
|
|||||||
|
|
||||||
return over_15, over_25, over_35, btts_yes
|
return over_15, over_25, over_35, btts_yes
|
||||||
|
|
||||||
def calculate(self, ctx: CalculationContext) -> OverUnderPrediction:
|
def calculate(self, ctx: CalculationContext) -> OverUnderPrediction: # type: ignore[override]
|
||||||
odds_pred = ctx.odds_pred
|
odds_pred = ctx.odds_pred
|
||||||
referee_mods = ctx.referee_mods
|
referee_mods = ctx.referee_mods
|
||||||
|
|
||||||
|
|||||||
@@ -67,12 +67,14 @@ class RiskAssessor(BaseCalculator):
|
|||||||
|
|
||||||
if sport_key == "basketball":
|
if sport_key == "basketball":
|
||||||
if is_top_league:
|
if is_top_league:
|
||||||
return float(
|
top_val = self.config.get("risk.surprise_threshold_basketball_top")
|
||||||
self.config.get("risk.surprise_threshold_basketball_top", self.config.get("risk.surprise_threshold_basketball", 0.30)),
|
if top_val is not None:
|
||||||
)
|
return float(top_val)
|
||||||
return float(
|
base_val = self.config.get("risk.surprise_threshold_basketball")
|
||||||
self.config.get("risk.surprise_threshold_basketball_non_top", 0.34),
|
return float(base_val) if base_val is not None else 0.30
|
||||||
)
|
|
||||||
|
non_top_val = self.config.get("risk.surprise_threshold_basketball_non_top")
|
||||||
|
return float(non_top_val) if non_top_val is not None else 0.34
|
||||||
|
|
||||||
if top_label not in ("1/2", "2/1"):
|
if top_label not in ("1/2", "2/1"):
|
||||||
return base_threshold
|
return base_threshold
|
||||||
@@ -81,27 +83,30 @@ class RiskAssessor(BaseCalculator):
|
|||||||
favorite_side, gap = self._favorite_profile_from_odds(ctx.odds_data)
|
favorite_side, gap = self._favorite_profile_from_odds(ctx.odds_data)
|
||||||
|
|
||||||
if is_top_league:
|
if is_top_league:
|
||||||
favorite_winner_threshold = float(
|
top_fav = self.config.get("risk.surprise_threshold_favorite_reversal_top")
|
||||||
self.config.get(
|
if top_fav is not None:
|
||||||
"risk.surprise_threshold_favorite_reversal_top",
|
favorite_winner_threshold = float(top_fav)
|
||||||
self.config.get("risk.surprise_threshold_favorite_reversal", 0.26),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
underdog_winner_threshold = float(
|
|
||||||
self.config.get(
|
|
||||||
"risk.surprise_threshold_underdog_reversal_top",
|
|
||||||
self.config.get("risk.surprise_threshold_underdog_reversal", 0.20),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
favorite_winner_threshold = float(
|
base_fav = self.config.get("risk.surprise_threshold_favorite_reversal")
|
||||||
self.config.get("risk.surprise_threshold_favorite_reversal_non_top", 0.30),
|
favorite_winner_threshold = float(base_fav) if base_fav is not None else 0.26
|
||||||
)
|
|
||||||
underdog_winner_threshold = float(
|
top_ud = self.config.get("risk.surprise_threshold_underdog_reversal_top")
|
||||||
self.config.get("risk.surprise_threshold_underdog_reversal_non_top", 0.24),
|
if top_ud is not None:
|
||||||
)
|
underdog_winner_threshold = float(top_ud)
|
||||||
gap_medium = float(self.config.get("risk.htft_reversal_gap_medium", 0.50))
|
else:
|
||||||
gap_strong = float(self.config.get("risk.htft_reversal_gap_strong", 1.00))
|
base_ud = self.config.get("risk.surprise_threshold_underdog_reversal")
|
||||||
|
underdog_winner_threshold = float(base_ud) if base_ud is not None else 0.20
|
||||||
|
else:
|
||||||
|
nt_fav = self.config.get("risk.surprise_threshold_favorite_reversal_non_top")
|
||||||
|
favorite_winner_threshold = float(nt_fav) if nt_fav is not None else 0.30
|
||||||
|
nt_ud = self.config.get("risk.surprise_threshold_underdog_reversal_non_top")
|
||||||
|
underdog_winner_threshold = float(nt_ud) if nt_ud is not None else 0.24
|
||||||
|
|
||||||
|
gm = self.config.get("risk.htft_reversal_gap_medium")
|
||||||
|
gap_medium = float(gm) if gm is not None else 0.50
|
||||||
|
|
||||||
|
gs = self.config.get("risk.htft_reversal_gap_strong")
|
||||||
|
gap_strong = float(gs) if gs is not None else 1.00
|
||||||
|
|
||||||
if favorite_side in ("H", "A"):
|
if favorite_side in ("H", "A"):
|
||||||
threshold = (
|
threshold = (
|
||||||
@@ -117,7 +122,7 @@ class RiskAssessor(BaseCalculator):
|
|||||||
|
|
||||||
return base_threshold
|
return base_threshold
|
||||||
|
|
||||||
def calculate(self, ctx: CalculationContext, ms_result=None) -> RiskAnalysis:
|
def calculate(self, ctx: CalculationContext, ms_result: Any = None) -> RiskAnalysis: # type: ignore[override]
|
||||||
"""
|
"""
|
||||||
Wrapper for assess_risk to match BaseCalculator interface but with extra arg.
|
Wrapper for assess_risk to match BaseCalculator interface but with extra arg.
|
||||||
"""
|
"""
|
||||||
@@ -173,9 +178,15 @@ class RiskAssessor(BaseCalculator):
|
|||||||
|
|
||||||
threshold = self._dynamic_reversal_threshold(ctx, top_label)
|
threshold = self._dynamic_reversal_threshold(ctx, top_label)
|
||||||
if getattr(ctx, "is_top_league", False):
|
if getattr(ctx, "is_top_league", False):
|
||||||
min_gap = float(self.config.get("risk.surprise_min_top_gap_top", self.config.get("risk.surprise_min_top_gap", 0.02)))
|
top_gap_val = self.config.get("risk.surprise_min_top_gap_top")
|
||||||
|
if top_gap_val is not None:
|
||||||
|
min_gap = float(top_gap_val)
|
||||||
else:
|
else:
|
||||||
min_gap = float(self.config.get("risk.surprise_min_top_gap_non_top", 0.03))
|
base_gap_val = self.config.get("risk.surprise_min_top_gap")
|
||||||
|
min_gap = float(base_gap_val) if base_gap_val is not None else 0.02
|
||||||
|
else:
|
||||||
|
non_top_gap_val = self.config.get("risk.surprise_min_top_gap_non_top")
|
||||||
|
min_gap = float(non_top_gap_val) if non_top_gap_val is not None else 0.03
|
||||||
|
|
||||||
# Trigger surprise only when reversal class is:
|
# Trigger surprise only when reversal class is:
|
||||||
# - top HT/FT outcome
|
# - top HT/FT outcome
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import pickle
|
|||||||
import pandas as pd
|
import pandas as pd
|
||||||
import xgboost as xgb
|
import xgboost as xgb
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import List, Dict, Tuple
|
from typing import List, Dict, Tuple, Optional
|
||||||
import math
|
import math
|
||||||
from .base_calculator import BaseCalculator, CalculationContext
|
from .base_calculator import BaseCalculator, CalculationContext
|
||||||
from .confidence import calc_confidence_3way, calc_confidence_dc
|
from .confidence import calc_confidence_3way, calc_confidence_dc
|
||||||
@@ -16,7 +16,7 @@ class ScorePrediction:
|
|||||||
ft_scores_top5: List[Dict]
|
ft_scores_top5: List[Dict]
|
||||||
|
|
||||||
# Reconciled MS/DC predictions (can be updated here)
|
# Reconciled MS/DC predictions (can be updated here)
|
||||||
reconciled_ms: MatchResultPrediction = None
|
reconciled_ms: Optional[MatchResultPrediction] = None
|
||||||
|
|
||||||
class ScoreCalculator(BaseCalculator):
|
class ScoreCalculator(BaseCalculator):
|
||||||
|
|
||||||
@@ -57,7 +57,8 @@ class ScoreCalculator(BaseCalculator):
|
|||||||
return 1.0 if k == 0 else 0.0
|
return 1.0 if k == 0 else 0.0
|
||||||
return (lam ** k) * math.exp(-lam) / math.factorial(k)
|
return (lam ** k) * math.exp(-lam) / math.factorial(k)
|
||||||
|
|
||||||
def calculate(self, ctx: CalculationContext, ms_result: MatchResultPrediction) -> ScorePrediction:
|
def calculate(self, ctx: CalculationContext, ms_result: MatchResultPrediction) -> ScorePrediction: # type: ignore[override]
|
||||||
|
predicted_ht = None
|
||||||
# Default Lambdas (fallback)
|
# Default Lambdas (fallback)
|
||||||
lambda_home = max(0.5, ctx.home_xg)
|
lambda_home = max(0.5, ctx.home_xg)
|
||||||
lambda_away = max(0.5, ctx.away_xg)
|
lambda_away = max(0.5, ctx.away_xg)
|
||||||
@@ -199,7 +200,7 @@ class ScoreCalculator(BaseCalculator):
|
|||||||
predicted_ft = top_overall_score
|
predicted_ft = top_overall_score
|
||||||
|
|
||||||
# If we didn't calculate HT via ML (exception case), do it now
|
# If we didn't calculate HT via ML (exception case), do it now
|
||||||
if 'predicted_ht' not in locals():
|
if predicted_ht is None:
|
||||||
ft_to_ht = self.config.get("half_time.ft_to_ht_ratio", 0.42)
|
ft_to_ht = self.config.get("half_time.ft_to_ht_ratio", 0.42)
|
||||||
ht_h = round(lambda_home * ft_to_ht)
|
ht_h = round(lambda_home * ft_to_ht)
|
||||||
ht_a = round(lambda_away * ft_to_ht)
|
ht_a = round(lambda_away * ft_to_ht)
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
# ai-engine/core/engines/__init__.py
|
# ai-engine/core/engines/__init__.py
|
||||||
"""
|
"""
|
||||||
V20 Ensemble Prediction Engines
|
Prediction Engines
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from .team_predictor import TeamPredictorEngine, get_team_predictor
|
|
||||||
from .player_predictor import PlayerPredictorEngine, get_player_predictor
|
from .player_predictor import PlayerPredictorEngine, get_player_predictor
|
||||||
from .odds_predictor import OddsPredictorEngine, get_odds_predictor
|
|
||||||
from .referee_predictor import RefereePredictorEngine, get_referee_predictor
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"TeamPredictorEngine", "get_team_predictor",
|
|
||||||
"PlayerPredictorEngine", "get_player_predictor",
|
"PlayerPredictorEngine", "get_player_predictor",
|
||||||
"OddsPredictorEngine", "get_odds_predictor",
|
|
||||||
"RefereePredictorEngine", "get_referee_predictor"
|
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,237 +0,0 @@
|
|||||||
"""
|
|
||||||
Odds Predictor Engine - V20 Ensemble Component
|
|
||||||
Uses market odds and Poisson mathematics for predictions.
|
|
||||||
|
|
||||||
Weight: 30% in ensemble
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from typing import Dict, Optional
|
|
||||||
from dataclasses import dataclass
|
|
||||||
|
|
||||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
|
||||||
|
|
||||||
from features.poisson_engine import get_poisson_engine
|
|
||||||
from features.value_calculator import get_value_calculator
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class OddsPrediction:
|
|
||||||
"""Odds engine prediction output."""
|
|
||||||
# Market-implied probabilities
|
|
||||||
market_home_prob: float = 0.33
|
|
||||||
market_draw_prob: float = 0.33
|
|
||||||
market_away_prob: float = 0.33
|
|
||||||
|
|
||||||
# Poisson xG
|
|
||||||
poisson_home_xg: float = 1.3
|
|
||||||
poisson_away_xg: float = 1.1
|
|
||||||
|
|
||||||
# Over/Under probabilities
|
|
||||||
over_15_prob: float = 0.75
|
|
||||||
over_25_prob: float = 0.55
|
|
||||||
over_35_prob: float = 0.30
|
|
||||||
|
|
||||||
# BTTS
|
|
||||||
btts_yes_prob: float = 0.50
|
|
||||||
|
|
||||||
# Most likely scores
|
|
||||||
most_likely_score: str = "1-1"
|
|
||||||
second_likely_score: str = "1-0"
|
|
||||||
third_likely_score: str = "2-1"
|
|
||||||
|
|
||||||
# Value bet opportunities
|
|
||||||
value_bets: list = None
|
|
||||||
|
|
||||||
confidence: float = 0.0
|
|
||||||
|
|
||||||
def __post_init__(self):
|
|
||||||
if self.value_bets is None:
|
|
||||||
self.value_bets = []
|
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
|
||||||
return {
|
|
||||||
"market_home_prob": round(self.market_home_prob * 100, 1),
|
|
||||||
"market_draw_prob": round(self.market_draw_prob * 100, 1),
|
|
||||||
"market_away_prob": round(self.market_away_prob * 100, 1),
|
|
||||||
"poisson_home_xg": round(self.poisson_home_xg, 2),
|
|
||||||
"poisson_away_xg": round(self.poisson_away_xg, 2),
|
|
||||||
"over_15_prob": round(self.over_15_prob * 100, 1),
|
|
||||||
"over_25_prob": round(self.over_25_prob * 100, 1),
|
|
||||||
"over_35_prob": round(self.over_35_prob * 100, 1),
|
|
||||||
"btts_yes_prob": round(self.btts_yes_prob * 100, 1),
|
|
||||||
"most_likely_score": self.most_likely_score,
|
|
||||||
"second_likely_score": self.second_likely_score,
|
|
||||||
"third_likely_score": self.third_likely_score,
|
|
||||||
"value_bets": self.value_bets,
|
|
||||||
"confidence": round(self.confidence, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class OddsPredictorEngine:
|
|
||||||
"""
|
|
||||||
Odds-based prediction engine.
|
|
||||||
|
|
||||||
Uses:
|
|
||||||
- Market odds to extract implied probabilities
|
|
||||||
- Poisson distribution for mathematical xG
|
|
||||||
- Value calculator for EV+ opportunities
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.poisson_engine = get_poisson_engine()
|
|
||||||
try:
|
|
||||||
self.value_calc = get_value_calculator()
|
|
||||||
except Exception:
|
|
||||||
self.value_calc = None
|
|
||||||
self.default_ms_h = 2.65
|
|
||||||
self.default_ms_d = 3.20
|
|
||||||
self.default_ms_a = 2.65
|
|
||||||
print("✅ OddsPredictorEngine initialized")
|
|
||||||
|
|
||||||
def _odds_to_prob(self, odds: float) -> float:
|
|
||||||
"""Convert decimal odds to probability."""
|
|
||||||
try:
|
|
||||||
odds = float(odds)
|
|
||||||
except (TypeError, ValueError):
|
|
||||||
return 0.0
|
|
||||||
if odds <= 1.0:
|
|
||||||
return 0.0
|
|
||||||
return 1.0 / odds
|
|
||||||
|
|
||||||
def predict(self,
|
|
||||||
odds_data: Dict[str, float],
|
|
||||||
home_goals_avg: float = 1.5,
|
|
||||||
home_conceded_avg: float = 1.2,
|
|
||||||
away_goals_avg: float = 1.2,
|
|
||||||
away_conceded_avg: float = 1.4) -> OddsPrediction:
|
|
||||||
"""
|
|
||||||
Generate odds-based prediction.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
odds_data: Dict with keys like 'ms_h', 'ms_d', 'ms_a', 'ou25_o', 'btts_y'
|
|
||||||
home_goals_avg: Home team's average goals scored
|
|
||||||
home_conceded_avg: Home team's average goals conceded
|
|
||||||
away_goals_avg: Away team's average goals scored
|
|
||||||
away_conceded_avg: Away team's average goals conceded
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
OddsPrediction with market and Poisson analysis
|
|
||||||
"""
|
|
||||||
|
|
||||||
# 1. Extract market probabilities from odds
|
|
||||||
ms_h = odds_data.get("ms_h", self.default_ms_h)
|
|
||||||
ms_d = odds_data.get("ms_d", self.default_ms_d)
|
|
||||||
ms_a = odds_data.get("ms_a", self.default_ms_a)
|
|
||||||
|
|
||||||
# Remove vig to get fair probabilities
|
|
||||||
raw_probs = [
|
|
||||||
self._odds_to_prob(ms_h),
|
|
||||||
self._odds_to_prob(ms_d),
|
|
||||||
self._odds_to_prob(ms_a)
|
|
||||||
]
|
|
||||||
total = sum(raw_probs) or 1
|
|
||||||
|
|
||||||
market_home = raw_probs[0] / total
|
|
||||||
market_draw = raw_probs[1] / total
|
|
||||||
market_away = raw_probs[2] / total
|
|
||||||
|
|
||||||
# 2. Poisson prediction
|
|
||||||
poisson_pred = self.poisson_engine.predict(
|
|
||||||
home_goals_avg, home_conceded_avg,
|
|
||||||
away_goals_avg, away_conceded_avg
|
|
||||||
)
|
|
||||||
|
|
||||||
# 3. Get most likely scores
|
|
||||||
likely_scores = poisson_pred.most_likely_scores[:3] if poisson_pred.most_likely_scores else []
|
|
||||||
score_1 = likely_scores[0]["score"] if len(likely_scores) > 0 else "1-1"
|
|
||||||
score_2 = likely_scores[1]["score"] if len(likely_scores) > 1 else "1-0"
|
|
||||||
score_3 = likely_scores[2]["score"] if len(likely_scores) > 2 else "2-1"
|
|
||||||
|
|
||||||
# 4. Value bet detection
|
|
||||||
value_bets = []
|
|
||||||
|
|
||||||
# Check if our Poisson model disagrees with market significantly
|
|
||||||
if abs(poisson_pred.home_win_prob - market_home) > 0.10:
|
|
||||||
if poisson_pred.home_win_prob > market_home:
|
|
||||||
value_bets.append({
|
|
||||||
"market": "MS 1",
|
|
||||||
"edge": round((poisson_pred.home_win_prob - market_home) * 100, 1),
|
|
||||||
"confidence": "medium"
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
value_bets.append({
|
|
||||||
"market": "MS 2",
|
|
||||||
"edge": round((poisson_pred.away_win_prob - market_away) * 100, 1),
|
|
||||||
"confidence": "medium"
|
|
||||||
})
|
|
||||||
|
|
||||||
# O/U value check
|
|
||||||
ou25_o = odds_data.get("ou25_o", 1.9)
|
|
||||||
market_over25 = self._odds_to_prob(ou25_o)
|
|
||||||
if abs(poisson_pred.over_25_prob - market_over25) > 0.08:
|
|
||||||
pick = "2.5 Üst" if poisson_pred.over_25_prob > market_over25 else "2.5 Alt"
|
|
||||||
edge = abs(poisson_pred.over_25_prob - market_over25) * 100
|
|
||||||
value_bets.append({
|
|
||||||
"market": pick,
|
|
||||||
"edge": round(edge, 1),
|
|
||||||
"confidence": "high" if edge > 10 else "medium"
|
|
||||||
})
|
|
||||||
|
|
||||||
# Calculate confidence
|
|
||||||
# Higher when market and Poisson agree
|
|
||||||
agreement = 1.0 - abs(poisson_pred.home_win_prob - market_home)
|
|
||||||
confidence = 50.0 + (agreement * 40) + (len(value_bets) * 5)
|
|
||||||
|
|
||||||
return OddsPrediction(
|
|
||||||
market_home_prob=market_home,
|
|
||||||
market_draw_prob=market_draw,
|
|
||||||
market_away_prob=market_away,
|
|
||||||
poisson_home_xg=poisson_pred.home_xg,
|
|
||||||
poisson_away_xg=poisson_pred.away_xg,
|
|
||||||
over_15_prob=poisson_pred.over_15_prob,
|
|
||||||
over_25_prob=poisson_pred.over_25_prob,
|
|
||||||
over_35_prob=poisson_pred.over_35_prob,
|
|
||||||
btts_yes_prob=poisson_pred.btts_yes_prob,
|
|
||||||
most_likely_score=score_1,
|
|
||||||
second_likely_score=score_2,
|
|
||||||
third_likely_score=score_3,
|
|
||||||
value_bets=value_bets,
|
|
||||||
confidence=min(99.9, confidence)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# Singleton
|
|
||||||
_engine: Optional[OddsPredictorEngine] = None
|
|
||||||
|
|
||||||
|
|
||||||
def get_odds_predictor() -> OddsPredictorEngine:
|
|
||||||
global _engine
|
|
||||||
if _engine is None:
|
|
||||||
_engine = OddsPredictorEngine()
|
|
||||||
return _engine
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
engine = get_odds_predictor()
|
|
||||||
|
|
||||||
print("\n🧪 Odds Predictor Engine Test")
|
|
||||||
print("=" * 50)
|
|
||||||
|
|
||||||
pred = engine.predict(
|
|
||||||
odds_data={
|
|
||||||
"ms_h": 1.85,
|
|
||||||
"ms_d": 3.40,
|
|
||||||
"ms_a": 4.20,
|
|
||||||
"ou25_o": 1.90
|
|
||||||
},
|
|
||||||
home_goals_avg=1.8,
|
|
||||||
home_conceded_avg=1.0,
|
|
||||||
away_goals_avg=1.2,
|
|
||||||
away_conceded_avg=1.5
|
|
||||||
)
|
|
||||||
|
|
||||||
print(f"\n📊 Prediction:")
|
|
||||||
for k, v in pred.to_dict().items():
|
|
||||||
print(f" {k}: {v}")
|
|
||||||
@@ -18,34 +18,36 @@ from features.sidelined_analyzer import get_sidelined_analyzer
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class PlayerPrediction:
|
class PlayerPrediction:
|
||||||
"""Player engine prediction output."""
|
"""Player engine prediction output.
|
||||||
home_squad_quality: float = 50.0 # 0-100
|
|
||||||
away_squad_quality: float = 50.0
|
IMPORTANT: squad_quality uses the SAME composite formula as
|
||||||
squad_diff: float = 0.0 # -100 to +100
|
extract_training_data.py so that inference values match the
|
||||||
|
distribution the model was trained on (~3-36 range).
|
||||||
|
"""
|
||||||
|
home_squad_quality: float = 12.0
|
||||||
|
away_squad_quality: float = 12.0
|
||||||
|
squad_diff: float = 0.0
|
||||||
home_key_players: int = 0
|
home_key_players: int = 0
|
||||||
away_key_players: int = 0
|
away_key_players: int = 0
|
||||||
home_missing_impact: float = 0.0 # 0-1, how much weaker due to missing players
|
home_missing_impact: float = 0.0
|
||||||
away_missing_impact: float = 0.0
|
away_missing_impact: float = 0.0
|
||||||
home_goals_form: int = 0 # Goals in last 5 matches
|
home_goals_form: int = 0
|
||||||
away_goals_form: int = 0
|
away_goals_form: int = 0
|
||||||
|
home_lineup_goals_per90: float = 0.0
|
||||||
|
away_lineup_goals_per90: float = 0.0
|
||||||
|
home_lineup_assists_per90: float = 0.0
|
||||||
|
away_lineup_assists_per90: float = 0.0
|
||||||
|
home_squad_continuity: float = 0.5
|
||||||
|
away_squad_continuity: float = 0.5
|
||||||
|
home_top_scorer_form: int = 0
|
||||||
|
away_top_scorer_form: int = 0
|
||||||
|
home_avg_player_exp: float = 0.0
|
||||||
|
away_avg_player_exp: float = 0.0
|
||||||
|
home_goals_diversity: float = 0.0
|
||||||
|
away_goals_diversity: float = 0.0
|
||||||
lineup_available: bool = False
|
lineup_available: bool = False
|
||||||
confidence: float = 0.0
|
confidence: float = 0.0
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
|
||||||
return {
|
|
||||||
"home_squad_quality": round(self.home_squad_quality, 1),
|
|
||||||
"away_squad_quality": round(self.away_squad_quality, 1),
|
|
||||||
"squad_diff": round(self.squad_diff, 1),
|
|
||||||
"home_key_players": self.home_key_players,
|
|
||||||
"away_key_players": self.away_key_players,
|
|
||||||
"home_missing_impact": round(self.home_missing_impact, 2),
|
|
||||||
"away_missing_impact": round(self.away_missing_impact, 2),
|
|
||||||
"home_goals_form": self.home_goals_form,
|
|
||||||
"away_goals_form": self.away_goals_form,
|
|
||||||
"lineup_available": self.lineup_available,
|
|
||||||
"confidence": round(self.confidence, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class PlayerPredictorEngine:
|
class PlayerPredictorEngine:
|
||||||
"""
|
"""
|
||||||
@@ -67,9 +69,9 @@ class PlayerPredictorEngine:
|
|||||||
match_id: str,
|
match_id: str,
|
||||||
home_team_id: str,
|
home_team_id: str,
|
||||||
away_team_id: str,
|
away_team_id: str,
|
||||||
home_lineup: List[str] = None,
|
home_lineup: Optional[List[str]] = None,
|
||||||
away_lineup: List[str] = None,
|
away_lineup: Optional[List[str]] = None,
|
||||||
sidelined_data: Dict = None) -> PlayerPrediction:
|
sidelined_data: Optional[Dict] = None) -> PlayerPrediction:
|
||||||
"""
|
"""
|
||||||
Generate player-based prediction.
|
Generate player-based prediction.
|
||||||
|
|
||||||
@@ -85,8 +87,9 @@ class PlayerPredictorEngine:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# Get squad features
|
# Get squad features
|
||||||
|
home_analysis = None
|
||||||
|
away_analysis = None
|
||||||
if home_lineup and away_lineup:
|
if home_lineup and away_lineup:
|
||||||
# Use provided lineups (for live matches)
|
|
||||||
home_analysis = self.squad_engine.analyze_squad_from_list(
|
home_analysis = self.squad_engine.analyze_squad_from_list(
|
||||||
home_lineup, home_team_id
|
home_lineup, home_team_id
|
||||||
)
|
)
|
||||||
@@ -94,19 +97,19 @@ class PlayerPredictorEngine:
|
|||||||
away_lineup, away_team_id
|
away_lineup, away_team_id
|
||||||
)
|
)
|
||||||
lineup_available = True
|
lineup_available = True
|
||||||
# Build features dict from analysis objects
|
|
||||||
features = {
|
features = {
|
||||||
"home_starting_11": home_analysis.starting_count or 11,
|
"home_starting_11": home_analysis.starting_count or 11,
|
||||||
"home_goals_last_5": home_analysis.total_goals_last_5,
|
"home_goals_last_5": home_analysis.total_goals_last_5,
|
||||||
"home_assists_last_5": home_analysis.total_assists_last_5,
|
"home_assists_last_5": home_analysis.total_assists_last_5,
|
||||||
"home_key_players": home_analysis.key_players_count,
|
"home_key_players": home_analysis.key_players_count,
|
||||||
|
"home_forwards": home_analysis.forward_count or 2,
|
||||||
"away_starting_11": away_analysis.starting_count or 11,
|
"away_starting_11": away_analysis.starting_count or 11,
|
||||||
"away_goals_last_5": away_analysis.total_goals_last_5,
|
"away_goals_last_5": away_analysis.total_goals_last_5,
|
||||||
"away_assists_last_5": away_analysis.total_assists_last_5,
|
"away_assists_last_5": away_analysis.total_assists_last_5,
|
||||||
"away_key_players": away_analysis.key_players_count,
|
"away_key_players": away_analysis.key_players_count,
|
||||||
|
"away_forwards": away_analysis.forward_count or 2,
|
||||||
}
|
}
|
||||||
elif match_id:
|
elif match_id:
|
||||||
# Try to get from database
|
|
||||||
try:
|
try:
|
||||||
features = self.squad_engine.get_features(
|
features = self.squad_engine.get_features(
|
||||||
match_id, home_team_id, away_team_id
|
match_id, home_team_id, away_team_id
|
||||||
@@ -126,31 +129,27 @@ class PlayerPredictorEngine:
|
|||||||
)
|
)
|
||||||
lineup_available = False
|
lineup_available = False
|
||||||
|
|
||||||
# Extract features
|
home_goals = int(features.get("home_goals_last_5", 0))
|
||||||
home_goals = features.get("home_goals_last_5", 0)
|
away_goals = int(features.get("away_goals_last_5", 0))
|
||||||
away_goals = features.get("away_goals_last_5", 0)
|
home_key = int(features.get("home_key_players", 0))
|
||||||
home_key = features.get("home_key_players", 0)
|
away_key = int(features.get("away_key_players", 0))
|
||||||
away_key = features.get("away_key_players", 0)
|
home_starting = features.get("home_starting_11", 11)
|
||||||
|
away_starting = features.get("away_starting_11", 11)
|
||||||
|
home_fwd = features.get("home_forwards", 2)
|
||||||
|
away_fwd = features.get("away_forwards", 2)
|
||||||
|
|
||||||
# Calculate squad quality (0-100)
|
# Squad quality — matches V25 extract_training_data.py:579
|
||||||
# Based on: goals scored, key players, assists
|
home_quality = home_starting * 0.3 + home_key * 3.0 + home_fwd * 1.5
|
||||||
home_quality = min(100, 50 + (home_goals * 3) + (home_key * 5) +
|
away_quality = away_starting * 0.3 + away_key * 3.0 + away_fwd * 1.5
|
||||||
features.get("home_assists_last_5", 0) * 2)
|
|
||||||
away_quality = min(100, 50 + (away_goals * 3) + (away_key * 5) +
|
|
||||||
features.get("away_assists_last_5", 0) * 2)
|
|
||||||
|
|
||||||
# Squad difference
|
|
||||||
squad_diff = home_quality - away_quality
|
squad_diff = home_quality - away_quality
|
||||||
|
|
||||||
# Missing player impact
|
# Missing player impact
|
||||||
# Priority: sidelined data (position-weighted) > lineup count (basic)
|
|
||||||
if sidelined_data:
|
if sidelined_data:
|
||||||
home_impact, away_impact = self.sidelined_analyzer.analyze_match(sidelined_data)
|
home_impact, away_impact = self.sidelined_analyzer.analyze_match(sidelined_data)
|
||||||
home_missing = home_impact.impact_score
|
home_missing = min(1.0, max(0.0, home_impact.impact_score))
|
||||||
away_missing = away_impact.impact_score
|
away_missing = min(1.0, max(0.0, away_impact.impact_score))
|
||||||
sidelined_available = True
|
sidelined_available = True
|
||||||
else:
|
else:
|
||||||
# Fallback: basic lineup count method
|
|
||||||
expected_xi = 11
|
expected_xi = 11
|
||||||
actual_home_xi = features.get("home_starting_11", 11)
|
actual_home_xi = features.get("home_starting_11", 11)
|
||||||
actual_away_xi = features.get("away_starting_11", 11)
|
actual_away_xi = features.get("away_starting_11", 11)
|
||||||
@@ -158,7 +157,13 @@ class PlayerPredictorEngine:
|
|||||||
away_missing = (expected_xi - actual_away_xi) / expected_xi if actual_away_xi < expected_xi else 0
|
away_missing = (expected_xi - actual_away_xi) / expected_xi if actual_away_xi < expected_xi else 0
|
||||||
sidelined_available = False
|
sidelined_available = False
|
||||||
|
|
||||||
# Confidence: more data sources = higher confidence
|
# Player-level features (matches extract_training_data.py:594-650)
|
||||||
|
player_feats = self._compute_player_level_features(
|
||||||
|
home_lineup or [], away_lineup or [],
|
||||||
|
home_team_id, away_team_id,
|
||||||
|
home_analysis, away_analysis,
|
||||||
|
)
|
||||||
|
|
||||||
confidence = 70.0 if lineup_available else 35.0
|
confidence = 70.0 if lineup_available else 35.0
|
||||||
if home_goals + away_goals > 10:
|
if home_goals + away_goals > 10:
|
||||||
confidence += 15
|
confidence += 15
|
||||||
@@ -177,17 +182,147 @@ class PlayerPredictorEngine:
|
|||||||
away_missing_impact=away_missing,
|
away_missing_impact=away_missing,
|
||||||
home_goals_form=home_goals,
|
home_goals_form=home_goals,
|
||||||
away_goals_form=away_goals,
|
away_goals_form=away_goals,
|
||||||
|
home_lineup_goals_per90=player_feats['home_lineup_goals_per90'],
|
||||||
|
away_lineup_goals_per90=player_feats['away_lineup_goals_per90'],
|
||||||
|
home_lineup_assists_per90=player_feats['home_lineup_assists_per90'],
|
||||||
|
away_lineup_assists_per90=player_feats['away_lineup_assists_per90'],
|
||||||
|
home_squad_continuity=player_feats['home_squad_continuity'],
|
||||||
|
away_squad_continuity=player_feats['away_squad_continuity'],
|
||||||
|
home_top_scorer_form=player_feats['home_top_scorer_form'],
|
||||||
|
away_top_scorer_form=player_feats['away_top_scorer_form'],
|
||||||
|
home_avg_player_exp=player_feats['home_avg_player_exp'],
|
||||||
|
away_avg_player_exp=player_feats['away_avg_player_exp'],
|
||||||
|
home_goals_diversity=player_feats['home_goals_diversity'],
|
||||||
|
away_goals_diversity=player_feats['away_goals_diversity'],
|
||||||
lineup_available=lineup_available,
|
lineup_available=lineup_available,
|
||||||
confidence=max(5.0, confidence)
|
confidence=max(5.0, confidence)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _compute_player_level_features(
|
||||||
|
self,
|
||||||
|
home_lineup: List[str],
|
||||||
|
away_lineup: List[str],
|
||||||
|
home_team_id: str,
|
||||||
|
away_team_id: str,
|
||||||
|
home_analysis,
|
||||||
|
away_analysis,
|
||||||
|
) -> Dict[str, float]:
|
||||||
|
defaults = {
|
||||||
|
'home_lineup_goals_per90': 0.0, 'away_lineup_goals_per90': 0.0,
|
||||||
|
'home_lineup_assists_per90': 0.0, 'away_lineup_assists_per90': 0.0,
|
||||||
|
'home_squad_continuity': 0.5, 'away_squad_continuity': 0.5,
|
||||||
|
'home_top_scorer_form': 0, 'away_top_scorer_form': 0,
|
||||||
|
'home_avg_player_exp': 0.0, 'away_avg_player_exp': 0.0,
|
||||||
|
'home_goals_diversity': 0.0, 'away_goals_diversity': 0.0,
|
||||||
|
}
|
||||||
|
conn = self.squad_engine.get_conn()
|
||||||
|
if conn is None:
|
||||||
|
return defaults
|
||||||
|
|
||||||
|
try:
|
||||||
|
from psycopg2.extras import RealDictCursor
|
||||||
|
result = {}
|
||||||
|
for prefix, lineup, team_id in [
|
||||||
|
('home', home_lineup, home_team_id),
|
||||||
|
('away', away_lineup, away_team_id),
|
||||||
|
]:
|
||||||
|
if not lineup:
|
||||||
|
for k in ('lineup_goals_per90', 'lineup_assists_per90',
|
||||||
|
'squad_continuity', 'top_scorer_form',
|
||||||
|
'avg_player_exp', 'goals_diversity'):
|
||||||
|
result[f'{prefix}_{k}'] = defaults[f'{prefix}_{k}']
|
||||||
|
continue
|
||||||
|
|
||||||
|
g90, a90, total_exp = 0.0, 0.0, 0
|
||||||
|
best_scorer_total, best_scorer_id = 0, None
|
||||||
|
scorers_in_lineup = 0
|
||||||
|
|
||||||
|
with conn.cursor(cursor_factory=RealDictCursor) as cur:
|
||||||
|
for pid in lineup:
|
||||||
|
cur.execute("""
|
||||||
|
SELECT
|
||||||
|
COUNT(*) as starts,
|
||||||
|
COALESCE(SUM(CASE WHEN e.event_type = 'goal'
|
||||||
|
AND (e.event_subtype IS NULL OR e.event_subtype NOT ILIKE '%%penaltı kaçırma%%')
|
||||||
|
THEN 1 ELSE 0 END), 0) as goals,
|
||||||
|
COALESCE((SELECT COUNT(*) FROM match_player_events
|
||||||
|
WHERE assist_player_id = %s), 0) as assists
|
||||||
|
FROM match_player_participation mpp
|
||||||
|
LEFT JOIN match_player_events e
|
||||||
|
ON e.match_id = mpp.match_id AND e.player_id = mpp.player_id
|
||||||
|
WHERE mpp.player_id = %s AND mpp.is_starting = true
|
||||||
|
""", (pid, pid))
|
||||||
|
row = cur.fetchone()
|
||||||
|
if not row or not row['starts']:
|
||||||
|
continue
|
||||||
|
starts = row['starts']
|
||||||
|
goals = row['goals'] or 0
|
||||||
|
assists = row['assists'] or 0
|
||||||
|
g90 += goals / starts
|
||||||
|
a90 += assists / starts
|
||||||
|
total_exp += starts
|
||||||
|
if goals > 0:
|
||||||
|
scorers_in_lineup += 1
|
||||||
|
if goals > best_scorer_total:
|
||||||
|
best_scorer_total = goals
|
||||||
|
best_scorer_id = pid
|
||||||
|
|
||||||
|
n_st = len(lineup) or 1
|
||||||
|
|
||||||
|
# Top scorer recent form (goals in last 5 starts)
|
||||||
|
top_scorer_form = 0
|
||||||
|
if best_scorer_id:
|
||||||
|
cur.execute("""
|
||||||
|
SELECT COUNT(*) as goals
|
||||||
|
FROM match_player_events mpe
|
||||||
|
WHERE mpe.player_id = %s AND mpe.event_type = 'goal'
|
||||||
|
AND mpe.match_id IN (
|
||||||
|
SELECT match_id FROM match_player_participation
|
||||||
|
WHERE player_id = %s AND is_starting = true
|
||||||
|
ORDER BY match_id DESC LIMIT 5
|
||||||
|
)
|
||||||
|
""", (best_scorer_id, best_scorer_id))
|
||||||
|
tsf_row = cur.fetchone()
|
||||||
|
if tsf_row:
|
||||||
|
top_scorer_form = tsf_row['goals'] or 0
|
||||||
|
|
||||||
|
# Squad continuity (overlap with previous match lineup)
|
||||||
|
squad_continuity = 0.5
|
||||||
|
cur.execute("""
|
||||||
|
SELECT mpp.player_id
|
||||||
|
FROM match_player_participation mpp
|
||||||
|
JOIN matches m ON mpp.match_id = m.id
|
||||||
|
WHERE mpp.team_id = %s AND mpp.is_starting = true
|
||||||
|
AND m.status = 'FT'
|
||||||
|
ORDER BY m.mst_utc DESC
|
||||||
|
LIMIT 11
|
||||||
|
""", (team_id,))
|
||||||
|
prev_starters = {r['player_id'] for r in cur.fetchall()}
|
||||||
|
if prev_starters:
|
||||||
|
overlap = len(set(lineup) & prev_starters)
|
||||||
|
squad_continuity = overlap / n_st
|
||||||
|
|
||||||
|
result[f'{prefix}_lineup_goals_per90'] = round(g90, 3)
|
||||||
|
result[f'{prefix}_lineup_assists_per90'] = round(a90, 3)
|
||||||
|
result[f'{prefix}_squad_continuity'] = round(squad_continuity, 3)
|
||||||
|
result[f'{prefix}_top_scorer_form'] = top_scorer_form
|
||||||
|
result[f'{prefix}_avg_player_exp'] = round(total_exp / n_st, 1)
|
||||||
|
result[f'{prefix}_goals_diversity'] = round(scorers_in_lineup / n_st, 3)
|
||||||
|
|
||||||
|
return result
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[PlayerPredictor] Player-level features failed: {e}")
|
||||||
|
return defaults
|
||||||
|
|
||||||
def get_1x2_modifier(self, prediction: PlayerPrediction) -> Dict[str, float]:
|
def get_1x2_modifier(self, prediction: PlayerPrediction) -> Dict[str, float]:
|
||||||
"""
|
"""
|
||||||
Calculate 1X2 probability modifiers based on squad analysis.
|
Calculate 1X2 probability modifiers based on squad analysis.
|
||||||
|
|
||||||
Returns modifiers to apply to base probabilities.
|
Returns modifiers to apply to base probabilities.
|
||||||
|
squad_diff is in training scale (~-33 to +33), normalize to -1..+1.
|
||||||
"""
|
"""
|
||||||
diff = prediction.squad_diff / 100 # -1 to +1
|
diff = prediction.squad_diff / 33.0 # training-scale normalisation
|
||||||
|
diff = max(-1.0, min(1.0, diff)) # clamp
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"home_modifier": 1.0 + (diff * 0.3), # Up to +/-30%
|
"home_modifier": 1.0 + (diff * 0.3), # Up to +/-30%
|
||||||
@@ -214,7 +349,7 @@ if __name__ == "__main__":
|
|||||||
print("=" * 50)
|
print("=" * 50)
|
||||||
|
|
||||||
pred = engine.predict(
|
pred = engine.predict(
|
||||||
match_id=None,
|
match_id="test_match",
|
||||||
home_team_id="test_home",
|
home_team_id="test_home",
|
||||||
away_team_id="test_away"
|
away_team_id="test_away"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,188 +0,0 @@
|
|||||||
"""
|
|
||||||
Referee Predictor Engine - V20 Ensemble Component
|
|
||||||
Analyzes referee patterns for cards, goals, and home bias.
|
|
||||||
|
|
||||||
Weight: 15% in ensemble
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from typing import Dict, Optional
|
|
||||||
from dataclasses import dataclass
|
|
||||||
|
|
||||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
|
||||||
|
|
||||||
from features.referee_engine import get_referee_engine
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class RefereePrediction:
|
|
||||||
"""Referee engine prediction output."""
|
|
||||||
referee_name: str = ""
|
|
||||||
matches_officiated: int = 0
|
|
||||||
|
|
||||||
# Card tendencies
|
|
||||||
avg_yellow_cards: float = 4.0
|
|
||||||
avg_red_cards: float = 0.2
|
|
||||||
is_card_heavy: bool = False # Above average cards
|
|
||||||
|
|
||||||
# Goal tendencies
|
|
||||||
avg_goals_per_match: float = 2.5
|
|
||||||
over_25_rate: float = 0.50
|
|
||||||
is_high_scoring: bool = False # Above average goals
|
|
||||||
|
|
||||||
# Home bias
|
|
||||||
home_win_rate: float = 0.45
|
|
||||||
home_bias: float = 0.0 # -1 to +1, positive = favors home
|
|
||||||
|
|
||||||
# Penalty tendency
|
|
||||||
penalty_rate: float = 0.15
|
|
||||||
|
|
||||||
confidence: float = 0.0
|
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
|
||||||
return {
|
|
||||||
"referee_name": self.referee_name,
|
|
||||||
"matches_officiated": self.matches_officiated,
|
|
||||||
"avg_yellow_cards": round(self.avg_yellow_cards, 1),
|
|
||||||
"avg_red_cards": round(self.avg_red_cards, 2),
|
|
||||||
"is_card_heavy": self.is_card_heavy,
|
|
||||||
"avg_goals_per_match": round(self.avg_goals_per_match, 2),
|
|
||||||
"over_25_rate": round(self.over_25_rate * 100, 1),
|
|
||||||
"is_high_scoring": self.is_high_scoring,
|
|
||||||
"home_win_rate": round(self.home_win_rate * 100, 1),
|
|
||||||
"home_bias": round(self.home_bias, 2),
|
|
||||||
"penalty_rate": round(self.penalty_rate * 100, 1),
|
|
||||||
"confidence": round(self.confidence, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class RefereePredictorEngine:
|
|
||||||
"""
|
|
||||||
Referee-based prediction engine.
|
|
||||||
|
|
||||||
Analyzes:
|
|
||||||
- Card tendency (sarı/kırmızı kart ortalaması)
|
|
||||||
- Goal tendency (maç başına gol, 2.5 üst oranı)
|
|
||||||
- Home bias (ev sahibi lehine karar oranı)
|
|
||||||
- Penalty tendency (penaltı verme oranı)
|
|
||||||
"""
|
|
||||||
|
|
||||||
# League average benchmarks
|
|
||||||
LEAGUE_AVG_GOALS = 2.65
|
|
||||||
LEAGUE_AVG_YELLOW = 4.0
|
|
||||||
LEAGUE_HOME_WIN_RATE = 0.45
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.referee_engine = get_referee_engine()
|
|
||||||
print("✅ RefereePredictorEngine initialized")
|
|
||||||
|
|
||||||
def predict(self,
|
|
||||||
match_id: str = None,
|
|
||||||
referee_name: str = None,
|
|
||||||
league_id: str = None) -> RefereePrediction:
|
|
||||||
"""
|
|
||||||
Generate referee-based prediction.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
match_id: Match ID to find referee
|
|
||||||
referee_name: Or provide referee name directly
|
|
||||||
league_id: League ID to scope stats (prevents name collisions)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
RefereePrediction with referee analysis
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Get referee features
|
|
||||||
if match_id:
|
|
||||||
features = self.referee_engine.get_features(match_id, league_id=league_id)
|
|
||||||
# Live flows may already have referee_name while match_officials table is sparse.
|
|
||||||
# Prefer the richer profile if direct-name lookup has more history.
|
|
||||||
if referee_name:
|
|
||||||
name_features = self.referee_engine.get_features_by_name(referee_name, league_id=league_id)
|
|
||||||
if (name_features.get("referee_matches", 0) or 0) > (features.get("referee_matches", 0) or 0):
|
|
||||||
features = name_features
|
|
||||||
elif referee_name:
|
|
||||||
features = self.referee_engine.get_features_by_name(referee_name, league_id=league_id)
|
|
||||||
else:
|
|
||||||
# Return default
|
|
||||||
return RefereePrediction(confidence=10.0)
|
|
||||||
|
|
||||||
ref_name = features.get("referee_name", "Unknown")
|
|
||||||
matches = features.get("referee_matches", 0)
|
|
||||||
|
|
||||||
if matches < 5:
|
|
||||||
# Not enough data
|
|
||||||
return RefereePrediction(
|
|
||||||
referee_name=ref_name,
|
|
||||||
matches_officiated=matches,
|
|
||||||
confidence=20.0
|
|
||||||
)
|
|
||||||
|
|
||||||
# Extract features
|
|
||||||
avg_yellow = features.get("referee_avg_yellow", 4.0)
|
|
||||||
avg_red = features.get("referee_avg_red", 0.2)
|
|
||||||
avg_goals = features.get("referee_avg_goals", 2.5)
|
|
||||||
over25_rate = features.get("referee_over25_rate", 0.5)
|
|
||||||
home_win_rate = features.get("referee_home_win_rate", 0.45) if "referee_home_win_rate" in features else 0.45
|
|
||||||
home_bias = features.get("referee_home_bias", 0.0)
|
|
||||||
penalty_rate = features.get("referee_penalty_rate", 0.15)
|
|
||||||
|
|
||||||
# Determine tendencies
|
|
||||||
is_card_heavy = (avg_yellow + avg_red * 4) > (self.LEAGUE_AVG_YELLOW + 1)
|
|
||||||
is_high_scoring = avg_goals > self.LEAGUE_AVG_GOALS
|
|
||||||
|
|
||||||
# Confidence based on matches officiated
|
|
||||||
confidence = min(90.0, 30.0 + matches * 2)
|
|
||||||
|
|
||||||
return RefereePrediction(
|
|
||||||
referee_name=ref_name,
|
|
||||||
matches_officiated=matches,
|
|
||||||
avg_yellow_cards=avg_yellow,
|
|
||||||
avg_red_cards=avg_red,
|
|
||||||
is_card_heavy=is_card_heavy,
|
|
||||||
avg_goals_per_match=avg_goals,
|
|
||||||
over_25_rate=over25_rate,
|
|
||||||
is_high_scoring=is_high_scoring,
|
|
||||||
home_win_rate=home_win_rate,
|
|
||||||
home_bias=home_bias,
|
|
||||||
penalty_rate=penalty_rate,
|
|
||||||
confidence=confidence
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_modifiers(self, prediction: RefereePrediction) -> Dict[str, float]:
|
|
||||||
"""
|
|
||||||
Get modifiers to apply to other predictions based on referee profile.
|
|
||||||
"""
|
|
||||||
return {
|
|
||||||
# Home team gets slight boost if referee has home bias
|
|
||||||
"home_modifier": 1.0 + (prediction.home_bias * 0.05),
|
|
||||||
# O/U modifier
|
|
||||||
"over_25_modifier": 1.0 + (prediction.avg_goals_per_match - self.LEAGUE_AVG_GOALS) * 0.1,
|
|
||||||
# Card modifier for card markets
|
|
||||||
"cards_modifier": 1.0 + (prediction.avg_yellow_cards - self.LEAGUE_AVG_YELLOW) * 0.05
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Singleton
|
|
||||||
_engine: Optional[RefereePredictorEngine] = None
|
|
||||||
|
|
||||||
|
|
||||||
def get_referee_predictor() -> RefereePredictorEngine:
|
|
||||||
global _engine
|
|
||||||
if _engine is None:
|
|
||||||
_engine = RefereePredictorEngine()
|
|
||||||
return _engine
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
engine = get_referee_predictor()
|
|
||||||
|
|
||||||
print("\n🧪 Referee Predictor Engine Test")
|
|
||||||
print("=" * 50)
|
|
||||||
|
|
||||||
pred = engine.predict(referee_name="Cüneyt Çakır")
|
|
||||||
|
|
||||||
print(f"\n📊 Prediction:")
|
|
||||||
for k, v in pred.to_dict().items():
|
|
||||||
print(f" {k}: {v}")
|
|
||||||
@@ -1,286 +0,0 @@
|
|||||||
"""
|
|
||||||
Team Predictor Engine - V20 Ensemble Component
|
|
||||||
Combines ELO ratings, form stats, H2H records and team statistics.
|
|
||||||
|
|
||||||
Weight: 30% in ensemble
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from typing import Dict, Optional, Tuple, Any
|
|
||||||
from dataclasses import dataclass, field
|
|
||||||
|
|
||||||
# Add parent to path
|
|
||||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
|
||||||
|
|
||||||
from features.elo_system import get_elo_system
|
|
||||||
from features.h2h_engine import get_h2h_engine
|
|
||||||
from features.momentum_engine import get_momentum_engine, MomentumData
|
|
||||||
from features.team_stats_engine import get_team_stats_engine
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class TeamPrediction:
|
|
||||||
"""Team engine prediction output."""
|
|
||||||
home_win_prob: float = 0.33
|
|
||||||
draw_prob: float = 0.33
|
|
||||||
away_win_prob: float = 0.33
|
|
||||||
home_xg: float = 1.3
|
|
||||||
away_xg: float = 1.1
|
|
||||||
form_advantage: float = 0.0 # -1 to +1, positive = home advantage
|
|
||||||
h2h_advantage: float = 0.0 # -1 to +1
|
|
||||||
elo_diff: float = 0.0
|
|
||||||
confidence: float = 0.0
|
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
|
||||||
return {
|
|
||||||
"home_win_prob": round(self.home_win_prob * 100, 1),
|
|
||||||
"draw_prob": round(self.draw_prob * 100, 1),
|
|
||||||
"away_win_prob": round(self.away_win_prob * 100, 1),
|
|
||||||
"home_xg": round(self.home_xg, 2),
|
|
||||||
"away_xg": round(self.away_xg, 2),
|
|
||||||
"form_advantage": round(self.form_advantage, 2),
|
|
||||||
"h2h_advantage": round(self.h2h_advantage, 2),
|
|
||||||
"elo_diff": round(self.elo_diff, 0),
|
|
||||||
"confidence": round(self.confidence, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
raw_features: Dict[str, Any] = field(default_factory=dict)
|
|
||||||
|
|
||||||
|
|
||||||
class TeamPredictorEngine:
|
|
||||||
"""
|
|
||||||
Team-based prediction engine.
|
|
||||||
|
|
||||||
Uses:
|
|
||||||
- ELO Rating System (venue-adjusted, league-weighted)
|
|
||||||
- H2H Engine (head-to-head history)
|
|
||||||
- Momentum Engine (recent form)
|
|
||||||
- Team Stats Engine (possession, shots, corners)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.elo_system = get_elo_system()
|
|
||||||
self.h2h_engine = get_h2h_engine()
|
|
||||||
self.momentum_engine = get_momentum_engine()
|
|
||||||
self.team_stats_engine = get_team_stats_engine()
|
|
||||||
|
|
||||||
print("✅ TeamPredictorEngine initialized")
|
|
||||||
|
|
||||||
def predict(self,
|
|
||||||
home_team_id: str,
|
|
||||||
away_team_id: str,
|
|
||||||
match_date_ms: int,
|
|
||||||
home_team_name: str = "",
|
|
||||||
away_team_name: str = "") -> TeamPrediction:
|
|
||||||
"""
|
|
||||||
Generate team-based prediction.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
home_team_id: Home team ID
|
|
||||||
away_team_id: Away team ID
|
|
||||||
match_date_ms: Match date in milliseconds
|
|
||||||
home_team_name: Home team name (for ELO)
|
|
||||||
away_team_name: Away team name (for ELO)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
TeamPrediction with 1X2 probabilities and xG
|
|
||||||
"""
|
|
||||||
|
|
||||||
# 1. Get ELO predictions
|
|
||||||
elo_pred = self.elo_system.predict_match(home_team_id, away_team_id)
|
|
||||||
elo_features = self.elo_system.get_match_features(home_team_id, away_team_id)
|
|
||||||
|
|
||||||
# 2. Get H2H features
|
|
||||||
try:
|
|
||||||
h2h_features = self.h2h_engine.get_features(
|
|
||||||
home_team_id, away_team_id, match_date_ms
|
|
||||||
)
|
|
||||||
except Exception:
|
|
||||||
h2h_features = {
|
|
||||||
"h2h_home_win_rate": 0.5,
|
|
||||||
"h2h_away_win_rate": 0.5,
|
|
||||||
"h2h_avg_goals": 2.5,
|
|
||||||
"h2h_btts_rate": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# 3. Get Momentum/Form features
|
|
||||||
try:
|
|
||||||
# key: form_score should be 0-1 derived from momentum_score (-1 to 1)
|
|
||||||
home_mom_data = self.momentum_engine.calculate_momentum(home_team_id, match_date_ms)
|
|
||||||
away_mom_data = self.momentum_engine.calculate_momentum(away_team_id, match_date_ms)
|
|
||||||
|
|
||||||
home_form_score = (home_mom_data.momentum_score + 1) / 2
|
|
||||||
away_form_score = (away_mom_data.momentum_score + 1) / 2
|
|
||||||
except Exception as e:
|
|
||||||
print(f"⚠️ MomentumEngine error: {e}")
|
|
||||||
home_mom_data = MomentumData()
|
|
||||||
away_mom_data = MomentumData()
|
|
||||||
home_form_score = 0.5
|
|
||||||
away_form_score = 0.5
|
|
||||||
|
|
||||||
# 4. Get Team Stats
|
|
||||||
home_stats = self.team_stats_engine.get_features(home_team_id, match_date_ms)
|
|
||||||
away_stats = self.team_stats_engine.get_features(away_team_id, match_date_ms)
|
|
||||||
|
|
||||||
# 5. Combine predictions
|
|
||||||
# ELO-based 1X2 (60% weight)
|
|
||||||
elo_home = elo_pred.get("home_win_prob", 0.33)
|
|
||||||
elo_draw = elo_pred.get("draw_prob", 0.33)
|
|
||||||
elo_away = elo_pred.get("away_win_prob", 0.33)
|
|
||||||
|
|
||||||
# Adjust based on H2H (20% weight)
|
|
||||||
h2h_home_rate = h2h_features.get("h2h_home_win_rate", 0.5)
|
|
||||||
h2h_away_rate = h2h_features.get("h2h_away_win_rate", 0.5)
|
|
||||||
|
|
||||||
# Adjust based on form (20% weight)
|
|
||||||
home_form = home_form_score
|
|
||||||
away_form = away_form_score
|
|
||||||
form_diff = (home_form - away_form) # -1 to +1
|
|
||||||
|
|
||||||
# Weighted combination
|
|
||||||
final_home = elo_home * 0.6 + h2h_home_rate * 0.2 + (0.5 + form_diff * 0.3) * 0.2
|
|
||||||
final_away = elo_away * 0.6 + h2h_away_rate * 0.2 + (0.5 - form_diff * 0.3) * 0.2
|
|
||||||
final_draw = 1.0 - final_home - final_away
|
|
||||||
|
|
||||||
# Normalize
|
|
||||||
total = final_home + final_draw + final_away
|
|
||||||
if total > 0:
|
|
||||||
final_home /= total
|
|
||||||
final_draw /= total
|
|
||||||
final_away /= total
|
|
||||||
|
|
||||||
# Calculate xG based on stats and form (conservative base)
|
|
||||||
home_conversion = home_stats.get("shot_conversion_rate", 0.1)
|
|
||||||
away_conversion = away_stats.get("shot_conversion_rate", 0.1)
|
|
||||||
|
|
||||||
base_home_xg = 1.35 + (home_conversion * 3.0)
|
|
||||||
base_away_xg = 1.10 + (away_conversion * 2.5)
|
|
||||||
|
|
||||||
# Defense weakness factor: opponent's defensive quality affects xG
|
|
||||||
# Higher shots on target against = weaker defense
|
|
||||||
away_def_weakness = away_stats.get("shot_accuracy", 0.35) # opponent's shot accuracy as proxy
|
|
||||||
home_def_weakness = home_stats.get("shot_accuracy", 0.35)
|
|
||||||
|
|
||||||
# Adjust xG: stronger opponent defense → lower xG
|
|
||||||
home_xg = base_home_xg * (1 + form_diff * 0.15) * (0.8 + away_def_weakness * 0.6)
|
|
||||||
away_xg = base_away_xg * (1 - form_diff * 0.15) * (0.8 + home_def_weakness * 0.6)
|
|
||||||
|
|
||||||
# Apply xG Underperformance Penalty directly to calculated xG
|
|
||||||
# If a team chronically underperforms its xG, we subtract that historical difference here
|
|
||||||
if hasattr(home_mom_data, 'xg_underperformance') and home_mom_data.xg_underperformance > 0.2:
|
|
||||||
home_xg -= min(0.5, home_mom_data.xg_underperformance * 0.5)
|
|
||||||
|
|
||||||
if hasattr(away_mom_data, 'xg_underperformance') and away_mom_data.xg_underperformance > 0.2:
|
|
||||||
away_xg -= min(0.5, away_mom_data.xg_underperformance * 0.5)
|
|
||||||
|
|
||||||
# H2H adjustment (more conservative)
|
|
||||||
h2h_avg_goals = h2h_features.get("h2h_avg_goals", 2.5)
|
|
||||||
if h2h_avg_goals > 3.0:
|
|
||||||
home_xg *= 1.05
|
|
||||||
away_xg *= 1.05
|
|
||||||
elif h2h_avg_goals < 2.0:
|
|
||||||
home_xg *= 0.95
|
|
||||||
away_xg *= 0.95
|
|
||||||
|
|
||||||
# Clamp xG to reasonable range
|
|
||||||
home_xg = max(0.5, min(3.5, home_xg))
|
|
||||||
away_xg = max(0.3, min(3.0, away_xg))
|
|
||||||
|
|
||||||
# Calculate confidence
|
|
||||||
# Higher when ELO, H2H, and Form all agree
|
|
||||||
elo_winner = "H" if elo_home > max(elo_draw, elo_away) else ("A" if elo_away > elo_draw else "D")
|
|
||||||
h2h_winner = "H" if h2h_home_rate > h2h_away_rate else "A"
|
|
||||||
form_winner = "H" if form_diff > 0.1 else ("A" if form_diff < -0.1 else "D")
|
|
||||||
|
|
||||||
agreement = sum([
|
|
||||||
elo_winner == h2h_winner,
|
|
||||||
elo_winner == form_winner,
|
|
||||||
h2h_winner == form_winner
|
|
||||||
])
|
|
||||||
|
|
||||||
max_prob = max(final_home, final_draw, final_away)
|
|
||||||
confidence = max_prob * 100 * (0.7 + agreement * 0.1)
|
|
||||||
|
|
||||||
# Collect Raw Features for XGBoost
|
|
||||||
# Note: home_mom_data is an object now
|
|
||||||
def get_rate(val): return val if val is not None else 0.5
|
|
||||||
|
|
||||||
raw_features = {
|
|
||||||
**elo_features, # 8 features
|
|
||||||
|
|
||||||
# Form Features (need key mapping to match extract_training_data.py)
|
|
||||||
"home_goals_avg": 1.5 + home_mom_data.goals_trend, # Proxy
|
|
||||||
"home_conceded_avg": 1.5 - home_mom_data.conceded_trend, # Proxy
|
|
||||||
"away_goals_avg": 1.5 + away_mom_data.goals_trend,
|
|
||||||
"away_conceded_avg": 1.5 - away_mom_data.conceded_trend,
|
|
||||||
|
|
||||||
"home_clean_sheet_rate": 0.2, # Not in new MomentumData
|
|
||||||
"away_clean_sheet_rate": 0.2,
|
|
||||||
"home_scoring_rate": 0.8,
|
|
||||||
"away_scoring_rate": 0.8,
|
|
||||||
|
|
||||||
"home_winning_streak": home_mom_data.winning_streak,
|
|
||||||
"away_winning_streak": away_mom_data.winning_streak,
|
|
||||||
"home_unbeaten_streak": home_mom_data.unbeaten_streak,
|
|
||||||
"away_unbeaten_streak": away_mom_data.unbeaten_streak,
|
|
||||||
|
|
||||||
# H2H Features
|
|
||||||
**h2h_features,
|
|
||||||
|
|
||||||
# Team Stats
|
|
||||||
"home_avg_possession": home_stats.get("avg_possession", 0.5),
|
|
||||||
"away_avg_possession": away_stats.get("avg_possession", 0.5),
|
|
||||||
"home_avg_shots_on_target": home_stats.get("avg_shots_on_target", 3.5),
|
|
||||||
"away_avg_shots_on_target": away_stats.get("avg_shots_on_target", 3.5),
|
|
||||||
"home_shot_conversion": home_stats.get("shot_conversion_rate", 0.1),
|
|
||||||
"away_shot_conversion": away_stats.get("shot_conversion_rate", 0.1),
|
|
||||||
"home_avg_corners": home_stats.get("avg_corners", 4.5),
|
|
||||||
"away_avg_corners": away_stats.get("avg_corners", 4.5),
|
|
||||||
|
|
||||||
# Derived
|
|
||||||
"home_xga": 1.5 - home_mom_data.conceded_trend, # reusing as proxy
|
|
||||||
"away_xga": 1.5 - away_mom_data.conceded_trend
|
|
||||||
}
|
|
||||||
|
|
||||||
return TeamPrediction(
|
|
||||||
home_win_prob=final_home,
|
|
||||||
draw_prob=final_draw,
|
|
||||||
away_win_prob=final_away,
|
|
||||||
home_xg=home_xg,
|
|
||||||
away_xg=away_xg,
|
|
||||||
form_advantage=form_diff,
|
|
||||||
h2h_advantage=h2h_home_rate - h2h_away_rate,
|
|
||||||
elo_diff=elo_features.get("elo_diff", 0),
|
|
||||||
confidence=confidence,
|
|
||||||
raw_features=raw_features
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# Singleton
|
|
||||||
_engine: Optional[TeamPredictorEngine] = None
|
|
||||||
|
|
||||||
|
|
||||||
def get_team_predictor() -> TeamPredictorEngine:
|
|
||||||
global _engine
|
|
||||||
if _engine is None:
|
|
||||||
_engine = TeamPredictorEngine()
|
|
||||||
return _engine
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
engine = get_team_predictor()
|
|
||||||
|
|
||||||
print("\n🧪 Team Predictor Engine Test")
|
|
||||||
print("=" * 50)
|
|
||||||
|
|
||||||
# Test with sample IDs
|
|
||||||
pred = engine.predict(
|
|
||||||
home_team_id="test_home",
|
|
||||||
away_team_id="test_away",
|
|
||||||
match_date_ms=1707393600000
|
|
||||||
)
|
|
||||||
|
|
||||||
print(f"\n📊 Prediction:")
|
|
||||||
for k, v in pred.to_dict().items():
|
|
||||||
print(f" {k}: {v}")
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
# data package
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
"""
|
||||||
|
Async Database Module — V2 Betting Engine
|
||||||
|
==========================================
|
||||||
|
Provides async SQLAlchemy sessions via asyncpg for the V2 router.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
async with get_session() as session:
|
||||||
|
result = await session.execute(text("SELECT ..."))
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
from contextlib import asynccontextmanager
|
||||||
|
from typing import AsyncGenerator
|
||||||
|
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from sqlalchemy.ext.asyncio import (
|
||||||
|
AsyncEngine,
|
||||||
|
AsyncSession,
|
||||||
|
async_sessionmaker,
|
||||||
|
create_async_engine,
|
||||||
|
)
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
_engine: AsyncEngine | None = None
|
||||||
|
_session_maker: async_sessionmaker[AsyncSession] | None = None
|
||||||
|
|
||||||
|
|
||||||
|
def _get_async_dsn() -> str:
|
||||||
|
"""
|
||||||
|
Convert DATABASE_URL to asyncpg-compatible format.
|
||||||
|
|
||||||
|
Handles:
|
||||||
|
1. Prisma's ``?schema=public`` suffix → stripped
|
||||||
|
2. ``postgresql://`` driver prefix → ``postgresql+asyncpg://``
|
||||||
|
"""
|
||||||
|
dsn = os.getenv(
|
||||||
|
"DATABASE_URL",
|
||||||
|
"postgresql://suggestbet:SuGGesT2026SecuRe@localhost:15432/boilerplate_db",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Strip Prisma's ?schema= parameter
|
||||||
|
if "?" in dsn:
|
||||||
|
base, query = dsn.split("?", 1)
|
||||||
|
kept_parts = [
|
||||||
|
part for part in query.split("&") if part and not part.startswith("schema=")
|
||||||
|
]
|
||||||
|
dsn = base if not kept_parts else f"{base}?{'&'.join(kept_parts)}"
|
||||||
|
|
||||||
|
# Convert driver prefix for asyncpg
|
||||||
|
if dsn.startswith("postgresql://"):
|
||||||
|
dsn = dsn.replace("postgresql://", "postgresql+asyncpg://", 1)
|
||||||
|
elif dsn.startswith("postgres://"):
|
||||||
|
dsn = dsn.replace("postgres://", "postgresql+asyncpg://", 1)
|
||||||
|
|
||||||
|
return dsn
|
||||||
|
|
||||||
|
|
||||||
|
def _ensure_engine() -> AsyncEngine:
|
||||||
|
global _engine, _session_maker
|
||||||
|
if _engine is None:
|
||||||
|
_engine = create_async_engine(
|
||||||
|
_get_async_dsn(),
|
||||||
|
pool_size=5,
|
||||||
|
max_overflow=5,
|
||||||
|
pool_timeout=10,
|
||||||
|
pool_pre_ping=True,
|
||||||
|
echo=False,
|
||||||
|
)
|
||||||
|
_session_maker = async_sessionmaker(
|
||||||
|
bind=_engine,
|
||||||
|
class_=AsyncSession,
|
||||||
|
expire_on_commit=False,
|
||||||
|
)
|
||||||
|
print("✅ Async database engine created (asyncpg)")
|
||||||
|
return _engine
|
||||||
|
|
||||||
|
|
||||||
|
@asynccontextmanager
|
||||||
|
async def get_session() -> AsyncGenerator[AsyncSession, None]:
|
||||||
|
"""Provide an async session context manager."""
|
||||||
|
_ensure_engine()
|
||||||
|
assert _session_maker is not None
|
||||||
|
async with _session_maker() as session:
|
||||||
|
yield session
|
||||||
|
|
||||||
|
|
||||||
|
async def dispose_engine() -> None:
|
||||||
|
"""Shut down the async engine cleanly."""
|
||||||
|
global _engine, _session_maker
|
||||||
|
if _engine is not None:
|
||||||
|
await _engine.dispose()
|
||||||
|
_engine = None
|
||||||
|
_session_maker = None
|
||||||
|
print("ℹ️ Async database engine disposed")
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
"""
|
||||||
|
Synchronous psycopg2 database helper for the AI Engine.
|
||||||
|
Uses a thread-safe connection pool for legacy V20+ endpoints.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
from contextlib import contextmanager
|
||||||
|
from typing import Generator
|
||||||
|
|
||||||
|
import psycopg2
|
||||||
|
from psycopg2 import pool
|
||||||
|
from psycopg2.extensions import connection as PgConnection
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
# Safe default with no credentials — will fail fast if not configured.
|
||||||
|
_DEFAULT_DSN = "postgresql://postgres:postgres@localhost:15432/boilerplate_db"
|
||||||
|
|
||||||
|
|
||||||
|
def get_clean_dsn() -> str:
|
||||||
|
"""
|
||||||
|
Return a psycopg2-compatible DSN from DATABASE_URL.
|
||||||
|
|
||||||
|
Handles DSN cleanup issues that break raw usage:
|
||||||
|
1. Prisma appends '?schema=public' which psycopg2 cannot parse.
|
||||||
|
"""
|
||||||
|
dsn: str = os.getenv("DATABASE_URL", _DEFAULT_DSN)
|
||||||
|
connect_timeout: str = os.getenv("PGCONNECT_TIMEOUT", "5").strip() or "5"
|
||||||
|
|
||||||
|
# Strip Prisma's ?schema= query parameter while preserving any other query args.
|
||||||
|
if "?" in dsn:
|
||||||
|
base, query = dsn.split("?", 1)
|
||||||
|
kept_parts: list[str] = [
|
||||||
|
part for part in query.split("&") if part and not part.startswith("schema=")
|
||||||
|
]
|
||||||
|
dsn = base if not kept_parts else f"{base}?{'&'.join(kept_parts)}"
|
||||||
|
|
||||||
|
# Force bounded DB connect attempts so API calls do not hang indefinitely.
|
||||||
|
if "connect_timeout=" not in dsn:
|
||||||
|
separator = "&" if "?" in dsn else "?"
|
||||||
|
dsn = f"{dsn}{separator}connect_timeout={connect_timeout}"
|
||||||
|
return dsn
|
||||||
|
|
||||||
|
|
||||||
|
class Database:
|
||||||
|
_pool: pool.ThreadedConnectionPool | None = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def initialize(cls) -> None:
|
||||||
|
if cls._pool is None:
|
||||||
|
dsn: str = get_clean_dsn()
|
||||||
|
try:
|
||||||
|
cls._pool = pool.ThreadedConnectionPool(
|
||||||
|
minconn=1,
|
||||||
|
maxconn=10,
|
||||||
|
dsn=dsn,
|
||||||
|
)
|
||||||
|
print("✅ Database connection pool created")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Failed to create DB pool: {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_conn(cls) -> PgConnection:
|
||||||
|
if cls._pool is None:
|
||||||
|
cls.initialize()
|
||||||
|
assert cls._pool is not None # guaranteed by initialize()
|
||||||
|
return cls._pool.getconn()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def return_conn(cls, conn: PgConnection) -> None:
|
||||||
|
if cls._pool:
|
||||||
|
cls._pool.putconn(conn)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@contextmanager
|
||||||
|
def connection(cls) -> Generator[PgConnection, None, None]:
|
||||||
|
"""Context manager for safe connection handling."""
|
||||||
|
conn: PgConnection = cls.get_conn()
|
||||||
|
try:
|
||||||
|
yield conn
|
||||||
|
finally:
|
||||||
|
cls.return_conn(conn)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def close_all(cls) -> None:
|
||||||
|
if cls._pool:
|
||||||
|
cls._pool.closeall()
|
||||||
|
print("ℹ️ Database connection pool closed")
|
||||||
@@ -0,0 +1,726 @@
|
|||||||
|
{
|
||||||
|
"version": "v1",
|
||||||
|
"description": "Per-league odds reliability scores computed from Brier Score analysis",
|
||||||
|
"min_matches_threshold": 50,
|
||||||
|
"total_leagues": 265,
|
||||||
|
"default_reliability": 0.35,
|
||||||
|
"lookup": {
|
||||||
|
"bx57cmq1edfq53ckfk791supi": 0.9476,
|
||||||
|
"55hcphd1ccc6eai1ms77460on": 0.9445,
|
||||||
|
"d9eaigzyfnfiraqc3ius757tl": 0.9402,
|
||||||
|
"1gxlzw2ezkyeykhcaa5x8ozkk": 0.9259,
|
||||||
|
"5jd0k2txwnq69frs79eulba8j": 0.9233,
|
||||||
|
"6694fff47wqxl10lrd9tb91f8": 0.9193,
|
||||||
|
"4jg7he1n3rb5dniq6hf49xorq": 0.9061,
|
||||||
|
"59tpnfrwnvhnhzmnvfyug68hj": 0.8988,
|
||||||
|
"ac42gi3penartj88fe9l6plpk": 0.8937,
|
||||||
|
"3j81qr7yc4gdnakfwnxf95ovh": 0.8771,
|
||||||
|
"9z5643nd06afqu01ea2wt8y4g": 0.8734,
|
||||||
|
"482ofyysbdbeoxauk19yg7tdt": 0.8722,
|
||||||
|
"ahl3vljaignq9ebaos4uqkrvo": 0.8696,
|
||||||
|
"8x3sbh85gc8qir50utw39jl04": 0.865,
|
||||||
|
"agpweohvn9tugnyl6ry4rhivp": 0.8428,
|
||||||
|
"4c1nfi2j1m731hcay25fcgndq": 0.8425,
|
||||||
|
"1j4ehtrbry9depwt6oghaq3lu": 0.8299,
|
||||||
|
"40yjcbx2sq6oq736iqqqczwt1": 0.8237,
|
||||||
|
"145hkd59i6foieuwr4mwi6wlq": 0.823,
|
||||||
|
"34pl8szyvrbwcmfkuocjm3r6t": 0.8227,
|
||||||
|
"cse5oqqt2pzfcy8uz6yz3tkbj": 0.8212,
|
||||||
|
"zs18qaehvhg3w1208874zvfa": 0.8176,
|
||||||
|
"57nu0wygurzkp6fuy5hhrtaa2": 0.8099,
|
||||||
|
"1eruend45vd20g9hbrpiggs5u": 0.8083,
|
||||||
|
"595nsvo7ykvoe690b1e4u5n56": 0.7987,
|
||||||
|
"6vq8j5p3av14nr3iuyi4okhjt": 0.793,
|
||||||
|
"486rhdgz7yc0sygziht7hje65": 0.7901,
|
||||||
|
"9hh6n2f84k31zmlcxyvmc1w2y": 0.789,
|
||||||
|
"3n5046abeu3x482ds3jwda238": 0.7863,
|
||||||
|
"8yi6ejjd1zudcqtbn07haahg6": 0.7752,
|
||||||
|
"byhmntnl1b4lxw0zz21im3zkd": 0.7719,
|
||||||
|
"2bmwykmdlcc2u1c40ytoc39vy": 0.7668,
|
||||||
|
"82jkgccg7phfjpd0mltdl3pat": 0.7643,
|
||||||
|
"2nttcoriwf5co73vmz1vr8frm": 0.7641,
|
||||||
|
"dr2xk7muj8aqcjdz2b3li1c0k": 0.759,
|
||||||
|
"4yngyfinzd6bb1k7anqtqs0wt": 0.7586,
|
||||||
|
"eog6knrkfei68si736fpquyzc": 0.756,
|
||||||
|
"eg6s9f1jj7jr6stmbosn0g6c8": 0.7538,
|
||||||
|
"ae1wva3zrzcp2zd15gpvsntg6": 0.7517,
|
||||||
|
"cesdwwnxbc5fmajgroc0hqzy2": 0.7466,
|
||||||
|
"8k1xcsyvxapl4jlsluh3eomre": 0.7463,
|
||||||
|
"bdtat25m14jy85y484z3e6lf": 0.7437,
|
||||||
|
"iu1vi94p4p28oozl1h9bvplr": 0.7411,
|
||||||
|
"1r097lpxe0xn03ihb7wi98kao": 0.7391,
|
||||||
|
"2kwbbcootiqqgmrzs6o5inle5": 0.7386,
|
||||||
|
"9fuwphq8kvugrlc3ckm7k8wes": 0.7358,
|
||||||
|
"civf31q1inxohs4a03y8reetf": 0.735,
|
||||||
|
"ili150pwfuf39f7yfdch9lhw": 0.7286,
|
||||||
|
"abs7n2ae3oydilk0tgmpnsj89": 0.7277,
|
||||||
|
"9nbpdi9q3ywcm4q0j5u0ekwcq": 0.7254,
|
||||||
|
"6by3h89i2eykc341oz7lv1ddd": 0.7252,
|
||||||
|
"4qehj8hfxmy6o2ohp4fxinnzo": 0.7244,
|
||||||
|
"9u4pm8x0lfmfq3r0pypmrls71": 0.7244,
|
||||||
|
"c7b8o53flg36wbuevfzy3lb10": 0.7144,
|
||||||
|
"89ovpy1rarewwzqvi30bfdr8b": 0.7068,
|
||||||
|
"4d5d3sf6805n5u6jdoa0hdlog": 0.7052,
|
||||||
|
"eqz64pn0qsp2y7aq4m9id3fn6": 0.7031,
|
||||||
|
"8q60vlvn3krynkob6igrncdjq": 0.703,
|
||||||
|
"6ihotpaocgiovlxw18e9r9prx": 0.7019,
|
||||||
|
"c0r21rtokgnbtc0o2rldjmkxu": 0.7013,
|
||||||
|
"1mpjd0vbxbtu9zw89yj09xk3z": 0.6996,
|
||||||
|
"4zwgbb66rif2spcoeeol2motx": 0.6995,
|
||||||
|
"bu1l7ckihyr0errxw61p0m05": 0.6995,
|
||||||
|
"cv3tuitw3ho3v0opjjxpn83b9": 0.6974,
|
||||||
|
"8r98daokeuzsamu5fmjtblqx5": 0.6922,
|
||||||
|
"dvstmwnvw0mt5p38twn9yttyb": 0.688,
|
||||||
|
"8y29fg2s85ppcb8uugm5ee8s4": 0.6866,
|
||||||
|
"19q13y6ruzo0o84ipblcuouzs": 0.6858,
|
||||||
|
"f4jc2cc5nq7flaoptpi5ua4k4": 0.6852,
|
||||||
|
"4oogyu6o156iphvdvphwpck10": 0.684,
|
||||||
|
"3e40pestup9xzagsu2o6c0i8u": 0.6824,
|
||||||
|
"4rls982p5uzil6x30mhyhv9f3": 0.6812,
|
||||||
|
"e21cf135btr8t3upw0vl6n6x0": 0.6771,
|
||||||
|
"65q4uwm6ol1rkf5dp89m8omny": 0.6754,
|
||||||
|
"46b141eaqq9q7o4gz5gtdpikk": 0.6752,
|
||||||
|
"75i269i1ak43magshljadydrh": 0.6741,
|
||||||
|
"3ab1uwtoyjopdj1y1fynyy9jg": 0.6737,
|
||||||
|
"4mbfidy8zum5u0aqjqo0vuqs2": 0.673,
|
||||||
|
"7wssxdqi4xihseeam8grqa2b8": 0.666,
|
||||||
|
"61fzfjogstjuukzcehighq7mu": 0.6641,
|
||||||
|
"6g8hw3acenrw828la7gwx4mvs": 0.663,
|
||||||
|
"e1kxdivp5g4cpldgpwvnzl1vv": 0.6626,
|
||||||
|
"9ikchyu9fb8bvx0s673jofj6s": 0.6622,
|
||||||
|
"a9vrdkelbgif0gtu3wxsr75xo": 0.6618,
|
||||||
|
"6sxm2iln2w45ux498pty9miw8": 0.6615,
|
||||||
|
"ea0h6cf3bhl698hkxhpulh2zz": 0.661,
|
||||||
|
"apdwh753fupxheygs8seahh7x": 0.6604,
|
||||||
|
"er5745q30wnr8jv9nr863omzg": 0.659,
|
||||||
|
"2z7257m7hj58zuxcjrsg4erzc": 0.6551,
|
||||||
|
"2o9svokc5s7diish3ycrzk7jm": 0.655,
|
||||||
|
"8usjlmziv3p2re0r2wwzezki9": 0.6549,
|
||||||
|
"c0yqkbilbbg70ij2473xymmqv": 0.6506,
|
||||||
|
"du6jsenbjql5e8f3yk880ox4g": 0.6494,
|
||||||
|
"cbdbziaqczfuyuwqsylqi26zd": 0.6478,
|
||||||
|
"725gd73msyt08xm76v7gkxj7u": 0.6445,
|
||||||
|
"enzlj1as2raqm4ids1zyb07y1": 0.6442,
|
||||||
|
"scf9p4y91yjvqvg5jndxzhxj": 0.6414,
|
||||||
|
"5z8v4mj6cjs9ex6hdrpourjzh": 0.6389,
|
||||||
|
"4zwjlzdszduqmxzusysvzymms": 0.6387,
|
||||||
|
"7nmz249q89qg5ezcvzlheljji": 0.6381,
|
||||||
|
"2mdmx668tyhy4u4z9zszwjv5v": 0.6345,
|
||||||
|
"4a7o9rf7ytl8g3ejwpblc6p5n": 0.6306,
|
||||||
|
"2ty8ihceabty8yddmu31iuuej": 0.6283,
|
||||||
|
"dy8zaksw5e9nwrs1p5ss4o1nu": 0.628,
|
||||||
|
"1b70m6qtxrp75b4vtk8hxh8c3": 0.6261,
|
||||||
|
"ajxs0e0g6ryg5ol8qvw3evrcz": 0.6249,
|
||||||
|
"a4fgj2rfbpf4ejo1qi624fefo": 0.6184,
|
||||||
|
"akmkihra9ruad09ljapsm84b3": 0.6182,
|
||||||
|
"907l7wtxdvugdo9i2249wcmr0": 0.6171,
|
||||||
|
"6lwpjhktjhl9g7x2w7njmzva6": 0.6164,
|
||||||
|
"ax1yf4nlzqpcji4j8epdgx3zl": 0.6163,
|
||||||
|
"6ybvtzejh91761lqe7y1csrqo": 0.6158,
|
||||||
|
"3btdfgw79qiz3jmyfudovtbu2": 0.6122,
|
||||||
|
"5cwsxtx37les6m10xj71htkgf": 0.6101,
|
||||||
|
"9p3nnxhdjahfn8qswpzy8oyc3": 0.61,
|
||||||
|
"2xg0qvif1rh7du6wmk2eleku3": 0.6091,
|
||||||
|
"1wwro3z1eb3fl601dju6inlc6": 0.6084,
|
||||||
|
"gfskxsdituog2kqp9yiu7bzi": 0.6076,
|
||||||
|
"zilopfej2h0n3vpan5tcynpo": 0.6051,
|
||||||
|
"2hsidwomhjsaaytdy9u5niyi4": 0.6012,
|
||||||
|
"1klyfth8tl6lu6ra7k8zmy2n2": 0.5996,
|
||||||
|
"cegl2ivkc25blcatxp4jmk1ec": 0.5993,
|
||||||
|
"7qf0jaayyxy3ruamsexv5p1kl": 0.5988,
|
||||||
|
"erpufio3qaujd9gkszcqvb0bf": 0.5972,
|
||||||
|
"cfesxhzb83yl8b779uv3revz1": 0.597,
|
||||||
|
"3ww12jab49q8q8mk9avdwjqgk": 0.5961,
|
||||||
|
"8t2o4huu2e48ij23dxnl9w5qx": 0.5928,
|
||||||
|
"5vq1bl8h8dxdr34w0jaanokto": 0.5919,
|
||||||
|
"ac112osli9fvox1epcg4ld3t6": 0.59,
|
||||||
|
"3frp1zxrqulrlrnk503n6l4l": 0.5808,
|
||||||
|
"c76z5d6j7dpi1e79tm8fpm39z": 0.5807,
|
||||||
|
"6ifaeunfdelecgticvxanikzu": 0.5796,
|
||||||
|
"81txfenlgw75nq3u2nfdkj92o": 0.5789,
|
||||||
|
"yv73ms6v1995b5wny16jcfi3": 0.5787,
|
||||||
|
"b3ufcd24wfnnd5j98ped6irfu": 0.5752,
|
||||||
|
"29actv1ohj8r10kd9hu0jnb0n": 0.5737,
|
||||||
|
"bfqezwfhot1l3p1cpk4oonh25": 0.5705,
|
||||||
|
"5taraea6mqjjldg9zxswo825y": 0.5696,
|
||||||
|
"7qdv1xae7ikfe8dft3oj29yqc": 0.5692,
|
||||||
|
"dm5ka0os1e3dxcp3vh05kmp33": 0.5678,
|
||||||
|
"ay4u6j7lfkcg7x21mx5q121j": 0.5676,
|
||||||
|
"7af85xa75vozt2l4hzi6ryts7": 0.5663,
|
||||||
|
"5k620c7y6dlbmcm88dt3eb7t": 0.5644,
|
||||||
|
"ejunkmfhjz9weugd2bqrkgobb": 0.564,
|
||||||
|
"3428tckxcirwwh3o3jgc1m8ji": 0.5597,
|
||||||
|
"d6zovb8puwgcmsg91iya6rbtm": 0.5593,
|
||||||
|
"2wolc27r8z03itcvwp43e38c5": 0.5592,
|
||||||
|
"alpfd99yd3lfv7bhjo0biuq7b": 0.5582,
|
||||||
|
"beqqnubkv05mamuwvimeum015": 0.5577,
|
||||||
|
"4w7x0s5gfs5abasphlha5de8k": 0.5558,
|
||||||
|
"9ynnnx1qmkizq1o3qr3v0nsuk": 0.554,
|
||||||
|
"722fdbecxzcq9788l6jqclzlw": 0.5539,
|
||||||
|
"287tckirbfj9nb8ar2k9r60vn": 0.5529,
|
||||||
|
"esrunz7rjb0td98mx9e5cedoy": 0.5516,
|
||||||
|
"32n2r9bl6x90psj0wa7bfs6vq": 0.5487,
|
||||||
|
"50ap4sua1xyut3mpu7ehesp63": 0.5483,
|
||||||
|
"5c96g1zm7vo5ons9c42uy2w3r": 0.5469,
|
||||||
|
"3p81ltz6845appgkbgkzxueii": 0.5454,
|
||||||
|
"3n9mk5b2mxmq831wfmv6pu86i": 0.5437,
|
||||||
|
"5zr0b05eyx25km7z1k03ca9jx": 0.5424,
|
||||||
|
"1owhvvge4wlx7e0e431b4vhqx": 0.5423,
|
||||||
|
"3iwftmprsznl6yribr11a8l9m": 0.5393,
|
||||||
|
"7r1f93t6ddrsa5n8v1nq6qlzm": 0.5393,
|
||||||
|
"1gwajyt0pk2jm5fx5mu36v114": 0.5389,
|
||||||
|
"581t4mywybx21wcpmpykhyzr3": 0.5388,
|
||||||
|
"6wubmo7di3kdpflluf6s8c7vs": 0.5375,
|
||||||
|
"bq89wbdvedtov6auzuh6rsv7s": 0.5363,
|
||||||
|
"byu00jvt1j6csyv4y1lkt2fm2": 0.5359,
|
||||||
|
"af79lqrc0ntom74zq13ccjslo": 0.5357,
|
||||||
|
"3ri6juw2w6ma0jezszdlv1uqm": 0.5356,
|
||||||
|
"3l29w00m506ex93t5bbh9cg2a": 0.5355,
|
||||||
|
"1zp1du9n4rj36p1ss9zbxtqfb": 0.5353,
|
||||||
|
"9chuiarcjofld1dkj9kysehmb": 0.5346,
|
||||||
|
"5aw6uyw4pz2bpj24t5z8aacim": 0.5333,
|
||||||
|
"by5nibd18nkt40t0j8a0j5yzx": 0.5332,
|
||||||
|
"4yzidekywejmxxp77gqmdgopg": 0.5323,
|
||||||
|
"7ntvbsyq31jnzoqoa8850b9b8": 0.5305,
|
||||||
|
"a7247po5qs29o3zsfmt222ydu": 0.5299,
|
||||||
|
"117yqo02rs8dykkxpm274w3bd": 0.5298,
|
||||||
|
"193wqkyb0v5jnsblhvd2ocmyo": 0.5296,
|
||||||
|
"8jh0jejuxfhrpawnoztz2jlv4": 0.5295,
|
||||||
|
"5y0z0l2epprzbscvzsgldw8vu": 0.5288,
|
||||||
|
"47s2kt0e8m444ftqvsrqa3bvq": 0.5268,
|
||||||
|
"2hj3286pqov1g1g59k2t2qcgm": 0.5245,
|
||||||
|
"7swf4kpu3v38i2it4h94c5s9k": 0.5227,
|
||||||
|
"78wml3z5wrfxe5iky50tiotgu": 0.5196,
|
||||||
|
"f39uq10c8xhg5e6rwwcf6lhgc": 0.5186,
|
||||||
|
"bbajzna018c79opa1kl5kmkqo": 0.5172,
|
||||||
|
"4davonpqws4a4ejl1awu98zdg": 0.5168,
|
||||||
|
"1fedahp0rws09tj451onten8r": 0.5163,
|
||||||
|
"aho73e5udydy96iun3tkzdzsi": 0.5149,
|
||||||
|
"3aa4mumjl6zyetg6o9hwd5hhx": 0.5125,
|
||||||
|
"7cwemnr3vi40znjq451zxkus6": 0.5115,
|
||||||
|
"ajm86skyzse4ym8g6fpgzncxa": 0.5112,
|
||||||
|
"bgen5kjer2ytfp7lo9949t72g": 0.5102,
|
||||||
|
"8ey0ww2zsosdmwr8ehsorh6t7": 0.51,
|
||||||
|
"8najqkluatpaxvqws78b9s17c": 0.5082,
|
||||||
|
"8v97rcbthsxmzqk4ufxws9mug": 0.506,
|
||||||
|
"degxm4y6gmvp011ccyrev6z5p": 0.5049,
|
||||||
|
"3oa9e03e7w9nr8kqwqc3tlqz9": 0.5049,
|
||||||
|
"5dycj9wdhxh3n33qubw18ohlk": 0.5036,
|
||||||
|
"3is4bkgf3loxv9qfg3hm8zfqb": 0.5033,
|
||||||
|
"f47f3717z2vtpxfxrpdd4jl1x": 0.498,
|
||||||
|
"8ivsfwex4dfx1tvgsiq8askcx": 0.4972,
|
||||||
|
"8vbck9a4mxjms783lf72779uu": 0.4946,
|
||||||
|
"aql5z4osw5wmun0emnakfpwji": 0.4946,
|
||||||
|
"e6vzdkz6l236s9p288mharefy": 0.4925,
|
||||||
|
"4nidzmunvpvxk1ir9b6m8mpay": 0.4874,
|
||||||
|
"ein4fkggto3pdh5msp8huafiq": 0.4856,
|
||||||
|
"1q4ab2bpg5e8jl1g2udnakrju": 0.4852,
|
||||||
|
"8ztsv3pzrsyq5w1r3a0nfk1y5": 0.4842,
|
||||||
|
"1qd0wvt30rlswa4g6nu4na660": 0.4826,
|
||||||
|
"jznihqxle06xych9ygwiwnsa": 0.4796,
|
||||||
|
"2y8bntiif3a9y6gtmauv30gt": 0.4782,
|
||||||
|
"477yyajzheg2z8u7uick0e13e": 0.4706,
|
||||||
|
"bockl24qpr7ryjl8b6obukga": 0.4671,
|
||||||
|
"7mxwwunvot2pi69pj1yr1kh8i": 0.466,
|
||||||
|
"3w1hkk9k9gr8fwssyn4icvdfo": 0.4657,
|
||||||
|
"1txej2dzohnydl21zc9pgx6hy": 0.464,
|
||||||
|
"b8rae0ib0frjmwlca429bq19q": 0.4624,
|
||||||
|
"b5udgm9vakjqz8dcmy5b2g0xt": 0.4582,
|
||||||
|
"eitf7hulqfv1clb7toewkil24": 0.458,
|
||||||
|
"7hl0svs2hg225i2zud0g3xzp2": 0.4559,
|
||||||
|
"2aso72utuctat2ecs6nahjss6": 0.4521,
|
||||||
|
"3ymqchdzk8tt6lfphf26xfvh0": 0.4519,
|
||||||
|
"2yyjcbbryf1r10apyzl7c7jvp": 0.4507,
|
||||||
|
"bly7ema5au6j40i0grhl0pnub": 0.4476,
|
||||||
|
"b1rveez5u792gess9w3e7v5le": 0.4444,
|
||||||
|
"8sdpk4aerruf515yh76ezo7vi": 0.4434,
|
||||||
|
"32vph7vcjqgo1ksj1548di90n": 0.44,
|
||||||
|
"65ggsqdi6drpa4m8y3gkll25k": 0.4394,
|
||||||
|
"xaouuwuk8qyhv1libkeexwjh": 0.4347,
|
||||||
|
"6qitd9h242qkvjenaytfdnsf2": 0.4312,
|
||||||
|
"duuc1qczfnawwncru1ly6o66": 0.4213,
|
||||||
|
"b60nisd3qn427jm0hrg9kvmab": 0.4203,
|
||||||
|
"xwnjb1az11zffwty3m6vn8y6": 0.4197,
|
||||||
|
"dkarmrybx9vx10rg7cywumth0": 0.4158,
|
||||||
|
"75434tz9rc14xkkvudex742ui": 0.4137,
|
||||||
|
"c1d9p6b2e9zr5tqlzx3ktjplg": 0.4129,
|
||||||
|
"b73zounsynk9d3u1p9nvpu7i2": 0.4049,
|
||||||
|
"913mb508il6jzwtlj28fl892h": 0.4044,
|
||||||
|
"e0lck99w8meo9qoalfrxgo33o": 0.401,
|
||||||
|
"8dn0w8zh7nbn2i904603eigwf": 0.3984,
|
||||||
|
"ddyrh5latwfhesgfh4w401n92": 0.3973,
|
||||||
|
"avs3xposm3t9x1x2vzsoxzcbu": 0.3957,
|
||||||
|
"eu2g5j36zzxiazpd729osx0wm": 0.3924,
|
||||||
|
"67uya58idol2eq18ljecsru5o": 0.3912,
|
||||||
|
"23e698ls3x6vi9x8wl0mz7bsa": 0.3838,
|
||||||
|
"6321dlqv4ziuwqte4xpohijtw": 0.382,
|
||||||
|
"8o5tv5viv4hy1qg9jp94k7ayb": 0.381,
|
||||||
|
"53tknno09wqihmwxrqcuwq9sa": 0.3782,
|
||||||
|
"82wo38rqeizxlfjjhfjy4rx7u": 0.3781,
|
||||||
|
"dvtl8sf1262pd2aqgu641qa7u": 0.3767,
|
||||||
|
"663a54fmymndjeev47qm7d3nf": 0.3522,
|
||||||
|
"macko16888165594668885588": 0.3309,
|
||||||
|
"macko16698982162572521585": 0.3262,
|
||||||
|
"6lkj3o21cr4g7bql6tb3fk222": 0.3261,
|
||||||
|
"cu0rmpyff5692eo06ltddjo8a": 0.3161,
|
||||||
|
"1cnx2c8g3hhp8ssxnwwli0mjb": 0.3121,
|
||||||
|
"4vt0ldrcl6thpxpcs8zmpdq1g": 0.2926,
|
||||||
|
"etta63x1t7tnkn4jheisjwk4p": 0.2907,
|
||||||
|
"1n9l0ex47bu0762qg574hzjtd": 0.2626,
|
||||||
|
"6jgwiu2gq3dllmrwt45pfdn2z": 0.2416,
|
||||||
|
"392slbmf1kdqlr6sd1ckt71rs": 0.24,
|
||||||
|
"8z3180hhw2pj1i65uftlk54uz": 0.2096
|
||||||
|
},
|
||||||
|
"details": [
|
||||||
|
{
|
||||||
|
"league_id": "bx57cmq1edfq53ckfk791supi",
|
||||||
|
"league_name": "CAF Konfederasyon Kupası",
|
||||||
|
"match_count": 98,
|
||||||
|
"brier_score": 0.3046,
|
||||||
|
"heavy_fav_win_pct": 84.1,
|
||||||
|
"fav_win_pct": 63.3,
|
||||||
|
"odds_reliability": 0.9476
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "55hcphd1ccc6eai1ms77460on",
|
||||||
|
"league_name": "Şampiyonlar Ligi Kadınlar",
|
||||||
|
"match_count": 89,
|
||||||
|
"brier_score": 0.3258,
|
||||||
|
"heavy_fav_win_pct": 83.3,
|
||||||
|
"fav_win_pct": 74.2,
|
||||||
|
"odds_reliability": 0.9445
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "d9eaigzyfnfiraqc3ius757tl",
|
||||||
|
"league_name": "Kupa",
|
||||||
|
"match_count": 78,
|
||||||
|
"brier_score": 0.3141,
|
||||||
|
"heavy_fav_win_pct": 81.2,
|
||||||
|
"fav_win_pct": 73.1,
|
||||||
|
"odds_reliability": 0.9402
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "1gxlzw2ezkyeykhcaa5x8ozkk",
|
||||||
|
"league_name": "Concacaf Orta Amerika Kupası",
|
||||||
|
"match_count": 88,
|
||||||
|
"brier_score": 0.3338,
|
||||||
|
"heavy_fav_win_pct": 79.4,
|
||||||
|
"fav_win_pct": 61.4,
|
||||||
|
"odds_reliability": 0.9259
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "5jd0k2txwnq69frs79eulba8j",
|
||||||
|
"league_name": "Kupa",
|
||||||
|
"match_count": 69,
|
||||||
|
"brier_score": 0.3223,
|
||||||
|
"heavy_fav_win_pct": 78.4,
|
||||||
|
"fav_win_pct": 66.7,
|
||||||
|
"odds_reliability": 0.9233
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "6694fff47wqxl10lrd9tb91f8",
|
||||||
|
"league_name": "Kupa",
|
||||||
|
"match_count": 55,
|
||||||
|
"brier_score": 0.3099,
|
||||||
|
"heavy_fav_win_pct": 78.8,
|
||||||
|
"fav_win_pct": 67.3,
|
||||||
|
"odds_reliability": 0.9193
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "4jg7he1n3rb5dniq6hf49xorq",
|
||||||
|
"league_name": "Premier Lig",
|
||||||
|
"match_count": 79,
|
||||||
|
"brier_score": 0.3333,
|
||||||
|
"heavy_fav_win_pct": 77.1,
|
||||||
|
"fav_win_pct": 64.6,
|
||||||
|
"odds_reliability": 0.9061
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "59tpnfrwnvhnhzmnvfyug68hj",
|
||||||
|
"league_name": "Libertadores Kupası",
|
||||||
|
"match_count": 180,
|
||||||
|
"brier_score": 0.3408,
|
||||||
|
"heavy_fav_win_pct": 76.2,
|
||||||
|
"fav_win_pct": 61.7,
|
||||||
|
"odds_reliability": 0.8988
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "ac42gi3penartj88fe9l6plpk",
|
||||||
|
"league_name": "Premier Lig",
|
||||||
|
"match_count": 185,
|
||||||
|
"brier_score": 0.3148,
|
||||||
|
"heavy_fav_win_pct": 70.7,
|
||||||
|
"fav_win_pct": 68.1,
|
||||||
|
"odds_reliability": 0.8937
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "3j81qr7yc4gdnakfwnxf95ovh",
|
||||||
|
"league_name": "Premier Lig",
|
||||||
|
"match_count": 106,
|
||||||
|
"brier_score": 0.333,
|
||||||
|
"heavy_fav_win_pct": 72.2,
|
||||||
|
"fav_win_pct": 60.4,
|
||||||
|
"odds_reliability": 0.8771
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "9z5643nd06afqu01ea2wt8y4g",
|
||||||
|
"league_name": "Kuu Bara Ligi",
|
||||||
|
"match_count": 110,
|
||||||
|
"brier_score": 0.3294,
|
||||||
|
"heavy_fav_win_pct": 70.3,
|
||||||
|
"fav_win_pct": 53.6,
|
||||||
|
"odds_reliability": 0.8734
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "482ofyysbdbeoxauk19yg7tdt",
|
||||||
|
"league_name": "Trendyol Süper Lig",
|
||||||
|
"match_count": 342,
|
||||||
|
"brier_score": 0.3627,
|
||||||
|
"heavy_fav_win_pct": 80.7,
|
||||||
|
"fav_win_pct": 59.6,
|
||||||
|
"odds_reliability": 0.8722
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "ahl3vljaignq9ebaos4uqkrvo",
|
||||||
|
"league_name": "Kupa",
|
||||||
|
"match_count": 105,
|
||||||
|
"brier_score": 0.331,
|
||||||
|
"heavy_fav_win_pct": 70.4,
|
||||||
|
"fav_win_pct": 63.8,
|
||||||
|
"odds_reliability": 0.8696
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "8x3sbh85gc8qir50utw39jl04",
|
||||||
|
"league_name": "UEFA Kadınlar Euro 2025 Elemeleri",
|
||||||
|
"match_count": 88,
|
||||||
|
"brier_score": 0.3421,
|
||||||
|
"heavy_fav_win_pct": 75.5,
|
||||||
|
"fav_win_pct": 61.4,
|
||||||
|
"odds_reliability": 0.865
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "agpweohvn9tugnyl6ry4rhivp",
|
||||||
|
"league_name": "Eredivisie Kadınlar",
|
||||||
|
"match_count": 51,
|
||||||
|
"brier_score": 0.3356,
|
||||||
|
"heavy_fav_win_pct": 72.0,
|
||||||
|
"fav_win_pct": 56.9,
|
||||||
|
"odds_reliability": 0.8428
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "4c1nfi2j1m731hcay25fcgndq",
|
||||||
|
"league_name": "Avrupa Ligi",
|
||||||
|
"match_count": 242,
|
||||||
|
"brier_score": 0.3625,
|
||||||
|
"heavy_fav_win_pct": 77.6,
|
||||||
|
"fav_win_pct": 61.6,
|
||||||
|
"odds_reliability": 0.8425
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "1j4ehtrbry9depwt6oghaq3lu",
|
||||||
|
"league_name": "Süper Lig",
|
||||||
|
"match_count": 84,
|
||||||
|
"brier_score": 0.3201,
|
||||||
|
"heavy_fav_win_pct": 65.9,
|
||||||
|
"fav_win_pct": 60.7,
|
||||||
|
"odds_reliability": 0.8299
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "40yjcbx2sq6oq736iqqqczwt1",
|
||||||
|
"league_name": "DK Elemeler",
|
||||||
|
"match_count": 88,
|
||||||
|
"brier_score": 0.3383,
|
||||||
|
"heavy_fav_win_pct": 68.6,
|
||||||
|
"fav_win_pct": 55.7,
|
||||||
|
"odds_reliability": 0.8237
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "145hkd59i6foieuwr4mwi6wlq",
|
||||||
|
"league_name": "Pro Lig",
|
||||||
|
"match_count": 143,
|
||||||
|
"brier_score": 0.3546,
|
||||||
|
"heavy_fav_win_pct": 73.8,
|
||||||
|
"fav_win_pct": 60.1,
|
||||||
|
"odds_reliability": 0.823
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "34pl8szyvrbwcmfkuocjm3r6t",
|
||||||
|
"league_name": "LaLiga",
|
||||||
|
"match_count": 364,
|
||||||
|
"brier_score": 0.3773,
|
||||||
|
"heavy_fav_win_pct": 80.2,
|
||||||
|
"fav_win_pct": 56.6,
|
||||||
|
"odds_reliability": 0.8227
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "cse5oqqt2pzfcy8uz6yz3tkbj",
|
||||||
|
"league_name": "CAF Şampiyonlar Ligi",
|
||||||
|
"match_count": 91,
|
||||||
|
"brier_score": 0.3513,
|
||||||
|
"heavy_fav_win_pct": 73.9,
|
||||||
|
"fav_win_pct": 57.1,
|
||||||
|
"odds_reliability": 0.8212
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "zs18qaehvhg3w1208874zvfa",
|
||||||
|
"league_name": "1. Lig",
|
||||||
|
"match_count": 225,
|
||||||
|
"brier_score": 0.3744,
|
||||||
|
"heavy_fav_win_pct": 82.1,
|
||||||
|
"fav_win_pct": 59.6,
|
||||||
|
"odds_reliability": 0.8176
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "57nu0wygurzkp6fuy5hhrtaa2",
|
||||||
|
"league_name": "1. Lig",
|
||||||
|
"match_count": 286,
|
||||||
|
"brier_score": 0.3626,
|
||||||
|
"heavy_fav_win_pct": 72.9,
|
||||||
|
"fav_win_pct": 59.1,
|
||||||
|
"odds_reliability": 0.8099
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "1eruend45vd20g9hbrpiggs5u",
|
||||||
|
"league_name": "Botola Pro",
|
||||||
|
"match_count": 265,
|
||||||
|
"brier_score": 0.3625,
|
||||||
|
"heavy_fav_win_pct": 72.9,
|
||||||
|
"fav_win_pct": 50.2,
|
||||||
|
"odds_reliability": 0.8083
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "595nsvo7ykvoe690b1e4u5n56",
|
||||||
|
"league_name": "UEFA Uluslar Ligi",
|
||||||
|
"match_count": 67,
|
||||||
|
"brier_score": 0.3687,
|
||||||
|
"heavy_fav_win_pct": 83.3,
|
||||||
|
"fav_win_pct": 50.7,
|
||||||
|
"odds_reliability": 0.7987
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "6vq8j5p3av14nr3iuyi4okhjt",
|
||||||
|
"league_name": "Süper Lig Kadınlar",
|
||||||
|
"match_count": 70,
|
||||||
|
"brier_score": 0.356,
|
||||||
|
"heavy_fav_win_pct": 73.5,
|
||||||
|
"fav_win_pct": 58.6,
|
||||||
|
"odds_reliability": 0.793
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "486rhdgz7yc0sygziht7hje65",
|
||||||
|
"league_name": "Kupa",
|
||||||
|
"match_count": 62,
|
||||||
|
"brier_score": 0.3704,
|
||||||
|
"heavy_fav_win_pct": 81.1,
|
||||||
|
"fav_win_pct": 66.1,
|
||||||
|
"odds_reliability": 0.7901
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "9hh6n2f84k31zmlcxyvmc1w2y",
|
||||||
|
"league_name": "2. Lig",
|
||||||
|
"match_count": 204,
|
||||||
|
"brier_score": 0.357,
|
||||||
|
"heavy_fav_win_pct": 69.2,
|
||||||
|
"fav_win_pct": 62.3,
|
||||||
|
"odds_reliability": 0.789
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "3n5046abeu3x482ds3jwda238",
|
||||||
|
"league_name": "WE Lig Kadınlar",
|
||||||
|
"match_count": 102,
|
||||||
|
"brier_score": 0.3761,
|
||||||
|
"heavy_fav_win_pct": 85.4,
|
||||||
|
"fav_win_pct": 58.8,
|
||||||
|
"odds_reliability": 0.7863
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "8yi6ejjd1zudcqtbn07haahg6",
|
||||||
|
"league_name": "Premier Lig",
|
||||||
|
"match_count": 302,
|
||||||
|
"brier_score": 0.3712,
|
||||||
|
"heavy_fav_win_pct": 72.1,
|
||||||
|
"fav_win_pct": 56.3,
|
||||||
|
"odds_reliability": 0.7752
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "byhmntnl1b4lxw0zz21im3zkd",
|
||||||
|
"league_name": "Kupa",
|
||||||
|
"match_count": 96,
|
||||||
|
"brier_score": 0.3528,
|
||||||
|
"heavy_fav_win_pct": 68.2,
|
||||||
|
"fav_win_pct": 58.3,
|
||||||
|
"odds_reliability": 0.7719
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "2bmwykmdlcc2u1c40ytoc39vy",
|
||||||
|
"league_name": "Açık Kupası",
|
||||||
|
"match_count": 93,
|
||||||
|
"brier_score": 0.3807,
|
||||||
|
"heavy_fav_win_pct": 84.6,
|
||||||
|
"fav_win_pct": 66.7,
|
||||||
|
"odds_reliability": 0.7668
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "82jkgccg7phfjpd0mltdl3pat",
|
||||||
|
"league_name": "Süper Lig",
|
||||||
|
"match_count": 289,
|
||||||
|
"brier_score": 0.3782,
|
||||||
|
"heavy_fav_win_pct": 74.0,
|
||||||
|
"fav_win_pct": 57.4,
|
||||||
|
"odds_reliability": 0.7643
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "2nttcoriwf5co73vmz1vr8frm",
|
||||||
|
"league_name": "Nesine 2. Lig",
|
||||||
|
"match_count": 525,
|
||||||
|
"brier_score": 0.3782,
|
||||||
|
"heavy_fav_win_pct": 71.8,
|
||||||
|
"fav_win_pct": 55.2,
|
||||||
|
"odds_reliability": 0.7641
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "dr2xk7muj8aqcjdz2b3li1c0k",
|
||||||
|
"league_name": "Meistaradeildin",
|
||||||
|
"match_count": 129,
|
||||||
|
"brier_score": 0.3714,
|
||||||
|
"heavy_fav_win_pct": 73.6,
|
||||||
|
"fav_win_pct": 61.2,
|
||||||
|
"odds_reliability": 0.759
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "4yngyfinzd6bb1k7anqtqs0wt",
|
||||||
|
"league_name": "Premier Lig",
|
||||||
|
"match_count": 195,
|
||||||
|
"brier_score": 0.3772,
|
||||||
|
"heavy_fav_win_pct": 74.4,
|
||||||
|
"fav_win_pct": 57.4,
|
||||||
|
"odds_reliability": 0.7586
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "eog6knrkfei68si736fpquyzc",
|
||||||
|
"league_name": "Lig Kupası",
|
||||||
|
"match_count": 120,
|
||||||
|
"brier_score": 0.3632,
|
||||||
|
"heavy_fav_win_pct": 69.9,
|
||||||
|
"fav_win_pct": 66.7,
|
||||||
|
"odds_reliability": 0.756
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "eg6s9f1jj7jr6stmbosn0g6c8",
|
||||||
|
"league_name": "Süper Lig",
|
||||||
|
"match_count": 108,
|
||||||
|
"brier_score": 0.3657,
|
||||||
|
"heavy_fav_win_pct": 71.2,
|
||||||
|
"fav_win_pct": 55.6,
|
||||||
|
"odds_reliability": 0.7538
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "ae1wva3zrzcp2zd15gpvsntg6",
|
||||||
|
"league_name": "Ulusal Lig",
|
||||||
|
"match_count": 278,
|
||||||
|
"brier_score": 0.3783,
|
||||||
|
"heavy_fav_win_pct": 72.7,
|
||||||
|
"fav_win_pct": 55.0,
|
||||||
|
"odds_reliability": 0.7517
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "cesdwwnxbc5fmajgroc0hqzy2",
|
||||||
|
"league_name": "Hazırlık Maçları Ülkeler",
|
||||||
|
"match_count": 235,
|
||||||
|
"brier_score": 0.3669,
|
||||||
|
"heavy_fav_win_pct": 67.6,
|
||||||
|
"fav_win_pct": 56.2,
|
||||||
|
"odds_reliability": 0.7466
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "8k1xcsyvxapl4jlsluh3eomre",
|
||||||
|
"league_name": "Premier Lig",
|
||||||
|
"match_count": 328,
|
||||||
|
"brier_score": 0.385,
|
||||||
|
"heavy_fav_win_pct": 74.2,
|
||||||
|
"fav_win_pct": 45.7,
|
||||||
|
"odds_reliability": 0.7463
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "bdtat25m14jy85y484z3e6lf",
|
||||||
|
"league_name": "Kupa",
|
||||||
|
"match_count": 90,
|
||||||
|
"brier_score": 0.3772,
|
||||||
|
"heavy_fav_win_pct": 75.7,
|
||||||
|
"fav_win_pct": 55.6,
|
||||||
|
"odds_reliability": 0.7437
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "iu1vi94p4p28oozl1h9bvplr",
|
||||||
|
"league_name": "1. Lig",
|
||||||
|
"match_count": 158,
|
||||||
|
"brier_score": 0.3729,
|
||||||
|
"heavy_fav_win_pct": 71.2,
|
||||||
|
"fav_win_pct": 50.0,
|
||||||
|
"odds_reliability": 0.7411
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "1r097lpxe0xn03ihb7wi98kao",
|
||||||
|
"league_name": "Serie A",
|
||||||
|
"match_count": 359,
|
||||||
|
"brier_score": 0.3732,
|
||||||
|
"heavy_fav_win_pct": 67.8,
|
||||||
|
"fav_win_pct": 56.5,
|
||||||
|
"odds_reliability": 0.7391
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "2kwbbcootiqqgmrzs6o5inle5",
|
||||||
|
"league_name": "Premier Lig",
|
||||||
|
"match_count": 369,
|
||||||
|
"brier_score": 0.3791,
|
||||||
|
"heavy_fav_win_pct": 70.2,
|
||||||
|
"fav_win_pct": 54.2,
|
||||||
|
"odds_reliability": 0.7386
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "9fuwphq8kvugrlc3ckm7k8wes",
|
||||||
|
"league_name": "Ligler Kupası",
|
||||||
|
"match_count": 143,
|
||||||
|
"brier_score": 0.3934,
|
||||||
|
"heavy_fav_win_pct": 81.6,
|
||||||
|
"fav_win_pct": 50.3,
|
||||||
|
"odds_reliability": 0.7358
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "civf31q1inxohs4a03y8reetf",
|
||||||
|
"league_name": "Premier Lig",
|
||||||
|
"match_count": 320,
|
||||||
|
"brier_score": 0.3721,
|
||||||
|
"heavy_fav_win_pct": 67.2,
|
||||||
|
"fav_win_pct": 57.8,
|
||||||
|
"odds_reliability": 0.735
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "ili150pwfuf39f7yfdch9lhw",
|
||||||
|
"league_name": "UEFA U21 Şampiyonası Elemeler",
|
||||||
|
"match_count": 112,
|
||||||
|
"brier_score": 0.3715,
|
||||||
|
"heavy_fav_win_pct": 70.4,
|
||||||
|
"fav_win_pct": 67.9,
|
||||||
|
"odds_reliability": 0.7286
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "abs7n2ae3oydilk0tgmpnsj89",
|
||||||
|
"league_name": "Azadegan Ligi",
|
||||||
|
"match_count": 217,
|
||||||
|
"brier_score": 0.3801,
|
||||||
|
"heavy_fav_win_pct": 71.4,
|
||||||
|
"fav_win_pct": 45.2,
|
||||||
|
"odds_reliability": 0.7277
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"league_id": "9nbpdi9q3ywcm4q0j5u0ekwcq",
|
||||||
|
"league_name": "Serie D",
|
||||||
|
"match_count": 232,
|
||||||
|
"brier_score": 0.3718,
|
||||||
|
"heavy_fav_win_pct": 67.2,
|
||||||
|
"fav_win_pct": 54.7,
|
||||||
|
"odds_reliability": 0.7254
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -323,8 +323,8 @@ class OddsBandAnalyzer:
|
|||||||
m.home_team_id,
|
m.home_team_id,
|
||||||
m.away_team_id,
|
m.away_team_id,
|
||||||
CASE
|
CASE
|
||||||
WHEN m.home_team_id = %(team_id)s THEN os_sel.odd_value
|
WHEN m.home_team_id = %(team_id)s THEN os_sel.odd_value::numeric
|
||||||
ELSE os_sel2.odd_value
|
ELSE os_sel2.odd_value::numeric
|
||||||
END AS team_odds
|
END AS team_odds
|
||||||
FROM matches m
|
FROM matches m
|
||||||
JOIN odd_categories oc
|
JOIN odd_categories oc
|
||||||
@@ -344,7 +344,7 @@ class OddsBandAnalyzer:
|
|||||||
AND m.score_home IS NOT NULL
|
AND m.score_home IS NOT NULL
|
||||||
AND m.score_away IS NOT NULL
|
AND m.score_away IS NOT NULL
|
||||||
AND m.mst_utc < %(before_ts)s
|
AND m.mst_utc < %(before_ts)s
|
||||||
AND COALESCE(os_sel.odd_value, os_sel2.odd_value)
|
AND COALESCE(os_sel.odd_value::numeric, os_sel2.odd_value::numeric)
|
||||||
BETWEEN %(band_low)s AND %(band_high)s
|
BETWEEN %(band_low)s AND %(band_high)s
|
||||||
ORDER BY m.mst_utc DESC
|
ORDER BY m.mst_utc DESC
|
||||||
LIMIT %(max_lookback)s
|
LIMIT %(max_lookback)s
|
||||||
@@ -432,7 +432,7 @@ class OddsBandAnalyzer:
|
|||||||
AND m.score_home IS NOT NULL
|
AND m.score_home IS NOT NULL
|
||||||
AND m.score_away IS NOT NULL
|
AND m.score_away IS NOT NULL
|
||||||
AND m.mst_utc < %(before_ts)s
|
AND m.mst_utc < %(before_ts)s
|
||||||
AND os_h.odd_value BETWEEN %(band_low)s AND %(band_high)s
|
AND os_h.odd_value::numeric BETWEEN %(band_low)s AND %(band_high)s
|
||||||
ORDER BY m.mst_utc DESC
|
ORDER BY m.mst_utc DESC
|
||||||
LIMIT %(max_lookback)s
|
LIMIT %(max_lookback)s
|
||||||
)
|
)
|
||||||
@@ -508,7 +508,7 @@ class OddsBandAnalyzer:
|
|||||||
f"İlk Yarı {line_str} Alt/Üst",
|
f"İlk Yarı {line_str} Alt/Üst",
|
||||||
f"Ilk Yari {line_str} Alt/Ust",
|
f"Ilk Yari {line_str} Alt/Ust",
|
||||||
]
|
]
|
||||||
score_expr = "COALESCE(m.score_ht_home, 0) + COALESCE(m.score_ht_away, 0)"
|
score_expr = "COALESCE(m.ht_score_home, 0) + COALESCE(m.ht_score_away, 0)"
|
||||||
else:
|
else:
|
||||||
cat_names = [
|
cat_names = [
|
||||||
f"{line_str} Alt/Üst",
|
f"{line_str} Alt/Üst",
|
||||||
@@ -535,7 +535,7 @@ class OddsBandAnalyzer:
|
|||||||
AND m.status = 'FT'
|
AND m.status = 'FT'
|
||||||
AND m.score_home IS NOT NULL
|
AND m.score_home IS NOT NULL
|
||||||
AND m.mst_utc < %(before_ts)s
|
AND m.mst_utc < %(before_ts)s
|
||||||
AND os_over.odd_value BETWEEN %(band_low)s AND %(band_high)s
|
AND os_over.odd_value::numeric BETWEEN %(band_low)s AND %(band_high)s
|
||||||
ORDER BY m.mst_utc DESC
|
ORDER BY m.mst_utc DESC
|
||||||
LIMIT %(max_lookback)s
|
LIMIT %(max_lookback)s
|
||||||
)
|
)
|
||||||
@@ -620,7 +620,7 @@ class OddsBandAnalyzer:
|
|||||||
AND m.status = 'FT'
|
AND m.status = 'FT'
|
||||||
AND m.score_home IS NOT NULL
|
AND m.score_home IS NOT NULL
|
||||||
AND m.mst_utc < %(before_ts)s
|
AND m.mst_utc < %(before_ts)s
|
||||||
AND os_yes.odd_value BETWEEN %(band_low)s AND %(band_high)s
|
AND os_yes.odd_value::numeric BETWEEN %(band_low)s AND %(band_high)s
|
||||||
ORDER BY m.mst_utc DESC
|
ORDER BY m.mst_utc DESC
|
||||||
LIMIT %(max_lookback)s
|
LIMIT %(max_lookback)s
|
||||||
)
|
)
|
||||||
@@ -696,7 +696,7 @@ class OddsBandAnalyzer:
|
|||||||
AND m.sport = 'football' AND m.status = 'FT'
|
AND m.sport = 'football' AND m.status = 'FT'
|
||||||
AND m.score_home IS NOT NULL
|
AND m.score_home IS NOT NULL
|
||||||
AND m.mst_utc < %(before_ts)s
|
AND m.mst_utc < %(before_ts)s
|
||||||
AND os_sel.odd_value BETWEEN %(bl)s AND %(bh)s
|
AND os_sel.odd_value::numeric BETWEEN %(bl)s AND %(bh)s
|
||||||
ORDER BY m.mst_utc DESC LIMIT %(ml)s
|
ORDER BY m.mst_utc DESC LIMIT %(ml)s
|
||||||
)
|
)
|
||||||
SELECT COUNT(*) AS ss,
|
SELECT COUNT(*) AS ss,
|
||||||
@@ -748,7 +748,7 @@ class OddsBandAnalyzer:
|
|||||||
try:
|
try:
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
WITH ht_matches AS (
|
WITH ht_matches AS (
|
||||||
SELECT m.score_ht_home, m.score_ht_away,
|
SELECT m.ht_score_home, m.ht_score_away,
|
||||||
m.home_team_id, m.away_team_id
|
m.home_team_id, m.away_team_id
|
||||||
FROM matches m
|
FROM matches m
|
||||||
JOIN odd_categories oc ON oc.match_id = m.id
|
JOIN odd_categories oc ON oc.match_id = m.id
|
||||||
@@ -761,18 +761,18 @@ class OddsBandAnalyzer:
|
|||||||
AND os2.name = '2' AND m.away_team_id = %(tid)s
|
AND os2.name = '2' AND m.away_team_id = %(tid)s
|
||||||
WHERE (m.home_team_id = %(tid)s OR m.away_team_id = %(tid)s)
|
WHERE (m.home_team_id = %(tid)s OR m.away_team_id = %(tid)s)
|
||||||
AND m.sport = 'football' AND m.status = 'FT'
|
AND m.sport = 'football' AND m.status = 'FT'
|
||||||
AND m.score_ht_home IS NOT NULL
|
AND m.ht_score_home IS NOT NULL
|
||||||
AND m.mst_utc < %(before_ts)s
|
AND m.mst_utc < %(before_ts)s
|
||||||
AND COALESCE(os1.odd_value, os2.odd_value)
|
AND COALESCE(os1.odd_value::numeric, os2.odd_value::numeric)
|
||||||
BETWEEN %(bl)s AND %(bh)s
|
BETWEEN %(bl)s AND %(bh)s
|
||||||
ORDER BY m.mst_utc DESC LIMIT %(ml)s
|
ORDER BY m.mst_utc DESC LIMIT %(ml)s
|
||||||
)
|
)
|
||||||
SELECT COUNT(*) AS ss,
|
SELECT COUNT(*) AS ss,
|
||||||
COALESCE(AVG(CASE
|
COALESCE(AVG(CASE
|
||||||
WHEN (home_team_id = %(tid)s AND score_ht_home > score_ht_away)
|
WHEN (home_team_id = %(tid)s AND ht_score_home > ht_score_away)
|
||||||
OR (away_team_id = %(tid)s AND score_ht_away > score_ht_home)
|
OR (away_team_id = %(tid)s AND ht_score_away > ht_score_home)
|
||||||
THEN 1.0 ELSE 0.0 END), 0.33) AS win_rate,
|
THEN 1.0 ELSE 0.0 END), 0.33) AS win_rate,
|
||||||
COALESCE(AVG(CASE WHEN score_ht_home = score_ht_away
|
COALESCE(AVG(CASE WHEN ht_score_home = ht_score_away
|
||||||
THEN 1.0 ELSE 0.0 END), 0.40) AS draw_rate
|
THEN 1.0 ELSE 0.0 END), 0.40) AS draw_rate
|
||||||
FROM ht_matches
|
FROM ht_matches
|
||||||
""", {
|
""", {
|
||||||
@@ -824,7 +824,7 @@ class OddsBandAnalyzer:
|
|||||||
AND m.sport = 'football' AND m.status = 'FT'
|
AND m.sport = 'football' AND m.status = 'FT'
|
||||||
AND m.score_home IS NOT NULL
|
AND m.score_home IS NOT NULL
|
||||||
AND m.mst_utc < %(before_ts)s
|
AND m.mst_utc < %(before_ts)s
|
||||||
AND os_odd.odd_value BETWEEN %(bl)s AND %(bh)s
|
AND os_odd.odd_value::numeric BETWEEN %(bl)s AND %(bh)s
|
||||||
ORDER BY m.mst_utc DESC LIMIT %(ml)s
|
ORDER BY m.mst_utc DESC LIMIT %(ml)s
|
||||||
)
|
)
|
||||||
SELECT COUNT(*) AS ss,
|
SELECT COUNT(*) AS ss,
|
||||||
@@ -1185,7 +1185,7 @@ class OddsBandAnalyzer:
|
|||||||
'IY/MS'
|
'IY/MS'
|
||||||
)
|
)
|
||||||
JOIN odd_selections os ON os.odd_category_db_id = oc.db_id
|
JOIN odd_selections os ON os.odd_category_db_id = oc.db_id
|
||||||
AND os.odd_value BETWEEN %(bl)s AND %(bh)s
|
AND os.odd_value::numeric BETWEEN %(bl)s AND %(bh)s
|
||||||
WHERE m.sport = 'football'
|
WHERE m.sport = 'football'
|
||||||
AND m.status = 'FT'
|
AND m.status = 'FT'
|
||||||
AND m.score_home IS NOT NULL
|
AND m.score_home IS NOT NULL
|
||||||
|
|||||||
@@ -15,13 +15,9 @@ Orijinal Faktörler:
|
|||||||
- Tarihsel upset pattern
|
- Tarihsel upset pattern
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from typing import Dict, Any, Optional, Tuple, List
|
from typing import Dict, Any, Optional, Tuple, List
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import psycopg2
|
import psycopg2
|
||||||
from psycopg2.extras import RealDictCursor
|
from psycopg2.extras import RealDictCursor
|
||||||
|
|||||||
+182
-21
@@ -7,17 +7,24 @@ import time
|
|||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
import uvicorn
|
import uvicorn
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from fastapi import FastAPI, HTTPException, Request
|
from fastapi import FastAPI, HTTPException, Request
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
|
import subprocess
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
try:
|
||||||
from models.basketball_v25 import get_basketball_v25_predictor
|
from models.basketball_v25 import get_basketball_v25_predictor
|
||||||
|
HAS_BASKETBALL = True
|
||||||
|
except ImportError:
|
||||||
|
HAS_BASKETBALL = False
|
||||||
from services.single_match_orchestrator import get_single_match_orchestrator
|
from services.single_match_orchestrator import get_single_match_orchestrator
|
||||||
from services.v26_shadow_engine import get_v26_shadow_engine
|
from services.v26_shadow_engine import get_v26_shadow_engine
|
||||||
from data.database import dispose_engine
|
from models.league_model import get_league_model_loader
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
@@ -34,6 +41,23 @@ class CouponRequest(BaseModel):
|
|||||||
min_confidence: float | None = None
|
min_confidence: float | None = None
|
||||||
|
|
||||||
|
|
||||||
|
class RetrainRequest(BaseModel):
|
||||||
|
reason: str | None = "manual"
|
||||||
|
markets: str | None = None # comma-separated, e.g. "MS,OU25,BTTS"
|
||||||
|
trials: int | None = 50
|
||||||
|
|
||||||
|
|
||||||
|
# ─── Retrain state tracking ──────────────────────────────────
|
||||||
|
_retrain_state: dict[str, Any] = {
|
||||||
|
"running": False,
|
||||||
|
"last_started": None,
|
||||||
|
"last_completed": None,
|
||||||
|
"last_status": None,
|
||||||
|
"last_error": None,
|
||||||
|
"pid": None,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def lifespan(_: FastAPI):
|
async def lifespan(_: FastAPI):
|
||||||
try:
|
try:
|
||||||
@@ -49,9 +73,6 @@ async def lifespan(_: FastAPI):
|
|||||||
|
|
||||||
yield
|
yield
|
||||||
|
|
||||||
# Cleanup async DB connections on shutdown
|
|
||||||
await dispose_engine()
|
|
||||||
|
|
||||||
|
|
||||||
app = FastAPI(
|
app = FastAPI(
|
||||||
title="Suggest-Bet AI Engine",
|
title="Suggest-Bet AI Engine",
|
||||||
@@ -114,6 +135,8 @@ def read_root() -> dict[str, Any]:
|
|||||||
"GET /v20plus/reversal-watchlist",
|
"GET /v20plus/reversal-watchlist",
|
||||||
"POST /v20plus/coupon",
|
"POST /v20plus/coupon",
|
||||||
"GET /v20plus/daily-banker",
|
"GET /v20plus/daily-banker",
|
||||||
|
"POST /v1/admin/retrain",
|
||||||
|
"GET /v1/admin/retrain/status",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,37 +146,68 @@ def health_check() -> dict[str, Any]:
|
|||||||
try:
|
try:
|
||||||
orchestrator = get_single_match_orchestrator()
|
orchestrator = get_single_match_orchestrator()
|
||||||
shadow_engine = get_v26_shadow_engine()
|
shadow_engine = get_v26_shadow_engine()
|
||||||
|
|
||||||
|
# Per-market V25 model status
|
||||||
|
v25_readiness: dict[str, Any] = {"fully_loaded": False}
|
||||||
|
try:
|
||||||
|
v25_predictor = orchestrator._get_v25_predictor()
|
||||||
|
v25_readiness = v25_predictor.readiness_summary()
|
||||||
|
except Exception as v25_err:
|
||||||
|
v25_readiness = {"fully_loaded": False, "error": str(v25_err)}
|
||||||
|
|
||||||
|
if HAS_BASKETBALL:
|
||||||
basketball_predictor = get_basketball_v25_predictor()
|
basketball_predictor = get_basketball_v25_predictor()
|
||||||
basketball_readiness = basketball_predictor.readiness_summary()
|
basketball_readiness = basketball_predictor.readiness_summary()
|
||||||
ready = bool(basketball_readiness["fully_loaded"])
|
ready = bool(basketball_readiness.get("fully_loaded", True))
|
||||||
|
else:
|
||||||
|
basketball_readiness = {"fully_loaded": False, "error": "Basketball module not found"}
|
||||||
|
ready = True
|
||||||
|
|
||||||
|
league_readiness = get_league_model_loader().readiness_summary()
|
||||||
|
overall_ready = ready and v25_readiness.get("fully_loaded", False)
|
||||||
return {
|
return {
|
||||||
"status": "healthy" if ready else "degraded",
|
"status": "healthy" if overall_ready else "degraded",
|
||||||
"engine": "v28.main",
|
"engine": "v28.main",
|
||||||
"mode": os.getenv("AI_ENGINE_MODE", "v28"),
|
"mode": os.getenv("AI_ENGINE_MODE", "v28"),
|
||||||
"ready": ready,
|
"ready": overall_ready,
|
||||||
|
"v25_football": v25_readiness,
|
||||||
|
"league_specific": league_readiness,
|
||||||
"basketball_v25": basketball_readiness,
|
"basketball_v25": basketball_readiness,
|
||||||
"v26_shadow": shadow_engine.readiness_summary(),
|
"v26_shadow": shadow_engine.readiness_summary(),
|
||||||
"prediction_service_ready": True,
|
"prediction_service_ready": True,
|
||||||
"model_loaded": ready,
|
"model_loaded": overall_ready,
|
||||||
"orchestrator_mode": getattr(orchestrator, "engine_mode", "v28"),
|
"orchestrator_mode": getattr(orchestrator, "engine_mode", "v28"),
|
||||||
}
|
}
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
return {"status": "unhealthy", "ready": False, "error": str(error)}
|
return {"status": "unhealthy", "ready": False, "error": str(error)}
|
||||||
|
|
||||||
|
|
||||||
|
_REQUIRED_RESPONSE_FIELDS = ("match_info", "market_board", "main_pick", "bet_summary", "data_quality")
|
||||||
|
|
||||||
|
|
||||||
@app.post("/v20plus/analyze/{match_id}")
|
@app.post("/v20plus/analyze/{match_id}")
|
||||||
async def analyze_match_v20plus(match_id: str) -> dict[str, Any]:
|
async def analyze_match_v20plus(match_id: str) -> dict[str, Any]:
|
||||||
|
started_at = time.time()
|
||||||
orchestrator = get_single_match_orchestrator()
|
orchestrator = get_single_match_orchestrator()
|
||||||
result = orchestrator.analyze_match(match_id)
|
result = await asyncio.to_thread(orchestrator.analyze_match, match_id)
|
||||||
|
elapsed_ms = int((time.time() - started_at) * 1000)
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
raise HTTPException(status_code=404, detail=f"Match not found: {match_id}")
|
raise HTTPException(status_code=404, detail=f"Match not found: {match_id}")
|
||||||
|
|
||||||
|
# Response validation: log missing required fields (non-fatal)
|
||||||
|
missing_fields = [f for f in _REQUIRED_RESPONSE_FIELDS if f not in result]
|
||||||
|
if missing_fields:
|
||||||
|
print(f"⚠️ [API] analyze/{match_id} response missing fields: {missing_fields} ({elapsed_ms}ms)")
|
||||||
|
|
||||||
|
result["timing_ms"] = elapsed_ms
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
@app.get("/v20plus/analyze-htms/{match_id}")
|
@app.get("/v20plus/analyze-htms/{match_id}")
|
||||||
async def analyze_match_htms_v20plus(match_id: str) -> dict[str, Any]:
|
async def analyze_match_htms_v20plus(match_id: str) -> dict[str, Any]:
|
||||||
orchestrator = get_single_match_orchestrator()
|
orchestrator = get_single_match_orchestrator()
|
||||||
result = orchestrator.analyze_match_htms(match_id)
|
result = await asyncio.to_thread(orchestrator.analyze_match_htms, match_id)
|
||||||
if not result:
|
if not result:
|
||||||
raise HTTPException(status_code=404, detail=f"Match not found: {match_id}")
|
raise HTTPException(status_code=404, detail=f"Match not found: {match_id}")
|
||||||
return result
|
return result
|
||||||
@@ -224,11 +278,12 @@ async def analyze_match_htft_v20plus(match_id: str, timeout_sec: int = 30) -> di
|
|||||||
@app.post("/v20plus/coupon")
|
@app.post("/v20plus/coupon")
|
||||||
async def generate_coupon_v20plus(request: CouponRequest) -> dict[str, Any]:
|
async def generate_coupon_v20plus(request: CouponRequest) -> dict[str, Any]:
|
||||||
orchestrator = get_single_match_orchestrator()
|
orchestrator = get_single_match_orchestrator()
|
||||||
return orchestrator.build_coupon(
|
return await asyncio.to_thread(
|
||||||
match_ids=request.match_ids,
|
orchestrator.build_coupon,
|
||||||
strategy=request.strategy or "BALANCED",
|
request.match_ids,
|
||||||
max_matches=request.max_matches,
|
request.strategy or "BALANCED",
|
||||||
min_confidence=request.min_confidence,
|
request.max_matches,
|
||||||
|
request.min_confidence,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -238,7 +293,7 @@ async def get_daily_banker_v20plus(count: int = 3) -> dict[str, Any]:
|
|||||||
raise HTTPException(status_code=400, detail="count must be >= 1")
|
raise HTTPException(status_code=400, detail="count must be >= 1")
|
||||||
|
|
||||||
orchestrator = get_single_match_orchestrator()
|
orchestrator = get_single_match_orchestrator()
|
||||||
bankers = orchestrator.get_daily_bankers(count=count)
|
bankers = await asyncio.to_thread(orchestrator.get_daily_bankers, count)
|
||||||
return {"count": len(bankers), "bankers": bankers}
|
return {"count": len(bankers), "bankers": bankers}
|
||||||
|
|
||||||
@app.get("/v20plus/reversal-watchlist")
|
@app.get("/v20plus/reversal-watchlist")
|
||||||
@@ -256,14 +311,120 @@ async def get_reversal_watchlist_v20plus(
|
|||||||
raise HTTPException(status_code=400, detail="min_score must be between 0 and 100")
|
raise HTTPException(status_code=400, detail="min_score must be between 0 and 100")
|
||||||
|
|
||||||
orchestrator = get_single_match_orchestrator()
|
orchestrator = get_single_match_orchestrator()
|
||||||
return orchestrator.get_reversal_watchlist(
|
return await asyncio.to_thread(
|
||||||
count=count,
|
orchestrator.get_reversal_watchlist,
|
||||||
horizon_hours=horizon_hours,
|
count,
|
||||||
min_score=min_score,
|
horizon_hours,
|
||||||
top_leagues_only=top_leagues_only,
|
min_score,
|
||||||
|
top_leagues_only,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# ─── ADMIN: Retrain Pipeline ─────────────────────────────────
|
||||||
|
|
||||||
|
def _run_retrain_pipeline(markets: str | None, trials: int):
|
||||||
|
"""Background function: extract data → train model → reload."""
|
||||||
|
global _retrain_state
|
||||||
|
ai_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
scripts_dir = os.path.join(ai_dir, "scripts")
|
||||||
|
python = os.path.join(ai_dir, "venv", "bin", "python3")
|
||||||
|
if not os.path.exists(python):
|
||||||
|
python = sys.executable # fallback
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Step 1: Extract training data
|
||||||
|
print("🔄 [RETRAIN] Step 1/3: Extracting training data...", flush=True)
|
||||||
|
result = subprocess.run(
|
||||||
|
[python, os.path.join(scripts_dir, "extract_training_data.py")],
|
||||||
|
capture_output=True, text=True, timeout=600, cwd=ai_dir,
|
||||||
|
)
|
||||||
|
if result.returncode != 0:
|
||||||
|
raise RuntimeError(f"Extract failed:\n{result.stderr[-500:]}")
|
||||||
|
print(f"✅ [RETRAIN] Extract done", flush=True)
|
||||||
|
|
||||||
|
# Step 2: Train V25 Pro
|
||||||
|
print("🔄 [RETRAIN] Step 2/3: Training V25 Pro model...", flush=True)
|
||||||
|
train_cmd = [python, os.path.join(scripts_dir, "train_v25_pro.py")]
|
||||||
|
if markets:
|
||||||
|
train_cmd += ["--markets", markets]
|
||||||
|
train_cmd += ["--trials", str(trials)]
|
||||||
|
|
||||||
|
result = subprocess.run(
|
||||||
|
train_cmd, capture_output=True, text=True, timeout=3600, cwd=ai_dir,
|
||||||
|
)
|
||||||
|
if result.returncode != 0:
|
||||||
|
raise RuntimeError(f"Training failed:\n{result.stderr[-500:]}")
|
||||||
|
print(f"✅ [RETRAIN] Training done", flush=True)
|
||||||
|
|
||||||
|
# Step 3: Reload models in memory
|
||||||
|
print("🔄 [RETRAIN] Step 3/3: Reloading models...", flush=True)
|
||||||
|
try:
|
||||||
|
orchestrator = get_single_match_orchestrator()
|
||||||
|
v25 = orchestrator._get_v25_predictor()
|
||||||
|
v25._loaded = False
|
||||||
|
v25.load_models()
|
||||||
|
print("✅ [RETRAIN] Models reloaded in memory", flush=True)
|
||||||
|
except Exception as reload_err:
|
||||||
|
print(f"⚠️ [RETRAIN] Hot reload failed (restart needed): {reload_err}", flush=True)
|
||||||
|
|
||||||
|
_retrain_state.update({
|
||||||
|
"running": False,
|
||||||
|
"last_completed": datetime.now().isoformat(),
|
||||||
|
"last_status": "success",
|
||||||
|
"last_error": None,
|
||||||
|
})
|
||||||
|
print("🎉 [RETRAIN] Pipeline complete!", flush=True)
|
||||||
|
|
||||||
|
except Exception as err:
|
||||||
|
_retrain_state.update({
|
||||||
|
"running": False,
|
||||||
|
"last_completed": datetime.now().isoformat(),
|
||||||
|
"last_status": "failed",
|
||||||
|
"last_error": str(err),
|
||||||
|
})
|
||||||
|
print(f"❌ [RETRAIN] Pipeline failed: {err}", flush=True)
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/v1/admin/retrain")
|
||||||
|
async def admin_retrain(request: RetrainRequest) -> dict[str, Any]:
|
||||||
|
"""Trigger full retrain pipeline: extract → train → reload."""
|
||||||
|
if _retrain_state["running"]:
|
||||||
|
return {
|
||||||
|
"status": "already_running",
|
||||||
|
"message": f"Retrain in progress since {_retrain_state['last_started']}",
|
||||||
|
}
|
||||||
|
|
||||||
|
_retrain_state.update({
|
||||||
|
"running": True,
|
||||||
|
"last_started": datetime.now().isoformat(),
|
||||||
|
"last_status": "running",
|
||||||
|
"last_error": None,
|
||||||
|
})
|
||||||
|
|
||||||
|
# Run in background thread
|
||||||
|
import threading
|
||||||
|
thread = threading.Thread(
|
||||||
|
target=_run_retrain_pipeline,
|
||||||
|
args=(request.markets, request.trials or 50),
|
||||||
|
daemon=True,
|
||||||
|
)
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
return {
|
||||||
|
"status": "triggered",
|
||||||
|
"message": "Retrain pipeline started in background",
|
||||||
|
"reason": request.reason,
|
||||||
|
"markets": request.markets or "all",
|
||||||
|
"trials": request.trials or 50,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/v1/admin/retrain/status")
|
||||||
|
async def admin_retrain_status() -> dict[str, Any]:
|
||||||
|
"""Check retrain pipeline status."""
|
||||||
|
return {**_retrain_state}
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
port = int(os.getenv("PORT", "8000"))
|
port = int(os.getenv("PORT", "8000"))
|
||||||
uvicorn.run("main:app", host="0.0.0.0", port=port, reload=True)
|
uvicorn.run("main:app", host="0.0.0.0", port=port, reload=True)
|
||||||
|
|||||||
@@ -0,0 +1,356 @@
|
|||||||
|
"""
|
||||||
|
Basketball V25 Predictor Package
|
||||||
|
=================================
|
||||||
|
Loads trained XGBoost + LightGBM models for basketball market predictions:
|
||||||
|
- ML (Money Line — home / away win)
|
||||||
|
- Total (Over/Under total points)
|
||||||
|
- Spread (ATS home cover / away cover)
|
||||||
|
|
||||||
|
Model files live in this directory:
|
||||||
|
xgb_basketball_v25_{market}.json — XGBoost (primary)
|
||||||
|
lgb_basketball_v25_{market}.txt — LightGBM (ensemble)
|
||||||
|
feature_cols.json — ordered feature list
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
|
# ── Constants ─────────────────────────────────────────────────────────────────
|
||||||
|
_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
_MARKETS = ("ml", "total", "spread")
|
||||||
|
|
||||||
|
|
||||||
|
# ── Output dataclass ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class BasketballMatchPrediction:
|
||||||
|
"""Complete basketball match prediction output."""
|
||||||
|
|
||||||
|
match_id: str
|
||||||
|
home_team_name: str
|
||||||
|
away_team_name: str
|
||||||
|
league_name: str = ""
|
||||||
|
|
||||||
|
# Money Line
|
||||||
|
ml_home_prob: float = 0.50
|
||||||
|
ml_away_prob: float = 0.50
|
||||||
|
ml_pick: str = ""
|
||||||
|
ml_confidence: float = 0.0
|
||||||
|
|
||||||
|
# Total (Over/Under)
|
||||||
|
total_line: float = 0.0
|
||||||
|
total_over_prob: float = 0.50
|
||||||
|
total_under_prob: float = 0.50
|
||||||
|
total_pick: str = ""
|
||||||
|
total_confidence: float = 0.0
|
||||||
|
|
||||||
|
# Spread (ATS)
|
||||||
|
spread_home_line: float = 0.0
|
||||||
|
spread_home_prob: float = 0.50
|
||||||
|
spread_away_prob: float = 0.50
|
||||||
|
spread_pick: str = ""
|
||||||
|
spread_confidence: float = 0.0
|
||||||
|
|
||||||
|
# Meta
|
||||||
|
model_version: str = "basketball_v25"
|
||||||
|
risk_level: str = "MEDIUM"
|
||||||
|
analysis_details: Dict[str, Any] = field(default_factory=dict)
|
||||||
|
market_board: Dict[str, Any] = field(default_factory=dict)
|
||||||
|
|
||||||
|
def to_dict(self) -> Dict[str, Any]:
|
||||||
|
return {
|
||||||
|
"match_id": self.match_id,
|
||||||
|
"home_team": self.home_team_name,
|
||||||
|
"away_team": self.away_team_name,
|
||||||
|
"league": self.league_name,
|
||||||
|
"model": self.model_version,
|
||||||
|
"risk_level": self.risk_level,
|
||||||
|
"ml": {
|
||||||
|
"home_prob": round(self.ml_home_prob * 100, 1),
|
||||||
|
"away_prob": round(self.ml_away_prob * 100, 1),
|
||||||
|
"pick": self.ml_pick,
|
||||||
|
"confidence": round(self.ml_confidence, 1),
|
||||||
|
},
|
||||||
|
"total": {
|
||||||
|
"line": self.total_line,
|
||||||
|
"over_prob": round(self.total_over_prob * 100, 1),
|
||||||
|
"under_prob": round(self.total_under_prob * 100, 1),
|
||||||
|
"pick": self.total_pick,
|
||||||
|
"confidence": round(self.total_confidence, 1),
|
||||||
|
},
|
||||||
|
"spread": {
|
||||||
|
"home_line": self.spread_home_line,
|
||||||
|
"home_prob": round(self.spread_home_prob * 100, 1),
|
||||||
|
"away_prob": round(self.spread_away_prob * 100, 1),
|
||||||
|
"pick": self.spread_pick,
|
||||||
|
"confidence": round(self.spread_confidence, 1),
|
||||||
|
},
|
||||||
|
"market_board": self.market_board,
|
||||||
|
"analysis_details": self.analysis_details,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# ── Predictor ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
class BasketballV25Predictor:
|
||||||
|
"""
|
||||||
|
Ensemble basketball predictor using XGBoost + LightGBM models.
|
||||||
|
|
||||||
|
Markets:
|
||||||
|
- ml → home/away win probability
|
||||||
|
- total → over/under total points
|
||||||
|
- spread → home/away ATS cover
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.feature_cols: List[str] = self._load_feature_cols()
|
||||||
|
self.models: Dict[str, Any] = {}
|
||||||
|
self._load_models()
|
||||||
|
print(f"✅ BasketballV25Predictor ready ({len(self.models)} models loaded)")
|
||||||
|
|
||||||
|
# ── Setup ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
def _load_feature_cols(self) -> List[str]:
|
||||||
|
path = os.path.join(_DIR, "feature_cols.json")
|
||||||
|
try:
|
||||||
|
with open(path, "r") as f:
|
||||||
|
return json.load(f)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"⚠️ [Basketball] Could not load feature_cols.json: {e}")
|
||||||
|
return []
|
||||||
|
|
||||||
|
def _load_models(self) -> None:
|
||||||
|
for market in _MARKETS:
|
||||||
|
xgb_path = os.path.join(_DIR, f"xgb_basketball_v25_{market}.json")
|
||||||
|
lgb_path = os.path.join(_DIR, f"lgb_basketball_v25_{market}.txt")
|
||||||
|
|
||||||
|
xgb_model = self._try_load_xgb(xgb_path, market)
|
||||||
|
lgb_model = self._try_load_lgb(lgb_path, market)
|
||||||
|
|
||||||
|
if xgb_model is not None or lgb_model is not None:
|
||||||
|
self.models[market] = {"xgb": xgb_model, "lgb": lgb_model}
|
||||||
|
|
||||||
|
def _try_load_xgb(self, path: str, market: str) -> Optional[Any]:
|
||||||
|
if not os.path.exists(path):
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
import xgboost as xgb # type: ignore[import-not-found]
|
||||||
|
m = xgb.XGBClassifier()
|
||||||
|
m.load_model(path)
|
||||||
|
return m
|
||||||
|
except Exception as e:
|
||||||
|
print(f"⚠️ [Basketball] XGB {market} load failed: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _try_load_lgb(self, path: str, market: str) -> Optional[Any]:
|
||||||
|
if not os.path.exists(path):
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
import lightgbm as lgb # type: ignore[import-not-found]
|
||||||
|
with open(path, "r", encoding="utf-8") as f:
|
||||||
|
model_str = f.read()
|
||||||
|
return lgb.Booster(model_str=model_str)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"⚠️ [Basketball] LGB {market} load failed: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# ── Inference ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
def _build_feature_row(self, odds_data: Dict[str, Any], **kwargs: Any) -> "Any":
|
||||||
|
"""Build a single-row DataFrame aligned to training feature columns."""
|
||||||
|
import pandas as pd # type: ignore[import-not-found]
|
||||||
|
|
||||||
|
row: Dict[str, float] = {}
|
||||||
|
for col in self.feature_cols:
|
||||||
|
row[col] = float(kwargs.get(col) or odds_data.get(col) or 0.0)
|
||||||
|
|
||||||
|
# Map common odds keys
|
||||||
|
row["ml_home_odds"] = float(odds_data.get("ml_h") or 0.0)
|
||||||
|
row["ml_away_odds"] = float(odds_data.get("ml_a") or 0.0)
|
||||||
|
row["total_line"] = float(odds_data.get("tot_line") or 0.0)
|
||||||
|
row["total_over_odds"] = float(odds_data.get("tot_o") or 0.0)
|
||||||
|
row["total_under_odds"] = float(odds_data.get("tot_u") or 0.0)
|
||||||
|
row["spread_home_line"] = float(odds_data.get("spread_home_line") or 0.0)
|
||||||
|
row["spread_home_odds"] = float(odds_data.get("spread_h") or 0.0)
|
||||||
|
row["spread_away_odds"] = float(odds_data.get("spread_a") or 0.0)
|
||||||
|
|
||||||
|
# Implied probabilities
|
||||||
|
def _imp(odd: float) -> float:
|
||||||
|
return (1.0 / odd) if odd > 1.01 else 0.5
|
||||||
|
|
||||||
|
ml_h = row["ml_home_odds"]
|
||||||
|
ml_a = row["ml_away_odds"]
|
||||||
|
if ml_h > 1.01 and ml_a > 1.01:
|
||||||
|
raw = _imp(ml_h) + _imp(ml_a)
|
||||||
|
row["implied_home"] = _imp(ml_h) / raw
|
||||||
|
row["implied_away"] = _imp(ml_a) / raw
|
||||||
|
row["odds_overround"] = raw - 1.0
|
||||||
|
|
||||||
|
tot_o = row["total_over_odds"]
|
||||||
|
tot_u = row["total_under_odds"]
|
||||||
|
if tot_o > 1.01 and tot_u > 1.01:
|
||||||
|
raw = _imp(tot_o) + _imp(tot_u)
|
||||||
|
row["implied_total_over"] = _imp(tot_o) / raw
|
||||||
|
row["implied_total_under"] = _imp(tot_u) / raw
|
||||||
|
|
||||||
|
sp_h = row["spread_home_odds"]
|
||||||
|
sp_a = row["spread_away_odds"]
|
||||||
|
if sp_h > 1.01 and sp_a > 1.01:
|
||||||
|
raw = _imp(sp_h) + _imp(sp_a)
|
||||||
|
row["implied_spread_home"] = _imp(sp_h) / raw
|
||||||
|
row["implied_spread_away"] = _imp(sp_a) / raw
|
||||||
|
|
||||||
|
return pd.DataFrame([row])
|
||||||
|
|
||||||
|
def _ensemble_predict(self, market: str, df: "Any") -> List[float]:
|
||||||
|
"""Return [p_class0, p_class1] from XGB+LGB ensemble."""
|
||||||
|
models = self.models.get(market, {})
|
||||||
|
xgb_model = models.get("xgb")
|
||||||
|
lgb_model = models.get("lgb")
|
||||||
|
|
||||||
|
probs_list: List[List[float]] = []
|
||||||
|
|
||||||
|
if xgb_model is not None:
|
||||||
|
try:
|
||||||
|
p = xgb_model.predict_proba(df)
|
||||||
|
probs_list.append([float(p[0][0]), float(p[0][1])])
|
||||||
|
except Exception as e:
|
||||||
|
print(f"⚠️ [Basketball] XGB {market} inference failed: {e}")
|
||||||
|
|
||||||
|
if lgb_model is not None:
|
||||||
|
try:
|
||||||
|
p_raw = lgb_model.predict(df)
|
||||||
|
p1 = float(p_raw[0]) if len(p_raw.shape) == 1 else float(p_raw[0][1])
|
||||||
|
probs_list.append([1.0 - p1, p1])
|
||||||
|
except Exception as e:
|
||||||
|
print(f"⚠️ [Basketball] LGB {market} inference failed: {e}")
|
||||||
|
|
||||||
|
if not probs_list:
|
||||||
|
return [0.5, 0.5]
|
||||||
|
|
||||||
|
p0 = sum(p[0] for p in probs_list) / len(probs_list)
|
||||||
|
p1 = sum(p[1] for p in probs_list) / len(probs_list)
|
||||||
|
total = p0 + p1 or 1.0
|
||||||
|
return [p0 / total, p1 / total]
|
||||||
|
|
||||||
|
# ── Public API ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
def predict(
|
||||||
|
self,
|
||||||
|
match_id: str,
|
||||||
|
home_team_id: str,
|
||||||
|
away_team_id: str,
|
||||||
|
home_team_name: str = "",
|
||||||
|
away_team_name: str = "",
|
||||||
|
league_id: str = "",
|
||||||
|
league_name: str = "",
|
||||||
|
odds_data: Optional[Dict[str, Any]] = None,
|
||||||
|
sidelined_data: Optional[Dict[str, Any]] = None,
|
||||||
|
**kwargs: Any,
|
||||||
|
) -> BasketballMatchPrediction:
|
||||||
|
odds = odds_data or {}
|
||||||
|
prediction = BasketballMatchPrediction(
|
||||||
|
match_id=match_id,
|
||||||
|
home_team_name=home_team_name,
|
||||||
|
away_team_name=away_team_name,
|
||||||
|
league_name=league_name,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Sidelined impact
|
||||||
|
home_sl = int((sidelined_data or {}).get("homeTeam", {}).get("totalSidelined", 0) or 0)
|
||||||
|
away_sl = int((sidelined_data or {}).get("awayTeam", {}).get("totalSidelined", 0) or 0)
|
||||||
|
kwargs.setdefault("home_sidelined_count", float(home_sl))
|
||||||
|
kwargs.setdefault("away_sidelined_count", float(away_sl))
|
||||||
|
kwargs.setdefault("sidelined_diff", float(home_sl - away_sl))
|
||||||
|
kwargs.setdefault("missing_players_impact", float(home_sl + away_sl) / 10.0)
|
||||||
|
|
||||||
|
if not self.models:
|
||||||
|
print("⚠️ [Basketball] No models loaded — returning neutral defaults")
|
||||||
|
return prediction
|
||||||
|
|
||||||
|
try:
|
||||||
|
df = self._build_feature_row(odds, **kwargs)
|
||||||
|
|
||||||
|
# ── ML ──
|
||||||
|
ml_probs = self._ensemble_predict("ml", df)
|
||||||
|
prediction.ml_home_prob = ml_probs[0]
|
||||||
|
prediction.ml_away_prob = ml_probs[1]
|
||||||
|
prediction.ml_pick = "1" if ml_probs[0] >= ml_probs[1] else "2"
|
||||||
|
prediction.ml_confidence = max(ml_probs) * 100.0
|
||||||
|
|
||||||
|
# ── Total ──
|
||||||
|
prediction.total_line = float(odds.get("tot_line") or 0.0)
|
||||||
|
tot_probs = self._ensemble_predict("total", df)
|
||||||
|
prediction.total_over_prob = tot_probs[1]
|
||||||
|
prediction.total_under_prob = tot_probs[0]
|
||||||
|
total_line = prediction.total_line
|
||||||
|
prediction.total_pick = (
|
||||||
|
f"Over {total_line}" if tot_probs[1] >= tot_probs[0] else f"Under {total_line}"
|
||||||
|
)
|
||||||
|
prediction.total_confidence = max(tot_probs) * 100.0
|
||||||
|
|
||||||
|
# ── Spread ──
|
||||||
|
prediction.spread_home_line = float(odds.get("spread_home_line") or 0.0)
|
||||||
|
sp_probs = self._ensemble_predict("spread", df)
|
||||||
|
prediction.spread_home_prob = sp_probs[0]
|
||||||
|
prediction.spread_away_prob = sp_probs[1]
|
||||||
|
home_line = prediction.spread_home_line
|
||||||
|
away_line = -home_line
|
||||||
|
prediction.spread_pick = (
|
||||||
|
f"Home {home_line:+.1f}" if sp_probs[0] >= sp_probs[1] else f"Away {away_line:+.1f}"
|
||||||
|
)
|
||||||
|
prediction.spread_confidence = max(sp_probs) * 100.0
|
||||||
|
|
||||||
|
# Market board summary
|
||||||
|
prediction.market_board = {
|
||||||
|
"ML": {
|
||||||
|
"1": f"{prediction.ml_home_prob * 100:.0f}%",
|
||||||
|
"2": f"{prediction.ml_away_prob * 100:.0f}%",
|
||||||
|
},
|
||||||
|
"Totals": {
|
||||||
|
f"Over {total_line}": f"{prediction.total_over_prob * 100:.0f}%",
|
||||||
|
f"Under {total_line}": f"{prediction.total_under_prob * 100:.0f}%",
|
||||||
|
},
|
||||||
|
"Spread": {
|
||||||
|
f"Home {home_line:+.1f}": f"{prediction.spread_home_prob * 100:.0f}%",
|
||||||
|
f"Away {away_line:+.1f}": f"{prediction.spread_away_prob * 100:.0f}%",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
# Risk
|
||||||
|
top_conf = max(prediction.ml_confidence, prediction.total_confidence, prediction.spread_confidence)
|
||||||
|
prediction.risk_level = "LOW" if top_conf >= 65 else "MEDIUM" if top_conf >= 55 else "HIGH"
|
||||||
|
prediction.analysis_details = {
|
||||||
|
"model_version": "basketball_v25",
|
||||||
|
"markets_predicted": list(self.models.keys()),
|
||||||
|
"ensemble_size": {m: sum(1 for k in v.values() if v[k] is not None) for m, v in self.models.items()},
|
||||||
|
}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"⚠️ [Basketball] Prediction failed for {match_id}: {e}")
|
||||||
|
|
||||||
|
return prediction
|
||||||
|
|
||||||
|
|
||||||
|
# ── Singleton factory ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
_predictor: Optional[BasketballV25Predictor] = None
|
||||||
|
|
||||||
|
|
||||||
|
def get_basketball_v25_predictor() -> BasketballV25Predictor:
|
||||||
|
"""Return the singleton BasketballV25Predictor (lazy-loaded)."""
|
||||||
|
global _predictor
|
||||||
|
if _predictor is None:
|
||||||
|
_predictor = BasketballV25Predictor()
|
||||||
|
return _predictor
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"BasketballMatchPrediction",
|
||||||
|
"BasketballV25Predictor",
|
||||||
|
"get_basketball_v25_predictor",
|
||||||
|
]
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
[
|
||||||
|
"home_overall_elo",
|
||||||
|
"away_overall_elo",
|
||||||
|
"elo_diff",
|
||||||
|
"home_home_elo",
|
||||||
|
"away_away_elo",
|
||||||
|
"home_form_elo",
|
||||||
|
"away_form_elo",
|
||||||
|
"home_form_score",
|
||||||
|
"away_form_score",
|
||||||
|
"form_score_diff",
|
||||||
|
"home_points_avg",
|
||||||
|
"away_points_avg",
|
||||||
|
"points_avg_diff",
|
||||||
|
"home_conceded_avg",
|
||||||
|
"away_conceded_avg",
|
||||||
|
"conceded_avg_diff",
|
||||||
|
"home_net_rating",
|
||||||
|
"away_net_rating",
|
||||||
|
"net_rating_diff",
|
||||||
|
"home_win_rate",
|
||||||
|
"away_win_rate",
|
||||||
|
"win_rate_diff",
|
||||||
|
"home_winning_streak",
|
||||||
|
"away_winning_streak",
|
||||||
|
"streak_diff",
|
||||||
|
"home_rest_days",
|
||||||
|
"away_rest_days",
|
||||||
|
"rest_diff",
|
||||||
|
"home_rebounds_avg",
|
||||||
|
"away_rebounds_avg",
|
||||||
|
"rebounds_diff",
|
||||||
|
"home_assists_avg",
|
||||||
|
"away_assists_avg",
|
||||||
|
"assists_diff",
|
||||||
|
"home_steals_avg",
|
||||||
|
"away_steals_avg",
|
||||||
|
"steals_diff",
|
||||||
|
"home_blocks_avg",
|
||||||
|
"away_blocks_avg",
|
||||||
|
"blocks_diff",
|
||||||
|
"home_turnovers_avg",
|
||||||
|
"away_turnovers_avg",
|
||||||
|
"turnovers_diff",
|
||||||
|
"home_fg_pct",
|
||||||
|
"away_fg_pct",
|
||||||
|
"fg_pct_diff",
|
||||||
|
"home_three_pt_pct",
|
||||||
|
"away_three_pt_pct",
|
||||||
|
"three_pt_pct_diff",
|
||||||
|
"home_ft_pct",
|
||||||
|
"away_ft_pct",
|
||||||
|
"ft_pct_diff",
|
||||||
|
"home_q1_avg",
|
||||||
|
"away_q1_avg",
|
||||||
|
"home_q4_avg",
|
||||||
|
"away_q4_avg",
|
||||||
|
"home_conc_rebounds_avg",
|
||||||
|
"away_conc_rebounds_avg",
|
||||||
|
"home_conc_assists_avg",
|
||||||
|
"away_conc_assists_avg",
|
||||||
|
"home_conc_turnovers_avg",
|
||||||
|
"away_conc_turnovers_avg",
|
||||||
|
"home_conc_fg_pct",
|
||||||
|
"away_conc_fg_pct",
|
||||||
|
"home_conc_three_pt_pct",
|
||||||
|
"away_conc_three_pt_pct",
|
||||||
|
"h2h_total_matches",
|
||||||
|
"h2h_home_win_rate",
|
||||||
|
"h2h_avg_points",
|
||||||
|
"h2h_avg_margin",
|
||||||
|
"h2h_over_total_rate",
|
||||||
|
"h2h_home_cover_rate",
|
||||||
|
"league_avg_points",
|
||||||
|
"league_home_win_rate",
|
||||||
|
"league_over_total_rate",
|
||||||
|
"league_home_cover_rate",
|
||||||
|
"ml_home_odds",
|
||||||
|
"ml_away_odds",
|
||||||
|
"implied_home",
|
||||||
|
"implied_away",
|
||||||
|
"total_line",
|
||||||
|
"total_over_odds",
|
||||||
|
"total_under_odds",
|
||||||
|
"implied_total_over",
|
||||||
|
"implied_total_under",
|
||||||
|
"spread_home_line",
|
||||||
|
"spread_home_odds",
|
||||||
|
"spread_away_odds",
|
||||||
|
"implied_spread_home",
|
||||||
|
"implied_spread_away",
|
||||||
|
"odds_overround",
|
||||||
|
"home_sidelined_count",
|
||||||
|
"away_sidelined_count",
|
||||||
|
"sidelined_diff",
|
||||||
|
"missing_players_impact",
|
||||||
|
"total_points_form",
|
||||||
|
"total_points_allowed_form",
|
||||||
|
"projected_total_delta_vs_line",
|
||||||
|
"projected_margin_vs_spread"
|
||||||
|
]
|
||||||
@@ -0,0 +1,655 @@
|
|||||||
|
tree
|
||||||
|
version=v4
|
||||||
|
num_class=1
|
||||||
|
num_tree_per_iteration=1
|
||||||
|
label_index=0
|
||||||
|
max_feature_idx=98
|
||||||
|
objective=binary sigmoid:1
|
||||||
|
feature_names=Column_0 Column_1 Column_2 Column_3 Column_4 Column_5 Column_6 Column_7 Column_8 Column_9 Column_10 Column_11 Column_12 Column_13 Column_14 Column_15 Column_16 Column_17 Column_18 Column_19 Column_20 Column_21 Column_22 Column_23 Column_24 Column_25 Column_26 Column_27 Column_28 Column_29 Column_30 Column_31 Column_32 Column_33 Column_34 Column_35 Column_36 Column_37 Column_38 Column_39 Column_40 Column_41 Column_42 Column_43 Column_44 Column_45 Column_46 Column_47 Column_48 Column_49 Column_50 Column_51 Column_52 Column_53 Column_54 Column_55 Column_56 Column_57 Column_58 Column_59 Column_60 Column_61 Column_62 Column_63 Column_64 Column_65 Column_66 Column_67 Column_68 Column_69 Column_70 Column_71 Column_72 Column_73 Column_74 Column_75 Column_76 Column_77 Column_78 Column_79 Column_80 Column_81 Column_82 Column_83 Column_84 Column_85 Column_86 Column_87 Column_88 Column_89 Column_90 Column_91 Column_92 Column_93 Column_94 Column_95 Column_96 Column_97 Column_98
|
||||||
|
feature_infos=none none none none none none none [0:100] [0:100] [-100:100] [54:128.875] [61:138] [-41.333333333333329:24] [61:130.125] [59:133] [-50:34.916666666666671] [-28.666666666666657:32.5] [-24.5:27] [-35.5:31.833333333333329] [0:1] [0:1] [-1:1] [0:12] [0:12] [-12:10] [0.91666666666666663:186.1875] [0.85416666666666663:185.08333333333337] [-179.02083333333334:184.16666666666663] [20:54] [22:56] [-21:15.833333333333332] [11:34.5] [9:36] [-15:13.333333333333332] [2:13] [3:13] [-8:5.5] [0.875:9] [0:12] [-9:4.875] [7:22] [8:23] [-10:10] [0.41025641025641019:0.67647058823529416] [0.39730639730639727:0.76744186046511631] [-0.3174418604651163:0.22647058823529409] [0.20419254658385089:0.4825000000000001] [0.1875:0.54166666666666663] [-0.22171945701357459:0.17923280423280419] [0.47826086956521741:0.87898457080200498] [0.42857142857142849:0.88636363636363635] [-0.29647435897435898:0.38962801311591622] [11:39.666666666666664] [15.5:40] [10:31.875] [11.5:34] [15:56] [17:57] [12:32.125] [10:38] [8:20] [7:22] [0.40000000000000002:0.69047619047619047] [0.3902439024390244:0.71739130434782605] [0.23753976670201479:0.51851851851851849] [0.1707317073170731:0.54545454545454541] [0:8] [0:1] [120:295] [-38:36] [0:1] [0:1] [140.39130434782609:233.09999999999999] [0:1] [0:1] [0:1] [1.05:4.1100000000000003] [1.05:4.1299999999999999] [0.2034883720930232:0.79729729729729726] [0.20270270270270269:0.79651162790697683] [145.5:257.5] [1.3:7.7599999999999998] [1.4099999999999999:7.5599999999999996] [0.1789976133651551:0.75977653631284914] [0.24022346368715081:0.82100238663484482] [-15.5:12.5] [1.3:2.7200000000000002] [1.1799999999999999:2.7799999999999998] [0.36298076923076922:0.64953271028037374] [0.35046728971962621:0.63701923076923073] [0.1918833727344364:0.21555133935749429] none none none none [132:250.6875] [126.25:256.625] [-63.5:88.6875] [-35.5:27.5]
|
||||||
|
tree_sizes=2312 2651 2758 2331 2348 2534 2554 2662 2359 2770 1932 1926 2552 2145 2460 2555 1931 2453 1831 2020 2352 2348 2035
|
||||||
|
|
||||||
|
Tree=0
|
||||||
|
num_leaves=21
|
||||||
|
num_cat=0
|
||||||
|
split_feature=77 77 95 50 40 97 37 25 73 56 81 57 35 17 50 97 25 23 23 9
|
||||||
|
split_gain=87.208 23.2965 12.6569 10.5307 10.1901 9.83622 9.59439 7.56522 7.2843 6.81795 6.60435 5.65211 7.74871 6.22559 5.61137 5.14301 3.28504 2.92219 2.6911 0.0931822
|
||||||
|
threshold=1.3750000000000002 2.6550000000000007 166.34375000000003 0.73851279305095374 11.062500000000002 5.9687500000000009 3.7750000000000004 1.8802083333333337 0.5344873150105709 30.803571428571434 1.5750000000000004 41.062500000000007 6.6937500000000005 -4.7749999999999977 0.71663103786665172 -3.4241071428571384 7.7864583333333348 1.0000000180025095e-35 1.0000000180025095e-35 -39.015151515151508
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=3 2 14 -1 -4 7 -7 -6 -3 -10 -5 12 -11 -13 -2 -16 18 -17 -12 -20
|
||||||
|
right_child=1 8 4 10 5 6 -8 -9 9 11 16 13 -14 -15 15 17 -18 -19 19 -21
|
||||||
|
leaf_value=-0.14765628269715012 -0.15600540791535678 -0.23353299922727577 -0.12151989070972055 -0.13344020462290634 -0.11780070546597361 -0.21612555668738542 -0.16327023115717296 -0.15881183656013212 -0.15004174704520915 -0.17986005139594724 -0.10382337530156519 -0.2025678370168939 -0.21889492254600434 -0.15072330828751174 -0.17027559642606713 -0.19596193574534582 -0.1164283857771044 -0.23353299922727577 -0.079223274212206221 -0.072514155733290175
|
||||||
|
leaf_weight=11.17881618440151 6.70728971064091 6.210453435778617 11.427234321832655 9.1914710849523527 7.94938039779663 9.1914710849523562 13.662997558712958 76.015950053930283 6.7072897106409064 14.159833833575247 8.943052947521215 6.4588715732097617 19.128196582198143 8.6946348100900632 6.9557078480720582 7.4525441229343361 8.1977985352277738 5.9620352983474731 5.9620352983474714 7.4525441229343414
|
||||||
|
leaf_count=45 27 25 46 37 32 37 55 306 27 57 36 26 77 35 28 30 33 24 24 30
|
||||||
|
internal_value=-0.160244 -0.171796 -0.16307 -0.113358 -0.157421 -0.161262 -0.184527 -0.154929 -0.192463 -0.187838 -0.103712 -0.193072 -0.202291 -0.172821 -0.187739 -0.198187 -0.0947688 -0.21266 -0.0868269 -0.075496
|
||||||
|
internal_weight=257.61 206.684 145.325 50.9257 118.247 106.82 22.8545 83.9653 61.3593 55.1488 39.7469 48.4415 33.288 15.1535 27.0776 20.3703 30.5554 13.4146 22.3576 13.4146
|
||||||
|
internal_count=1037 832 585 205 476 430 92 338 247 222 160 195 134 61 109 82 123 54 90 54
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=1
|
||||||
|
|
||||||
|
|
||||||
|
Tree=1
|
||||||
|
num_leaves=24
|
||||||
|
num_cat=0
|
||||||
|
split_feature=78 78 95 46 40 97 37 41 13 50 75 83 22 17 50 97 15 81 65 43 23 43 25
|
||||||
|
split_gain=80.2042 21.5716 11.6989 11.0897 9.36546 9.08525 8.91556 8.1723 7.75226 7.09679 6.96929 6.56155 6.17385 5.70382 5.20301 4.788 4.74542 3.71513 3.26193 3.12932 2.73996 1.35961 0.11562
|
||||||
|
threshold=0.39285714285714285 0.68693349935065817 166.34375000000003 0.34153389001132711 11.062500000000002 5.9687500000000009 3.7750000000000004 14.612500000000002 109.93750000000001 0.74692579813599125 0.36503968253968255 0.47970222696600762 1.5000000000000002 6.5625000000000009 0.71663103786665172 -3.4241071428571384 1.5166666666666659 1.635 0.35759117986701622 0.52557970719916269 1.0000000180025095e-35 0.51924929840975398 3.0312500000000004
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=3 2 14 8 -4 7 -7 -6 9 -1 16 -12 17 21 -2 -16 18 -13 -3 -20 -17 22 -5
|
||||||
|
right_child=1 10 4 13 5 6 -8 -9 -10 -11 11 12 -14 -15 15 20 -18 -19 19 -21 -22 -23 -24
|
||||||
|
leaf_value=0.0055530680640734674 0.0032845293651423612 -0.072766645625454485 0.036292826760507588 0.077436849336701308 -0.0022894176915147862 -0.054725292524358454 -0.003689958048423233 0.027881485430822688 -0.013760354637319356 0.059619560028970849 -0.050594773409676115 -0.0085801885492360844 -0.033840627756109222 0.036366913393967221 -0.010423432121785391 -0.035188847843671808 -0.021864921616209863 0.033823144597002808 -0.060759072260146665 -0.021284474578964662 -0.071669256311519158 0.058239915950701049 0.085149025961743521
|
||||||
|
leaf_weight=6.4684473276138368 6.7090961784124401 9.4034554809331912 11.457648575305937 5.9847112745046669 65.60038697719574 9.142817825078966 13.658771887421606 18.391589343547821 6.4761682301759711 9.7236045598983747 7.1794854700565365 7.4327530264854449 8.1723358631134015 9.9696762263774854 6.9495052695274415 7.4284560978412575 10.15483947098255 5.9542565494775772 6.6812664419412595 6.190190851688385 5.9189314842224121 5.978186532855033 6.4756923913955688
|
||||||
|
leaf_count=26 27 38 46 24 264 37 55 74 26 39 29 30 33 40 28 30 41 24 27 25 24 24 26
|
||||||
|
internal_value=-0.000786037 -0.0118905 -0.00349945 0.0440926 0.00192543 -0.00176177 -0.0241537 0.00431706 0.0232273 0.0380209 -0.0318166 -0.0174741 -0.00644452 0.0607419 -0.0272534 -0.0373477 -0.0445269 0.0102799 -0.0548581 -0.0417748 -0.0513662 0.0739213 0.0814449
|
||||||
|
internal_weight=257.502 206.426 145.257 51.0765 118.251 106.794 22.8016 83.992 22.6682 16.1921 61.1686 28.7388 21.5593 28.4083 27.006 20.2969 32.4298 13.387 22.2749 12.8715 13.3474 18.4386 12.4604
|
||||||
|
internal_count=1037 832 585 205 476 430 92 338 91 65 247 116 87 114 109 82 131 54 90 52 54 74 50
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=2
|
||||||
|
num_leaves=25
|
||||||
|
num_cat=0
|
||||||
|
split_feature=77 76 10 46 51 75 75 42 12 51 74 44 9 61 86 41 49 17 85 44 27 49 74 97
|
||||||
|
split_gain=73.8475 19.9927 10.9898 10.1665 9.79528 8.50828 11.1493 9.23472 9.00307 8.63936 8.14649 7.11143 7.43675 10.0884 8.56935 6.6516 6.48284 5.22574 5.21615 4.45089 3.01631 2.88722 1.39723 0.105613
|
||||||
|
threshold=1.3750000000000002 1.2250000000000003 80.937500000000014 0.34153389001132711 0.011242161620033652 0.44508064516129037 0.39517441860465125 -0.61249999999999971 2.5499999999999976 0.012462680598456451 0.40642170329670335 0.55897334407178179 8.7121212121212164 11.866071428571431 1.635 14.225000000000001 0.78414366883116904 6.5625000000000009 6.0000000000000009 0.51258507460016867 -0.10937499999999993 0.73610958414604988 0.62250000000000016 1.1937499999999945
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=3 11 19 4 18 6 8 10 -4 -9 -7 12 13 -2 -15 20 -8 22 -1 -3 -14 -21 23 -5
|
||||||
|
right_child=1 2 5 17 -6 7 16 9 -10 -11 -12 -13 15 14 -16 -17 -18 -19 -20 21 -22 -23 -24 -25
|
||||||
|
leaf_value=0.017705783755189462 0.028974497745101052 -0.0060737041061852126 0.028384924190391733 0.081917709440956332 -0.011007695119626166 0.051971315475459197 -0.05418693058345065 -0.015490981812325239 -0.030486429608756988 0.017134873390643509 0.01007092726093781 -0.071582917658417497 -0.024872499607636107 0.0039725729814389819 -0.046514665309970234 -0.0035756501646253529 -0.0037995538175229883 0.034855017993211231 0.06661466771004268 -0.026672382631287159 -0.057894168683677763 -0.065766238281201289 0.054894232678188361 0.074556160849369266
|
||||||
|
leaf_weight=6.7373062372207659 7.4330984354019192 7.1768550276756313 11.678280815482141 6.4950603991746956 8.7123459726572019 11.683709740638731 11.923531427979471 30.992172449827194 6.4527826756238928 22.351678267121315 20.364999443292618 5.9138691127300254 5.9248394817113939 9.3952521085739154 12.583362787961958 6.4179672747850409 6.2149500101804724 9.9856856316328031 7.2363171875476837 6.1660670638084394 17.493629351258278 5.9290464669466019 5.9967442750930777 5.9974743723869324
|
||||||
|
leaf_count=27 30 29 47 26 35 47 48 125 26 90 82 24 24 38 51 26 25 40 29 25 71 24 24 24
|
||||||
|
internal_value=-0.000757575 -0.0114353 -0.00296399 0.0422564 0.0222795 0.00148162 -0.0147493 0.00837551 0.00743281 -0.00182038 0.0253462 -0.0297572 -0.0255824 -0.011309 -0.0249328 -0.0396526 -0.0369223 0.058172 0.0430335 -0.0310287 -0.0495397 -0.0458363 0.0707651 0.0783835
|
||||||
|
internal_weight=257.257 206.096 140.934 51.1609 22.686 121.662 36.2695 85.3926 18.1311 53.3439 32.0487 65.162 59.2481 29.4117 21.9786 29.8364 18.1385 28.475 13.9736 19.272 23.4185 12.0951 18.4893 12.4925
|
||||||
|
internal_count=1037 832 568 205 91 490 146 344 73 215 129 264 240 119 89 121 73 114 56 78 95 49 74 50
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=3
|
||||||
|
num_leaves=21
|
||||||
|
num_cat=0
|
||||||
|
split_feature=77 77 95 46 51 86 49 42 73 69 54 7 31 85 50 81 61 44 53 77
|
||||||
|
split_gain=68.0698 18.5538 10.4158 9.36539 9.01462 7.14355 8.22377 7.01134 6.54248 6.34821 10.3019 8.78745 4.815 4.79475 4.79 3.98009 3.96113 2.92643 3.60798 2.21945
|
||||||
|
threshold=1.3750000000000002 2.6550000000000007 166.34375000000003 0.34153389001132711 0.011242161620033652 2.2450000000000006 0.80827483213138251 -0.61249999999999971 0.5344873150105709 4.6500000000000012 23.062500000000004 40.833333333333343 23.550000000000004 6.0000000000000009 0.71663103786665172 1.7750000000000001 12.062500000000002 0.53723539037745083 24.803571428571434 1.925
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=3 2 14 4 13 6 7 -4 -3 11 -11 -10 -8 -1 -2 19 -13 18 -5 -16
|
||||||
|
right_child=1 8 5 17 -6 -7 12 -9 9 10 -12 16 -14 -15 15 -17 -18 -19 -20 -21
|
||||||
|
leaf_value=0.016987942399224069 0.0035814571364199662 -0.068907535589063609 0.01429912015371851 0.079098125792394905 -0.010575188509827679 -0.033022257030977734 0.059900457392998388 -0.008250813675967944 0.00010937594628987166 -0.040766144429216389 0.025542986379799158 -0.019382488279346841 0.013986965287345072 0.063856791784991249 -0.032605400222488659 -0.0094169329033003141 -0.05275351833756161 0.039347381597312048 0.041332957240490006 -0.064822733951046208
|
||||||
|
leaf_weight=6.7410361915826815 6.703504994511607 6.0858818590641013 35.323686808347702 11.494772866368299 8.7060475498437864 8.6918699741363508 5.9581677168607703 58.758967056870461 9.3814801126718503 6.6312184035778037 8.6243968755006772 7.6371410340070751 9.4523572921752912 7.2466183453798294 7.3598874658346194 6.4097239673137656 22.335135906934738 10.743333801627157 6.2475921660661689 6.3931281566619873
|
||||||
|
leaf_count=27 27 25 142 46 35 35 24 237 38 27 35 31 38 29 30 26 91 43 25 26
|
||||||
|
internal_value=-0.000730438 -0.0109991 -0.00322902 0.0405507 0.0213801 0.00188154 0.0046523 0.000215644 -0.0295683 -0.0251842 -0.00327986 -0.0336755 0.0317385 0.0412694 -0.0257105 -0.0354492 -0.0442504 0.0558234 0.0657999 -0.0475817
|
||||||
|
internal_weight=256.926 205.747 145.051 51.1794 22.6937 118.185 109.493 94.0827 60.6953 54.6094 15.2556 39.3538 15.4105 13.9877 26.8662 20.1627 29.9723 28.4857 17.7424 13.753
|
||||||
|
internal_count=1037 832 585 205 91 476 441 379 247 222 62 160 62 56 109 82 122 114 71 56
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=4
|
||||||
|
num_leaves=21
|
||||||
|
num_cat=0
|
||||||
|
split_feature=77 76 10 46 38 52 90 13 63 35 27 50 50 12 36 17 44 49 74 45
|
||||||
|
split_gain=62.8093 17.2545 9.84388 8.65527 8.50818 8.94286 7.35721 7.1083 6.79729 7.71767 6.73811 6.55324 5.90783 5.04228 9.19595 4.75428 4.11592 2.77884 1.29074 0.102719
|
||||||
|
threshold=1.3750000000000002 1.2250000000000003 80.937500000000014 0.34153389001132711 2.6904761904761911 26.562500000000004 0.19724305626860048 109.93750000000001 0.55212996425566885 6.2750000000000012 -0.020833333333333648 0.76335870360422431 0.74692579813599125 7.3125000000000009 -0.26190476190476181 6.5625000000000009 0.51258507460016867 0.73610958414604988 0.62250000000000016 -0.0013187490579748998
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=3 8 16 7 11 6 -6 12 9 -2 -7 -4 -1 14 -11 18 -3 -18 19 -5
|
||||||
|
right_child=1 2 4 15 5 10 -8 -9 -10 13 -12 -13 -14 -15 -16 -17 17 -19 -20 -21
|
||||||
|
leaf_value=0.0050560182108375287 0.01454555314741844 -0.0053774531433530308 0.0088078452630964664 0.076512274772428487 0.012372105311854016 0.04280070757761658 -0.015898578376521092 -0.014892135795344198 -0.057603106440945573 -0.013716056812372755 -2.743210612548636e-05 0.06049972094546327 0.054367671817810027 -0.0053464224261316716 -0.054858503781032956 0.031440123411904081 -0.024849777283710722 -0.063361316106082435 0.050431436557637821 0.069244124813442359
|
||||||
|
leaf_weight=6.4694478660821977 7.8782515972852698 7.1609281748533276 10.659276410937311 6.4840846359729793 19.36934831738472 10.460701778531076 61.473121464252472 6.4756214618682852 10.231325536966322 16.168815225362774 13.415295347571371 6.2101935893297187 9.7394945174455625 11.545304596424101 18.798230275511745 9.9960098117589933 6.1246920526027662 5.871805265545845 5.9897889196872702 5.9808590859174755
|
||||||
|
leaf_count=26 32 29 43 26 78 42 248 26 42 66 54 25 39 47 77 40 25 24 24 24
|
||||||
|
internal_value=-0.0007041 -0.010581 -0.00272469 0.0389631 0.00147434 -0.00277256 -0.0091251 0.0205332 -0.0276919 -0.0220654 0.0187367 0.0278373 0.034686 -0.0282665 -0.0358342 0.0536577 -0.029375 -0.0436996 0.0656918 0.0730249
|
||||||
|
internal_weight=256.503 205.367 140.745 51.1353 121.588 104.718 80.8425 22.6846 64.6219 54.3906 23.876 16.8695 16.2089 46.5124 34.967 28.4507 19.1574 11.9965 18.4547 12.4649
|
||||||
|
internal_count=1037 832 568 205 490 422 326 91 264 222 96 68 65 190 143 114 78 49 74 50
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=5
|
||||||
|
num_leaves=23
|
||||||
|
num_cat=0
|
||||||
|
split_feature=77 77 49 8 59 55 59 9 40 35 50 74 36 58 97 86 49 8 95 56 52 48
|
||||||
|
split_gain=59.2137 16.5141 9.9144 11.7486 12.1383 8.99339 10.5611 8.66857 10.2694 8.14362 7.72674 7.72484 12.0149 7.4839 7.07919 6.69422 4.48655 4.69909 4.36454 2.6211 3.68984 2.53359
|
||||||
|
threshold=1.3550000000000002 2.2550000000000003 0.75657876131221735 31.666666666666668 17.267857142857146 19.535714285714288 18.937500000000004 -2.6785714285714266 12.937500000000002 8.3875000000000011 0.73851279305095374 0.54575358851674649 0.066964285714285574 24.354166666666668 2.9821428571428616 1.7450000000000003 0.77175549922512843 65.151515151515156 173.36607142857147 40.38750000000001 20.937500000000004 0.0091659973707001029
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=10 2 3 -2 -5 -3 18 8 -8 11 -1 14 -13 -6 -4 -9 19 -18 21 20 -12 -7
|
||||||
|
right_child=1 5 9 4 13 6 7 15 -10 -11 16 12 -14 -15 -16 -17 17 -19 -20 -21 -22 -23
|
||||||
|
leaf_value=0.011681667207113649 0.033908823443212138 0.017536154054844273 0.021215365730383975 0.03251466321515277 -0.035698618619601191 -0.069217953298740698 0.040352083533208016 -0.037782244586161744 -0.02378355379185353 -0.016829989475423059 0.067034861961705272 0.039469073342078345 -0.028155083253979179 0.009683122942141572 0.064205028012414941 -0.003245990990143062 0.008774257662963655 0.054818660291170745 -0.016792700372560584 0.076628087701740399 0.026483773237715093 -0.038854738339966714
|
||||||
|
leaf_weight=10.698686346411703 8.1725911200046522 9.060679689049719 26.58554495871067 6.4189013689756385 30.358332172036171 10.46654355525971 8.4112317115068453 24.458471849560738 7.6072484105825415 11.665961533784865 8.4696357846260089 6.9492753297090557 10.640220895409582 7.1914227455854407 7.9649787694215766 14.189488068222998 6.9667989164590818 7.2231719940900803 5.8842895776033393 9.7066867947578412 6.2319085150957099 7.58248247206211
|
||||||
|
leaf_count=43 33 37 107 26 123 43 34 100 31 47 34 28 43 29 32 58 28 29 24 39 25 31
|
||||||
|
internal_value=0.0024258 -0.0070979 0.00280729 -0.0101318 -0.0183177 -0.0201993 -0.0245493 -0.0148477 0.00989378 0.0133809 0.0417609 0.0201404 -0.00143807 -0.0270072 0.0311258 -0.0251024 0.0500983 0.0322124 -0.046709 0.0604964 0.0498455 -0.0564622
|
||||||
|
internal_weight=252.905 203.608 115.947 52.1412 43.9687 87.6604 78.5998 54.6664 16.0185 63.806 49.2969 52.14 17.5895 37.5498 34.5505 38.648 38.5982 14.19 23.9333 24.4082 14.7015 18.049
|
||||||
|
internal_count=1024 826 468 211 178 358 321 223 65 257 198 210 71 152 139 158 155 57 98 98 59 74
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=6
|
||||||
|
num_leaves=23
|
||||||
|
num_cat=0
|
||||||
|
split_feature=76 78 27 46 86 11 55 29 65 47 50 46 18 61 81 36 44 9 13 43 81 44
|
||||||
|
split_gain=54.7148 15.7289 10.7788 14.3867 9.58583 8.78499 8.46201 10.8596 9.81775 8.03411 7.677 7.45074 5.6669 7.59424 5.03116 4.82371 4.8014 4.00902 3.45566 2.28622 3.41567 0.00497756
|
||||||
|
threshold=2.1950000000000007 0.62900904125363766 -2.3020833333333326 0.34016393531964906 2.1450000000000005 122.43750000000001 19.854166666666668 39.812500000000007 0.3770676732818225 0.36593380560885896 0.73563272044162131 0.35736791305409527 -3.1874999999999996 12.690476190476192 1.5150000000000003 0.25833333333333336 0.49644821746513607 -8.7121212121212164 117.43750000000001 0.50247426971013531 1.7450000000000003 0.53567202664757096
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 2 11 9 5 -5 -3 8 17 16 -2 15 -9 -14 -12 -1 -4 -8 19 21 -21 -16
|
||||||
|
right_child=10 6 3 4 -6 -7 7 12 -10 -11 14 -13 13 -15 18 -17 -18 -19 -20 20 -22 -23
|
||||||
|
leaf_value=0.070324761157363386 0.0084031851759769002 0.012486475233554927 -0.014274497772434848 0.02062654133633882 -0.032240672579085888 -0.029937743516828159 -0.020241102484534694 0.022406478756216045 0.0013966323082333749 0.0049975598343196606 0.016976514726108942 -0.0032581054169875008 0.011631640379196602 -0.033623046124736253 0.073425640497252462 0.021730508558563181 -0.050815423135628625 -0.053986984893246243 0.028244335395794146 0.069298036861864615 0.028035945730723436 0.075014904249462944
|
||||||
|
leaf_weight=6.9250844269990939 9.2112289071083051 11.516124725341795 9.6139747798442858 48.390351086854935 7.907471075654029 6.2022370845079413 7.0930576324462846 7.9190109968185416 8.3109913170337659 11.12387755513191 6.4693672657012931 7.1976774334907523 9.5812086164951342 15.581949874758719 6.6890226900577598 6.1896365433931351 14.328032165765761 27.358511343598369 5.9492755085229865 6.9541786164045316 5.9617312103509903 5.9650087505578995
|
||||||
|
leaf_count=28 37 47 39 195 32 25 29 32 34 45 26 29 39 64 27 25 58 113 24 28 24 24
|
||||||
|
internal_value=0.00233149 -0.00659898 0.00293381 -0.00258517 0.00892003 0.014882 -0.0194618 -0.0243128 -0.0376256 -0.0230916 0.0411639 0.029443 -0.00710444 -0.0163917 0.0491075 0.0473902 -0.0361423 -0.0470392 0.0557024 0.062091 0.0502523 0.0741748
|
||||||
|
internal_weight=252.439 205.239 117.878 97.5659 62.5001 54.5926 87.3609 75.8447 42.7626 35.0659 47.1998 20.3124 33.0822 25.1632 37.9886 13.1147 23.942 34.4516 31.5192 25.5699 12.9159 12.654
|
||||||
|
internal_count=1024 834 476 394 252 220 358 311 176 142 190 82 135 103 153 53 97 142 127 103 52 51
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=7
|
||||||
|
num_leaves=24
|
||||||
|
num_cat=0
|
||||||
|
split_feature=76 78 27 31 32 42 58 74 15 40 46 26 76 97 98 73 62 60 46 61 90 97 42
|
||||||
|
split_gain=50.8947 11.0049 9.32122 10.5702 10.4712 9.27532 8.02666 7.19583 7.79066 6.93078 7.78095 6.76995 6.46148 6.98083 6.77168 6.35566 6.68601 5.47664 5.22172 4.56413 4.30903 3.83111 0.826657
|
||||||
|
threshold=1.8750000000000002 0.70062845714719713 -9.1770833333333304 18.401785714285719 20.645833333333339 -2.774999999999999 26.401785714285719 0.63245614035087727 -0.43749999999999994 11.866071428571431 0.37542254586435625 6.7812500000000009 2.4650000000000003 -3.4241071428571384 -6.3184523809523787 0.55383792139841859 0.51117533329139231 13.35416666666667 0.35034659555724629 12.062500000000002 0.19829454556786633 0.28125000000000006 0.19761904761904778
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 2 -1 7 11 -6 12 8 -4 19 15 -5 14 -14 -2 -11 -17 18 -16 -3 -15 -19 -22
|
||||||
|
right_child=6 9 3 4 5 -7 -8 -9 -10 10 -12 -13 13 20 17 16 -18 21 -20 -21 22 -23 -24
|
||||||
|
leaf_value=0.036083213444415528 0.053277627847354556 -0.021782130288108433 -0.0091325820237097618 0.049355787080620245 0.039957936624339677 -0.010162507947377566 0.066494523434590488 0.007861663962773149 -0.056001702923737531 -0.05035447873268746 0.025153534242404262 -0.0002279551315397668 0.0074196720389386114 0.025979484890861368 -0.0040180493742294409 -0.035722871972219031 0.012557904583466907 -0.037148801270085199 0.040822377329808285 -0.065566429091563946 0.054687788523123476 0.0082770984108304652 0.074704189299082305
|
||||||
|
leaf_weight=9.12299896776676 5.9481788575649253 6.5940756052732459 9.5768276453018242 10.393245324492456 6.4848928600549689 66.375781863927841 8.9054767787456495 7.6045115441083899 13.925430610775946 9.6051787436008471 6.321256920695304 7.647834599018096 7.4389976263046291 6.437974855303767 7.4326431751251283 8.6875483840703982 9.7281266301870328 5.9339717775583249 9.4233583807945234 9.0198750644922239 5.9406516849994642 5.9482765197753906 7.4301211833953857
|
||||||
|
leaf_count=37 24 27 39 42 26 268 36 31 57 40 26 31 30 26 30 36 40 24 38 38 24 24 30
|
||||||
|
internal_value=0.00224138 -0.00900344 -0.00291719 -0.00583339 0.00105391 -0.00570159 0.0309866 -0.0259598 -0.0369032 -0.0249795 -0.0149333 0.0283366 0.0258809 0.0404581 0.0144298 -0.0239765 -0.0102184 0.00638917 0.02105 -0.0470755 0.0528654 -0.0144085 0.0658109
|
||||||
|
internal_weight=251.927 181.088 131.132 122.009 90.9018 72.8607 70.8397 31.1068 23.5023 49.9561 34.3421 18.0411 61.9342 27.2477 34.6864 28.0209 18.4157 28.7382 16.856 15.614 19.8087 11.8822 13.3708
|
||||||
|
internal_count=1024 738 531 494 367 294 286 127 96 207 142 73 250 110 140 116 76 116 68 65 80 48 54
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=8
|
||||||
|
num_leaves=21
|
||||||
|
num_cat=0
|
||||||
|
split_feature=76 78 27 10 18 88 65 58 48 76 75 50 55 57 45 61 52 16 37 64
|
||||||
|
split_gain=47.0285 10.2297 8.57167 9.90629 8.49863 11.7596 8.93582 7.47628 6.70549 7.3988 6.88535 6.62498 6.53575 6.19036 7.25158 6.45563 5.31391 3.33594 2.78119 2.27511
|
||||||
|
threshold=1.8750000000000002 0.70062845714719713 -9.1770833333333304 82.267857142857153 -4.3541666666666705 0.49939467312348679 0.34321545037197632 26.401785714285719 0.021174040484134952 2.2250000000000005 0.64837092731829593 0.73563272044162131 19.854166666666668 41.062500000000007 0.0031867569273384007 12.062500000000002 20.937500000000004 -6.3124999999999991 2.6125000000000003 0.36408812715877942
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 2 -1 17 5 -5 -6 8 9 10 -2 -11 -3 15 -15 -14 -13 -4 -19 -17
|
||||||
|
right_child=7 12 3 4 6 -7 -8 -9 -10 11 -12 16 13 14 -16 19 -18 18 -20 -21
|
||||||
|
leaf_value=0.034533388049788116 0.023208498381564548 0.010691617096435792 -0.0099350499244745989 -0.013374654384074001 -0.030791758397498405 0.036260912427308507 0.00098553848763632086 0.064191286864412847 0.055107303489570873 -0.0011209989712481605 -0.023658767436963126 0.066673274412926392 -0.0085936349487782514 0.018687811460451158 -0.034036012019189175 -0.064822499725983529 0.027488397354637369 -0.062556001891513391 -0.025921626974491768 -0.035460654646497967
|
||||||
|
leaf_weight=9.1505375951528531 10.182640746235849 7.3519092053174964 8.031925320625307 12.611105665564539 19.997042715549469 19.363006785511971 48.494191810488701 8.8569523096084577 9.8766392171382886 7.7215904891490963 9.8834861069917661 8.600008040666582 6.5588535666465786 7.2764098048210171 9.7889975756406766 12.264306232333185 15.548548832535742 6.0707129538059217 7.3061331808567047 6.4392972588539115
|
||||||
|
leaf_count=37 41 30 33 51 81 78 196 36 40 31 40 35 27 30 41 52 63 25 30 27
|
||||||
|
internal_value=0.00215494 -0.00866469 -0.0028044 -0.00560779 -0.000343403 0.0166838 -0.00829232 0.029821 0.0248962 0.019151 0.000124224 0.0311307 -0.0241206 -0.0301671 -0.0115554 -0.0427397 0.0414433 -0.0303121 -0.0425471 -0.0547138
|
||||||
|
internal_weight=251.374 180.704 131.025 121.874 100.465 31.9741 68.4912 70.6699 61.8129 51.9363 20.0661 31.8701 49.6798 42.3279 17.0654 25.2625 24.1486 21.4088 13.3768 18.7036
|
||||||
|
internal_count=1024 738 531 494 406 129 277 286 250 210 81 129 207 177 71 106 98 88 55 79
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=9
|
||||||
|
num_leaves=25
|
||||||
|
num_cat=0
|
||||||
|
split_feature=78 78 49 49 88 63 41 34 8 52 58 40 46 48 78 75 50 73 62 52 52 89 61 30
|
||||||
|
split_gain=43.4968 9.51409 8.12139 9.24718 9.16177 10.1476 7.62239 8.2415 7.26498 6.99079 6.98605 6.58508 7.12245 6.22401 6.86036 6.34938 6.1593 5.87831 6.08977 5.0965 5.00399 4.68377 4.18568 2.8965
|
||||||
|
threshold=0.44444541990764314 0.70062845714719713 0.75617247776303531 0.7645406242769327 0.53179766719418564 0.50671990539912803 11.35416666666667 6.322916666666667 57.738095238095248 21.387500000000003 26.401785714285719 11.866071428571431 0.37542254586435625 0.021174040484134952 0.37587731721902251 0.64837092731829593 0.73563272044162131 0.55383792139841859 0.51117533329139231 20.145833333333339 20.937500000000004 0.48209613271233459 12.062500000000002 0.14583333333333218
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=10 2 4 21 5 9 -5 -8 -7 -2 13 22 17 14 16 -16 -1 -13 -19 -6 -18 -4 -3 -21
|
||||||
|
right_child=1 11 3 6 19 8 7 -9 -10 -11 -12 12 -14 -15 15 -17 20 18 -20 23 -22 -23 -24 -25
|
||||||
|
leaf_value=-0.0010761821563351997 -0.0504521132857738 -0.020888576146344352 0.063381196536312773 0.031300149180180752 -0.0091861880185250058 0.032629739057098435 0.026755708854807866 -0.014960107933453847 -0.014669550109854696 0.0014514898694815139 0.062084955523258885 -0.047888703413600249 0.024824846695046907 0.053148590255660884 0.022272644170989585 -0.022746839774489575 0.064616726934294752 -0.033579092631573867 0.012687158247053376 -0.033188047394488003 0.026459678285886239 0.014128239830164315 -0.063091908329842183 -0.070867855155932621
|
||||||
|
leaf_weight=7.7214295715093639 8.7155217230319995 6.5707600712776175 5.9724875986576063 10.170844271779059 7.820334509015086 14.327638953924181 9.4181414246559125 38.771787792444229 8.1518821418285352 7.9293809384107581 8.7924163937568647 9.4247248619794863 6.3216789960861197 9.8318816572427732 10.185996487736704 9.8688251972198469 8.5203529894351977 8.5675740987062472 9.7116009145975095 7.3497301340103132 15.507762670516966 6.3991550505161285 8.7900275439023954 5.8721687346696854
|
||||||
|
leaf_count=31 36 27 24 41 32 58 38 157 33 32 36 40 26 40 41 40 35 36 40 30 63 26 38 24
|
||||||
|
internal_value=0.00207304 -0.00834038 -0.00269623 0.00649292 -0.0134991 -0.00205203 -0.000166073 -0.00680725 0.0154773 -0.025726 0.0287296 -0.0233003 -0.0134864 0.0239715 0.018434 0.000118899 0.0300029 -0.0222285 -0.00899815 -0.0347829 0.0399901 0.0379054 -0.0450389 -0.0499226
|
||||||
|
internal_weight=250.714 180.285 130.899 70.7324 60.1667 39.1244 58.3608 48.1899 22.4795 16.6449 70.4287 49.3864 34.0256 61.6362 51.8044 20.0548 31.7495 27.7039 18.2792 21.0422 24.0281 12.3716 15.3608 13.2219
|
||||||
|
internal_count=1024 738 531 286 245 159 236 195 91 68 286 207 142 250 210 81 129 116 76 86 98 50 65 54
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=10
|
||||||
|
num_leaves=17
|
||||||
|
num_cat=0
|
||||||
|
split_feature=77 77 46 27 54 57 10 43 97 43 40 54 36 76 74 37
|
||||||
|
split_gain=38.196 8.66905 8.17628 11.664 9.48906 7.12349 6.31154 5.47718 7.96438 4.78449 4.32492 4.31373 3.38709 2.74196 2.35164 0.967464
|
||||||
|
threshold=1.3550000000000002 3.2850000000000006 0.30594944598976864 -7.9791666666666661 21.145833333333339 39.267857142857146 82.267857142857153 0.517251622710314 -4.4062499999999991 0.53429184335543722 13.062500000000002 21.387500000000003 0.25833333333333336 1.6050000000000002 0.49258241758241766 4.354166666666667
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=7 2 13 11 6 -6 -5 8 -1 14 -9 -4 15 -2 -3 -10
|
||||||
|
right_child=1 9 3 4 5 -7 -8 10 12 -11 -12 -13 -14 -15 -16 -17
|
||||||
|
leaf_value=0.0010938350878875731 -0.056271458252691184 -0.059825392191432909 0.059788669423910978 -0.039005664596234592 0.013116780911492858 -0.0075331438797635181 -0.0060155405307781556 -0.0070478699384603017 0.069320208232492922 -0.0094715712429085195 0.037723823315383334 0.012087841826597247 0.032449698237748015 -0.017612173431570215 -0.028207255364314641 0.049213209433963845
|
||||||
|
leaf_weight=6.4049855172634116 5.8483278751373273 7.5306213200092333 5.9356311261653882 18.997604206204414 43.460418909788132 69.426650807261467 18.137169808149338 8.3646507412195188 10.436919420957571 11.170329853892325 5.8781122714281073 6.2036552876234055 10.014484807848929 5.8936225026845932 7.5243068188428879 6.0471841692924491
|
||||||
|
leaf_count=26 24 32 24 79 177 282 74 34 43 47 24 25 41 24 32 25
|
||||||
|
internal_value=-0.000237742 -0.00786817 -0.00463523 -0.00230133 -0.00535295 0.000416875 -0.0228928 0.0321521 0.0411221 -0.0293062 0.0114298 0.0354117 0.0507973 -0.0368673 -0.044023 0.061944
|
||||||
|
internal_weight=247.275 200.128 173.903 162.161 150.022 112.887 37.1348 47.1463 32.9036 26.2253 14.2428 12.1393 26.4986 11.742 15.0549 16.4841
|
||||||
|
internal_count=1013 820 709 661 612 459 153 193 135 111 58 49 109 48 64 68
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=11
|
||||||
|
num_leaves=17
|
||||||
|
num_cat=0
|
||||||
|
split_feature=77 77 46 86 10 15 15 82 23 59 38 40 31 28 26 76
|
||||||
|
split_gain=35.3726 8.07222 7.58645 6.89209 6.39755 8.67145 7.68194 5.36328 4.76149 6.47719 8.94184 5.29839 3.97447 5.87629 4.03464 2.57596
|
||||||
|
threshold=1.3550000000000002 3.2850000000000006 0.30594944598976864 2.1550000000000007 81.291666666666671 -3.3523809523809471 -7.5624999999999991 1.7550000000000001 1.5000000000000002 22.062500000000004 3.0625000000000004 13.550000000000002 21.550000000000004 41.937500000000007 7.2708333333333348 1.6050000000000002
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=8 2 15 4 5 -4 -6 -5 9 10 -1 -10 14 -14 -3 -2
|
||||||
|
right_child=1 12 3 7 6 -7 -8 -9 11 -11 -12 -13 13 -15 -16 -17
|
||||||
|
leaf_value=0.028732650584569908 -0.054519811278789007 -0.064491542130753823 0.014624725366248799 -0.0085976653870859041 -0.017414530959728048 -0.043244668184488785 0.0081240637328352395 -0.056808196775163779 0.027059814047174627 0.044509876383840984 -0.03008579237684399 0.070067154331982448 0.011727805368536705 -0.043007463941734977 -0.020379238714872804 -0.016944262076966699
|
||||||
|
leaf_weight=10.437584459781652 5.7958323061466199 7.0121503621339816 6.5479190945625332 9.3588718920946103 22.927828788757324 11.280139639973639 105.82874263823032 6.0974729955196372 9.9562236517667788 11.169452026486395 6.8490484803915015 8.4930274337530118 7.1303854584693891 5.6052840352058411 6.2962067276239395 5.8811570256948471
|
||||||
|
leaf_count=43 24 30 27 38 94 47 430 25 41 46 28 35 30 24 27 24
|
||||||
|
internal_value=-0.000229245 -0.00756918 -0.0044558 -0.00221187 0.000466882 -0.0219903 0.00357638 -0.0276165 0.0310303 0.0207685 0.0054285 0.046858 -0.0283359 -0.0123625 -0.0436219 -0.0355948
|
||||||
|
internal_weight=246.667 199.762 173.718 162.041 146.585 17.8281 128.757 15.4563 46.9053 28.4561 17.2866 18.4493 26.044 12.7357 13.3084 11.677
|
||||||
|
internal_count=1013 820 709 661 598 74 524 63 193 117 71 76 111 54 57 48
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=12
|
||||||
|
num_leaves=23
|
||||||
|
num_cat=0
|
||||||
|
split_feature=77 77 52 75 51 26 74 17 75 82 54 32 27 33 81 83 85 32 72 61 77 52
|
||||||
|
split_gain=32.7624 7.68874 8.64181 8.25451 7.32214 6.8233 6.75593 6.44176 8.25947 8.69321 6.36363 7.17186 5.52164 5.23358 7.14313 7.28422 6.71979 4.33821 3.0057 2.88005 2.0103 1.97945
|
||||||
|
threshold=1.3550000000000002 2.7750000000000004 26.437500000000004 0.36503968253968255 0.0031256509629944006 8.0104166666666696 0.53482673267326752 5.7142857142857162 0.37048387096774199 1.5250000000000001 21.387500000000003 23.401785714285719 0.041666666666666609 0.48750000000000077 1.5450000000000002 0.49675474226372424 7.0000000000000009 23.937500000000004 168.45500000000001 12.866071428571431 3.5750000000000006 20.937500000000004
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=13 2 7 17 -4 6 -5 8 -2 -10 -9 -12 -6 14 -1 16 -16 18 -3 -15 -20 -17
|
||||||
|
right_child=1 3 4 5 12 -7 -8 10 9 -11 11 -13 -14 19 15 21 -18 -19 20 -21 -22 -23
|
||||||
|
leaf_value=-0.013704229151213245 0.027450875173411476 -0.023064966047954667 -0.0059624168736026485 -0.038589566739523094 0.056326441355657071 0.030446921359459631 0.016883396721917278 -0.016350382639718393 0.013627075998421501 -0.021633517290006031 0.05028258642359236 0.0009173349354000002 0.0072316487440658916 0.068524301803199614 -0.018133517520923233 0.068692298622940004 0.040971194599499342 -0.0050561417900614513 -0.063950555049639521 0.032780066279364729 -0.033589087879592569 0.036867444471177346
|
||||||
|
leaf_weight=7.3369961380958548 7.6220861226320258 8.4552565813064628 11.61829833686352 9.1469356268644351 8.95874175429344 7.0741493850946418 5.7027423083782187 10.210099041461946 13.296437010169027 70.522654443979263 8.4501094073057192 10.635228663682936 6.2034237682819358 6.9417874813079816 6.5973821580410021 6.2351381480693799 5.7690534591674805 6.4230835288763037 9.5591890364885312 7.5070647299289703 5.4950702935457221 6.273080438375473
|
||||||
|
leaf_count=30 31 36 47 39 36 29 24 42 54 288 34 43 25 29 27 26 24 27 41 31 24 26
|
||||||
|
internal_value=-0.000221457 -0.00728287 -0.00262557 -0.0205316 0.0179311 -0.00188419 -0.0172862 -0.00718521 -0.0124149 -0.01604 0.0091383 0.022774 0.0362399 0.0299509 0.0209788 0.0312089 0.00943936 -0.0341897 -0.0421493 0.049953 -0.0528681 0.0527316
|
||||||
|
internal_weight=246.034 199.374 147.517 51.8564 26.7805 21.9238 14.8497 120.737 91.4412 83.8191 29.2954 19.0853 15.1622 46.6605 32.2117 24.8747 12.3664 29.9326 23.5095 14.4489 15.0543 12.5082
|
||||||
|
internal_count=1013 820 600 220 108 92 63 492 373 342 119 77 61 193 133 103 51 128 101 60 65 52
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=13
|
||||||
|
num_leaves=19
|
||||||
|
num_cat=0
|
||||||
|
split_feature=77 27 31 81 14 38 21 55 43 97 42 50 49 41 11 29 36 46
|
||||||
|
split_gain=30.365 7.27107 9.52487 12.2996 9.0589 7.41691 9.90203 7.25389 5.08675 7.54296 5.07106 4.74587 4.44817 3.59305 3.39298 3.01366 2.9941 0.448837
|
||||||
|
threshold=1.3550000000000002 -9.1770833333333304 19.267857142857146 1.7250000000000003 122.31250000000001 2.6904761904761911 0.083333333333333273 24.291666666666668 0.517251622710314 -3.4687499999999996 -1.0000000180025095e-35 0.74140914232826016 0.76659506707061065 13.937500000000002 82.225000000000009 31.645833333333339 0.25833333333333336 0.36329415664585835
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=8 10 3 13 5 6 -4 -7 9 -1 -2 -5 -10 15 -13 -3 17 -11
|
||||||
|
right_child=1 2 4 11 -6 7 -8 -9 12 16 -12 14 -14 -15 -16 -17 -18 -19
|
||||||
|
leaf_value=0.0041476899979937393 -0.0034999926541034228 -0.023850556255963173 0.062374335339732266 0.019436960650830851 -0.040563681465367818 -0.014906923971429929 -0.0074965637413479513 0.0059412375908438819 0.030706710820604975 0.065449418006224877 0.045123507823127261 -0.039381405838009649 -0.014252467415403541 -0.014092509822306006 -0.0010383997769504584 -0.056317419451033038 0.031129941687341473 0.051133321323921815
|
||||||
|
leaf_weight=8.055756524205206 6.7893940508365631 6.2344330102205339 6.6629877835512143 9.740582004189493 9.6089727431535703 49.483073160052299 6.3268143832683563 58.00315548479557 7.2527140378952009 9.1974637508392352 6.9395729303359968 6.112829089164733 6.8431497812271118 6.5173709690570822 9.326295539736746 17.179670557379723 9.3787097781896573 5.6604025810956946
|
||||||
|
leaf_count=33 28 26 27 40 40 203 26 237 30 39 28 26 28 27 39 73 39 24
|
||||||
|
internal_value=-0.000213824 -0.00700969 -0.00909187 -0.0230288 -0.00318742 -0.000206347 0.028343 -0.00365656 0.0289287 0.03768 0.0210777 -0.00242612 0.00888028 -0.0403607 -0.0162196 -0.0476725 0.0488255 0.0599954
|
||||||
|
internal_weight=245.313 198.925 185.196 55.1112 130.085 120.476 12.9898 107.486 46.3882 32.2923 13.729 25.1797 14.0959 29.9315 15.4391 23.4141 24.2366 14.8579
|
||||||
|
internal_count=1013 820 764 231 533 493 53 440 193 135 56 105 58 126 65 99 102 63
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=14
|
||||||
|
num_leaves=22
|
||||||
|
num_cat=0
|
||||||
|
split_feature=77 77 46 75 82 55 32 17 38 46 57 30 61 33 98 65 51 27 98 47 61
|
||||||
|
split_gain=28.1527 7.12874 8.477 7.73926 6.50746 5.98775 7.72785 8.6859 7.74875 5.93269 5.06747 5.06776 4.95308 4.91574 6.80815 7.34665 4.31144 3.2933 2.95919 4.65978 2.76263
|
||||||
|
threshold=1.3550000000000002 2.7750000000000004 0.31724837366825204 0.36503968253968255 1.6250000000000002 25.387500000000003 23.162500000000005 5.4375000000000009 4.5357142857142865 0.38268646215659091 43.267857142857146 1.616071428571429 12.937500000000002 0.48750000000000077 -7.4374999999999991 0.33749469440953833 -0.013613105968960247 -1.0000000180025095e-35 -3.8124999999999996 0.35584581233114326 12.866071428571431
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=13 2 17 9 -5 6 7 -4 -8 18 11 -7 -6 14 -1 -16 -17 -2 19 -3 -15
|
||||||
|
right_child=1 3 5 4 12 10 8 -9 -10 -11 -12 -13 -14 20 15 16 -18 -19 -20 -21 -22
|
||||||
|
leaf_value=0.049192658968065413 -0.0067623296175654806 -0.0059097661371454915 -0.0050944451331990034 -0.03421558742429949 0.036155385236969206 0.014169839641633519 -0.043477105235728328 0.028316035394997729 0.0010581675575233177 0.003886886786396461 -0.0086753300433371153 0.054580295048802033 -0.0096808854134481682 0.065934772628735538 -0.023746444878321241 0.051631222052607971 0.0076433857618228972 -0.040918404046466461 -0.058216504004969173 -0.052238605686860437 0.030637453650431135
|
||||||
|
leaf_weight=8.7887725979089755 7.5061362385749844 6.7677073627710378 50.746787026524544 6.7268268465995815 7.4960924834012967 19.041952610015873 13.521969988942148 16.497406467795372 11.624812230467795 5.6693915277719489 10.139670595526693 6.716789945960044 7.5927126258611679 6.7980895787477476 7.8056097179651287 5.6656755805015573 9.6161311566829646 11.340498879551886 10.0033008903265 7.136577308177948 7.4203208535909653
|
||||||
|
leaf_count=37 31 29 208 29 31 77 55 67 47 24 41 27 32 29 32 24 40 47 44 31 31
|
||||||
|
internal_value=-0.000206417 -0.00674501 -0.00226535 -0.0195702 -0.00149628 0.00141462 -0.00397204 0.00310234 -0.0228894 -0.0329013 0.0152781 0.0247072 0.0130905 0.0279552 0.0192311 0.00782548 0.0239517 -0.0273149 -0.0416252 -0.0296887 0.0475138
|
||||||
|
internal_weight=244.623 198.529 147.136 51.3926 21.8156 128.289 92.391 67.2442 25.1468 29.577 35.8984 25.7587 15.0888 46.0946 31.8762 23.0874 15.2818 18.8466 23.9076 13.9043 14.2184
|
||||||
|
internal_count=1013 820 600 220 92 522 377 275 102 128 145 104 63 193 133 96 64 78 104 60 60
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=15
|
||||||
|
num_leaves=23
|
||||||
|
num_cat=0
|
||||||
|
split_feature=77 78 26 31 57 17 43 18 88 36 86 43 43 83 26 73 29 74 16 55 49 68
|
||||||
|
split_gain=30.6549 12.7043 7.98721 10.8099 12.9808 8.83958 9.66696 7.6233 8.30341 7.00237 7.84435 6.65312 6.67534 5.83636 5.52421 4.95185 4.66908 4.3802 2.29615 1.92109 0.661162 0.1601
|
||||||
|
threshold=1.9950000000000003 0.33644919786096261 21.770833333333339 20.133928571428573 35.187500000000007 -5.0624999999999991 0.53857630126707601 1.8541666666666716 0.53866359200690284 0.82291666666666663 1.8550000000000002 0.45900318339543572 0.4818732325807798 0.47597575932472408 12.94791666666667 0.53851851851851873 32.38750000000001 0.45972972972972981 3.4375000000000004 22.133928571428573 0.73531540336276224 213.70833333333334
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 14 3 13 -5 17 -7 8 11 10 -9 -3 -13 -2 15 -1 -15 -6 -12 -17 -18 -21
|
||||||
|
right_child=2 7 -4 4 5 6 -8 9 -10 -11 18 12 -14 16 -16 19 20 -19 -20 21 -22 -23
|
||||||
|
leaf_value=0.010871073320075295 -0.01172908397497561 -0.046441338207332344 0.019672691938767486 0.046075447983197577 -0.061569404959666424 0.0074003860750678123 -0.03202888807961754 0.0051474644513716042 0.036884377615520249 -0.003400242373786107 0.074863846195407729 0.029393863715199694 -0.0074553467007233889 -0.02523852343490229 -0.00025978536454887422 0.034473210798287857 -0.04795709241166466 -0.021389238996026894 0.039593407313705566 0.06652884725665352 -0.0649082592606154 0.057420779027093437
|
||||||
|
leaf_weight=5.6847298443317476 11.006925001740454 5.903722643852233 9.1704158484935743 6.0783775299787512 7.7922967374324825 29.886689186096191 14.913227543234823 7.632679730653769 8.1395289301872236 10.812797814607618 5.8884793967008573 9.226744741201399 53.322611838579178 10.414219856262209 5.7322616279125205 5.7362669706344631 5.4735058695077923 9.8010887205600721 5.9245722442865372 6.8773611485958082 11.245072126388548 5.6040449738502502
|
||||||
|
leaf_count=24 47 25 38 25 33 123 62 31 33 44 24 38 218 44 24 24 24 42 24 29 48 24
|
||||||
|
internal_value=-0.00100969 0.011833 -0.0161489 -0.0192302 -0.00972405 -0.0151601 -0.00572503 0.00540609 -0.00130932 0.0224046 0.0367534 -0.00585081 -0.00201967 -0.0362963 0.0350059 0.0434633 -0.0462625 -0.0391855 0.0571747 0.0536336 -0.0593586 0.0624394
|
||||||
|
internal_weight=252.268 136.486 115.782 106.611 68.4717 62.3933 44.7999 106.851 76.5926 30.2585 19.4457 68.4531 62.5494 38.1397 29.6347 23.9024 27.1328 17.5934 11.8131 18.2177 16.7186 12.4814
|
||||||
|
internal_count=1048 562 486 448 285 260 185 437 314 123 79 281 256 163 125 101 116 75 48 77 72 53
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=16
|
||||||
|
num_leaves=17
|
||||||
|
num_cat=0
|
||||||
|
split_feature=76 76 33 62 60 32 55 73 17 64 98 25 97 51 64 46
|
||||||
|
split_gain=28.3621 12.2502 8.00023 7.56697 8.78584 8.59503 10.2753 7.68395 7.41413 7.20524 7.00591 5.23347 2.9989 2.73623 2.05561 2.04323
|
||||||
|
threshold=1.4350000000000003 2.4650000000000003 4.2946428571428585 0.47839506172839513 11.437500000000002 16.162500000000005 19.854166666666668 0.53494186046511638 -7.4374999999999991 0.32494646077353467 5.2142857142857162 7.713541666666667 3.7187500000000004 -0.004282105062106599 0.35502948224071251 0.3406679635524858
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=3 2 8 15 12 -6 -7 -8 -2 -10 -11 13 14 -3 -5 -1
|
||||||
|
right_child=1 11 -4 4 5 6 7 -9 9 10 -12 -13 -14 -15 -16 -17
|
||||||
|
leaf_value=-0.029356541192986724 0.037955112610862249 0.059695040893734667 0.043145015879701695 -0.032469843140688813 -0.046002450801952505 0.045093595797352712 -0.042281712918251578 -0.0013799114657325063 0.028081928029134246 -0.010286395434884021 0.025869758711122577 0.011074792109595291 -0.016203413481459306 0.029391271532808353 -0.066050254966225394 -0.059556082391998284
|
||||||
|
leaf_weight=8.2328822761774045 8.3526985198259336 10.85255688428879 8.1492396891117078 6.0218881517648715 7.7615482956171027 6.8014763444662085 8.401523217558859 58.652556464076042 11.53392608463764 68.72949393093586 9.7969980090856534 10.286443859338759 7.4116774648427954 8.5023315101861971 5.6562657654285431 6.3488157242536536
|
||||||
|
leaf_count=36 34 47 33 26 33 28 36 245 47 282 40 43 31 36 24 27
|
||||||
|
internal_value=-0.000973738 0.0113848 0.00505797 -0.0155743 -0.0116748 -0.00596092 -0.00175292 -0.00650469 0.00190411 -0.00143945 -0.00577554 0.03413 -0.0361041 0.046383 -0.0487344 -0.0425053
|
||||||
|
internal_weight=251.492 136.204 106.562 115.289 100.707 81.6171 73.8556 67.0541 98.4131 90.0604 78.5265 29.6413 19.0898 19.3549 11.6782 14.5817
|
||||||
|
internal_count=1048 562 436 486 423 342 309 281 403 369 322 126 81 83 50 63
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=17
|
||||||
|
num_leaves=22
|
||||||
|
num_cat=0
|
||||||
|
split_feature=76 76 33 26 31 57 43 97 60 18 96 88 18 83 26 39 73 7 55 45 68
|
||||||
|
split_gain=26.2331 11.4465 7.36965 7.34122 10.0074 11.7565 7.00539 6.9993 6.88815 10.1637 8.77606 8.04063 5.85928 5.44514 5.13063 4.51191 4.39613 4.1986 1.8532 1.64881 0.156111
|
||||||
|
threshold=1.4350000000000003 2.4650000000000003 4.2946428571428585 21.770833333333339 20.133928571428573 35.187500000000007 0.53857630126707601 4.7812500000000009 12.937500000000002 7.8125000000000009 227.02083333333337 0.50795806360821849 -4.2250000000000076 0.47597575932472408 12.94791666666667 -0.14642857142857144 0.53851851851851873 38.750000000000007 22.133928571428573 -0.022501766737042645 213.70833333333334
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=3 2 8 4 13 -6 7 -7 10 12 11 -2 -10 -1 16 -8 -3 -15 -18 -19 -20
|
||||||
|
right_child=1 14 -4 -5 5 6 15 -9 9 -11 -12 -13 -14 17 -16 -17 18 19 20 -21 -22
|
||||||
|
leaf_value=-0.010786926974099898 -0.010875891059966199 0.011190352480577235 0.041404682122757074 0.019321738062697564 0.044141656903284171 0.0050650165981334172 -0.0061370748531028195 -0.031081442136894771 0.0018664483503017856 0.037131975018793693 0.045073208415421694 0.031828378125081415 -0.026128862170482447 -0.019454829109928577 -0.00098318851507109848 -0.04740967911986986 0.032230447411375152 -0.036142993762053356 0.064020839936514432 -0.062063497067667478 0.054909341919742859
|
||||||
|
leaf_weight=10.931022465229033 21.17684800922871 5.8557388037443223 8.1520167738199216 9.167889401316641 6.0991687178611746 30.766112342476845 6.2713132798671749 11.881261780858038 21.166444480419155 7.1458795964717856 10.812558114528654 10.578455105423926 27.506209731101993 7.7223432809114483 5.709469035267829 13.0707770884037 5.6604651659727123 5.5588853806257275 6.7105195671319944 13.371022954583166 5.4539281576871872
|
||||||
|
leaf_count=47 87 25 33 38 25 128 26 50 87 29 44 43 113 33 24 56 24 24 29 59 24
|
||||||
|
internal_value=-0.00093843 0.0109531 0.00485653 -0.0150137 -0.0179926 -0.00884725 -0.0140609 -0.00500514 0.00182825 -0.00741437 0.013948 0.00334993 -0.0139544 -0.034561 0.0330532 -0.0340278 0.0412595 -0.0443116 0.0511376 -0.0544518 0.0599357
|
||||||
|
internal_weight=250.768 135.929 106.538 114.84 105.672 68.0886 61.9895 42.6474 98.3864 55.8185 42.5679 31.7553 48.6727 37.5833 29.3901 19.3421 23.6807 26.6523 17.8249 18.9299 12.1644
|
||||||
|
internal_count=1048 562 436 486 448 285 260 178 403 229 174 130 200 163 126 82 102 116 77 83 53
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=18
|
||||||
|
num_leaves=16
|
||||||
|
num_cat=0
|
||||||
|
split_feature=78 79 27 72 42 35 26 33 9 30 47 48 55 36 10
|
||||||
|
split_gain=24.4334 9.31464 8.11491 7.61266 8.41054 8.43587 6.62119 7.15164 9.45035 5.28003 4.33177 4.03099 3.63878 2.72794 1.40327
|
||||||
|
threshold=0.39285714285714285 0.25425685425685435 -9.1770833333333304 165.36681435533896 -3.4833333333333329 9.133928571428573 2.0104166666666674 0.48750000000000077 -37.987012987012982 -0.56249999999999989 0.37693449058527589 0.029982232931730853 20.062500000000004 0.19374999999999967 112.93750000000001
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=6 11 -3 10 -5 -6 14 8 -8 -10 12 13 -4 -2 -1
|
||||||
|
right_child=1 2 3 4 5 -7 7 -9 9 -11 -12 -13 -14 -15 -16
|
||||||
|
leaf_value=0.063369704073235666 -0.060192057816396222 0.028277022360530538 -0.016384609809915053 0.044115984475752157 -0.002478065592223366 -0.051567336834095104 0.039068426318397236 0.043825566156782063 0.011510346359810335 -0.030717352367799409 0.0045260873425609898 -0.0079952149779249845 -0.050175542136173798 -0.02646344151553905 0.03565855117598455
|
||||||
|
leaf_weight=6.1944728344678861 7.4922285825014132 11.610384106636046 9.429924696683889 5.9105293601751319 126.33686858415604 5.8609887659549704 9.0260636359453184 10.688595429062842 9.03087270259857 9.9656709432601982 5.7869970500469199 8.0647390484809858 11.101787701249121 7.8635760098695755 5.5375995486974716
|
||||||
|
leaf_count=27 34 47 40 24 521 24 39 46 38 41 24 36 48 35 24
|
||||||
|
internal_value=-0.000905355 -0.00719526 -0.00404233 -0.00632444 -0.00256724 -0.00465444 0.0239656 0.0159876 0.00536936 -0.0106425 -0.0260405 -0.0308938 -0.0346558 -0.0429199 0.0502899
|
||||||
|
internal_weight=249.901 199.458 176.037 164.427 138.108 132.198 50.4433 38.7112 28.0226 18.9965 26.3187 23.4205 20.5317 15.3558 11.7321
|
||||||
|
internal_count=1048 833 728 681 569 545 215 164 118 79 112 105 88 69 51
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=19
|
||||||
|
num_leaves=18
|
||||||
|
num_cat=0
|
||||||
|
split_feature=76 76 62 60 60 32 55 33 17 64 86 25 97 63 12 64 81
|
||||||
|
split_gain=23.1068 9.98848 7.01309 7.92354 7.95102 8.25678 10.3579 6.71651 6.62639 6.59888 6.66891 4.82438 2.76159 2.56144 2.27179 1.91893 0.744688
|
||||||
|
threshold=1.4350000000000003 2.4650000000000003 0.47839506172839513 11.437500000000002 15.225000000000001 16.162500000000005 19.854166666666668 4.2946428571428585 -7.4374999999999991 0.32494646077353467 2.1850000000000005 7.713541666666667 3.7187500000000004 0.4972961247664654 -0.52499999999999847 0.35502948224071251 1.675
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=2 7 14 12 5 -5 -7 8 -2 -10 -11 13 15 -3 -1 -4 -15
|
||||||
|
right_child=1 11 3 4 -6 6 -8 -9 9 10 -12 -13 -14 16 -16 -17 -18
|
||||||
|
leaf_value=-0.020188921856989679 0.035859126989343022 0.020130209700355124 -0.030330032249617687 -0.042500863549311367 -0.05090993952028721 0.051411801287769635 -0.0022541904826031737 0.03956776202840788 0.026837614548232368 -0.0020673320148814839 -0.04439110542553347 0.008982843264200761 -0.014705883428948159 0.04205717024579949 -0.053006940553933922 -0.063196273867381317 0.061135640318500738
|
||||||
|
leaf_weight=5.4853323251008979 8.3379970937967283 5.4507957398891511 5.8967574089765566 7.1303204596042624 5.6088133603334418 6.3442998528480521 61.878040820360184 8.1366265416145307 11.526250436902044 71.76362943649292 6.4958909302949897 10.161600232124327 7.33974365890026 5.8689189553260785 8.7720085084438306 5.4874216467142105 7.4020354598760605
|
||||||
|
leaf_count=24 34 24 26 31 24 26 261 33 47 295 27 43 31 26 39 24 33
|
||||||
|
internal_value=-0.000872267 0.0103144 -0.0141404 -0.0103874 -0.00496412 -0.00154418 0.00273645 0.00464481 0.00174893 -0.00141873 -0.00558039 0.0311724 -0.0338375 0.0432163 -0.0403806 -0.0461723 0.0526984
|
||||||
|
internal_weight=249.086 135.144 113.943 99.6854 80.9615 75.3527 68.2223 106.26 98.1238 89.7858 78.2595 28.8834 18.7239 18.7218 14.2573 11.3842 13.271
|
||||||
|
internal_count=1048 562 486 423 342 318 287 436 403 369 322 126 81 83 63 50 59
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=20
|
||||||
|
num_leaves=21
|
||||||
|
num_cat=0
|
||||||
|
split_feature=77 85 42 26 33 48 29 51 51 88 47 49 9 43 18 45 13 97 90 77
|
||||||
|
split_gain=21.5323 9.97521 10.2057 13.3659 8.32088 7.657 7.45302 7.27519 7.64625 7.10753 6.89749 6.08818 4.68215 4.36106 4.27259 4.17883 3.76513 3.4333 0.930107 0.105107
|
||||||
|
threshold=1.3050000000000004 -5.9999999999999991 1.0000000180025095e-35 9.0104166666666696 4.4375000000000009 0.059692514253813854 39.812500000000007 0.045203152003977003 0.023949864400422651 0.52433570113128136 0.36314281963351264 0.78248216953695626 -13.09523809523809 0.51328944240770225 -16.645833333333325 -0.0072528547698737485 85.062500000000014 1.0937500000000002 0.19841107122821819 3.1550000000000007
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=12 2 6 9 5 7 16 8 -3 15 -9 17 14 -14 -1 -4 -2 -8 -16 -18
|
||||||
|
right_child=1 4 3 -5 -6 -7 11 10 -10 -11 -12 -13 13 -15 18 -17 19 -19 -20 -21
|
||||||
|
leaf_value=0.013957264641046819 -0.027472132914840498 -0.0020934000360734932 0.022613724189803789 0.050832305755293579 0.037916740044630914 0.040588735510979898 0.027960766295875104 -0.003405364332683979 -0.031143520168862283 -0.05384418391600191 0.040275812485981034 -0.044330514984326927 0.030259337595429918 -0.015671661984799638 0.062645279427693656 -0.020045453140862098 -0.066399946636320761 -0.01585144878027565 0.043445571662247148 -0.058570658366565144
|
||||||
|
leaf_weight=7.1345093548297873 8.8107999712228793 87.334490463137627 6.9631915688514745 6.7626315653324118 9.8303922265768033 6.9817947149276725 5.6945501416921633 11.879387885332109 17.382111921906471 5.3163712173700324 11.272227853536604 5.8104494661092749 7.708228871226309 5.7933596074581146 6.5536312311887803 7.778242379426958 5.6191599071025831 5.7529874593019485 10.513165161013601 5.361001193523407
|
||||||
|
leaf_count=31 39 362 29 28 40 29 24 49 72 24 46 25 33 25 29 33 24 25 47 25
|
||||||
|
internal_value=0.00160475 -0.00342443 -0.0165911 0.00220167 0.002388 -0.000201998 -0.0301955 -0.00242923 -0.00691549 -0.0141945 0.0178624 -0.0109833 0.0294231 0.0105509 0.0399517 0.000104827 -0.0469487 0.00594283 0.0508182 -0.0625773
|
||||||
|
internal_weight=246.253 208.55 63.8694 26.8204 144.68 134.85 37.0489 127.868 104.717 20.0578 23.1516 17.258 37.7029 13.5016 24.2013 14.7414 19.791 11.4475 17.0668 10.9802
|
||||||
|
internal_count=1039 874 276 114 598 558 162 529 434 86 95 74 165 58 107 62 88 49 76 49
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=21
|
||||||
|
num_leaves=21
|
||||||
|
num_cat=0
|
||||||
|
split_feature=77 85 42 26 25 51 29 88 90 36 49 14 9 18 61 43 13 59 90 77
|
||||||
|
split_gain=20.02 9.2622 9.52085 12.2814 7.88967 7.82256 7.04841 6.6998 6.53054 7.87452 5.68149 5.30824 4.42523 4.07084 4.07033 4.04241 3.62375 3.25279 0.898801 0.0879165
|
||||||
|
threshold=1.3050000000000004 -5.9999999999999991 1.0000000180025095e-35 9.0104166666666696 1.8541666666666667 0.080538861184771923 39.812500000000007 0.52433570113128136 0.19969875129044842 -1.0875000000000001 0.78248216953695626 118.93750000000001 -13.09523809523809 -16.645833333333325 13.816666666666668 0.51328944240770225 85.062500000000014 23.535714285714288 0.19841107122821819 3.1550000000000007
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=12 2 6 7 -3 8 16 14 11 -10 17 -6 13 -1 -4 -14 -2 -8 -15 -18
|
||||||
|
right_child=1 4 3 -5 5 -7 10 -9 9 -11 -12 -13 15 18 -16 -17 19 -19 -20 -21
|
||||||
|
leaf_value=0.013447805314569216 -0.026577780088672762 0.034080468035460186 0.017293051569916593 0.048557724592127684 0.007825469574374657 0.040280280315047955 -0.016199932862450934 -0.052623204127446775 -0.047796064224015833 -0.0064826859346349495 -0.043040720837339654 -0.024990244369414837 0.029249467101270982 0.061303641269563863 -0.025610761209309305 -0.014994478156697251 -0.064751343135519002 0.026458734247185672 0.042272167151271647 -0.057522795432648433
|
||||||
|
leaf_weight=7.10912762582302 8.7443605959415454 11.499579980969427 8.8282703608274513 6.7955194860696784 70.869819477200508 7.13891777396202 5.5701393187046069 5.2240076065063468 9.2205274105072004 37.017053097486496 5.7464897632598868 8.8745380789041501 7.6564510315656644 6.4316389113664689 5.9041270762681952 5.8124003708362579 5.5334616154432279 5.8780088722705841 10.375598087906836 5.2427052408456802
|
||||||
|
leaf_count=31 39 47 37 28 292 29 24 24 39 154 25 37 33 29 25 25 24 25 47 25
|
||||||
|
internal_value=0.00154432 -0.00329759 -0.0160366 0.0021131 0.00229294 -0.000453006 -0.029261 -0.0137021 -0.00276121 -0.0147212 -0.0105873 0.0041735 0.0284946 0.0388221 9.90026e-05 0.0101563 -0.0457098 0.005703 0.049555 -0.0612346
|
||||||
|
internal_weight=245.473 208.088 63.4671 26.7519 144.62 133.121 36.7152 19.9564 125.982 46.2376 17.1946 79.7444 37.3852 23.9164 14.7324 13.4689 19.5205 11.4481 16.8072 10.7762
|
||||||
|
internal_count=1039 874 276 114 598 551 162 86 522 193 74 329 165 107 62 58 88 49 76 49
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=22
|
||||||
|
num_leaves=18
|
||||||
|
num_cat=0
|
||||||
|
split_feature=77 78 25 48 51 25 9 35 9 48 27 30 9 18 43 50 72
|
||||||
|
split_gain=18.621 8.70394 7.91958 7.02031 6.21305 7.48529 6.53645 5.17821 7.11278 5.11576 6.50119 6.92842 4.18572 3.88527 3.74781 0.796232 0.173612
|
||||||
|
threshold=1.3050000000000004 0.69515163347650677 1.7395833333333337 0.059692514253813854 0.043626967279394004 7.8802083333333348 8.333333333333341 6.6937500000000005 8.7121212121212164 -0.018202373884811395 0.98958333333333315 0.22500000000000142 -13.09523809523809 -16.645833333333325 0.51328944240770225 0.74854124348714812 225.04250000000002
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=12 2 -2 4 6 -6 -4 8 -3 -9 11 -11 13 -1 -14 -15 -17
|
||||||
|
right_child=1 7 3 -5 5 -7 -8 9 -10 10 -12 -13 14 15 -16 16 -18
|
||||||
|
leaf_value=0.012956313378187341 0.036677286509223014 0.027307971594871701 -0.0022506819015889979 0.032532340700343249 0.001223625287223337 0.048438323769350811 -0.026039625377917281 -0.053747110254001744 -0.024750955618137494 -0.0073465850093818175 0.015119548741830309 -0.055928592960106001 0.028278098346949592 0.036190897477542942 -0.014350124084243559 0.059344625765782907 0.049204905261110286
|
||||||
|
leaf_weight=7.0841730237007132 9.6115598380565626 8.2046131193637866 86.82922887802124 9.458725377917288 19.787809953093532 7.3747483491897574 23.477235645055771 8.3150889277458173 8.6016630232334119 10.108060508966451 7.039140820503234 8.7735196799039823 7.6037576496601087 5.6597618609666887 5.8300840854644775 5.8845966756343824 4.9951938986778259
|
||||||
|
leaf_count=31 39 35 359 39 81 30 97 39 39 45 31 40 33 25 25 27 24
|
||||||
|
internal_value=0.00148631 -0.00317645 0.00150065 -0.0008005 -0.00309401 0.0140426 -0.00731384 -0.0175205 0.000663559 -0.026447 -0.0176894 -0.0299207 0.0276052 0.0377427 0.00977809 0.0483592 0.0546892
|
||||||
|
internal_weight=244.639 207.581 156.539 146.928 137.469 27.1626 110.306 51.0421 16.8063 34.2358 25.9207 18.8816 37.0576 23.6237 13.4338 16.5396 10.8798
|
||||||
|
internal_count=1039 874 645 606 567 111 456 229 74 155 116 85 165 107 58 76 51
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
end of trees
|
||||||
|
|
||||||
|
feature_importances:
|
||||||
|
Column_77=25
|
||||||
|
Column_46=15
|
||||||
|
Column_76=15
|
||||||
|
Column_97=14
|
||||||
|
Column_43=13
|
||||||
|
Column_50=13
|
||||||
|
Column_49=12
|
||||||
|
Column_27=11
|
||||||
|
Column_78=11
|
||||||
|
Column_9=10
|
||||||
|
Column_26=10
|
||||||
|
Column_51=10
|
||||||
|
Column_55=10
|
||||||
|
Column_61=10
|
||||||
|
Column_17=9
|
||||||
|
Column_18=8
|
||||||
|
Column_25=8
|
||||||
|
Column_36=8
|
||||||
|
Column_42=8
|
||||||
|
Column_52=8
|
||||||
|
Column_74=8
|
||||||
|
Column_75=8
|
||||||
|
Column_81=8
|
||||||
|
Column_33=7
|
||||||
|
Column_40=7
|
||||||
|
Column_48=7
|
||||||
|
Column_73=7
|
||||||
|
Column_86=7
|
||||||
|
Column_10=6
|
||||||
|
Column_31=6
|
||||||
|
Column_32=6
|
||||||
|
Column_44=6
|
||||||
|
Column_57=6
|
||||||
|
Column_88=6
|
||||||
|
Column_13=5
|
||||||
|
Column_29=5
|
||||||
|
Column_35=5
|
||||||
|
Column_60=5
|
||||||
|
Column_64=5
|
||||||
|
Column_85=5
|
||||||
|
Column_90=5
|
||||||
|
Column_15=4
|
||||||
|
Column_23=4
|
||||||
|
Column_30=4
|
||||||
|
Column_37=4
|
||||||
|
Column_38=4
|
||||||
|
Column_41=4
|
||||||
|
Column_45=4
|
||||||
|
Column_47=4
|
||||||
|
Column_54=4
|
||||||
|
Column_58=4
|
||||||
|
Column_59=4
|
||||||
|
Column_62=4
|
||||||
|
Column_65=4
|
||||||
|
Column_83=4
|
||||||
|
Column_95=4
|
||||||
|
Column_98=4
|
||||||
|
Column_8=3
|
||||||
|
Column_12=3
|
||||||
|
Column_63=3
|
||||||
|
Column_72=3
|
||||||
|
Column_82=3
|
||||||
|
Column_7=2
|
||||||
|
Column_11=2
|
||||||
|
Column_14=2
|
||||||
|
Column_16=2
|
||||||
|
Column_56=2
|
||||||
|
Column_68=2
|
||||||
|
Column_21=1
|
||||||
|
Column_22=1
|
||||||
|
Column_28=1
|
||||||
|
Column_34=1
|
||||||
|
Column_39=1
|
||||||
|
Column_53=1
|
||||||
|
Column_69=1
|
||||||
|
Column_79=1
|
||||||
|
Column_89=1
|
||||||
|
Column_96=1
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
[boosting: gbdt]
|
||||||
|
[objective: binary]
|
||||||
|
[metric: binary_logloss]
|
||||||
|
[tree_learner: serial]
|
||||||
|
[device_type: cpu]
|
||||||
|
[data_sample_strategy: bagging]
|
||||||
|
[data: ]
|
||||||
|
[valid: ]
|
||||||
|
[num_iterations: 1200]
|
||||||
|
[learning_rate: 0.04]
|
||||||
|
[num_leaves: 31]
|
||||||
|
[num_threads: 4]
|
||||||
|
[seed: 42]
|
||||||
|
[deterministic: 0]
|
||||||
|
[force_col_wise: 0]
|
||||||
|
[force_row_wise: 0]
|
||||||
|
[histogram_pool_size: -1]
|
||||||
|
[max_depth: 6]
|
||||||
|
[min_data_in_leaf: 24]
|
||||||
|
[min_sum_hessian_in_leaf: 0.001]
|
||||||
|
[bagging_fraction: 0.84]
|
||||||
|
[pos_bagging_fraction: 1]
|
||||||
|
[neg_bagging_fraction: 1]
|
||||||
|
[bagging_freq: 5]
|
||||||
|
[bagging_seed: 400]
|
||||||
|
[bagging_by_query: 0]
|
||||||
|
[feature_fraction: 0.82]
|
||||||
|
[feature_fraction_bynode: 1]
|
||||||
|
[feature_fraction_seed: 30056]
|
||||||
|
[extra_trees: 0]
|
||||||
|
[extra_seed: 12879]
|
||||||
|
[early_stopping_round: 0]
|
||||||
|
[early_stopping_min_delta: 0]
|
||||||
|
[first_metric_only: 0]
|
||||||
|
[max_delta_step: 0]
|
||||||
|
[lambda_l1: 0]
|
||||||
|
[lambda_l2: 0]
|
||||||
|
[linear_lambda: 0]
|
||||||
|
[min_gain_to_split: 0]
|
||||||
|
[drop_rate: 0.1]
|
||||||
|
[max_drop: 50]
|
||||||
|
[skip_drop: 0.5]
|
||||||
|
[xgboost_dart_mode: 0]
|
||||||
|
[uniform_drop: 0]
|
||||||
|
[drop_seed: 17869]
|
||||||
|
[top_rate: 0.2]
|
||||||
|
[other_rate: 0.1]
|
||||||
|
[min_data_per_group: 100]
|
||||||
|
[max_cat_threshold: 32]
|
||||||
|
[cat_l2: 10]
|
||||||
|
[cat_smooth: 10]
|
||||||
|
[max_cat_to_onehot: 4]
|
||||||
|
[top_k: 20]
|
||||||
|
[monotone_constraints: ]
|
||||||
|
[monotone_constraints_method: basic]
|
||||||
|
[monotone_penalty: 0]
|
||||||
|
[feature_contri: ]
|
||||||
|
[forcedsplits_filename: ]
|
||||||
|
[refit_decay_rate: 0.9]
|
||||||
|
[cegb_tradeoff: 1]
|
||||||
|
[cegb_penalty_split: 0]
|
||||||
|
[cegb_penalty_feature_lazy: ]
|
||||||
|
[cegb_penalty_feature_coupled: ]
|
||||||
|
[path_smooth: 0]
|
||||||
|
[interaction_constraints: ]
|
||||||
|
[verbosity: -1]
|
||||||
|
[saved_feature_importance_type: 0]
|
||||||
|
[use_quantized_grad: 0]
|
||||||
|
[num_grad_quant_bins: 4]
|
||||||
|
[quant_train_renew_leaf: 0]
|
||||||
|
[stochastic_rounding: 1]
|
||||||
|
[linear_tree: 0]
|
||||||
|
[max_bin: 255]
|
||||||
|
[max_bin_by_feature: ]
|
||||||
|
[min_data_in_bin: 3]
|
||||||
|
[bin_construct_sample_cnt: 200000]
|
||||||
|
[data_random_seed: 175]
|
||||||
|
[is_enable_sparse: 1]
|
||||||
|
[enable_bundle: 1]
|
||||||
|
[use_missing: 1]
|
||||||
|
[zero_as_missing: 0]
|
||||||
|
[feature_pre_filter: 1]
|
||||||
|
[pre_partition: 0]
|
||||||
|
[two_round: 0]
|
||||||
|
[header: 0]
|
||||||
|
[label_column: ]
|
||||||
|
[weight_column: ]
|
||||||
|
[group_column: ]
|
||||||
|
[ignore_column: ]
|
||||||
|
[categorical_feature: ]
|
||||||
|
[forcedbins_filename: ]
|
||||||
|
[precise_float_parser: 0]
|
||||||
|
[parser_config_file: ]
|
||||||
|
[objective_seed: 16083]
|
||||||
|
[num_class: 1]
|
||||||
|
[is_unbalance: 0]
|
||||||
|
[scale_pos_weight: 1]
|
||||||
|
[sigmoid: 1]
|
||||||
|
[boost_from_average: 1]
|
||||||
|
[reg_sqrt: 0]
|
||||||
|
[alpha: 0.9]
|
||||||
|
[fair_c: 1]
|
||||||
|
[poisson_max_delta_step: 0.7]
|
||||||
|
[tweedie_variance_power: 1.5]
|
||||||
|
[lambdarank_truncation_level: 30]
|
||||||
|
[lambdarank_norm: 1]
|
||||||
|
[label_gain: ]
|
||||||
|
[lambdarank_position_bias_regularization: 0]
|
||||||
|
[eval_at: ]
|
||||||
|
[multi_error_top_k: 1]
|
||||||
|
[auc_mu_weights: ]
|
||||||
|
[num_machines: 1]
|
||||||
|
[local_listen_port: 12400]
|
||||||
|
[time_out: 120]
|
||||||
|
[machine_list_filename: ]
|
||||||
|
[machines: ]
|
||||||
|
[gpu_platform_id: -1]
|
||||||
|
[gpu_device_id: -1]
|
||||||
|
[gpu_use_dp: 0]
|
||||||
|
[num_gpu: 1]
|
||||||
|
|
||||||
|
end of parameters
|
||||||
|
|
||||||
|
pandas_categorical:null
|
||||||
@@ -0,0 +1,790 @@
|
|||||||
|
tree
|
||||||
|
version=v4
|
||||||
|
num_class=1
|
||||||
|
num_tree_per_iteration=1
|
||||||
|
label_index=0
|
||||||
|
max_feature_idx=98
|
||||||
|
objective=binary sigmoid:1
|
||||||
|
feature_names=Column_0 Column_1 Column_2 Column_3 Column_4 Column_5 Column_6 Column_7 Column_8 Column_9 Column_10 Column_11 Column_12 Column_13 Column_14 Column_15 Column_16 Column_17 Column_18 Column_19 Column_20 Column_21 Column_22 Column_23 Column_24 Column_25 Column_26 Column_27 Column_28 Column_29 Column_30 Column_31 Column_32 Column_33 Column_34 Column_35 Column_36 Column_37 Column_38 Column_39 Column_40 Column_41 Column_42 Column_43 Column_44 Column_45 Column_46 Column_47 Column_48 Column_49 Column_50 Column_51 Column_52 Column_53 Column_54 Column_55 Column_56 Column_57 Column_58 Column_59 Column_60 Column_61 Column_62 Column_63 Column_64 Column_65 Column_66 Column_67 Column_68 Column_69 Column_70 Column_71 Column_72 Column_73 Column_74 Column_75 Column_76 Column_77 Column_78 Column_79 Column_80 Column_81 Column_82 Column_83 Column_84 Column_85 Column_86 Column_87 Column_88 Column_89 Column_90 Column_91 Column_92 Column_93 Column_94 Column_95 Column_96 Column_97 Column_98
|
||||||
|
feature_infos=none none none none none none none [0:100] [0:100] [-100:100] [54:128.875] [61:138] [-41.333333333333329:24] [61:130.125] [59:133] [-50:34.916666666666671] [-28.666666666666657:32.5] [-24.5:27] [-35.5:31.833333333333329] [0:1] [0:1] [-1:1] [0:12] [0:12] [-12:10] [0.91666666666666663:186.1875] [0.85416666666666663:185.08333333333337] [-179.02083333333334:184.16666666666663] [20:54] [22:56] [-21:15.833333333333332] [11:34.5] [9:36] [-15:13.333333333333332] [2:13] [3:13] [-8:5.5] [0.875:9] [0:12] [-9:4.875] [7:22] [8:23] [-10:10] [0.41025641025641019:0.67647058823529416] [0.39730639730639727:0.76744186046511631] [-0.3174418604651163:0.22647058823529409] [0.20419254658385089:0.4825000000000001] [0.1875:0.54166666666666663] [-0.22171945701357459:0.17923280423280419] [0.47826086956521741:0.87898457080200498] [0.42857142857142849:0.88636363636363635] [-0.29647435897435898:0.38962801311591622] [11:39.666666666666664] [15.5:40] [10:31.875] [11.5:34] [15:56] [17:57] [12:32.125] [10:38] [8:20] [7:22] [0.40000000000000002:0.69047619047619047] [0.3902439024390244:0.71739130434782605] [0.23753976670201479:0.51851851851851849] [0.1707317073170731:0.54545454545454541] [0:8] [0:1] [120:295] [-38:36] [0:1] [0:1] [140.39130434782609:233.09999999999999] [0:1] [0:1] [0:1] [1.05:4.1100000000000003] [1.05:4.1299999999999999] [0.2034883720930232:0.79729729729729726] [0.20270270270270269:0.79651162790697683] [145.5:257.5] [1.3:7.7599999999999998] [1.4099999999999999:7.5599999999999996] [0.1789976133651551:0.75977653631284914] [0.24022346368715081:0.82100238663484482] [-15.5:12.5] [1.3:2.7200000000000002] [1.1799999999999999:2.7799999999999998] [0.36298076923076922:0.64953271028037374] [0.35046728971962621:0.63701923076923073] [0.1918833727344364:0.21555133935749429] none none none none [132:250.6875] [126.25:256.625] [-63.5:88.6875] [-35.5:27.5]
|
||||||
|
tree_sizes=1917 2132 1711 1718 2135 1820 1814 2034 1817 1826 2446 2567 2567 2150 2344 1601 1499 1400 990 1399 1731 1721 2040 1829 1725 1721 1504 1717 1516 1931
|
||||||
|
|
||||||
|
Tree=0
|
||||||
|
num_leaves=17
|
||||||
|
num_cat=0
|
||||||
|
split_feature=87 40 77 86 73 40 95 12 17 82 74 40 55 71 81 53
|
||||||
|
split_gain=15.1457 13.2046 13.5042 11.2099 13.4357 11.4245 10.2245 9.8615 9.24196 7.11979 6.96376 9.0178 6.02258 5.9784 5.26359 4.73348
|
||||||
|
threshold=1.5850000000000002 11.267857142857144 1.7850000000000004 1.7450000000000003 0.5344873150105709 11.79166666666667 228.96875000000003 0.14583333333333573 -3.8124999999999996 1.905 0.63245614035087727 15.401785714285717 22.645833333333339 0.22500000000000003 1.7350000000000001 23.437500000000004
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=15 8 6 4 -4 -6 10 -8 -2 13 11 -3 -12 -5 -10 -1
|
||||||
|
right_child=1 2 3 9 5 -7 7 -9 14 -11 12 -13 -14 -15 -16 -17
|
||||||
|
leaf_value=-0.097004150398104866 -0.032826856509161513 -0.0043502309061410754 0.01431771893192204 -0.091075161948939082 -0.0036225823237434548 -0.050018228661574106 -0.029276859267249353 -0.092899466087143945 -0.061043546543381851 -0.031637052746051886 -0.012858122023405583 -0.051389190877909906 -0.063112770479224672 -0.058465725478527159 -0.099324189356474121 -0.059651523168360317
|
||||||
|
leaf_weight=10.494576394557955 9.2452220618724805 41.228692978620529 7.2462551295757285 13.49302679300308 9.9948346614837629 56.47081583738327 9.7449637949466723 6.4966425299644461 11.494059860706331 9.9948346614837629 6.4966425299644461 7.7459968626499167 9.2452220618724805 26.986053586006165 11.494059860706328 11.244188994169233
|
||||||
|
leaf_count=42 37 165 29 54 40 226 39 26 46 40 26 31 37 108 46 45
|
||||||
|
internal_value=-0.0457273 -0.0428007 -0.0390611 -0.0473474 -0.0374027 -0.0430414 -0.0263504 -0.0547259 -0.0666008 -0.0618705 -0.0192291 -0.0117901 -0.0423728 -0.0693355 -0.0801839 -0.0776838
|
||||||
|
internal_weight=259.116 237.377 205.144 124.186 73.7119 66.4657 80.9582 16.2416 32.2333 50.4739 64.7166 48.9747 15.7419 40.4791 22.9881 21.7388
|
||||||
|
internal_count=1037 950 821 497 295 266 324 65 129 202 259 196 63 162 92 87
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=1
|
||||||
|
|
||||||
|
|
||||||
|
Tree=1
|
||||||
|
num_leaves=19
|
||||||
|
num_cat=0
|
||||||
|
split_feature=87 40 75 64 30 36 33 63 36 17 39 47 17 64 15 30 11 25
|
||||||
|
split_gain=13.9729 12.1763 14.362 13.4541 10.6931 12.6392 11.2985 10.0326 8.61679 8.52999 8.49866 8.85202 6.83713 6.53966 4.98946 6.17658 4.17697 6.76785
|
||||||
|
threshold=1.5850000000000002 11.267857142857144 0.4095454545454546 0.35791741982096692 -3.850000000000001 -0.13125000000000001 2.8660714285714275 0.50088993919059788 -0.17708333333333343 -3.8124999999999996 0.4702380952380954 0.34444905543815357 -7.8374999999999977 0.33306045819490598 -4.4732142857142838 -2.0744047619047588 90.687500000000014 3.9114583333333335
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=16 9 3 12 5 -4 8 -8 -6 -2 11 -5 -3 -14 -11 -16 -1 -18
|
||||||
|
right_child=1 2 4 10 6 -7 7 -9 -10 14 -12 -13 13 -15 15 -17 17 -19
|
||||||
|
leaf_value=-0.057851344720467247 0.012127031371442692 -0.065070317857066393 -0.046234344564243093 -0.034302041708384759 0.0097538558374562559 0.015919168977055184 -0.044150175296378553 0.012931828545225675 0.032691802732617729 -0.063902755868288641 0.044060792595361865 0.025258066535241798 0.0038131771685337061 -0.035910700877364692 0.0058413187436127693 -0.043222266889543948 -0.041738488387342523 0.012479643131747724
|
||||||
|
leaf_weight=6.4850978553295162 9.2475084811449033 6.2444083094596854 9.9929635822772997 8.2424890547990817 47.478157848119736 10.994390726089476 8.24348331987858 12.243208199739454 58.476858302950859 6.238056123256686 8.4939699023962003 7.743343085050582 11.740369915962221 15.236236929893492 7.2386563420295742 9.484264671802519 8.9887140691280347 6.2415239214897147
|
||||||
|
leaf_count=26 37 25 40 33 190 44 33 49 234 25 34 31 47 61 29 38 36 25
|
||||||
|
internal_value=-0.00025478 0.00255523 0.0061453 -0.0107729 0.0127667 -0.0136747 0.0171556 -0.010037 0.0224134 -0.0203093 0.011728 -0.00545185 -0.0273532 -0.0186226 -0.033373 -0.0219847 -0.0309668 -0.0195193
|
||||||
|
internal_weight=259.054 237.338 205.13 57.7008 147.429 20.9874 126.442 20.4867 105.955 32.2085 24.4798 15.9858 33.221 26.9766 22.961 16.7229 21.7153 15.2302
|
||||||
|
internal_count=1037 950 821 231 590 84 506 82 424 129 98 64 133 108 92 67 87 61
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=2
|
||||||
|
num_leaves=15
|
||||||
|
num_cat=0
|
||||||
|
split_feature=87 79 86 40 80 29 95 46 61 76 27 42 51 53
|
||||||
|
split_gain=12.8995 11.4587 12.6562 11.6114 9.74256 9.00377 8.40775 12.7519 9.12686 9.48882 6.86723 5.78581 4.37714 4.21145
|
||||||
|
threshold=1.5850000000000002 0.47526524006473664 1.425 11.437500000000002 159.00000000000003 40.312500000000007 228.96875000000003 0.35543310268494094 12.225000000000001 2.6550000000000007 -13.968749999999998 -0.61249999999999971 -0.024362426215342146 23.437500000000004
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=13 2 5 -3 -4 -2 8 -8 12 -10 -6 -12 -5 -1
|
||||||
|
right_child=1 3 4 6 10 -7 7 -9 9 -11 11 -13 -14 -15
|
||||||
|
leaf_value=-0.048059265540188849 0.06036588533776735 -0.030072544599413102 0.030990903589822205 0.026560568681132761 -0.051938571878065741 0.0015271190921610995 0.033770613746158619 -0.039908770322941725 0.026584849929801698 -0.017941657017813275 -0.018812929986079977 -0.0011568414139026314 0.070670836690303579 -0.012775033151309585
|
||||||
|
leaf_weight=10.448318898677828 7.7465823441743877 8.4830420017242414 9.4921096563339216 5.9989815205335608 6.2402391731739035 8.9906333237886411 6.7452828139066687 8.4876060187816602 35.739069759845734 9.7458354085683805 52.919037282466888 67.668311461806297 8.9985922873020154 11.229458034038542
|
||||||
|
leaf_count=42 31 34 38 24 25 36 27 34 143 39 212 271 36 45
|
||||||
|
internal_value=-0.000245346 0.00245334 -0.00406662 0.0143054 -0.00809702 0.0287598 0.0192774 -0.00728277 0.0259668 0.0170444 -0.0110225 -0.00890511 0.0530269 -0.0297814
|
||||||
|
internal_weight=258.933 237.255 153.057 84.1984 136.32 16.7372 75.7154 15.2329 60.4825 45.4849 126.828 120.587 14.9976 21.6778
|
||||||
|
internal_count=1037 950 613 337 546 67 303 61 242 182 508 483 60 87
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=3
|
||||||
|
num_leaves=15
|
||||||
|
num_cat=0
|
||||||
|
split_feature=87 79 33 88 72 60 95 12 15 52 14 30 65 53
|
||||||
|
split_gain=11.9137 10.5659 11.7467 12.0731 10.7663 8.68363 8.59661 13.4701 7.47172 9.03668 6.50335 5.61483 4.0183 3.91278
|
||||||
|
threshold=1.5850000000000002 0.47526524006473664 5.4583333333333348 0.57686355548965829 164.17133924969747 13.133928571428573 228.96875000000003 0.14583333333333573 -3.4499999999999953 18.645833333333339 82.937500000000014 -2.0119047619047588 0.34544552124032007 23.437500000000004
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=13 2 3 4 10 -6 8 -8 -3 -10 -2 -11 -5 -1
|
||||||
|
right_child=1 6 -4 12 5 -7 7 -9 9 11 -12 -13 -14 -15
|
||||||
|
leaf_value=-0.046319955261748876 0.037448948902587834 -0.0088284694187992091 -0.057678550882037501 0.059995488602543341 -0.019214067900304579 0.0032492412381891801 0.018976181265562397 -0.053115091799964251 -0.018039785729919627 0.013382514787688078 -0.0088821137810651384 0.041942269689724629 0.013681980687733714 -0.012271034609450827
|
||||||
|
leaf_weight=10.407825455069544 13.739773482084276 11.737559467554091 6.2349889278411856 5.9960742145776731 66.626564428210258 46.927813142538071 9.7444915026426333 7.219090297818183 6.492861956357955 16.732775956392288 7.4898996800184241 32.22684919834137 5.9935915470123291 11.223179444670675
|
||||||
|
leaf_count=42 55 47 25 24 267 188 39 29 26 67 30 129 24 45
|
||||||
|
internal_value=-0.000235931 0.00235599 -0.00390538 -0.00162108 -0.00504269 -0.00993082 0.0137405 -0.0117033 0.0201643 0.0263011 0.0211032 0.0321815 0.0368435 -0.0286538
|
||||||
|
internal_weight=258.793 237.162 153.009 146.774 134.784 113.554 84.1536 16.9636 67.19 55.4525 21.2297 48.9596 11.9897 21.631
|
||||||
|
internal_count=1037 950 613 588 540 455 337 68 269 222 85 196 48 87
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=4
|
||||||
|
num_leaves=19
|
||||||
|
num_cat=0
|
||||||
|
split_feature=87 40 75 64 80 66 15 15 61 64 88 17 95 39 81 63 59 33
|
||||||
|
split_gain=11.0085 10.3158 11.8546 12.6055 10.3939 11.5844 9.67074 10.8155 9.0703 7.92497 7.91682 7.84355 6.80908 5.80185 4.70535 3.79881 3.16026 2.99516
|
||||||
|
threshold=1.5850000000000002 11.267857142857144 0.4095454545454546 0.35791741982096692 165.00000000000003 1.0000000180025095e-35 -9.1071428571428523 -3.725000000000001 12.690476190476192 0.33306045819490598 0.51341535239840341 -3.8124999999999996 225.46875000000003 0.33333333333333331 1.7350000000000001 0.4972961247664654 21.775000000000002 -1.0000000180025095e-35
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=15 11 3 8 5 17 12 -8 -3 -10 -5 -2 -6 -12 -13 -1 -17 -4
|
||||||
|
right_child=1 2 4 10 6 -7 7 -9 9 -11 13 14 -14 -15 -16 16 -18 -19
|
||||||
|
leaf_value=-0.00040554144175779727 0.012283500305906152 -0.058979450937986018 0.078347880748130691 -0.01274589698312884 0.010508267343845815 0.0014292549509687211 -0.030425427623467446 0.0073372268956942068 0.014443127755364691 -0.032407221257139643 0.0078896532861558941 -0.013267174082330087 0.063584791906166116 0.060934134607739728 -0.049547993082610223 -0.054100670196884616 -0.017902921750126199 0.042409147472346274
|
||||||
|
leaf_weight=5.95706579089165 9.2431617081165296 9.4672348201274854 5.9933577626943579 11.224958077073099 7.9917045235633832 10.236197039484976 13.982299685478209 91.852746203541756 9.9857960343360919 13.705725058913229 6.9919697046279889 11.458065599203112 7.4933722615242004 6.2467137277126312 11.419983848929403 8.6485812216997129 6.9683696925640097 9.7404364198446292
|
||||||
|
leaf_count=24 37 38 24 45 32 41 56 368 40 55 28 46 30 25 46 35 28 39
|
||||||
|
internal_value=-0.000227018 0.00226278 0.00556662 -0.00981529 0.0115843 0.0345507 0.00666807 0.00234825 -0.0258849 -0.0126602 0.0119659 -0.0188136 0.0361925 0.0329189 -0.0313774 -0.0275824 -0.037949 0.056099
|
||||||
|
internal_weight=258.608 237.034 204.913 57.6224 147.29 25.97 121.32 105.835 33.1588 23.6915 24.4636 32.1212 15.4851 13.2387 22.878 21.574 15.617 15.7338
|
||||||
|
internal_count=1037 950 821 231 590 104 486 424 133 95 98 129 62 53 92 87 63 63
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=5
|
||||||
|
num_leaves=16
|
||||||
|
num_cat=0
|
||||||
|
split_feature=33 88 55 55 17 54 73 52 77 17 41 97 29 62 40
|
||||||
|
split_gain=15.351 13.8158 14.9232 12.5185 11.4912 11.3671 8.05265 14.2571 9.45676 11.7484 10.6395 4.12203 3.9043 3.69138 2.1447
|
||||||
|
threshold=5.4583333333333348 0.54438855792157115 24.062500000000004 21.387500000000003 -9.4642857142857064 26.312500000000004 0.53494186046511638 25.387500000000003 2.0850000000000004 3.0625000000000004 12.775000000000002 0.7544642857142777 35.562500000000007 0.5081756463571766 12.803571428571431
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 4 3 -3 11 13 7 12 9 -8 -10 -1 -6 -4 -5
|
||||||
|
right_child=-2 2 5 14 6 -7 8 -9 10 -11 -12 -13 -14 -15 -16
|
||||||
|
leaf_value=-0.019289747362067435 -0.049291431039616411 0.0079530049109373772 -0.0023167773542189392 0.049152011733235204 0.016609632632338327 0.040013888589411864 0.013951234712260528 -0.0188765863308245 -0.039607282005252709 -0.012366184034748687 -0.0024271531554327401 -0.063622619627354979 0.056973143291589742 -0.043118301029727156 0.079727872448937878
|
||||||
|
leaf_weight=6.9703347086906415 10.684137105941771 11.479128912091257 6.2386636584997204 7.7240137755870801 6.2296538949012819 5.9881500154733649 54.543849483132362 10.221605300903319 23.669574245810509 54.01922245323658 25.669763669371605 6.4709125310182571 9.9719207286834699 8.2252761721611005 6.9943185448646545
|
||||||
|
leaf_count=28 43 46 25 31 25 24 219 41 95 217 103 26 40 33 28
|
||||||
|
internal_value=-0.00235947 -0.000307937 0.0192731 0.0392628 -0.00492675 -0.00633208 -0.00232303 0.018115 -0.0057431 0.000856114 -0.0202636 -0.0406326 0.041453 -0.0255196 0.063682
|
||||||
|
internal_weight=255.101 244.416 46.6496 26.1975 197.767 20.4521 184.326 26.4232 157.902 108.563 49.3393 13.4412 16.2016 14.4639 14.7183
|
||||||
|
internal_count=1024 981 187 105 794 82 740 106 634 436 198 54 65 58 59
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=6
|
||||||
|
num_leaves=16
|
||||||
|
num_cat=0
|
||||||
|
split_feature=60 62 73 75 86 9 86 68 9 75 55 17 12 53 82
|
||||||
|
split_gain=10.7843 10.6542 9.72935 12.6928 12.2359 16.8146 10.0524 12.101 8.66024 8.63902 8.35887 7.20778 6.43585 4.33555 3.6338
|
||||||
|
threshold=15.225000000000001 0.4697988539447821 0.53158244680851074 0.64508064516129038 1.7450000000000003 -8.3333333333333233 1.4450000000000001 207.25000000000003 -37.987012987012982 0.61348484848484863 24.291666666666668 -2.7083333333333353 3.2678571428571463 22.387500000000003 1.8350000000000002
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 11 4 6 -3 -6 7 -4 -5 -8 13 -1 -10 -2 -13
|
||||||
|
right_child=10 2 3 8 5 -7 9 -9 12 -11 -12 14 -14 -15 -16
|
||||||
|
leaf_value=-0.014255420135607853 0.023310237479360944 0.060688099681206698 0.047635605094340575 -0.022508370276938035 0.03702793647430791 -0.038866757036159119 -0.017236539926759407 -0.026749878847924364 0.026448512176737455 -0.054467609884275854 -0.007621975235864803 0.052597905023238606 -0.014975239364821315 0.067546521320461253 0.012566451021375784
|
||||||
|
leaf_weight=6.2201643437147167 8.2134438902139681 6.9778638184070614 7.975793316960333 11.688230097293852 9.2276621013879812 9.4580885171890223 113.23386019468307 6.2343348562717438 27.121811106801033 10.934748843312262 8.4812200069427472 9.2266680598258954 7.7061219811439505 6.2366772443056098 5.9792356044054022
|
||||||
|
leaf_count=25 33 28 32 47 37 38 455 25 109 44 34 37 31 25 24
|
||||||
|
internal_value=-0.00226718 -0.00485385 -0.00758834 -0.0107917 0.0154908 -0.00138736 -0.0168681 0.0150009 0.00728451 -0.0205152 0.0239009 0.0220185 0.017283 0.0424026 0.0368568
|
||||||
|
internal_weight=254.916 231.985 210.559 184.895 25.6636 18.6858 138.379 14.2101 46.5162 124.169 22.9313 21.4261 34.8279 14.4501 15.2059
|
||||||
|
internal_count=1024 932 846 743 103 75 556 57 187 499 92 86 140 58 61
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=7
|
||||||
|
num_leaves=18
|
||||||
|
num_cat=0
|
||||||
|
split_feature=89 55 54 8 43 96 98 40 90 55 37 97 49 80 65 97 62
|
||||||
|
split_gain=10.4246 11.2262 10.7967 9.95568 11.3883 8.90539 8.65133 12.0582 11.6055 8.30861 8.22307 8.46564 6.54104 5.03193 4.78896 4.43026 4.16993
|
||||||
|
threshold=0.45561144207842896 24.062500000000004 26.387500000000003 31.666666666666668 0.45725155221122971 175.77083333333337 -6.2083333333333348 11.162500000000001 0.19645540169586981 21.387500000000003 2.3541666666666674 1.7812500000000002 0.71927164205124738 212.00000000000003 0.35922103320833165 1.0312500000000002 0.50486813817504161
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 9 16 5 -5 -2 10 14 -9 -1 11 -6 -12 -7 -8 -11 -3
|
||||||
|
right_child=3 2 -4 4 6 13 7 8 -10 15 12 -13 -14 -15 -16 -17 -18
|
||||||
|
leaf_value=0.0056796349867628713 0.0048498008748587788 0.0010948092386472363 0.038285447553195809 0.03821577456306921 0.045277568585778402 -0.075491676385977521 -0.0073319216517205438 -0.028247542141635638 0.013897886134041438 0.075581548081493269 -0.059494968657228614 -0.018282852479456907 -0.017519335700108753 -0.030147268708022427 -0.056245855074949898 0.032607041143986076 -0.041584861624048911
|
||||||
|
leaf_weight=11.720010221004488 8.2118753790855425 5.9827445000410107 5.9779978692531577 10.210737749934195 6.474472910165785 5.959468916058543 5.9542931914329511 12.197263866662977 73.146875634789467 6.4630497843027106 6.7146378159523001 6.953786626458168 51.473725467920303 11.417679086327551 6.9297584295272827 9.4506065398454648 9.4453652203083021
|
||||||
|
leaf_count=47 33 24 24 41 26 24 24 49 294 26 27 28 207 46 28 38 38
|
||||||
|
internal_value=-0.00217862 0.0143933 -0.00735136 -0.00613051 -0.00281263 -0.0294766 -0.00527918 0.00242922 0.00787452 0.0312376 -0.0158519 0.012363 -0.0223631 -0.0456981 -0.0336406 0.0500604 -0.0250345
|
||||||
|
internal_weight=254.684 49.0398 21.4061 205.645 180.056 25.589 169.845 98.2282 85.3441 27.6337 71.6166 13.4283 58.1884 17.3771 12.8841 15.9137 15.4281
|
||||||
|
internal_count=1024 197 86 827 724 103 683 395 343 111 288 54 234 70 52 64 62
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=8
|
||||||
|
num_leaves=16
|
||||||
|
num_cat=0
|
||||||
|
split_feature=33 88 55 55 17 54 27 62 59 60 11 86 27 15 39
|
||||||
|
split_gain=14.0335 11.5183 12.3907 10.6473 9.85957 9.50449 8.91174 9.57804 8.94568 7.22924 4.21001 3.63151 3.58218 2.92798 2.2831
|
||||||
|
threshold=5.4583333333333348 0.54438855792157115 24.062500000000004 21.535714285714288 -9.4642857142857064 26.312500000000004 -7.9791666666666661 0.47163958632520975 19.162500000000005 15.225000000000001 114.68750000000001 1.885 -0.06770833333333344 -1.0000000180025095e-35 -0.11249999999999999
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 4 3 12 11 10 8 13 -6 -9 -4 -1 -3 -8 -5
|
||||||
|
right_child=-2 2 5 14 6 -7 7 9 -10 -11 -12 -13 -14 -15 -16
|
||||||
|
leaf_value=-0.017506959694980919 -0.047093096159148848 -0.013030607518081373 -0.0050211407760301866 0.041861979165786371 -0.0054470000340854632 0.036839736021523913 0.0084047253587021115 -0.0053865642716596834 -0.068322690853454923 0.024130364791092217 -0.048932153004977219 -0.059267051521897846 0.029896871945299459 0.042249585564822965 0.074866216000504499
|
||||||
|
leaf_weight=6.9434050768613798 10.625629082322119 5.9767347723245621 8.4471292942762393 5.9510868340730667 8.7058147490024549 5.9711179584264746 6.7232442200183895 137.19698540866375 6.1981060206890097 14.698398649692534 5.9571634531021109 6.405640184879303 6.4850186705589312 10.441370263695715 7.6831773668527585
|
||||||
|
leaf_count=28 43 24 34 24 35 24 27 552 25 59 24 26 26 42 31
|
||||||
|
internal_value=-0.00209418 -0.000132847 0.017783 0.0360337 -0.0043524 -0.00559187 -0.00194377 0.000670223 -0.0315952 -0.00253031 -0.0231814 -0.0375459 0.00930858 0.0289928 0.0604605
|
||||||
|
internal_weight=254.41 243.784 46.4714 26.096 197.313 20.3754 183.964 169.06 14.9039 151.895 14.4043 13.349 12.4618 17.1646 13.6343
|
||||||
|
internal_count=1024 981 187 105 794 82 740 680 60 611 58 54 50 69 55
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=9
|
||||||
|
num_leaves=16
|
||||||
|
num_cat=0
|
||||||
|
split_feature=33 88 55 55 54 8 43 98 37 50 96 80 11 38 39
|
||||||
|
split_gain=13.0015 10.6389 11.4582 9.90804 8.77538 8.77091 9.15232 8.52658 12.059 8.78208 8.37899 5.06162 3.90198 3.4714 2.1433
|
||||||
|
threshold=5.4583333333333348 0.54438855792157115 24.062500000000004 21.535714285714288 26.312500000000004 31.666666666666668 0.45725155221122971 -6.2083333333333348 3.0625000000000004 0.77107730652069451 175.77083333333337 212.00000000000003 114.68750000000001 3.0625000000000004 -0.11249999999999999
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 5 3 13 12 10 -7 9 -9 -8 -1 -12 -4 -3 -5
|
||||||
|
right_child=-2 2 4 14 -6 6 7 8 -10 -11 11 -13 -14 -15 -16
|
||||||
|
leaf_value=0.0073464817079793203 -0.045435105019414168 -0.011342813791158599 -0.0048216877875364326 0.040315188023492481 0.035433511001246025 0.035818050318993391 -0.0019489232180927723 -0.01869102791191958 0.013448791274373359 -0.030954345333154155 -0.072293858788171919 -0.026294701048497598 -0.047141285128800781 0.030922033964920961 0.072368292940394013
|
||||||
|
leaf_weight=7.9585580676794079 10.573872312903402 6.4793082326650637 8.4447395205497759 5.9326046109199524 5.9599837511777869 10.172822326421736 40.264701783657074 25.803554385900497 67.645555391907692 28.539862290024757 5.9069683849811581 10.872051388025282 5.9365375787019721 5.9781518280506134 7.6314401328563672
|
||||||
|
leaf_count=32 43 26 34 24 24 41 162 104 272 115 24 44 24 24 31
|
||||||
|
internal_value=-0.0020131 -0.00012773 0.0171133 0.0346948 -0.00537778 -0.00418193 -0.000986385 -0.00329391 0.00457421 -0.0139803 -0.0264556 -0.0424885 -0.0222911 0.00893946 0.058349
|
||||||
|
internal_weight=254.101 243.527 46.3628 26.0215 20.3413 197.164 172.426 162.254 93.4491 68.8046 24.7376 16.779 14.3813 12.4575 13.564
|
||||||
|
internal_count=1024 981 187 105 82 794 694 653 376 277 100 68 58 50 55
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=10
|
||||||
|
num_leaves=22
|
||||||
|
num_cat=0
|
||||||
|
split_feature=75 87 95 14 11 36 58 58 8 58 40 54 31 17 32 95 54 90 30 18 46
|
||||||
|
split_gain=10.0606 13.2442 13.2354 7.28198 9.27874 9.24179 8.65882 8.65277 7.77526 9.89423 8.92987 8.43675 7.69243 6.47202 5.91656 6.71204 5.41747 5.66364 4.6817 4.44902 4.42172
|
||||||
|
threshold=0.58007633587786267 1.5850000000000002 229.28125000000003 117.31250000000001 115.18750000000001 0.59375000000000011 24.803571428571434 24.354166666666668 42.261904761904766 17.062500000000004 13.35416666666667 20.062500000000004 24.562500000000004 5.4375000000000009 20.145833333333339 220.46875000000003 20.775000000000002 0.19788825188533934 0.60416666666666796 -4.3541666666666705 0.35905136104149266
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=3 18 13 4 8 7 19 -5 11 -10 -11 -1 -13 16 -15 -16 -3 -18 -2 -6 -4
|
||||||
|
right_child=1 2 20 5 6 -7 -8 -9 9 10 -12 12 -14 14 15 -17 17 -19 -20 -21 -22
|
||||||
|
leaf_value=0.016260010087575247 -0.00081200744809965017 0.009281923181331737 0.0032509448060061706 -0.025493613615531322 -0.074632317496072326 0.049617586690472636 0.0010470202171259946 0.03284274215952835 -0.029153960626547033 0.0012674975757078009 0.038103679086545161 -0.037991918317932111 0.0028048182430481369 0.031585379031769001 -0.038777627179031486 0.020611308349097066 0.013481360235318833 0.054225087511587569 -0.04021991897983087 -0.030101771519433589 -0.04216852229361847
|
||||||
|
leaf_weight=9.4118207991123182 10.595016002655031 9.211836025118826 7.6921787559986097 10.383948802948003 6.9398950040340432 7.9301784783601752 7.663398250937461 6.6885293126106253 11.645323514938353 37.428400799632072 14.651625692844389 25.72077003121376 10.378917679190634 10.19868426024914 6.2205115109682065 5.9642188549041748 7.1979017257690456 22.59254564344883 8.8545045703649503 7.4363927543163308 6.1885804086923599
|
||||||
|
leaf_count=38 43 37 31 42 28 32 31 27 47 151 59 104 42 41 25 24 29 91 36 30 25
|
||||||
|
internal_value=0.000384931 0.0106717 0.0182752 -0.00584956 -0.00961775 0.0139354 -0.0332929 -0.00263903 -0.00484104 0.00417752 0.0116306 -0.0174689 -0.0262626 0.0262515 0.00910688 -0.00970775 0.0360908 0.0443807 -0.0187527 -0.0515981 -0.0169988
|
||||||
|
internal_weight=250.995 94.716 75.2665 156.279 131.277 25.0027 22.0397 17.0725 109.237 63.7254 52.08 45.5115 36.0997 61.3857 22.3834 12.1847 39.0023 29.7904 19.4495 14.3763 13.8808
|
||||||
|
internal_count=1013 382 303 631 530 101 89 69 441 257 210 184 146 247 90 49 157 120 79 58 56
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=11
|
||||||
|
num_leaves=23
|
||||||
|
num_cat=0
|
||||||
|
split_feature=46 34 52 26 15 25 38 25 38 45 51 29 31 85 45 97 77 48 50 89 35 15
|
||||||
|
split_gain=8.75369 11.3656 14.889 8.46246 7.41306 7.3335 8.41222 8.91166 7.82615 7.37315 7.16896 7.00775 6.83601 6.4889 6.43695 6.32157 6.2568 5.61316 5.35895 4.7914 4.5558 2.75508
|
||||||
|
threshold=0.38135121729750621 6.8875000000000011 22.775000000000002 7.1406250000000009 -7.5624999999999991 2.0520833333333335 2.6904761904761911 13.989583333333334 3.0625000000000004 0.026346315240645454 0.014637337657707453 41.401785714285722 17.354166666666668 -2.9999999999999996 -0.03868421822005879 -3.0312499999999996 1.7550000000000001 0.050581642342345606 0.78802449932964647 0.44915558749550849 7.4226190476190483 3.7857142857142851
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 5 3 15 20 16 9 8 -8 12 11 18 -7 -5 -6 -3 -1 -12 -2 -16 -4 -17
|
||||||
|
right_child=10 2 4 13 14 6 7 -9 -10 -11 17 -13 -14 -15 19 21 -18 -19 -20 -21 -22 -23
|
||||||
|
leaf_value=-0.0054894704946171517 0.0015186659314490275 0.012422457986275524 0.045080183146636456 -0.016969101137900868 -0.040094377162748857 0.019099728305053802 0.028826737553279212 0.048811854341376415 -0.010159784240800534 -0.052368685379215477 -0.057749287922771578 0.032139891068220787 -0.025625732807283655 0.02903959599951628 0.028393278510576315 0.063703565821716004 -0.055469403457085856 -0.0080914581224991559 -0.047345864671010984 -0.006544736689285552 0.00014063060048828728 0.032655129091640721
|
||||||
|
leaf_weight=7.6778917312622097 9.1392136514186877 8.1994599252939242 8.1893729716539365 8.9037519246339816 7.9227678179740897 9.4139631241560036 11.599057033658026 7.4388175308704367 28.433443784713745 7.6398711800575247 9.4042548984289152 6.4537621885538092 13.044003814458845 10.920071274042128 7.412743777036666 14.361867994070055 8.3833764642477018 5.9441701322793952 5.9151509106159201 41.112754985690117 6.4537106007337561 6.7087357491254798
|
||||||
|
leaf_count=31 37 33 33 36 32 38 47 30 115 31 38 26 53 44 30 58 34 24 24 166 26 27
|
||||||
|
internal_value=0.000369477 0.00347289 0.0116128 0.0285547 -8.68246e-05 -0.0069756 -0.00188168 0.00860705 0.00113621 -0.0184248 -0.0176344 -0.00273177 -0.00687765 0.00837506 -0.00666555 0.0422218 -0.0315771 -0.0385177 -0.0176812 -0.00120761 0.0252738 0.053818
|
||||||
|
internal_weight=250.672 213.816 120.185 49.0939 71.0914 93.6304 77.5692 47.4713 40.0325 30.0978 36.8566 21.5081 22.458 19.8238 56.4483 29.2701 16.0613 15.3484 15.0544 48.5255 14.6431 21.0706
|
||||||
|
internal_count=1013 864 485 198 287 379 314 192 162 122 149 87 91 80 228 118 65 62 61 196 59 85
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=12
|
||||||
|
num_leaves=23
|
||||||
|
num_cat=0
|
||||||
|
split_feature=75 60 11 14 27 80 97 64 82 74 61 28 51 77 17 18 26 73 77 29 17 40
|
||||||
|
split_gain=9.16434 11.0589 9.72885 16.5355 11.7419 10.0895 9.63264 9.40553 6.81505 6.89416 6.69885 7.87536 6.2381 5.78129 6.43908 7.23032 5.6961 5.53399 5.51269 7.0191 3.79526 2.70316
|
||||||
|
threshold=0.40070422535211275 12.937500000000002 115.68750000000001 116.31250000000001 -0.9583333333333337 166.00000000000003 7.8229166666666581 0.35791741982096692 2.3750000000000004 0.68460526315789483 11.312500000000002 43.669642857142868 -0.00055870543754424991 2.4850000000000008 2.6875000000000004 11.267857142857148 3.0104166666666674 0.54977477477477488 3.5300000000000007 41.937500000000007 -3.0624999999999996 13.062500000000002
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=7 8 4 17 5 -3 16 13 9 10 -2 -12 -7 -1 15 21 -6 -4 19 20 -9 -15
|
||||||
|
right_child=1 2 3 -5 6 12 -8 18 -10 -11 11 -13 -14 14 -16 -17 -18 -19 -20 -21 -22 -23
|
||||||
|
leaf_value=-0.054673857447064877 0.031426635667739504 0.027443307507820841 -0.0071693293359852243 0.038925915934784942 0.050420363552369514 -0.055974948859624327 -0.015254363709585871 -0.00096046171680576385 -0.04185499138480625 -0.033145360136453486 -0.0080473225873038019 0.03965940078614745 0.00028714853340948784 -0.057615503467417908 0.017966063373814029 0.0078546298795259799 0.022851321189234875 -0.052721746825391283 0.037758480535269187 0.02828748068011893 -0.046251148347414762 -0.023260226786483273
|
||||||
|
leaf_weight=8.6124199628829938 10.635522291064261 9.4400324672460574 8.4194629490375572 8.1747892647981626 24.48761148750782 6.1720191240310669 6.4190221130847922 5.9309897720813787 7.6241378188133231 10.108165323734282 52.924647763371468 6.1832769215106955 6.4464221149682981 8.5726141929626518 6.4193207621574393 6.403973162174224 23.496750026941299 8.652211129665373 6.4387345761060706 6.4527361392974845 5.9104709476232546 6.4002304375171652
|
||||||
|
leaf_count=35 43 38 34 33 99 25 26 24 31 41 214 25 26 35 26 26 95 35 26 26 24 26
|
||||||
|
internal_value=0.000354686 0.00470563 0.0136746 -0.00785498 0.0207833 -0.00383352 0.0307644 -0.013108 -0.00572256 -0.00227267 0.00220181 -0.00305672 -0.0272322 -0.0260387 -0.0171663 -0.0277163 0.0369205 -0.0302561 0.00592675 -0.00527659 -0.0235666 -0.0429301
|
||||||
|
internal_weight=250.326 189.184 101.708 25.2465 76.4619 22.0585 54.4034 61.1415 87.4758 79.8516 69.7434 59.1079 12.6184 36.4086 27.7961 21.3768 47.9844 17.0717 24.7329 18.2942 11.8415 14.9728
|
||||||
|
internal_count=1013 765 411 102 309 89 220 248 354 323 282 239 51 148 113 87 194 69 100 74 48 61
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=13
|
||||||
|
num_leaves=19
|
||||||
|
num_cat=0
|
||||||
|
split_feature=75 87 95 39 88 58 95 57 51 48 58 32 63 24 83 55 97 82
|
||||||
|
split_gain=8.61924 11.4411 11.6705 8.28079 6.48928 6.06533 8.08152 14.8066 8.57749 8.46636 7.40152 6.03526 6.41459 8.82896 6.7274 5.49578 4.98309 3.77165
|
||||||
|
threshold=0.58007633587786267 1.5850000000000002 229.28125000000003 -0.08571428571428534 0.57686355548965829 16.437500000000004 171.09375000000003 38.687500000000007 -0.016939089932731747 -0.033449118040512087 27.387500000000003 17.062500000000004 0.48324752364570916 -1.0000000180025095e-35 0.52167307176691413 21.937500000000004 3.2187500000000004 1.6850000000000003
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=4 15 11 -4 5 -1 8 9 -7 -8 -9 -3 13 -13 -14 -2 -17 -10
|
||||||
|
right_child=1 2 3 -5 -6 6 7 10 17 -11 -12 12 14 -15 -16 16 -18 -19
|
||||||
|
leaf_value=-0.037191415145792946 -0.049107836359544479 0.057010861992900341 0.011593508527805042 -0.050683110628723223 0.024122659092291082 -0.013516688468798235 0.0070009506232722408 -0.0048723531932253544 0.015903788969995617 -0.045659362164178104 0.041619476315647989 -0.040633960200292647 0.017460987223942896 0.023949802445685821 0.054172151049742406 0.018705900435433812 -0.030600473896497015 0.053826338845108651
|
||||||
|
leaf_weight=10.358175262808798 6.0601196587085751 7.9332039654254904 7.6448924392461777 6.1759819239377958 11.035771340131758 11.594122901558878 6.1791122853755978 69.580003947019577 10.684715464711191 23.321105942130089 5.9471079260110846 5.9447444081306458 28.258737400174141 7.8707564771175367 11.133399918675421 7.4004974067211133 5.8894641548395157 6.9099283069372168
|
||||||
|
leaf_count=42 25 32 31 25 45 47 25 282 43 95 24 24 114 32 45 30 24 28
|
||||||
|
internal_value=0.000340314 0.00988207 0.0169604 -0.0162354 -0.00544273 -0.00769954 -0.0054235 -0.0105979 0.0131951 -0.0346291 -0.00121152 0.0244643 0.0196117 -0.00384028 0.0278367 -0.0175393 -0.00314428 0.0307971
|
||||||
|
internal_weight=249.922 94.3118 74.9617 13.8209 155.61 144.574 134.216 105.027 29.1888 29.5002 75.5271 61.1408 53.2076 13.8155 39.3921 19.3501 13.29 17.5946
|
||||||
|
internal_count=1013 382 303 56 631 586 544 426 118 120 306 247 215 56 159 79 54 71
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=14
|
||||||
|
num_leaves=21
|
||||||
|
num_cat=0
|
||||||
|
split_feature=75 79 28 27 14 60 31 69 47 53 31 75 36 41 56 46 49 46 77 74
|
||||||
|
split_gain=8.04256 13.9131 8.58147 7.46144 10.122 9.11597 10.0351 11.5688 9.90082 8.37289 8.31104 8.15738 7.02093 6.34993 5.18118 6.69615 5.11523 3.3449 3.22441 5.46203
|
||||||
|
threshold=0.6718233349078887 0.6464920911223796 41.687500000000007 -2.3020833333333326 91.062500000000014 12.937500000000002 25.803571428571434 1.7083333333333337 0.37218684558476361 25.812500000000004 17.354166666666668 0.3980198019801981 -0.26190476190476181 12.775000000000002 40.062500000000007 0.37106571647400344 0.76572220694348403 0.35494543794947025 1.4850000000000001 0.49543388429752072
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=3 18 12 4 13 6 14 -8 10 -10 -7 -12 -3 -1 15 -5 -16 -6 19 -2
|
||||||
|
right_child=1 2 -4 5 17 8 7 -9 9 -11 11 -13 -14 -15 16 -17 -18 -19 -20 -21
|
||||||
|
leaf_value=-0.019711473750247656 0.056394721780793459 -0.014592747921604247 -0.045243698355551337 0.0010942635313375348 -0.026082382729623245 0.059046481579424839 0.042087030208466859 -0.025395196611899901 -0.0380827165006535 0.012578046288920864 -0.012429649451340766 0.020979301067090405 0.03089449715034762 0.032768838321915822 -0.061831820327718327 -0.032477187860471046 -0.018967296365290393 -0.062065664493685058 0.060078921525471347 0.0051456786696745154
|
||||||
|
leaf_weight=8.626388296484949 5.9154238402843493 10.863973572850233 6.1918527483940116 30.794128924608231 9.0536976456642169 6.6757322102785102 11.092378646135332 6.415662854909896 11.35324338078499 9.6619694828987104 16.008781462907791 43.380531519651413 10.852814644575117 6.4449361413717261 6.8486602157354382 13.751119881868361 12.741591066122053 7.6055790930986396 7.6382495164871207 7.6053119897842407
|
||||||
|
leaf_count=35 24 44 25 125 37 27 45 26 46 39 65 176 44 26 28 56 52 31 31 31
|
||||||
|
internal_value=0.000326808 0.0148417 -0.00370442 -0.00322617 -0.0210218 0.000120512 -0.00948172 0.0173588 0.00912325 -0.0147909 0.0167303 0.0119737 0.00813919 0.00273063 -0.0168088 -0.00926924 -0.0339525 -0.0425101 0.0393039 0.0275675
|
||||||
|
internal_weight=249.522 49.0676 27.9086 200.454 31.7306 168.724 81.6435 17.508 87.0803 21.0152 66.065 59.3893 21.7168 15.0713 64.1355 44.5452 19.5903 16.6593 21.159 13.5207
|
||||||
|
internal_count=1013 199 113 814 129 685 332 71 353 85 268 241 88 61 261 181 80 68 86 55
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=15
|
||||||
|
num_leaves=14
|
||||||
|
num_cat=0
|
||||||
|
split_feature=86 40 27 10 41 31 73 65 28 74 14 97 65
|
||||||
|
split_gain=9.19077 7.28223 7.35402 9.11593 7.22847 7.50822 7.14398 7.51306 6.94962 5.72956 5.5869 4.91206 4.48842
|
||||||
|
threshold=1.425 10.937500000000002 -10.947916666666666 84.062500000000014 13.645833333333334 15.29166666666667 0.5344873150105709 0.32491602042266449 39.687500000000007 0.47029411764705881 85.535714285714292 -0.42708333333332854 0.35541085304317482
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=8 11 10 4 5 -4 9 -8 -1 -5 -3 -2 -13
|
||||||
|
right_child=1 2 3 6 -6 -7 7 -9 -10 -11 -12 12 -14
|
||||||
|
leaf_value=0.059592270356515986 0.0053735337050535084 0.0014536342489078382 -0.0042774365987278294 0.047077753667467796 -0.014197369069938693 0.036529368742735643 0.01583862591245707 -0.0087913938399981923 0.0061247756213370069 0.0052192588836833601 -0.050790366696786798 -0.012402789325272627 -0.059610908501483095
|
||||||
|
leaf_weight=7.3100549280643454 6.1067151725292232 5.9317886233329755 9.6296757310628873 7.8829693347215679 8.6421001106500608 28.761566951870918 23.91489639878273 115.60252341628075 8.3125372529029828 15.558673441410063 7.3123210966587067 5.9148542433977109 7.0790839940309525
|
||||||
|
leaf_count=30 25 24 39 32 35 117 97 469 34 63 30 24 29
|
||||||
|
internal_value=0.00140631 -0.00051071 0.00151755 0.00334081 0.0188538 0.0262938 -0.00113655 -0.00456952 0.0311431 0.0192955 -0.0273913 -0.0242158 -0.0381217
|
||||||
|
internal_weight=257.96 242.337 223.237 209.992 47.0333 38.3912 162.959 139.517 15.6226 23.4416 13.2441 19.1007 12.9939
|
||||||
|
internal_count=1048 984 906 852 191 156 661 566 64 95 54 78 53
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=16
|
||||||
|
num_leaves=13
|
||||||
|
num_cat=0
|
||||||
|
split_feature=33 88 64 14 97 55 33 27 95 11 62 89
|
||||||
|
split_gain=8.94152 9.44973 8.34757 9.96923 9.2269 7.77034 6.84612 6.71789 8.91623 11.1245 5.59099 2.07466
|
||||||
|
threshold=5.4583333333333348 0.5709995709995711 0.32539627952456907 83.535714285714292 -1.5982142857142916 24.062500000000004 0.3184523809523796 -12.94270833333333 170.79017857142858 87.645833333333357 0.50771095194186133 0.48370246267843525
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 2 3 4 -1 -3 11 -4 10 -10 -9 -5
|
||||||
|
right_child=-2 5 7 6 -6 -7 -8 8 9 -11 -12 -13
|
||||||
|
leaf_value=-0.021346605099593578 -0.036738482853078236 0.058873571365345455 -0.029645258704030009 -0.03604840849327056 0.042575470200724393 0.0048157514196816237 -0.0070588968786982603 0.037451850608501855 -0.041717482942480864 0.0036108240465800787 0.0091615077619154172 -0.067942279025163504
|
||||||
|
leaf_weight=7.6162292957305908 9.497162461280821 8.4247576445341128 9.057781442999838 6.4219828844070452 6.8739977478981 8.594713091850279 9.099840894341467 19.09737765789032 9.280805364251135 130.09927693009377 26.950699493288994 6.6345582008361816
|
||||||
|
leaf_count=31 39 35 37 26 28 35 37 78 38 528 109 27
|
||||||
|
internal_value=0.00135171 0.00280948 0.00069135 -0.0168207 0.0089773 0.0315748 -0.0336925 0.00399111 0.00563418 0.000592579 0.0208943 -0.052255
|
||||||
|
internal_weight=257.649 248.152 231.133 36.6466 14.4902 17.0195 22.1564 194.486 185.428 139.38 46.0481 13.0565
|
||||||
|
internal_count=1048 1009 939 149 59 70 90 790 753 566 187 53
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=17
|
||||||
|
num_leaves=12
|
||||||
|
num_cat=0
|
||||||
|
split_feature=33 88 55 27 10 32 31 60 75 90 14
|
||||||
|
split_gain=8.28401 8.76598 7.29837 6.5019 6.36672 9.86493 7.51301 7.17497 6.93615 6.2403 5.35126
|
||||||
|
threshold=5.4583333333333348 0.5709995709995711 24.062500000000004 -12.94270833333333 84.062500000000014 20.062500000000004 25.803571428571434 12.937500000000002 0.42318766937669378 0.19774467682950328 85.535714285714292
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 3 -3 10 5 8 7 -6 -5 -8 -1
|
||||||
|
right_child=-2 2 -4 4 6 -7 9 -9 -10 -11 -12
|
||||||
|
leaf_value=5.5780973020133532e-06 -0.035467582222402753 0.05716359984226644 0.004623749836194309 -0.010644706886582317 -0.01582380049665728 -0.034391445298106116 0.046794179848204068 0.0026044549279971439 0.028201993083561465 0.0052060024656404988 -0.051579011297576027
|
||||||
|
leaf_weight=6.1612475216388685 9.4450326114892942 8.3315776139497775 8.5935685932636243 9.1481379419565183 59.708019092679024 5.8809057772159568 8.1617092192173022 77.918728813529015 37.500212237238884 19.722670719027519 6.7347901910543442
|
||||||
|
leaf_count=25 39 35 35 37 243 24 33 316 153 80 28
|
||||||
|
internal_value=0.00129938 0.00270042 0.030487 0.000663966 0.00229624 0.0144291 -0.00155443 -0.00539046 0.0205838 0.0173788 -0.0269338
|
||||||
|
internal_weight=257.307 247.862 16.9251 230.936 218.04 52.5293 165.511 137.627 46.6484 27.8844 12.896
|
||||||
|
internal_count=1048 1009 70 939 886 214 672 559 190 113 53
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=18
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=33 88 55 11 17 87 45
|
||||||
|
split_gain=7.67811 8.13711 6.86921 6.16429 9.02438 5.74349 6.3002
|
||||||
|
threshold=5.4583333333333348 0.5709995709995711 24.062500000000004 74.354166666666671 -10.687499999999998 2.1450000000000005 -0.0034592463243838995
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 3 -3 -1 -5 6 -6
|
||||||
|
right_child=-2 2 -4 4 5 -7 -8
|
||||||
|
leaf_value=0.036528500712599402 -0.034255437987614025 0.0555735632038485 0.004439425576339767 -0.038357932926460371 -0.0070697236803132311 0.030356748335144887 0.0070235502949047429
|
||||||
|
leaf_weight=7.4107095897197715 9.3892168849706632 8.2292238324880618 8.5923809558153135 9.6656254380941373 105.90707743167877 10.260427355766295 97.451314657926559
|
||||||
|
leaf_count=30 39 35 35 40 431 42 396
|
||||||
|
internal_value=0.00124942 0.00259625 0.0294545 0.000637822 -0.000553374 0.00115717 -0.00031609
|
||||||
|
internal_weight=256.906 247.517 16.8216 230.695 223.284 213.619 203.358
|
||||||
|
internal_count=1048 1009 70 939 909 869 827
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=19
|
||||||
|
num_leaves=12
|
||||||
|
num_cat=0
|
||||||
|
split_feature=33 86 64 12 27 95 11 49 62 29 63
|
||||||
|
split_gain=7.11864 7.56899 6.11087 12.4985 5.73268 8.29302 10.1577 5.48698 5.06855 4.93802 3.11264
|
||||||
|
threshold=5.4583333333333348 1.4150000000000003 0.32539627952456907 1.9375000000000002 -12.94270833333333 170.79017857142858 87.645833333333357 0.77175549922512843 0.54605872496633345 41.401785714285722 0.51856200631031568
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 9 3 8 -4 7 -7 -6 10 -1 -3
|
||||||
|
right_child=-2 2 4 -5 5 6 -8 -9 -10 -11 -12
|
||||||
|
leaf_value=0.054127893054378734 -0.033097093119392906 -0.024347971534982155 -0.027558678245584001 0.020697790803193339 0.012679398061121673 -0.0402735013491324 0.0031588930417813959 0.046340548831502577 0.0016157647003835103 0.0053158736723644484 -0.056291390595480988
|
||||||
|
leaf_weight=7.2425345033407194 9.3303139358758909 10.320196986198431 8.9888450950384122 11.517354950308798 36.484531104564667 9.2175567746162397 131.94763413071632 9.837190628051756 6.3723442256450644 6.1165111809968948 9.2601860165595991
|
||||||
|
leaf_count=31 39 42 37 47 149 38 536 40 26 25 38
|
||||||
|
internal_value=0.0012009 0.0024949 0.00082268 -0.0139809 0.00364588 0.00514195 0.000322921 0.0198279 -0.0293706 0.031779 -0.039455
|
||||||
|
internal_weight=256.635 247.305 233.946 37.4701 196.476 187.487 141.165 46.3217 25.9527 13.359 19.5804
|
||||||
|
internal_count=1048 1009 953 153 800 763 574 189 106 56 80
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=20
|
||||||
|
num_leaves=15
|
||||||
|
num_cat=0
|
||||||
|
split_feature=60 18 88 26 36 31 9 24 61 35 75 60 95 51
|
||||||
|
split_gain=8.03818 7.72948 8.40414 12.0656 10.8001 9.64736 8.20128 6.93288 5.91815 6.68838 6.79855 4.79664 4.70914 4.49622
|
||||||
|
threshold=15.225000000000001 -0.29166666666667135 0.56584311806914556 14.937500000000002 -0.83124999999999971 19.645833333333339 16.515151515151516 -1.0000000180025095e-35 15.645833333333334 8.5669642857142865 0.58007633587786267 15.775000000000002 222.78125000000003 0.0018411019890782001
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 6 3 4 13 -6 8 -2 9 10 -1 -9 -4 -3
|
||||||
|
right_child=7 2 12 -5 5 -7 -8 11 -10 -11 -12 -13 -14 -15
|
||||||
|
leaf_value=-0.0089530653611645094 -0.013396078382306617 -0.012100783857722328 0.043432242412436123 -0.05470139039712181 0.021915508768684949 -0.01294489712125084 0.048027122146776596 0.063122343027819355 0.035214924114047572 -0.036143728924515048 0.011385864248782825 0.018228963324568446 -0.0045408979170662904 -0.049373438013463097
|
||||||
|
leaf_weight=53.602775543928146 6.6217800229787853 8.524589270353319 6.1861436218023282 11.381553843617437 18.768473565578461 39.295118644833565 6.1146008819341651 6.1183906942605999 7.3963862508535376 8.3620016276836378 51.616437286138535 10.084086462855337 6.9543650448322296 13.191540747880934
|
||||||
|
leaf_count=219 27 35 26 47 77 160 25 25 30 34 210 41 29 54
|
||||||
|
internal_value=-0.00155888 -0.00379275 -0.0118627 -0.0161736 -0.0106771 -0.00167662 0.00283011 0.0210883 0.000545703 -0.00171195 0.00102442 0.0351816 0.0180434 -0.0347422
|
||||||
|
internal_weight=254.218 231.394 104.302 91.1613 79.7797 58.0636 127.092 22.8243 120.978 113.581 105.219 16.2025 13.1405 21.7161
|
||||||
|
internal_count=1039 946 428 373 326 237 518 93 493 463 429 66 55 89
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=21
|
||||||
|
num_leaves=15
|
||||||
|
num_cat=0
|
||||||
|
split_feature=60 18 88 26 36 31 9 9 61 35 35 95 51 28
|
||||||
|
split_gain=7.42241 7.14338 7.76759 11.245 10.0048 8.89861 7.56719 6.33462 5.44938 6.18568 6.60464 4.38569 4.18924 2.06881
|
||||||
|
threshold=15.225000000000001 -0.29166666666667135 0.56584311806914556 14.937500000000002 -0.83124999999999971 19.645833333333339 16.515151515151516 -4.2748917748917838 15.645833333333334 8.5669642857142865 8.2678571428571441 222.78125000000003 0.0018411019890782001 41.187500000000007
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 6 3 4 12 -6 8 -2 9 10 -1 -4 -3 -9
|
||||||
|
right_child=7 2 11 -5 5 -7 -8 13 -10 -11 -12 -13 -14 -15
|
||||||
|
leaf_value=-0.0020580613462284694 -0.0067757984042552816 -0.011632476414499757 0.042031501598029888 -0.052911002493618228 0.021055706218397436 -0.012438211689475422 0.046156795546078516 0.022002629364403069 0.033775328851131076 -0.034815903882803013 0.034011731538430165 -0.0043576236343065185 -0.047663392508499491 0.052589999762468774
|
||||||
|
leaf_weight=96.316321060061455 8.6104428470134753 8.5132995098829287 6.1375970840454084 11.297693848609923 18.753774255514145 39.26072384417057 6.1079912632703772 7.3507572114467603 7.4030207246541968 8.3342373967170698 8.8703934699296934 6.9569248706102371 13.119665667414663 6.8210117071866989
|
||||||
|
leaf_count=393 35 35 26 47 77 160 25 30 30 34 36 29 54 28
|
||||||
|
internal_value=-0.00149909 -0.00364675 -0.0114181 -0.0155653 -0.010268 -0.00161096 0.002718 0.0202838 0.000523866 -0.00164456 0.000983704 0.0173856 -0.033484 0.0367246
|
||||||
|
internal_weight=253.854 231.072 104.04 90.9452 79.6475 58.0145 127.032 22.7822 120.924 113.521 105.187 13.0945 21.633 14.1718
|
||||||
|
internal_count=1039 946 428 373 326 237 518 93 493 463 429 55 89 58
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=22
|
||||||
|
num_leaves=18
|
||||||
|
num_cat=0
|
||||||
|
split_feature=75 10 73 56 97 33 54 28 63 53 73 64 38 53 14 13 63
|
||||||
|
split_gain=6.8389 8.24825 6.33351 8.88087 6.18565 5.67783 6.55094 5.59704 6.85557 8.66603 7.65659 7.21773 11.1113 8.66033 3.97328 3.82022 2.45765
|
||||||
|
threshold=0.71055555555555572 112.31250000000001 0.53158244680851074 39.937500000000007 -0.42708333333332854 -3.077380952380953 21.145833333333339 44.937500000000007 0.51560927336724371 25.687500000000004 0.63958726168028501 0.34495732674280544 4.3875000000000011 27.437500000000004 110.18750000000001 98.625000000000014 0.51800407176145413
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=2 5 3 15 -5 -2 -7 8 9 10 -4 12 -10 -13 -11 -1 -8
|
||||||
|
right_child=1 -3 7 4 -6 6 16 -9 11 14 -12 13 -14 -15 -16 -17 -18
|
||||||
|
leaf_value=0.015837814614419042 -0.0054090476665669711 -0.020413774544095844 -0.0067905346474414312 0.026068878291681773 -0.024468940768756574 0.010241531744467547 0.073552533225814301 0.020224466305667418 -0.0046266451570048392 -0.021209825690180987 -0.052758572611820695 0.0025546027891674618 -0.064146045205184979 0.052111362242983086 -0.062702945254864487 0.060247018203511145 0.036959564623549768
|
||||||
|
leaf_weight=5.9841428995132464 7.3666127473115912 8.3540667146444303 65.92797489464283 6.133746981620793 10.522817611694332 9.2578747272491508 5.8667192012071592 11.480442628264425 29.450126886367798 6.6407066881656638 6.3565134406089774 47.05113098025322 6.0492770820856085 6.4109846800565711 8.3170198649167997 6.4289718419313431 5.8796851336956024
|
||||||
|
leaf_count=25 30 34 271 25 43 38 24 47 121 27 26 193 25 26 34 26 24
|
||||||
|
internal_value=-0.00144173 0.0145202 -0.00414618 0.0132275 -0.00585849 0.0248068 0.0354041 -0.00683713 -0.00860031 -0.0165676 -0.0108328 -0.000786974 -0.0147691 0.00849727 -0.0442815 0.0388381 0.0552359
|
||||||
|
internal_weight=253.479 36.725 216.754 29.0697 16.6566 28.3709 21.0043 187.684 176.204 87.2422 72.2845 88.9615 35.4994 53.4621 14.9577 12.4131 11.7464
|
||||||
|
internal_count=1039 150 889 119 68 116 86 770 723 358 297 365 146 219 61 51 48
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=23
|
||||||
|
num_leaves=16
|
||||||
|
num_cat=0
|
||||||
|
split_feature=60 18 35 26 21 11 72 34 42 69 65 24 60 29 16
|
||||||
|
split_gain=6.76622 6.44432 7.43603 8.61975 6.98342 7.45293 9.26335 8.42599 8.25952 6.4395 7.95854 6.13581 4.32375 3.78406 2.36778
|
||||||
|
threshold=15.225000000000001 -0.29166666666667135 8.8229166666666696 14.937500000000002 0.16515151515151519 123.68750000000001 227.82000000000002 8.4687500000000018 -0.84166666666666667 8.2500000000000018 0.32491602042266449 -1.0000000180025095e-35 15.775000000000002 32.708333333333336 4.9375000000000009
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 4 3 9 5 6 7 -1 -8 10 -3 -2 -13 -5 -11
|
||||||
|
right_child=11 2 -4 13 -6 -7 8 -9 -10 14 -12 12 -14 -15 -16
|
||||||
|
leaf_value=0.0068377190178299978 -0.012999968486144695 0.046209360196903707 -0.047916200210550458 -0.016602574178768866 0.044382956007966268 0.041711064554847729 0.012542729748890782 -0.040858831579305734 -0.041878353739748291 -0.047809843446037739 -0.0025966166987321858 0.059424945850961183 0.016650328155874659 -0.061312735990994086 -0.01220746979923833
|
||||||
|
leaf_weight=86.415405079722404 6.6122610569000271 5.8188596814870825 7.9874863028526297 5.9741610884666425 6.0946186929941168 6.6349345445632926 6.355574399232867 6.3623842000961295 14.977498367428778 6.0902193337678892 65.746306836605072 6.0662906020879772 10.036743447184561 6.1432460248470306 5.8692503720521927
|
||||||
|
leaf_count=353 27 24 33 25 25 27 26 26 61 25 271 25 41 26 24
|
||||||
|
internal_value=-0.00138606 -0.00343895 -0.0108389 -0.0077424 0.00260686 0.000498221 -0.00189808 0.00356685 -0.0256652 -0.00316857 0.00137173 0.0194426 0.0327643 -0.0392696 -0.0303376
|
||||||
|
internal_weight=253.185 230.47 103.63 95.642 126.84 120.746 114.111 92.7778 21.3331 83.5246 71.5652 22.7153 16.103 12.1174 11.9595
|
||||||
|
internal_count=1039 946 428 395 518 493 466 379 87 344 295 93 66 51 49
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=24
|
||||||
|
num_leaves=15
|
||||||
|
num_cat=0
|
||||||
|
split_feature=60 18 88 27 62 9 11 72 12 48 36 24 43 95
|
||||||
|
split_gain=6.25224 5.95135 7.10947 8.50211 8.95714 6.45695 6.86321 8.56032 7.77198 7.68621 6.38574 5.67858 4.21565 3.98223
|
||||||
|
threshold=15.225000000000001 -0.29166666666667135 0.56584311806914556 -6.9999999999999973 0.46489792570397087 16.515151515151516 123.68750000000001 227.82000000000002 -0.75595238095237949 0.025274304665849606 -1.705357142857143 -1.0000000180025095e-35 0.50860236372279055 222.78125000000003
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 5 3 -3 -5 6 7 9 -9 -1 -6 -2 -13 -4
|
||||||
|
right_child=11 2 13 4 10 -7 -8 8 -10 -11 -12 12 -14 -15
|
||||||
|
leaf_value=0.0087138894445027461 -0.01248475536504879 -0.052100240369848241 0.040799272900499305 0.024363685744045852 -0.051816351953662361 0.042735686521304467 0.040009035522266888 -0.046006108176515285 0.00273483800408156 -0.021635092287458264 -0.0115203606180113 0.0090547062831142257 0.050240538556617337 -0.0035196794361016148
|
||||||
|
leaf_weight=76.604642063379288 6.6097762733697918 8.6576687693595868 6.0909906178712827 10.348592042922972 6.9732603579759589 6.0767100751399985 6.6403718292713156 11.978713899850847 9.2968079298734647 16.170377686619759 64.432133376598358 7.2736790329217937 8.7717214673757535 6.9399073719978333
|
||||||
|
leaf_count=313 27 37 26 43 29 25 27 49 38 66 264 30 36 29
|
||||||
|
internal_value=-0.00133294 -0.00330607 -0.0104257 -0.0144068 -0.0104152 0.0025036 0.000477939 -0.00182368 -0.0247077 0.00342416 -0.0154556 0.0187169 0.0315702 0.0171962
|
||||||
|
internal_weight=252.865 230.21 103.443 90.4117 81.754 126.768 120.691 114.051 21.2755 92.775 71.4054 22.6552 16.0454 13.0309
|
||||||
|
internal_count=1039 946 428 373 336 518 493 466 87 379 293 93 66 55
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=25
|
||||||
|
num_leaves=15
|
||||||
|
num_cat=0
|
||||||
|
split_feature=33 87 85 10 83 10 39 86 72 49 13 16 38 27
|
||||||
|
split_gain=7.25855 6.38507 8.41516 9.2502 8.14048 7.48236 8.40852 7.85339 11.0386 8.60242 6.83818 5.86449 5.49791 3.04698
|
||||||
|
threshold=5.4583333333333348 1.5850000000000002 1.0000000180025095e-35 117.22500000000001 0.54234668644906048 116.93750000000001 -1.0000000180025095e-35 1.5650000000000002 162.69282608695656 0.75102962846491172 104.77500000000002 -8.9374999999999982 4.1833333333333345 0.020833333333333655
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 10 5 4 11 7 -7 9 -9 -3 -1 -4 -8 -6
|
||||||
|
right_child=-2 2 3 -5 13 6 12 8 -10 -11 -12 -13 -14 -15
|
||||||
|
leaf_value=-0.041539672781130549 -0.031422067002150791 0.042995214924070081 0.042296436297125074 -0.023883650662784965 0.072297264891014304 -0.009582647504040049 0.058812399794648744 0.021985462315431858 -0.014896003510037621 -0.0040262327529876152 0.0035283522947714635 0.0075685995167286092 0.011039775290075307 0.0323219849604569
|
||||||
|
leaf_weight=10.137894913554193 10.139534831047056 10.71300193667412 9.8288029283285123 7.8387844264507285 5.8450987040996534 9.664890334010126 8.7909274846315366 15.362282529473303 83.881821304559708 14.860007524490355 11.493947580456732 37.329559937119484 6.8639661371707907 6.381435826420784
|
||||||
|
leaf_count=42 43 45 40 32 24 40 36 63 345 62 47 153 28 26
|
||||||
|
internal_value=0.00172561 0.00313194 0.0051945 0.0169566 0.0223475 -7.19483e-05 0.0197544 -0.00409382 -0.00918701 0.0156719 -0.0175931 0.0148066 0.0378663 0.0514328
|
||||||
|
internal_weight=249.132 238.992 217.361 67.2237 59.3849 150.137 25.3198 124.817 99.2441 25.573 21.6318 47.1584 15.6549 12.2265
|
||||||
|
internal_count=1026 983 894 275 243 619 104 515 408 107 89 193 64 50
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=26
|
||||||
|
num_leaves=13
|
||||||
|
num_cat=0
|
||||||
|
split_feature=48 87 75 13 13 26 98 83 54 28 63 26
|
||||||
|
split_gain=6.07316 5.62173 8.54781 6.21306 5.95377 6.62941 7.29602 6.07248 5.64674 6.51449 5.46195 3.27744
|
||||||
|
threshold=0.064872666259492118 1.5850000000000002 0.69045454545454554 104.77500000000002 120.56250000000001 15.072916666666668 -11.562499999999998 0.49675474226372424 20.535714285714288 40.187500000000007 0.51085383914331295 6.072916666666667
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 3 4 -1 5 6 -3 -7 -4 11 -2 -10
|
||||||
|
right_child=10 2 8 -5 -6 7 -8 -9 9 -11 -12 -13
|
||||||
|
leaf_value=-0.039674658535771484 -0.052512934017087537 -0.014023176104202862 -0.005798976431383154 0.0036351517375994916 -0.026305412473366974 0.0062814492481233046 0.010148203473004854 -0.041049983242601396 0.028561765576098901 0.0087152875473318417 -0.0029143682076594587 0.066287713324515871
|
||||||
|
leaf_weight=9.8422116041183489 6.0319006294012061 23.719328477978706 7.8761165887117377 11.48290069401264 11.350633054971693 7.9110089093446758 126.75102043151855 9.5997582674026471 6.5257693231105831 10.448119834065436 8.6423251926898939 8.462289631366728
|
||||||
|
leaf_count=41 25 97 32 47 47 33 522 41 27 43 36 35
|
||||||
|
internal_value=0.00166 0.00322559 0.00518911 -0.0163537 0.00173262 0.00362718 0.00633796 -0.0196666 0.0237966 0.0329606 -0.0233021 0.0498619
|
||||||
|
internal_weight=248.643 233.969 212.644 21.3251 179.332 167.981 150.47 17.5108 33.3123 25.4362 14.6742 14.9881
|
||||||
|
internal_count=1026 965 877 88 740 693 619 74 137 105 61 62
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=27
|
||||||
|
num_leaves=15
|
||||||
|
num_cat=0
|
||||||
|
split_feature=33 40 43 64 56 29 74 7 16 12 36 53 32 33
|
||||||
|
split_gain=6.67537 6.00723 6.58775 6.4086 6.22146 8.22654 7.17113 5.57557 10.8982 10.7588 6.64454 7.95563 6.24334 4.86842
|
||||||
|
threshold=5.4583333333333348 10.937500000000002 0.53985767334155887 0.34495732674280544 30.562500000000004 32.791666666666679 0.62250000000000016 59.166666666666679 3.7916666666666647 9.1339285714285712 -0.34166666666666673 22.387500000000003 23.791666666666668 -0.29166666666666602
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 3 7 -1 -4 -6 -7 8 9 -3 12 -12 -9 -5
|
||||||
|
right_child=-2 2 4 13 5 6 -8 10 -10 -11 11 -13 -14 -15
|
||||||
|
leaf_value=-0.04539631182232725 -0.030331123415790143 0.0036500818553591068 -0.017115468469559102 -0.026046588004955247 0.065457960355147352 0.02547423439415672 -0.018488966847576102 0.017724882848208653 -0.041424367213409224 -0.047501812723565191 -0.0045522301063454888 0.04416916038732871 -0.038718688099103261 0.024752126334750945
|
||||||
|
leaf_weight=8.1224037855863589 10.053963825106619 115.14034233987331 6.9894797801971427 5.7684260606765747 6.3827460259199134 27.928439050912857 7.5389710813760749 6.7571853250265104 10.671643391251562 6.9777127951383582 8.1633969545364398 15.628093481063841 5.8501180559396744 6.3321559280157071
|
||||||
|
leaf_count=34 43 476 29 24 26 114 31 28 44 29 34 64 24 26
|
||||||
|
internal_value=0.00159555 0.00294283 0.00487723 -0.0179123 0.0178183 0.0236527 0.0161294 0.00114151 -0.00266021 0.00072731 0.0150109 0.0274518 -0.00846641 0.000536049
|
||||||
|
internal_weight=248.305 238.251 218.028 20.223 48.8396 41.8502 35.4674 169.188 132.79 122.118 36.3988 23.7915 12.6073 12.1006
|
||||||
|
internal_count=1026 983 899 84 200 171 145 699 549 505 150 98 52 50
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=28
|
||||||
|
num_leaves=13
|
||||||
|
num_cat=0
|
||||||
|
split_feature=33 27 14 48 24 53 59 57 34 47 81 50
|
||||||
|
split_gain=6.19142 5.48502 8.27407 6.44704 5.11208 5.11786 5.55155 5.07182 5.97421 8.76085 8.56983 3.46147
|
||||||
|
threshold=5.4583333333333348 -2.3020833333333326 85.312500000000014 0.064872666259492118 -1.0000000180025095e-35 21.291666666666668 23.387500000000003 45.687500000000007 6.8875000000000011 0.37218684558476361 1.7150000000000001 0.74075516458343793
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 2 11 7 -4 -6 -7 8 10 -10 -3 -1
|
||||||
|
right_child=-2 3 4 -5 5 6 -8 -9 9 -11 -12 -13
|
||||||
|
leaf_value=0.036467676081935275 -0.029325034647802492 0.012704755728250297 -0.051764929617036118 -0.023669451716433799 -0.044508533316403635 0.026446805663908529 -0.027271352696527536 -0.022833580306035422 0.022463638898768467 -0.0033374130186977686 -0.014458359978742813 -0.0028572785771652266
|
||||||
|
leaf_weight=6.0484680682420722 9.9843682050704938 40.375474900007248 7.6424536705017116 11.367303296923636 5.5812820345163372 6.6618274450302106 5.7221347242593765 8.4949828088283521 73.357022643089294 29.534479916095734 34.431760281324387 8.7800204604864103
|
||||||
|
leaf_count=25 43 166 32 47 24 28 24 35 302 121 143 36
|
||||||
|
internal_value=0.0015332 0.00282775 -0.0105946 0.005575 -0.0243635 -0.0127068 0.00162579 0.0073604 0.00880384 0.0150576 0.000202303 0.0131832
|
||||||
|
internal_weight=247.982 237.997 40.4362 197.561 25.6077 17.9652 12.384 186.194 177.699 102.892 74.8072 14.8285
|
||||||
|
internal_count=1026 983 169 814 108 76 52 767 732 423 309 61
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
Tree=29
|
||||||
|
num_leaves=17
|
||||||
|
num_cat=0
|
||||||
|
split_feature=87 85 10 83 41 73 86 39 8 44 13 76 61 36 97 45
|
||||||
|
split_gain=5.37924 8.77104 7.1461 6.5763 6.24618 5.74552 7.24104 5.90731 7.82727 5.90939 5.68942 4.92086 12.7968 7.49136 4.69159 2.29423
|
||||||
|
threshold=1.5850000000000002 1.0000000180025095e-35 117.22500000000001 0.54234668644906048 10.812500000000002 0.53158244680851074 1.7450000000000003 -0.61249999999999993 47.727272727272734 0.48331411181158185 104.77500000000002 2.4650000000000003 12.866071428571431 0.28869047619047633 1.4062500000000002 -0.013905145374354397
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=10 4 3 11 -2 6 -6 8 -7 -9 -1 13 -13 -3 -12 -5
|
||||||
|
right_child=1 2 -4 15 5 7 -8 9 -10 -11 14 12 -14 -15 -16 -17
|
||||||
|
leaf_value=-0.039294680659493833 -0.031671221811972641 0.037455766277146953 -0.018600965920339822 0.063774142191859146 0.050889907105456336 -0.036046187526128669 -0.0011468294092016626 -0.016947588402893 -0.00031638211057623142 0.0084049263294318916 0.026762860869410491 0.035225255717854904 -0.041754796373233906 -0.00065805839704901963 -0.023845024484234915 0.029272484285479398
|
||||||
|
leaf_weight=10.1972071826458 10.532053381204603 19.837578102946281 8.7409028112888318 6.0329279154539108 7.6620817482471493 16.978984668850899 9.6890967190265638 18.620566442608833 23.233949556946754 70.049215823411942 5.8855016827583295 6.3545227348804456 7.5724885612726212 14.127186641097067 5.8383642733097076 6.3081436455249769
|
||||||
|
leaf_count=43 44 82 36 25 32 71 40 78 96 290 24 26 31 58 24 26
|
||||||
|
internal_value=0.0014732 0.00331024 0.0151971 0.0201018 -0.00191971 0.000223048 0.021832 -0.00268611 -0.0154025 0.00308092 -0.0174444 0.0133924 -0.00663086 0.0216028 0.00156066 0.0461386
|
||||||
|
internal_weight=247.661 225.74 68.9738 60.2328 156.766 146.234 17.3512 128.883 40.2129 88.6698 21.9211 47.8918 13.927 33.9648 11.7239 12.3411
|
||||||
|
internal_count=1026 935 284 248 651 607 72 535 167 368 91 197 57 140 48 51
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
end of trees
|
||||||
|
|
||||||
|
feature_importances:
|
||||||
|
Column_33=16
|
||||||
|
Column_55=14
|
||||||
|
Column_75=13
|
||||||
|
Column_95=13
|
||||||
|
Column_17=12
|
||||||
|
Column_27=12
|
||||||
|
Column_40=12
|
||||||
|
Column_60=12
|
||||||
|
Column_88=12
|
||||||
|
Column_87=11
|
||||||
|
Column_11=10
|
||||||
|
Column_97=10
|
||||||
|
Column_14=9
|
||||||
|
Column_36=9
|
||||||
|
Column_53=9
|
||||||
|
Column_64=9
|
||||||
|
Column_86=9
|
||||||
|
Column_31=8
|
||||||
|
Column_54=8
|
||||||
|
Column_73=8
|
||||||
|
Column_15=7
|
||||||
|
Column_26=7
|
||||||
|
Column_29=7
|
||||||
|
Column_39=7
|
||||||
|
Column_62=7
|
||||||
|
Column_63=7
|
||||||
|
Column_9=6
|
||||||
|
Column_10=6
|
||||||
|
Column_12=6
|
||||||
|
Column_18=6
|
||||||
|
Column_28=6
|
||||||
|
Column_51=6
|
||||||
|
Column_61=6
|
||||||
|
Column_77=6
|
||||||
|
Column_13=5
|
||||||
|
Column_24=5
|
||||||
|
Column_35=5
|
||||||
|
Column_38=5
|
||||||
|
Column_46=5
|
||||||
|
Column_48=5
|
||||||
|
Column_58=5
|
||||||
|
Column_65=5
|
||||||
|
Column_74=5
|
||||||
|
Column_80=5
|
||||||
|
Column_8=4
|
||||||
|
Column_30=4
|
||||||
|
Column_32=4
|
||||||
|
Column_41=4
|
||||||
|
Column_43=4
|
||||||
|
Column_45=4
|
||||||
|
Column_49=4
|
||||||
|
Column_72=4
|
||||||
|
Column_82=4
|
||||||
|
Column_83=4
|
||||||
|
Column_16=3
|
||||||
|
Column_25=3
|
||||||
|
Column_34=3
|
||||||
|
Column_47=3
|
||||||
|
Column_50=3
|
||||||
|
Column_52=3
|
||||||
|
Column_56=3
|
||||||
|
Column_59=3
|
||||||
|
Column_79=3
|
||||||
|
Column_81=3
|
||||||
|
Column_85=3
|
||||||
|
Column_89=3
|
||||||
|
Column_90=3
|
||||||
|
Column_98=3
|
||||||
|
Column_37=2
|
||||||
|
Column_42=2
|
||||||
|
Column_57=2
|
||||||
|
Column_69=2
|
||||||
|
Column_76=2
|
||||||
|
Column_96=2
|
||||||
|
Column_7=1
|
||||||
|
Column_21=1
|
||||||
|
Column_44=1
|
||||||
|
Column_66=1
|
||||||
|
Column_68=1
|
||||||
|
Column_71=1
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
[boosting: gbdt]
|
||||||
|
[objective: binary]
|
||||||
|
[metric: binary_logloss]
|
||||||
|
[tree_learner: serial]
|
||||||
|
[device_type: cpu]
|
||||||
|
[data_sample_strategy: bagging]
|
||||||
|
[data: ]
|
||||||
|
[valid: ]
|
||||||
|
[num_iterations: 1200]
|
||||||
|
[learning_rate: 0.04]
|
||||||
|
[num_leaves: 31]
|
||||||
|
[num_threads: 4]
|
||||||
|
[seed: 42]
|
||||||
|
[deterministic: 0]
|
||||||
|
[force_col_wise: 0]
|
||||||
|
[force_row_wise: 0]
|
||||||
|
[histogram_pool_size: -1]
|
||||||
|
[max_depth: 6]
|
||||||
|
[min_data_in_leaf: 24]
|
||||||
|
[min_sum_hessian_in_leaf: 0.001]
|
||||||
|
[bagging_fraction: 0.84]
|
||||||
|
[pos_bagging_fraction: 1]
|
||||||
|
[neg_bagging_fraction: 1]
|
||||||
|
[bagging_freq: 5]
|
||||||
|
[bagging_seed: 400]
|
||||||
|
[bagging_by_query: 0]
|
||||||
|
[feature_fraction: 0.82]
|
||||||
|
[feature_fraction_bynode: 1]
|
||||||
|
[feature_fraction_seed: 30056]
|
||||||
|
[extra_trees: 0]
|
||||||
|
[extra_seed: 12879]
|
||||||
|
[early_stopping_round: 0]
|
||||||
|
[early_stopping_min_delta: 0]
|
||||||
|
[first_metric_only: 0]
|
||||||
|
[max_delta_step: 0]
|
||||||
|
[lambda_l1: 0]
|
||||||
|
[lambda_l2: 0]
|
||||||
|
[linear_lambda: 0]
|
||||||
|
[min_gain_to_split: 0]
|
||||||
|
[drop_rate: 0.1]
|
||||||
|
[max_drop: 50]
|
||||||
|
[skip_drop: 0.5]
|
||||||
|
[xgboost_dart_mode: 0]
|
||||||
|
[uniform_drop: 0]
|
||||||
|
[drop_seed: 17869]
|
||||||
|
[top_rate: 0.2]
|
||||||
|
[other_rate: 0.1]
|
||||||
|
[min_data_per_group: 100]
|
||||||
|
[max_cat_threshold: 32]
|
||||||
|
[cat_l2: 10]
|
||||||
|
[cat_smooth: 10]
|
||||||
|
[max_cat_to_onehot: 4]
|
||||||
|
[top_k: 20]
|
||||||
|
[monotone_constraints: ]
|
||||||
|
[monotone_constraints_method: basic]
|
||||||
|
[monotone_penalty: 0]
|
||||||
|
[feature_contri: ]
|
||||||
|
[forcedsplits_filename: ]
|
||||||
|
[refit_decay_rate: 0.9]
|
||||||
|
[cegb_tradeoff: 1]
|
||||||
|
[cegb_penalty_split: 0]
|
||||||
|
[cegb_penalty_feature_lazy: ]
|
||||||
|
[cegb_penalty_feature_coupled: ]
|
||||||
|
[path_smooth: 0]
|
||||||
|
[interaction_constraints: ]
|
||||||
|
[verbosity: -1]
|
||||||
|
[saved_feature_importance_type: 0]
|
||||||
|
[use_quantized_grad: 0]
|
||||||
|
[num_grad_quant_bins: 4]
|
||||||
|
[quant_train_renew_leaf: 0]
|
||||||
|
[stochastic_rounding: 1]
|
||||||
|
[linear_tree: 0]
|
||||||
|
[max_bin: 255]
|
||||||
|
[max_bin_by_feature: ]
|
||||||
|
[min_data_in_bin: 3]
|
||||||
|
[bin_construct_sample_cnt: 200000]
|
||||||
|
[data_random_seed: 175]
|
||||||
|
[is_enable_sparse: 1]
|
||||||
|
[enable_bundle: 1]
|
||||||
|
[use_missing: 1]
|
||||||
|
[zero_as_missing: 0]
|
||||||
|
[feature_pre_filter: 1]
|
||||||
|
[pre_partition: 0]
|
||||||
|
[two_round: 0]
|
||||||
|
[header: 0]
|
||||||
|
[label_column: ]
|
||||||
|
[weight_column: ]
|
||||||
|
[group_column: ]
|
||||||
|
[ignore_column: ]
|
||||||
|
[categorical_feature: ]
|
||||||
|
[forcedbins_filename: ]
|
||||||
|
[precise_float_parser: 0]
|
||||||
|
[parser_config_file: ]
|
||||||
|
[objective_seed: 16083]
|
||||||
|
[num_class: 1]
|
||||||
|
[is_unbalance: 0]
|
||||||
|
[scale_pos_weight: 1]
|
||||||
|
[sigmoid: 1]
|
||||||
|
[boost_from_average: 1]
|
||||||
|
[reg_sqrt: 0]
|
||||||
|
[alpha: 0.9]
|
||||||
|
[fair_c: 1]
|
||||||
|
[poisson_max_delta_step: 0.7]
|
||||||
|
[tweedie_variance_power: 1.5]
|
||||||
|
[lambdarank_truncation_level: 30]
|
||||||
|
[lambdarank_norm: 1]
|
||||||
|
[label_gain: ]
|
||||||
|
[lambdarank_position_bias_regularization: 0]
|
||||||
|
[eval_at: ]
|
||||||
|
[multi_error_top_k: 1]
|
||||||
|
[auc_mu_weights: ]
|
||||||
|
[num_machines: 1]
|
||||||
|
[local_listen_port: 12400]
|
||||||
|
[time_out: 120]
|
||||||
|
[machine_list_filename: ]
|
||||||
|
[machines: ]
|
||||||
|
[gpu_platform_id: -1]
|
||||||
|
[gpu_device_id: -1]
|
||||||
|
[gpu_use_dp: 0]
|
||||||
|
[num_gpu: 1]
|
||||||
|
|
||||||
|
end of parameters
|
||||||
|
|
||||||
|
pandas_categorical:null
|
||||||
@@ -0,0 +1,202 @@
|
|||||||
|
tree
|
||||||
|
version=v4
|
||||||
|
num_class=1
|
||||||
|
num_tree_per_iteration=1
|
||||||
|
label_index=0
|
||||||
|
max_feature_idx=98
|
||||||
|
objective=binary sigmoid:1
|
||||||
|
feature_names=Column_0 Column_1 Column_2 Column_3 Column_4 Column_5 Column_6 Column_7 Column_8 Column_9 Column_10 Column_11 Column_12 Column_13 Column_14 Column_15 Column_16 Column_17 Column_18 Column_19 Column_20 Column_21 Column_22 Column_23 Column_24 Column_25 Column_26 Column_27 Column_28 Column_29 Column_30 Column_31 Column_32 Column_33 Column_34 Column_35 Column_36 Column_37 Column_38 Column_39 Column_40 Column_41 Column_42 Column_43 Column_44 Column_45 Column_46 Column_47 Column_48 Column_49 Column_50 Column_51 Column_52 Column_53 Column_54 Column_55 Column_56 Column_57 Column_58 Column_59 Column_60 Column_61 Column_62 Column_63 Column_64 Column_65 Column_66 Column_67 Column_68 Column_69 Column_70 Column_71 Column_72 Column_73 Column_74 Column_75 Column_76 Column_77 Column_78 Column_79 Column_80 Column_81 Column_82 Column_83 Column_84 Column_85 Column_86 Column_87 Column_88 Column_89 Column_90 Column_91 Column_92 Column_93 Column_94 Column_95 Column_96 Column_97 Column_98
|
||||||
|
feature_infos=none none none none none none none [0:100] [0:100] [-100:100] [54:128.875] [61:138] [-41.333333333333329:24] [61:130.125] [59:133] [-50:34.916666666666671] [-28.666666666666657:32.5] [-24.5:27] [-35.5:31.833333333333329] [0:1] [0:1] [-1:1] [0:12] [0:12] [-12:10] [0.91666666666666663:186.1875] [0.85416666666666663:185.08333333333337] [-179.02083333333334:184.16666666666663] [20:54] [22:56] [-21:15.833333333333332] [11:34.5] [9:36] [-15:13.333333333333332] [2:13] [3:13] [-8:5.5] [0.875:9] [0:12] [-9:4.875] [7:22] [8:23] [-10:10] [0.41025641025641019:0.67647058823529416] [0.39730639730639727:0.76744186046511631] [-0.3174418604651163:0.22647058823529409] [0.20419254658385089:0.4825000000000001] [0.1875:0.54166666666666663] [-0.22171945701357459:0.17923280423280419] [0.47826086956521741:0.87898457080200498] [0.42857142857142849:0.88636363636363635] [-0.29647435897435898:0.38962801311591622] [11:39.666666666666664] [15.5:40] [10:31.875] [11.5:34] [15:56] [17:57] [12:32.125] [10:38] [8:20] [7:22] [0.40000000000000002:0.69047619047619047] [0.3902439024390244:0.71739130434782605] [0.23753976670201479:0.51851851851851849] [0.1707317073170731:0.54545454545454541] [0:8] [0:1] [120:295] [-38:36] [0:1] [0:1] [140.39130434782609:233.09999999999999] [0:1] [0:1] [0:1] [1.05:4.1100000000000003] [1.05:4.1299999999999999] [0.2034883720930232:0.79729729729729726] [0.20270270270270269:0.79651162790697683] [145.5:257.5] [1.3:7.7599999999999998] [1.4099999999999999:7.5599999999999996] [0.1789976133651551:0.75977653631284914] [0.24022346368715081:0.82100238663484482] [-15.5:12.5] [1.3:2.7200000000000002] [1.1799999999999999:2.7799999999999998] [0.36298076923076922:0.64953271028037374] [0.35046728971962621:0.63701923076923073] [0.1918833727344364:0.21555133935749429] none none none none [132:250.6875] [126.25:256.625] [-63.5:88.6875] [-35.5:27.5]
|
||||||
|
tree_sizes=1714 1917
|
||||||
|
|
||||||
|
Tree=0
|
||||||
|
num_leaves=15
|
||||||
|
num_cat=0
|
||||||
|
split_feature=72 82 49 25 36 25 17 77 34 69 25 40 80 40
|
||||||
|
split_gain=11.2305 10.9895 14.5557 11.7291 11.5678 6.991 6.42947 6.52716 10.0318 9.34909 5.86638 5.89396 5.34606 8.20903
|
||||||
|
threshold=232.51500000000001 1.8250000000000004 0.74446554478882077 2.8645833333333335 -0.46874999999999994 1.0104166666666667 12.562500000000002 2.6750000000000003 5.6339285714285721 -5.4166666666666652 3.1145833333333335 12.803571428571431 162.00000000000003 13.937500000000002
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=1 5 10 4 -4 -1 7 8 -7 -9 -3 -12 -5 -14
|
||||||
|
right_child=-2 2 3 12 -6 6 -8 9 -10 -11 11 -13 13 -15
|
||||||
|
leaf_value=-0.014742735215146609 -0.095823069621212592 -0.030752227995962191 -0.086785452728816673 0.017792685597478597 -0.021483574280753166 -0.0010203128315903962 -0.085759203191584921 -0.020079232808751797 -0.05043362279072628 -0.074223259488395713 -0.046761720776777753 -0.098557138597063443 -0.031433483007911781 0.014451045738105336
|
||||||
|
leaf_weight=7.4955528974533072 7.7454046607017508 6.2462940812110928 7.995256423950198 7.7454046607017508 9.4943670034408552 6.99584937095642 9.7442187666892988 5.9964423179626456 108.93536877632141 34.229691565036774 5.9964423179626456 8.4949599504470807 23.486065745353702 8.4949599504470807
|
||||||
|
leaf_count=30 31 25 32 31 38 28 39 24 436 137 24 34 94 34
|
||||||
|
internal_value=-0.0483827 -0.0469209 -0.0344467 -0.0240408 -0.0513359 -0.0525288 -0.054236 -0.052269 -0.0474518 -0.0661521 -0.063157 -0.0771246 -0.0120241 -0.0192454
|
||||||
|
internal_weight=259.096 251.351 77.9538 57.2161 17.4896 173.397 165.902 156.157 115.931 40.2261 20.7377 14.4914 39.7264 31.981
|
||||||
|
internal_count=1037 1006 312 229 70 694 664 625 464 161 83 58 159 128
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=1
|
||||||
|
|
||||||
|
|
||||||
|
Tree=1
|
||||||
|
num_leaves=17
|
||||||
|
num_cat=0
|
||||||
|
split_feature=52 63 82 49 63 11 9 22 47 27 26 50 60 68 37 64
|
||||||
|
split_gain=9.46149 12.0286 10.1725 11.5657 11.422 11.4943 11.2254 9.35335 10.3758 7.46163 7.15253 10.8161 5.87382 5.6308 5.10807 3.94362
|
||||||
|
threshold=18.267857142857146 0.57978414386394084 1.7650000000000003 0.74446554478882077 0.52121781606433182 81.062500000000014 8.7121212121212164 1.5000000000000002 0.36820747200853426 0.06249999999999991 7.0312500000000009 0.79401716042796011 12.35416666666667 161.75000000000003 4.5500000000000007 0.34986080718052731
|
||||||
|
decision_type=2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
left_child=15 2 4 9 5 -2 -7 8 -6 13 11 -5 -12 -4 -9 -1
|
||||||
|
right_child=1 -3 3 10 7 6 -8 14 -10 -11 12 -13 -14 -15 -16 -17
|
||||||
|
leaf_value=-0.057339030773059012 0.028542958096860364 -0.044782355190073488 0.032618410031766333 0.0057409124284739923 0.013389736272609485 -0.026136292703093016 0.010233031617588078 0.056167817502913067 -0.029699787865729181 -0.038327130963158276 0.074132616447759023 0.052492105838845886 0.026735863001827433 -0.01725653802460729 0.0087599672849197358 -0.011453089463718463
|
||||||
|
leaf_weight=5.9920798838138563 9.7432544529438001 8.4919032305479032 7.2431264519691485 42.224371567368507 31.477784723043442 57.952298685908318 17.733558729290962 9.2429284304380399 12.488689020276068 9.2367470711469633 6.4985252916812923 9.7452246546745283 11.743822261691092 7.2440863251686096 5.9950847774744025 5.9950532913208008
|
||||||
|
leaf_count=24 39 34 29 169 126 232 71 37 50 37 26 39 47 29 24 24
|
||||||
|
internal_value=0.000314777 0.00199863 0.0036638 0.0139129 -0.00299273 -0.0123505 -0.0176148 0.01051 0.00115015 -0.010233 0.0220716 0.0145076 0.0436201 0.00767928 0.0375162 -0.0343904
|
||||||
|
internal_weight=259.049 247.061 238.57 93.9359 144.634 85.4291 75.6859 59.2045 43.9665 23.724 70.2119 51.9696 18.2423 14.4872 15.238 11.9871
|
||||||
|
internal_count=1037 989 955 376 579 342 303 237 176 95 281 208 73 58 61 48
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.04
|
||||||
|
|
||||||
|
|
||||||
|
end of trees
|
||||||
|
|
||||||
|
feature_importances:
|
||||||
|
Column_25=3
|
||||||
|
Column_40=2
|
||||||
|
Column_49=2
|
||||||
|
Column_63=2
|
||||||
|
Column_82=2
|
||||||
|
Column_9=1
|
||||||
|
Column_11=1
|
||||||
|
Column_17=1
|
||||||
|
Column_22=1
|
||||||
|
Column_26=1
|
||||||
|
Column_27=1
|
||||||
|
Column_34=1
|
||||||
|
Column_36=1
|
||||||
|
Column_37=1
|
||||||
|
Column_47=1
|
||||||
|
Column_50=1
|
||||||
|
Column_52=1
|
||||||
|
Column_60=1
|
||||||
|
Column_64=1
|
||||||
|
Column_68=1
|
||||||
|
Column_69=1
|
||||||
|
Column_72=1
|
||||||
|
Column_77=1
|
||||||
|
Column_80=1
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
[boosting: gbdt]
|
||||||
|
[objective: binary]
|
||||||
|
[metric: binary_logloss]
|
||||||
|
[tree_learner: serial]
|
||||||
|
[device_type: cpu]
|
||||||
|
[data_sample_strategy: bagging]
|
||||||
|
[data: ]
|
||||||
|
[valid: ]
|
||||||
|
[num_iterations: 1200]
|
||||||
|
[learning_rate: 0.04]
|
||||||
|
[num_leaves: 31]
|
||||||
|
[num_threads: 4]
|
||||||
|
[seed: 42]
|
||||||
|
[deterministic: 0]
|
||||||
|
[force_col_wise: 0]
|
||||||
|
[force_row_wise: 0]
|
||||||
|
[histogram_pool_size: -1]
|
||||||
|
[max_depth: 6]
|
||||||
|
[min_data_in_leaf: 24]
|
||||||
|
[min_sum_hessian_in_leaf: 0.001]
|
||||||
|
[bagging_fraction: 0.84]
|
||||||
|
[pos_bagging_fraction: 1]
|
||||||
|
[neg_bagging_fraction: 1]
|
||||||
|
[bagging_freq: 5]
|
||||||
|
[bagging_seed: 400]
|
||||||
|
[bagging_by_query: 0]
|
||||||
|
[feature_fraction: 0.82]
|
||||||
|
[feature_fraction_bynode: 1]
|
||||||
|
[feature_fraction_seed: 30056]
|
||||||
|
[extra_trees: 0]
|
||||||
|
[extra_seed: 12879]
|
||||||
|
[early_stopping_round: 0]
|
||||||
|
[early_stopping_min_delta: 0]
|
||||||
|
[first_metric_only: 0]
|
||||||
|
[max_delta_step: 0]
|
||||||
|
[lambda_l1: 0]
|
||||||
|
[lambda_l2: 0]
|
||||||
|
[linear_lambda: 0]
|
||||||
|
[min_gain_to_split: 0]
|
||||||
|
[drop_rate: 0.1]
|
||||||
|
[max_drop: 50]
|
||||||
|
[skip_drop: 0.5]
|
||||||
|
[xgboost_dart_mode: 0]
|
||||||
|
[uniform_drop: 0]
|
||||||
|
[drop_seed: 17869]
|
||||||
|
[top_rate: 0.2]
|
||||||
|
[other_rate: 0.1]
|
||||||
|
[min_data_per_group: 100]
|
||||||
|
[max_cat_threshold: 32]
|
||||||
|
[cat_l2: 10]
|
||||||
|
[cat_smooth: 10]
|
||||||
|
[max_cat_to_onehot: 4]
|
||||||
|
[top_k: 20]
|
||||||
|
[monotone_constraints: ]
|
||||||
|
[monotone_constraints_method: basic]
|
||||||
|
[monotone_penalty: 0]
|
||||||
|
[feature_contri: ]
|
||||||
|
[forcedsplits_filename: ]
|
||||||
|
[refit_decay_rate: 0.9]
|
||||||
|
[cegb_tradeoff: 1]
|
||||||
|
[cegb_penalty_split: 0]
|
||||||
|
[cegb_penalty_feature_lazy: ]
|
||||||
|
[cegb_penalty_feature_coupled: ]
|
||||||
|
[path_smooth: 0]
|
||||||
|
[interaction_constraints: ]
|
||||||
|
[verbosity: -1]
|
||||||
|
[saved_feature_importance_type: 0]
|
||||||
|
[use_quantized_grad: 0]
|
||||||
|
[num_grad_quant_bins: 4]
|
||||||
|
[quant_train_renew_leaf: 0]
|
||||||
|
[stochastic_rounding: 1]
|
||||||
|
[linear_tree: 0]
|
||||||
|
[max_bin: 255]
|
||||||
|
[max_bin_by_feature: ]
|
||||||
|
[min_data_in_bin: 3]
|
||||||
|
[bin_construct_sample_cnt: 200000]
|
||||||
|
[data_random_seed: 175]
|
||||||
|
[is_enable_sparse: 1]
|
||||||
|
[enable_bundle: 1]
|
||||||
|
[use_missing: 1]
|
||||||
|
[zero_as_missing: 0]
|
||||||
|
[feature_pre_filter: 1]
|
||||||
|
[pre_partition: 0]
|
||||||
|
[two_round: 0]
|
||||||
|
[header: 0]
|
||||||
|
[label_column: ]
|
||||||
|
[weight_column: ]
|
||||||
|
[group_column: ]
|
||||||
|
[ignore_column: ]
|
||||||
|
[categorical_feature: ]
|
||||||
|
[forcedbins_filename: ]
|
||||||
|
[precise_float_parser: 0]
|
||||||
|
[parser_config_file: ]
|
||||||
|
[objective_seed: 16083]
|
||||||
|
[num_class: 1]
|
||||||
|
[is_unbalance: 0]
|
||||||
|
[scale_pos_weight: 1]
|
||||||
|
[sigmoid: 1]
|
||||||
|
[boost_from_average: 1]
|
||||||
|
[reg_sqrt: 0]
|
||||||
|
[alpha: 0.9]
|
||||||
|
[fair_c: 1]
|
||||||
|
[poisson_max_delta_step: 0.7]
|
||||||
|
[tweedie_variance_power: 1.5]
|
||||||
|
[lambdarank_truncation_level: 30]
|
||||||
|
[lambdarank_norm: 1]
|
||||||
|
[label_gain: ]
|
||||||
|
[lambdarank_position_bias_regularization: 0]
|
||||||
|
[eval_at: ]
|
||||||
|
[multi_error_top_k: 1]
|
||||||
|
[auc_mu_weights: ]
|
||||||
|
[num_machines: 1]
|
||||||
|
[local_listen_port: 12400]
|
||||||
|
[time_out: 120]
|
||||||
|
[machine_list_filename: ]
|
||||||
|
[machines: ]
|
||||||
|
[gpu_platform_id: -1]
|
||||||
|
[gpu_device_id: -1]
|
||||||
|
[gpu_use_dp: 0]
|
||||||
|
[num_gpu: 1]
|
||||||
|
|
||||||
|
end of parameters
|
||||||
|
|
||||||
|
pandas_categorical:null
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,456 @@
|
|||||||
|
"""
|
||||||
|
Calibration Module for XGBoost Models
|
||||||
|
=====================================
|
||||||
|
Calibrates raw probabilities from XGBoost models using Isotonic Regression.
|
||||||
|
Ensures that a predicted probability of 70% actually corresponds to a 70% win rate.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
from ai_engine.models.calibration import Calibrator
|
||||||
|
calibrator = Calibrator()
|
||||||
|
calibrated_prob = calibrator.calibrate("ms", raw_prob)
|
||||||
|
|
||||||
|
# Training new calibration models:
|
||||||
|
calibrator.train_calibration(valid_df, market="ms")
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import pickle
|
||||||
|
import json
|
||||||
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
|
from datetime import datetime
|
||||||
|
from typing import Dict, List, Optional, Tuple, Any
|
||||||
|
from sklearn.isotonic import IsotonicRegression
|
||||||
|
from sklearn.calibration import calibration_curve
|
||||||
|
from sklearn.metrics import brier_score_loss
|
||||||
|
|
||||||
|
AI_ENGINE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
CALIBRATION_DIR = os.path.join(AI_ENGINE_DIR, "models", "calibration")
|
||||||
|
|
||||||
|
os.makedirs(CALIBRATION_DIR, exist_ok=True)
|
||||||
|
|
||||||
|
# Supported markets for calibration
|
||||||
|
SUPPORTED_MARKETS = [
|
||||||
|
"ms", # Match Result (1X2) - multi-class, calibrated per class
|
||||||
|
"ms_home", # Standard Home win probability
|
||||||
|
"ms_home_heavy_fav", # Context: home odds <= 1.40
|
||||||
|
"ms_home_fav", # Context: 1.40 < home odds <= 1.80
|
||||||
|
"ms_home_balanced", # Context: 1.80 < home odds <= 2.50
|
||||||
|
"ms_home_underdog", # Context: home odds > 2.50
|
||||||
|
"ms_draw", # Draw probability
|
||||||
|
"ms_away", # Away win probability
|
||||||
|
"ou15", # Over/Under 1.5
|
||||||
|
"ou25", # Over/Under 2.5
|
||||||
|
"ou35", # Over/Under 3.5
|
||||||
|
"btts", # Both Teams to Score
|
||||||
|
"ht_ft", # Half-Time/Full-Time
|
||||||
|
"dc", # Double Chance
|
||||||
|
"ht", # Half-Time Result
|
||||||
|
"ht_home", # Half-Time Home win
|
||||||
|
"ht_draw", # Half-Time Draw
|
||||||
|
"ht_away", # Half-Time Away win
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class CalibrationMetrics:
|
||||||
|
"""Stores calibration quality metrics for a market."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.brier_score: float = 0.0
|
||||||
|
self.calibration_error: float = 0.0
|
||||||
|
self.sample_count: int = 0
|
||||||
|
self.last_trained: str = ""
|
||||||
|
self.mean_predicted: float = 0.0
|
||||||
|
self.mean_actual: float = 0.0
|
||||||
|
|
||||||
|
def to_dict(self) -> Dict:
|
||||||
|
return {
|
||||||
|
"brier_score": round(self.brier_score, 4),
|
||||||
|
"calibration_error": round(self.calibration_error, 4),
|
||||||
|
"sample_count": self.sample_count,
|
||||||
|
"last_trained": self.last_trained,
|
||||||
|
"mean_predicted": round(self.mean_predicted, 4),
|
||||||
|
"mean_actual": round(self.mean_actual, 4),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Calibrator:
|
||||||
|
"""
|
||||||
|
Probability calibration using Isotonic Regression.
|
||||||
|
|
||||||
|
Isotonic Regression is a non-parametric method that fits a piecewise
|
||||||
|
constant function that is monotonically increasing. It's ideal for
|
||||||
|
calibrating probabilities because:
|
||||||
|
|
||||||
|
1. It preserves ranking (if P(A) > P(B) before, P(A) > P(B) after)
|
||||||
|
2. It doesn't assume a specific distribution shape
|
||||||
|
3. It can correct systematic over/under-confidence
|
||||||
|
|
||||||
|
Example:
|
||||||
|
# Before calibration: model predicts 70% but actual win rate is 60%
|
||||||
|
# After calibration: model predicts 70% → calibrated to 60%
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.calibrators: Dict[str, IsotonicRegression] = {}
|
||||||
|
self.metrics: Dict[str, CalibrationMetrics] = {}
|
||||||
|
# Less aggressive shrinkage — only meaningful overconfident bands are pulled.
|
||||||
|
# Default raised from ~0.85-0.90 to 0.95+ since the orchestrator and config
|
||||||
|
# already apply market-level multipliers; double-shrinkage was the root cause
|
||||||
|
# of 24-35pt avg calibrated-vs-raw drops in production traces.
|
||||||
|
self.heuristic_fallback: Dict[str, float] = {
|
||||||
|
"ms": 0.96,
|
||||||
|
"ms_home": 0.96,
|
||||||
|
"ms_home_heavy_fav": 0.98,
|
||||||
|
"ms_home_fav": 0.96,
|
||||||
|
"ms_home_balanced": 0.94,
|
||||||
|
"ms_home_underdog": 0.92,
|
||||||
|
"ms_draw": 0.94,
|
||||||
|
"ms_away": 0.96,
|
||||||
|
"ou15": 0.96,
|
||||||
|
"ou25": 0.96,
|
||||||
|
"ou35": 0.94,
|
||||||
|
"btts": 0.96,
|
||||||
|
"ht_ft": 0.92,
|
||||||
|
"dc": 0.97,
|
||||||
|
"ht": 0.92,
|
||||||
|
"ht_home": 0.92,
|
||||||
|
"ht_draw": 0.92,
|
||||||
|
"ht_away": 0.92,
|
||||||
|
}
|
||||||
|
self._load_calibrators()
|
||||||
|
|
||||||
|
def _load_calibrators(self):
|
||||||
|
"""Load trained calibrators for each market from disk."""
|
||||||
|
for market in SUPPORTED_MARKETS:
|
||||||
|
model_path = os.path.join(CALIBRATION_DIR, f"{market}_calibrator.pkl")
|
||||||
|
metrics_path = os.path.join(CALIBRATION_DIR, f"{market}_metrics.json")
|
||||||
|
|
||||||
|
if os.path.exists(model_path):
|
||||||
|
try:
|
||||||
|
with open(model_path, "rb") as f:
|
||||||
|
self.calibrators[market] = pickle.load(f)
|
||||||
|
print(f"[Calibrator] Loaded calibration model for {market}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[Calibrator] Warning: Failed to load {market}: {e}")
|
||||||
|
|
||||||
|
if os.path.exists(metrics_path):
|
||||||
|
try:
|
||||||
|
with open(metrics_path, "r") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
metrics = CalibrationMetrics()
|
||||||
|
metrics.brier_score = data.get("brier_score", 0.0)
|
||||||
|
metrics.calibration_error = data.get("calibration_error", 0.0)
|
||||||
|
metrics.sample_count = data.get("sample_count", 0)
|
||||||
|
metrics.last_trained = data.get("last_trained", "")
|
||||||
|
metrics.mean_predicted = data.get("mean_predicted", 0.0)
|
||||||
|
metrics.mean_actual = data.get("mean_actual", 0.0)
|
||||||
|
self.metrics[market] = metrics
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[Calibrator] Warning: Failed to load metrics for {market}: {e}")
|
||||||
|
|
||||||
|
# Below this sample count, blend isotonic with raw_prob to dampen overfit jumps.
|
||||||
|
# Above this count, trust isotonic fully.
|
||||||
|
TRUSTED_SAMPLE_FLOOR = 30
|
||||||
|
TRUSTED_SAMPLE_CEILING = 200
|
||||||
|
# Hard cap on how far calibration can move probability in either direction.
|
||||||
|
MAX_DELTA = 0.20
|
||||||
|
|
||||||
|
def calibrate(self, market_type: str, raw_prob: float, odds_val: Optional[float] = None) -> float:
|
||||||
|
"""
|
||||||
|
Calibrate a raw probability using Isotonic Regression with safeguards.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
market_type (str): 'ms_home', 'ou25', 'btts', 'ht_ft', etc.
|
||||||
|
raw_prob (float): The raw probability from XGBoost (0.0 - 1.0)
|
||||||
|
odds_val (float, optional): The pre-match odds, used for context-aware bucket mapping
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
float: Calibrated probability (0.0 - 1.0)
|
||||||
|
|
||||||
|
Safeguards:
|
||||||
|
* Low-sample trained models are blended with raw_prob to dampen overfit.
|
||||||
|
* MAX_DELTA caps the per-call adjustment (prevents 40pp swings).
|
||||||
|
"""
|
||||||
|
# Normalize market type
|
||||||
|
market_key = market_type.lower().replace("-", "_")
|
||||||
|
|
||||||
|
# Route to bucket if ms_home and odds provided
|
||||||
|
if market_key == "ms_home" and odds_val is not None and odds_val > 1.0:
|
||||||
|
if odds_val <= 1.40:
|
||||||
|
bucket_key = "ms_home_heavy_fav"
|
||||||
|
elif odds_val <= 1.80:
|
||||||
|
bucket_key = "ms_home_fav"
|
||||||
|
elif odds_val <= 2.50:
|
||||||
|
bucket_key = "ms_home_balanced"
|
||||||
|
else:
|
||||||
|
bucket_key = "ms_home_underdog"
|
||||||
|
|
||||||
|
if bucket_key in self.calibrators:
|
||||||
|
market_key = bucket_key
|
||||||
|
|
||||||
|
# If we have a trained Isotonic Regression model, use it (with safeguards)
|
||||||
|
if market_key in self.calibrators:
|
||||||
|
try:
|
||||||
|
iso_pred = float(self.calibrators[market_key].predict([raw_prob])[0])
|
||||||
|
|
||||||
|
# Sample-count weighted blend with raw probability.
|
||||||
|
# Sparse models barely move probability; mature models dominate.
|
||||||
|
metrics = self.metrics.get(market_key)
|
||||||
|
n_samples = metrics.sample_count if metrics else 0
|
||||||
|
if n_samples >= self.TRUSTED_SAMPLE_CEILING:
|
||||||
|
iso_weight = 1.0
|
||||||
|
elif n_samples <= self.TRUSTED_SAMPLE_FLOOR:
|
||||||
|
# Very sparse: at least 30% trust to surface the signal
|
||||||
|
iso_weight = max(0.30, n_samples / self.TRUSTED_SAMPLE_CEILING)
|
||||||
|
else:
|
||||||
|
# Linearly ramp 30% → 100% between floor and ceiling
|
||||||
|
span = self.TRUSTED_SAMPLE_CEILING - self.TRUSTED_SAMPLE_FLOOR
|
||||||
|
iso_weight = 0.30 + 0.70 * (n_samples - self.TRUSTED_SAMPLE_FLOOR) / span
|
||||||
|
blended = iso_weight * iso_pred + (1.0 - iso_weight) * raw_prob
|
||||||
|
|
||||||
|
# Cap delta to avoid huge swings on noisy calibrators
|
||||||
|
delta = blended - raw_prob
|
||||||
|
if delta > self.MAX_DELTA:
|
||||||
|
blended = raw_prob + self.MAX_DELTA
|
||||||
|
elif delta < -self.MAX_DELTA:
|
||||||
|
blended = raw_prob - self.MAX_DELTA
|
||||||
|
|
||||||
|
return float(np.clip(blended, 0.01, 0.99))
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[Calibrator] Warning: Isotonic failed for {market_key}: {e}")
|
||||||
|
# Fall through to heuristic
|
||||||
|
|
||||||
|
# Fallback to heuristic calibration
|
||||||
|
return self._heuristic_calibrate(market_key, raw_prob)
|
||||||
|
|
||||||
|
def _heuristic_calibrate(self, market_type: str, raw_prob: float) -> float:
|
||||||
|
"""
|
||||||
|
Heuristic calibration fallback when no trained model exists.
|
||||||
|
|
||||||
|
This applies a conservative shrinkage towards the mean:
|
||||||
|
- Binary markets (OU, BTTS): shrink towards 0.5
|
||||||
|
- Multi-class (MS): shrink towards 0.33
|
||||||
|
- HT/FT: stronger shrinkage due to higher variance
|
||||||
|
"""
|
||||||
|
# Get shrinkage factor for this market
|
||||||
|
shrinkage = self.heuristic_fallback.get(market_type, 0.90)
|
||||||
|
|
||||||
|
if market_type in ["ms", "ms_home", "ms_home_heavy_fav", "ms_home_fav", "ms_home_balanced", "ms_home_underdog", "ms_draw", "ms_away"]:
|
||||||
|
# Pull towards 0.33 (uniform for 3-class)
|
||||||
|
return (raw_prob * shrinkage) + (0.33 * (1.0 - shrinkage))
|
||||||
|
|
||||||
|
elif market_type in ["ou15", "ou25", "ou35", "btts"]:
|
||||||
|
# Pull towards 0.5 (uniform for binary)
|
||||||
|
return (raw_prob * shrinkage) + (0.5 * (1.0 - shrinkage))
|
||||||
|
|
||||||
|
elif market_type in ["ht_ft", "ht"]:
|
||||||
|
# Stronger shrinkage for high-variance markets
|
||||||
|
return raw_prob * shrinkage
|
||||||
|
|
||||||
|
elif market_type == "dc":
|
||||||
|
# Double chance is more reliable
|
||||||
|
return (raw_prob * shrinkage) + (0.66 * (1.0 - shrinkage))
|
||||||
|
|
||||||
|
return raw_prob
|
||||||
|
|
||||||
|
def train_calibration(
|
||||||
|
self,
|
||||||
|
df: pd.DataFrame,
|
||||||
|
market: str,
|
||||||
|
prob_col: str,
|
||||||
|
actual_col: str,
|
||||||
|
min_samples: int = 100,
|
||||||
|
save: bool = True,
|
||||||
|
) -> CalibrationMetrics:
|
||||||
|
"""
|
||||||
|
Train an Isotonic Regression calibration model for a specific market.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: DataFrame with predictions and actual outcomes
|
||||||
|
market: Market identifier (e.g., 'ms_home', 'ou25', 'btts')
|
||||||
|
prob_col: Column name for raw probabilities
|
||||||
|
actual_col: Column name for actual outcomes (0 or 1)
|
||||||
|
min_samples: Minimum samples required to train
|
||||||
|
save: Whether to save the model to disk
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
CalibrationMetrics with quality metrics
|
||||||
|
"""
|
||||||
|
# Filter valid data
|
||||||
|
valid_df = df[[prob_col, actual_col]].dropna()
|
||||||
|
n_samples = len(valid_df)
|
||||||
|
|
||||||
|
if n_samples < min_samples:
|
||||||
|
print(f"[Calibrator] Warning: Only {n_samples} samples for {market}, "
|
||||||
|
f"need at least {min_samples}")
|
||||||
|
metrics = CalibrationMetrics()
|
||||||
|
metrics.sample_count = n_samples
|
||||||
|
return metrics
|
||||||
|
|
||||||
|
# Extract arrays
|
||||||
|
raw_probs = valid_df[prob_col].values
|
||||||
|
actuals = valid_df[actual_col].values
|
||||||
|
|
||||||
|
# Train Isotonic Regression
|
||||||
|
iso = IsotonicRegression(out_of_bounds="clip", increasing=True)
|
||||||
|
iso.fit(raw_probs, actuals)
|
||||||
|
|
||||||
|
# Calculate calibrated probabilities
|
||||||
|
calibrated_probs = iso.predict(raw_probs)
|
||||||
|
|
||||||
|
# Calculate metrics
|
||||||
|
metrics = CalibrationMetrics()
|
||||||
|
metrics.sample_count = n_samples
|
||||||
|
metrics.last_trained = datetime.utcnow().isoformat()
|
||||||
|
metrics.brier_score = brier_score_loss(actuals, calibrated_probs)
|
||||||
|
metrics.mean_predicted = np.mean(raw_probs)
|
||||||
|
metrics.mean_actual = np.mean(actuals)
|
||||||
|
|
||||||
|
# Calculate Expected Calibration Error (ECE)
|
||||||
|
metrics.calibration_error = self._calculate_ece(
|
||||||
|
calibrated_probs, actuals, n_bins=10
|
||||||
|
)
|
||||||
|
|
||||||
|
# Store in memory
|
||||||
|
self.calibrators[market] = iso
|
||||||
|
self.metrics[market] = metrics
|
||||||
|
|
||||||
|
# Save to disk
|
||||||
|
if save:
|
||||||
|
self._save_calibration(market, iso, metrics)
|
||||||
|
|
||||||
|
print(f"[Calibrator] Trained {market}: "
|
||||||
|
f"Brier={metrics.brier_score:.4f}, "
|
||||||
|
f"ECE={metrics.calibration_error:.4f}, "
|
||||||
|
f"n={n_samples}")
|
||||||
|
|
||||||
|
return metrics
|
||||||
|
|
||||||
|
def train_all_markets(
|
||||||
|
self,
|
||||||
|
df: pd.DataFrame,
|
||||||
|
market_config: Dict[str, Tuple[str, str]],
|
||||||
|
min_samples: int = 100,
|
||||||
|
) -> Dict[str, CalibrationMetrics]:
|
||||||
|
"""
|
||||||
|
Train calibration models for multiple markets at once.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: DataFrame with all predictions and outcomes
|
||||||
|
market_config: Dict mapping market -> (prob_col, actual_col)
|
||||||
|
e.g., {'ou25': ('ou25_over_prob', 'ou25_over_actual')}
|
||||||
|
min_samples: Minimum samples per market
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dict of market -> CalibrationMetrics
|
||||||
|
"""
|
||||||
|
results = {}
|
||||||
|
|
||||||
|
for market, (prob_col, actual_col) in market_config.items():
|
||||||
|
print(f"\n[Calibrator] Training {market}...")
|
||||||
|
try:
|
||||||
|
metrics = self.train_calibration(
|
||||||
|
df=df,
|
||||||
|
market=market,
|
||||||
|
prob_col=prob_col,
|
||||||
|
actual_col=actual_col,
|
||||||
|
min_samples=min_samples,
|
||||||
|
save=True,
|
||||||
|
)
|
||||||
|
results[market] = metrics
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[Calibrator] Failed to train {market}: {e}")
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
def _calculate_ece(
|
||||||
|
self,
|
||||||
|
probs: np.ndarray,
|
||||||
|
actuals: np.ndarray,
|
||||||
|
n_bins: int = 10
|
||||||
|
) -> float:
|
||||||
|
"""
|
||||||
|
Calculate Expected Calibration Error (ECE).
|
||||||
|
|
||||||
|
ECE = sum(|bin_accuracy - bin_confidence| * bin_weight)
|
||||||
|
|
||||||
|
Lower is better. Perfect calibration = 0.
|
||||||
|
"""
|
||||||
|
bin_boundaries = np.linspace(0, 1, n_bins + 1)
|
||||||
|
ece = 0.0
|
||||||
|
|
||||||
|
for i in range(n_bins):
|
||||||
|
in_bin = (probs >= bin_boundaries[i]) & (probs < bin_boundaries[i + 1])
|
||||||
|
prop_in_bin = np.mean(in_bin)
|
||||||
|
|
||||||
|
if prop_in_bin > 0:
|
||||||
|
accuracy_in_bin = np.mean(actuals[in_bin])
|
||||||
|
avg_confidence_in_bin = np.mean(probs[in_bin])
|
||||||
|
ece += np.abs(accuracy_in_bin - avg_confidence_in_bin) * prop_in_bin
|
||||||
|
|
||||||
|
return ece
|
||||||
|
|
||||||
|
def _save_calibration(
|
||||||
|
self,
|
||||||
|
market: str,
|
||||||
|
calibrator: IsotonicRegression,
|
||||||
|
metrics: CalibrationMetrics
|
||||||
|
):
|
||||||
|
"""Save calibration model and metrics to disk."""
|
||||||
|
# Save model
|
||||||
|
model_path = os.path.join(CALIBRATION_DIR, f"{market}_calibrator.pkl")
|
||||||
|
with open(model_path, "wb") as f:
|
||||||
|
pickle.dump(calibrator, f)
|
||||||
|
|
||||||
|
# Save metrics
|
||||||
|
metrics_path = os.path.join(CALIBRATION_DIR, f"{market}_metrics.json")
|
||||||
|
with open(metrics_path, "w") as f:
|
||||||
|
json.dump(metrics.to_dict(), f, indent=2)
|
||||||
|
|
||||||
|
print(f"[Calibrator] Saved {market} to {CALIBRATION_DIR}")
|
||||||
|
|
||||||
|
def get_calibration_report(self) -> Dict[str, Any]:
|
||||||
|
"""Generate a summary report of all calibration models."""
|
||||||
|
report = {
|
||||||
|
"trained_markets": list(self.calibrators.keys()),
|
||||||
|
"metrics": {},
|
||||||
|
"heuristic_only": [],
|
||||||
|
}
|
||||||
|
|
||||||
|
for market in SUPPORTED_MARKETS:
|
||||||
|
if market in self.metrics:
|
||||||
|
report["metrics"][market] = self.metrics[market].to_dict()
|
||||||
|
elif market not in self.calibrators:
|
||||||
|
report["heuristic_only"].append(market)
|
||||||
|
|
||||||
|
return report
|
||||||
|
|
||||||
|
def get_calibrated_probabilities(
|
||||||
|
self,
|
||||||
|
market: str,
|
||||||
|
raw_probs: np.ndarray
|
||||||
|
) -> np.ndarray:
|
||||||
|
"""
|
||||||
|
Batch calibration for array of probabilities.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
market: Market type
|
||||||
|
raw_probs: Array of raw probabilities
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Array of calibrated probabilities
|
||||||
|
"""
|
||||||
|
return np.array([self.calibrate(market, p) for p in raw_probs])
|
||||||
|
|
||||||
|
|
||||||
|
# Singleton instance
|
||||||
|
_calibrator_instance: Optional[Calibrator] = None
|
||||||
|
|
||||||
|
|
||||||
|
def get_calibrator() -> Calibrator:
|
||||||
|
"""Get or create the global Calibrator instance."""
|
||||||
|
global _calibrator_instance
|
||||||
|
if _calibrator_instance is None:
|
||||||
|
_calibrator_instance = Calibrator()
|
||||||
|
return _calibrator_instance
|
||||||
Binary file not shown.
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"brier_score": 0.1264,
|
||||||
|
"calibration_error": 0.0,
|
||||||
|
"sample_count": 26,
|
||||||
|
"last_trained": "2026-05-11T23:38:11.473645",
|
||||||
|
"mean_predicted": 0.757,
|
||||||
|
"mean_actual": 0.6923
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"brier_score": 0.1667,
|
||||||
|
"calibration_error": 0.0,
|
||||||
|
"sample_count": 12,
|
||||||
|
"last_trained": "2026-05-11T23:38:11.484990",
|
||||||
|
"mean_predicted": 0.3579,
|
||||||
|
"mean_actual": 0.25
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"brier_score": 0.196,
|
||||||
|
"calibration_error": 0.0,
|
||||||
|
"sample_count": 13,
|
||||||
|
"last_trained": "2026-05-11T23:38:11.500966",
|
||||||
|
"mean_predicted": 0.7239,
|
||||||
|
"mean_actual": 0.6154
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"brier_score": 0.2222,
|
||||||
|
"calibration_error": 0.0,
|
||||||
|
"sample_count": 18,
|
||||||
|
"last_trained": "2026-05-11T23:38:11.508353",
|
||||||
|
"mean_predicted": 0.6258,
|
||||||
|
"mean_actual": 0.5
|
||||||
|
}
|
||||||
@@ -0,0 +1,191 @@
|
|||||||
|
"""
|
||||||
|
League-Specific Model Loader
|
||||||
|
=============================
|
||||||
|
Loads per-league XGBoost models + isotonic calibrators trained by
|
||||||
|
scripts/train_league_models.py and provides a unified prediction interface.
|
||||||
|
|
||||||
|
Falls back to general V25 for any market/league without a dedicated model.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import pickle
|
||||||
|
from functools import lru_cache
|
||||||
|
from typing import Dict, Optional, Tuple
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
|
import xgboost as xgb
|
||||||
|
|
||||||
|
AI_ENGINE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
LEAGUE_MODEL_DIR = os.path.join(AI_ENGINE_DIR, "models", "league_specific")
|
||||||
|
|
||||||
|
# Market file name → (num_class, label_list)
|
||||||
|
MARKET_META: Dict[str, Tuple[int, list]] = {
|
||||||
|
"ms": (3, ["1", "X", "2"]),
|
||||||
|
"ou15": (2, ["Over", "Under"]),
|
||||||
|
"ou25": (2, ["Over", "Under"]),
|
||||||
|
"ou35": (2, ["Over", "Under"]),
|
||||||
|
"btts": (2, ["Yes", "No"]),
|
||||||
|
"ht": (3, ["1", "X", "2"]),
|
||||||
|
"ht_ou05": (2, ["Over", "Under"]),
|
||||||
|
"ht_ou15": (2, ["Over", "Under"]),
|
||||||
|
"htft": (9, ["1/1","1/X","1/2","X/1","X/X","X/2","2/1","2/X","2/2"]),
|
||||||
|
"oe": (2, ["Odd", "Even"]),
|
||||||
|
"cards": (2, ["Over", "Under"]),
|
||||||
|
"handicap": (3, ["1", "X", "2"]),
|
||||||
|
}
|
||||||
|
|
||||||
|
# Signal key map (file key → uppercase signal key used in _get_v25_signal)
|
||||||
|
FILE_TO_SIGNAL = {
|
||||||
|
"ms": "MS", "ou15": "OU15", "ou25": "OU25", "ou35": "OU35",
|
||||||
|
"btts": "BTTS", "ht": "HT", "ht_ou05": "HT_OU05", "ht_ou15": "HT_OU15",
|
||||||
|
"htft": "HTFT", "oe": "OE", "cards": "CARDS", "handicap": "HCAP",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class LeagueModel:
|
||||||
|
"""Holds XGBoost models + isotonic calibrators for one league."""
|
||||||
|
|
||||||
|
def __init__(self, league_id: str):
|
||||||
|
self.league_id = league_id
|
||||||
|
self.league_dir = os.path.join(LEAGUE_MODEL_DIR, league_id)
|
||||||
|
self.models: Dict[str, xgb.Booster] = {} # market_key → booster
|
||||||
|
self.calibrators: Dict[str, object] = {} # cal_key → isotonic
|
||||||
|
self.feature_cols: Optional[list] = None
|
||||||
|
self._loaded = False
|
||||||
|
|
||||||
|
def load(self) -> bool:
|
||||||
|
if not os.path.isdir(self.league_dir):
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
fc_path = os.path.join(self.league_dir, "feature_cols.json")
|
||||||
|
if os.path.exists(fc_path):
|
||||||
|
with open(fc_path) as f:
|
||||||
|
self.feature_cols = json.load(f)
|
||||||
|
|
||||||
|
for mkey in MARKET_META:
|
||||||
|
xgb_path = os.path.join(self.league_dir, f"xgb_{mkey}.json")
|
||||||
|
if os.path.exists(xgb_path) and os.path.getsize(xgb_path) > 100:
|
||||||
|
b = xgb.Booster()
|
||||||
|
b.load_model(xgb_path)
|
||||||
|
self.models[mkey] = b
|
||||||
|
|
||||||
|
for fname in os.listdir(self.league_dir):
|
||||||
|
if fname.startswith("cal_") and fname.endswith(".pkl"):
|
||||||
|
cal_key = fname[4:-4] # strip cal_ and .pkl
|
||||||
|
with open(os.path.join(self.league_dir, fname), "rb") as f:
|
||||||
|
self.calibrators[cal_key] = pickle.load(f)
|
||||||
|
|
||||||
|
self._loaded = bool(self.models or self.calibrators)
|
||||||
|
return self._loaded
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[LeagueModel] Load failed for {self.league_id}: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def has_market(self, mkey: str) -> bool:
|
||||||
|
return mkey in self.models
|
||||||
|
|
||||||
|
def predict_market(
|
||||||
|
self,
|
||||||
|
mkey: str,
|
||||||
|
feature_row: Dict[str, float],
|
||||||
|
) -> Optional[Dict[str, float]]:
|
||||||
|
"""
|
||||||
|
Predict one market using league-specific XGBoost + isotonic calibration.
|
||||||
|
Returns {label: prob} dict or None if no model available.
|
||||||
|
"""
|
||||||
|
if mkey not in self.models:
|
||||||
|
return None
|
||||||
|
|
||||||
|
num_class, labels = MARKET_META[mkey]
|
||||||
|
fc = self.feature_cols
|
||||||
|
if fc is None:
|
||||||
|
# Fallback to whatever the booster expects (it knows its feature names)
|
||||||
|
fc = list(self.models[mkey].feature_names or [])
|
||||||
|
|
||||||
|
try:
|
||||||
|
X = pd.DataFrame([{col: feature_row.get(col, 0.0) for col in fc}])
|
||||||
|
dmat = xgb.DMatrix(X)
|
||||||
|
raw = self.models[mkey].predict(dmat)
|
||||||
|
|
||||||
|
if num_class > 2:
|
||||||
|
probs_arr = raw.reshape(-1, num_class)[0]
|
||||||
|
probs = {labels[i]: float(probs_arr[i]) for i in range(num_class)}
|
||||||
|
# Apply isotonic calibration per class
|
||||||
|
cal_total = 0.0
|
||||||
|
for i, label in enumerate(labels):
|
||||||
|
cal_key = f"{mkey}_{i}"
|
||||||
|
if cal_key in self.calibrators:
|
||||||
|
p_cal = float(self.calibrators[cal_key].predict([probs_arr[i]])[0])
|
||||||
|
probs[label] = max(0.01, min(0.99, p_cal))
|
||||||
|
cal_total += probs[label]
|
||||||
|
if cal_total > 0:
|
||||||
|
probs = {k: v / cal_total for k, v in probs.items()}
|
||||||
|
else:
|
||||||
|
p = float(raw[0])
|
||||||
|
cal_key = mkey
|
||||||
|
if cal_key in self.calibrators:
|
||||||
|
p = float(self.calibrators[cal_key].predict([p])[0])
|
||||||
|
p = max(0.01, min(0.99, p))
|
||||||
|
probs = {labels[0]: p, labels[1]: 1.0 - p}
|
||||||
|
|
||||||
|
return probs
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[LeagueModel] predict_market({mkey}) failed for {self.league_id}: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class LeagueModelLoader:
|
||||||
|
"""
|
||||||
|
In-memory cache for league-specific models.
|
||||||
|
Thread-safe for single-process async servers (FastAPI/uvicorn).
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, max_cached: int = 80):
|
||||||
|
self._cache: Dict[str, Optional[LeagueModel]] = {}
|
||||||
|
self._max_cached = max_cached
|
||||||
|
|
||||||
|
def get(self, league_id: str) -> Optional[LeagueModel]:
|
||||||
|
"""Return loaded LeagueModel for this league, or None if unavailable."""
|
||||||
|
if league_id in self._cache:
|
||||||
|
return self._cache[league_id]
|
||||||
|
|
||||||
|
# Evict oldest entry if cache is full
|
||||||
|
if len(self._cache) >= self._max_cached:
|
||||||
|
oldest = next(iter(self._cache))
|
||||||
|
del self._cache[oldest]
|
||||||
|
|
||||||
|
model = LeagueModel(league_id)
|
||||||
|
loaded = model.load()
|
||||||
|
self._cache[league_id] = model if loaded else None
|
||||||
|
if loaded:
|
||||||
|
n_models = len(model.models)
|
||||||
|
n_cals = len(model.calibrators)
|
||||||
|
print(f"[LeagueModel] Loaded {league_id}: {n_models} XGB models, {n_cals} calibrators")
|
||||||
|
return self._cache[league_id]
|
||||||
|
|
||||||
|
def available_leagues(self) -> list:
|
||||||
|
if not os.path.isdir(LEAGUE_MODEL_DIR):
|
||||||
|
return []
|
||||||
|
return [d for d in os.listdir(LEAGUE_MODEL_DIR)
|
||||||
|
if os.path.isdir(os.path.join(LEAGUE_MODEL_DIR, d))]
|
||||||
|
|
||||||
|
def readiness_summary(self) -> dict:
|
||||||
|
leagues = self.available_leagues()
|
||||||
|
return {
|
||||||
|
"league_specific_dir": LEAGUE_MODEL_DIR,
|
||||||
|
"available_leagues": len(leagues),
|
||||||
|
"cached": len([v for v in self._cache.values() if v is not None]),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# ── Singleton ──────────────────────────────────────────────────────
|
||||||
|
_loader: Optional[LeagueModelLoader] = None
|
||||||
|
|
||||||
|
|
||||||
|
def get_league_model_loader() -> LeagueModelLoader:
|
||||||
|
global _loader
|
||||||
|
if _loader is None:
|
||||||
|
_loader = LeagueModelLoader()
|
||||||
|
return _loader
|
||||||
Binary file not shown.
@@ -0,0 +1,154 @@
|
|||||||
|
[
|
||||||
|
"home_overall_elo",
|
||||||
|
"away_overall_elo",
|
||||||
|
"elo_diff",
|
||||||
|
"home_home_elo",
|
||||||
|
"away_away_elo",
|
||||||
|
"home_form_elo",
|
||||||
|
"away_form_elo",
|
||||||
|
"form_elo_diff",
|
||||||
|
"home_goals_avg",
|
||||||
|
"home_conceded_avg",
|
||||||
|
"away_goals_avg",
|
||||||
|
"away_conceded_avg",
|
||||||
|
"home_clean_sheet_rate",
|
||||||
|
"away_clean_sheet_rate",
|
||||||
|
"home_scoring_rate",
|
||||||
|
"away_scoring_rate",
|
||||||
|
"home_winning_streak",
|
||||||
|
"away_winning_streak",
|
||||||
|
"home_unbeaten_streak",
|
||||||
|
"away_unbeaten_streak",
|
||||||
|
"h2h_total_matches",
|
||||||
|
"h2h_home_win_rate",
|
||||||
|
"h2h_draw_rate",
|
||||||
|
"h2h_avg_goals",
|
||||||
|
"h2h_btts_rate",
|
||||||
|
"h2h_over25_rate",
|
||||||
|
"home_avg_possession",
|
||||||
|
"away_avg_possession",
|
||||||
|
"home_avg_shots_on_target",
|
||||||
|
"away_avg_shots_on_target",
|
||||||
|
"home_shot_conversion",
|
||||||
|
"away_shot_conversion",
|
||||||
|
"home_avg_corners",
|
||||||
|
"away_avg_corners",
|
||||||
|
"odds_ms_h",
|
||||||
|
"odds_ms_d",
|
||||||
|
"odds_ms_a",
|
||||||
|
"implied_home",
|
||||||
|
"implied_draw",
|
||||||
|
"implied_away",
|
||||||
|
"odds_ht_ms_h",
|
||||||
|
"odds_ht_ms_d",
|
||||||
|
"odds_ht_ms_a",
|
||||||
|
"odds_ou05_o",
|
||||||
|
"odds_ou05_u",
|
||||||
|
"odds_ou15_o",
|
||||||
|
"odds_ou15_u",
|
||||||
|
"odds_ou25_o",
|
||||||
|
"odds_ou25_u",
|
||||||
|
"odds_ou35_o",
|
||||||
|
"odds_ou35_u",
|
||||||
|
"odds_ht_ou05_o",
|
||||||
|
"odds_ht_ou05_u",
|
||||||
|
"odds_ht_ou15_o",
|
||||||
|
"odds_ht_ou15_u",
|
||||||
|
"odds_btts_y",
|
||||||
|
"odds_btts_n",
|
||||||
|
"odds_ms_h_present",
|
||||||
|
"odds_ms_d_present",
|
||||||
|
"odds_ms_a_present",
|
||||||
|
"odds_ht_ms_h_present",
|
||||||
|
"odds_ht_ms_d_present",
|
||||||
|
"odds_ht_ms_a_present",
|
||||||
|
"odds_ou05_o_present",
|
||||||
|
"odds_ou05_u_present",
|
||||||
|
"odds_ou15_o_present",
|
||||||
|
"odds_ou15_u_present",
|
||||||
|
"odds_ou25_o_present",
|
||||||
|
"odds_ou25_u_present",
|
||||||
|
"odds_ou35_o_present",
|
||||||
|
"odds_ou35_u_present",
|
||||||
|
"odds_ht_ou05_o_present",
|
||||||
|
"odds_ht_ou05_u_present",
|
||||||
|
"odds_ht_ou15_o_present",
|
||||||
|
"odds_ht_ou15_u_present",
|
||||||
|
"odds_btts_y_present",
|
||||||
|
"odds_btts_n_present",
|
||||||
|
"home_xga",
|
||||||
|
"away_xga",
|
||||||
|
"league_avg_goals",
|
||||||
|
"league_zero_goal_rate",
|
||||||
|
"upset_atmosphere",
|
||||||
|
"upset_motivation",
|
||||||
|
"upset_fatigue",
|
||||||
|
"upset_potential",
|
||||||
|
"referee_home_bias",
|
||||||
|
"referee_avg_goals",
|
||||||
|
"referee_cards_total",
|
||||||
|
"referee_avg_yellow",
|
||||||
|
"referee_experience",
|
||||||
|
"home_momentum_score",
|
||||||
|
"away_momentum_score",
|
||||||
|
"momentum_diff",
|
||||||
|
"home_squad_quality",
|
||||||
|
"away_squad_quality",
|
||||||
|
"squad_diff",
|
||||||
|
"home_key_players",
|
||||||
|
"away_key_players",
|
||||||
|
"home_missing_impact",
|
||||||
|
"away_missing_impact",
|
||||||
|
"home_goals_form",
|
||||||
|
"away_goals_form",
|
||||||
|
"home_lineup_goals_per90",
|
||||||
|
"away_lineup_goals_per90",
|
||||||
|
"home_lineup_assists_per90",
|
||||||
|
"away_lineup_assists_per90",
|
||||||
|
"home_squad_continuity",
|
||||||
|
"away_squad_continuity",
|
||||||
|
"home_top_scorer_form",
|
||||||
|
"away_top_scorer_form",
|
||||||
|
"home_avg_player_exp",
|
||||||
|
"away_avg_player_exp",
|
||||||
|
"home_goals_diversity",
|
||||||
|
"away_goals_diversity",
|
||||||
|
"h2h_home_goals_avg",
|
||||||
|
"h2h_away_goals_avg",
|
||||||
|
"h2h_recent_trend",
|
||||||
|
"h2h_venue_advantage",
|
||||||
|
"home_rolling5_goals",
|
||||||
|
"home_rolling5_conceded",
|
||||||
|
"home_rolling10_goals",
|
||||||
|
"home_rolling10_conceded",
|
||||||
|
"home_rolling20_goals",
|
||||||
|
"home_rolling20_conceded",
|
||||||
|
"away_rolling5_goals",
|
||||||
|
"away_rolling5_conceded",
|
||||||
|
"away_rolling10_goals",
|
||||||
|
"away_rolling10_conceded",
|
||||||
|
"home_rolling5_cs",
|
||||||
|
"away_rolling5_cs",
|
||||||
|
"home_venue_goals",
|
||||||
|
"home_venue_conceded",
|
||||||
|
"away_venue_goals",
|
||||||
|
"away_venue_conceded",
|
||||||
|
"home_goal_trend",
|
||||||
|
"away_goal_trend",
|
||||||
|
"home_days_rest",
|
||||||
|
"away_days_rest",
|
||||||
|
"match_month",
|
||||||
|
"is_season_start",
|
||||||
|
"is_season_end",
|
||||||
|
"attack_vs_defense_home",
|
||||||
|
"attack_vs_defense_away",
|
||||||
|
"xg_diff",
|
||||||
|
"form_momentum_interaction",
|
||||||
|
"elo_form_consistency",
|
||||||
|
"upset_x_elo_gap",
|
||||||
|
"league_home_win_rate",
|
||||||
|
"league_draw_rate",
|
||||||
|
"league_btts_rate",
|
||||||
|
"league_ou25_rate",
|
||||||
|
"league_reliability_score"
|
||||||
|
]
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,891 @@
|
|||||||
|
tree
|
||||||
|
version=v4
|
||||||
|
num_class=1
|
||||||
|
num_tree_per_iteration=1
|
||||||
|
label_index=0
|
||||||
|
max_feature_idx=151
|
||||||
|
objective=binary sigmoid:1
|
||||||
|
feature_names=Column_0 Column_1 Column_2 Column_3 Column_4 Column_5 Column_6 Column_7 Column_8 Column_9 Column_10 Column_11 Column_12 Column_13 Column_14 Column_15 Column_16 Column_17 Column_18 Column_19 Column_20 Column_21 Column_22 Column_23 Column_24 Column_25 Column_26 Column_27 Column_28 Column_29 Column_30 Column_31 Column_32 Column_33 Column_34 Column_35 Column_36 Column_37 Column_38 Column_39 Column_40 Column_41 Column_42 Column_43 Column_44 Column_45 Column_46 Column_47 Column_48 Column_49 Column_50 Column_51 Column_52 Column_53 Column_54 Column_55 Column_56 Column_57 Column_58 Column_59 Column_60 Column_61 Column_62 Column_63 Column_64 Column_65 Column_66 Column_67 Column_68 Column_69 Column_70 Column_71 Column_72 Column_73 Column_74 Column_75 Column_76 Column_77 Column_78 Column_79 Column_80 Column_81 Column_82 Column_83 Column_84 Column_85 Column_86 Column_87 Column_88 Column_89 Column_90 Column_91 Column_92 Column_93 Column_94 Column_95 Column_96 Column_97 Column_98 Column_99 Column_100 Column_101 Column_102 Column_103 Column_104 Column_105 Column_106 Column_107 Column_108 Column_109 Column_110 Column_111 Column_112 Column_113 Column_114 Column_115 Column_116 Column_117 Column_118 Column_119 Column_120 Column_121 Column_122 Column_123 Column_124 Column_125 Column_126 Column_127 Column_128 Column_129 Column_130 Column_131 Column_132 Column_133 Column_134 Column_135 Column_136 Column_137 Column_138 Column_139 Column_140 Column_141 Column_142 Column_143 Column_144 Column_145 Column_146 Column_147 Column_148 Column_149 Column_150 Column_151
|
||||||
|
feature_infos=[1150.3663761896189:1903.4781806887747] [1158.5088961211511:1916.84579108047] [-496.81477567713546:573.10259120534784] [1159.8767670517543:1884.5959848901657] [1151.7894548779084:1919.4116678360419] [1426.1496448360797:1585.9817930954068] [1427.9817118206745:1588.9895054335384] [-113.02538114266532:114.69704651598067] [0:5.9333333333333336] [0:6.2666666666666666] [0:6.0666666666666664] [0:5.2000000000000002] [0:1] [0:1] [0:1] [0:1] [0:5] [0:5] [0:5] [0:5] [0:8] [0:1] [0:1] [0:11] [0:1] [0:1] [0.20999999999999999:0.81000000000000005] [0.22500000000000001:0.76000000000000001] [0:13] [0:13] [0:6.333333333333333] [0:6.666666666666667] [0:4.5] [0:4.5] [0:22.550000000000001] [0:17.5] [0:35.5] [0.065285302506677897:0.80962131918207236] [0.1044438556117265:0.4288719106684401] [0.056651501780225801:0.79902050363656307] [0:26] [0:5.0899999999999999] [0:26.5] [0:1.0900000000000001] [0:13.050000000000001] [0:1.76] [0:13.25] [0:3.7400000000000002] [0:7.6500000000000004] [0:8.5600000000000005] [0:3.5299999999999998] [0:1.72] [0:7.3300000000000001] [0:5.0199999999999996] [0:2.5800000000000001] [0:3.77] [0:4.1299999999999999] [0:1] [0:1] [0:1] [0:1] [0:1] [0:1] [0:1] [0:1] [0:1] [0:1] [0:1] [0:1] [0:1] [0:1] [0:1] [0:1] [0:1] [0:1] [0:1] [0:1] [0:6.2666666666666666] [0:5.2000000000000002] [2.0046118370484245:4.1840324763193504] [0.018042399639151999:0.1552651806302843] [0:0.45000000000000001] none none [0:0.1575] [-0.92000000000000004:1] [0:7] none none [0:1] [-1:0.61250000000000004] [-1:0.59166666666666667] [-1.2908333333333333:1.3799999999999999] [0:40.799999999999997] [0:36.299999999999997] [-29.999999999999996:31.499999999999996] [0:10] [0:10] [0:1] [0:1] [0:5.7999999999999998] [0:5] [0:5] [0:6.25] [0:4] [0:5] [0:1] [0:1] [0:10] [0:11] [0:42.100000000000001] [0:41.799999999999997] [0:1] [0:1] [0:8] [0:8] [-1:1] [0:1] [0:5.7999999999999998] [0:6.5] [0:5.2000000000000002] [0:6.5] [0:4.4119999999999999] [0:6.5] [0:5.3330000000000002] [0:4.7999999999999998] [0:5.3330000000000002] [0:4.5] [0:1] [0:1] [0:7] [0:8] [0:6] [0:7] [-1.8:1.8] [-2.2000000000000002:2] [1:30] [1.2:30] [1:12] [0:1] [0:1] [-4.4669999999999996:4.5999999999999996] [-5.2000000000000002:5] [-4.133:5.3330000000000002] [-0.045499999999999999:0.088099999999999998] [0.063600000000000004:1] [0:0.088800000000000004] [0.35623409669211198:0.51556156968876865] [0.1051136363636363:0.32744043043812449] [0.40430438124519602:0.64185836716283262] [0.32129131437355879:0.77537212449255755] [0.70399999999999996:1]
|
||||||
|
tree_sizes=946 1005 993 986 1007 997 994 1005 992 1009 984 1007 997 684 1002 999 897 992 991 990 1001 905 1003 995 896 1010 908 1005 1007 1014 1012 1005 1005 691 688
|
||||||
|
|
||||||
|
Tree=0
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=45 54 46 96 4 3 16
|
||||||
|
split_gain=174.584 35.5641 24.9346 16.8552 14.3832 11.0732 10.8094
|
||||||
|
threshold=1.155 1.405 2.5850000000000004 4.5000000000000009 1704.4687685416313 1441.3975280143418 1.0000000180025095e-35
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 3 5 -1 -4 -2 -3
|
||||||
|
right_child=2 6 4 -5 -6 -7 -8
|
||||||
|
leaf_value=0.87683759709368503 0.84782001969484888 0.90404985782878589 0.85793883408869098 0.90097077069702014 0.73127673195863474 0.81008235044809496 0.93515098554525133
|
||||||
|
leaf_weight=939.87957760691643 113.51603642106056 283.89385342597961 418.36988925933838 472.32632339000702 9.9611878395080549 330.17187193036079 212.09029108285904
|
||||||
|
leaf_count=4529 547 1368 2016 2276 48 1591 1022
|
||||||
|
internal_value=0.875686 0.893342 0.837052 0.884909 0.85499 0.819737 0.91735
|
||||||
|
internal_weight=2780.21 1908.19 872.019 1412.21 428.331 443.688 495.984
|
||||||
|
internal_count=13397 9195 4202 6805 2064 2138 2390
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=1
|
||||||
|
|
||||||
|
|
||||||
|
Tree=1
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=47 48 49 86 141 133 150
|
||||||
|
split_gain=140.072 28.5634 26.9673 23.4898 19.0464 14.6224 10.7313
|
||||||
|
threshold=1.6850000000000003 2.1650000000000005 3.3850000000000002 3.3279569892473124 1.2620000000000002 0.31650000000000006 0.48538789856891795
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 3 5 -1 -4 -2 -3
|
||||||
|
right_child=2 6 4 -5 -6 -7 -8
|
||||||
|
leaf_value=0.0068305934170468773 -0.15031955758812821 -0.031384052219233315 -0.052289652303345355 0.062911487393225371 0.031971580220150592 -0.011449057668411599 0.04709896679065162
|
||||||
|
leaf_weight=1284.6507234424353 8.3659095764160138 19.989385187625885 501.71516834199429 86.587033972144127 30.929726287722588 495.32643516361713 353.17835873365402
|
||||||
|
leaf_count=6221 40 98 2370 419 146 2373 1730
|
||||||
|
internal_value=-0.000699774 0.0173296 -0.0310475 0.0103722 -0.0473963 -0.0137584 0.0428942
|
||||||
|
internal_weight=2780.74 1744.41 1036.34 1371.24 532.645 503.692 373.168
|
||||||
|
internal_count=13397 8468 4929 6640 2516 2413 1828
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=2
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=45 50 53 39 96 28 150
|
||||||
|
split_gain=110.988 23.3948 18.1465 13.3271 12.0676 11.8858 11.7377
|
||||||
|
threshold=1.155 1.4150000000000003 3.3250000000000006 0.36187197152743827 4.5000000000000009 3.9500000000000006 0.48538789856891795
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 4 5 -4 -1 -2 -3
|
||||||
|
right_child=2 6 3 -5 -6 -7 -8
|
||||||
|
leaf_value=0.0012888166907150367 -0.037269165059036741 -0.040251887739062138 -0.05134333704385069 -0.13896201271441588 0.020859848952961575 -0.011322757210899898 0.041785901483228478
|
||||||
|
leaf_weight=991.85861267149448 395.00907251238823 20.026126876473427 106.85419258475304 22.895305529236794 522.50144763290882 372.75306884944439 348.38899676501751
|
||||||
|
leaf_count=4802 1851 97 494 106 2555 1751 1741
|
||||||
|
internal_value=-0.000605268 0.0137719 -0.0307651 -0.0668133 0.00804152 -0.0246723 0.0373256
|
||||||
|
internal_weight=2780.29 1882.78 897.512 129.749 1514.36 767.762 368.415
|
||||||
|
internal_count=13397 9195 4202 600 7357 3602 1838
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=3
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=45 48 86 11 53 144 104
|
||||||
|
split_gain=91.2855 30.6398 20.2224 17.4942 14.4128 10.3549 10.2483
|
||||||
|
threshold=1.155 2.2850000000000006 3.3279569892473124 0.30952380952380959 3.4950000000000006 0.0075500000000000003 1.0005000000000002
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 2 -1 -3 6 -6 -2
|
||||||
|
right_child=4 3 -4 -5 5 -7 -8
|
||||||
|
leaf_value=0.0040069597334026 -0.027086096902533729 -0.1715719381102207 0.053726932967164444 0.048773966775503941 -0.061900987427835959 -0.23396750965062757 0.016338062312498316
|
||||||
|
leaf_weight=1510.6300098896027 782.38381478190422 3.9652889966964713 94.400425717234612 257.22131448984146 73.248439565300941 3.9991354644298545 63.84617380797863
|
||||||
|
leaf_count=7369 3628 20 471 1306 331 18 297
|
||||||
|
internal_value=-0.000943352 0.0123188 0.00693156 0.0454226 -0.0277441 -0.0708364 -0.0238097
|
||||||
|
internal_weight=2789.69 1866.22 1605.03 261.187 923.478 77.2476 846.23
|
||||||
|
internal_count=13440 9166 7840 1326 4274 349 3925
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=4
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=49 35 6 53 44 126 38
|
||||||
|
split_gain=70.6071 28.8927 21.165 13.8246 12.9797 16.2351 8.96833
|
||||||
|
threshold=2.8350000000000004 3.3550000000000004 1541.1282734213053 1.9650000000000001 6.5150000000000006 1.8450000000000002 0.27603289214361998
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 2 -1 -3 5 -2 -6
|
||||||
|
right_child=4 3 -4 -5 6 -7 -8
|
||||||
|
leaf_value=-0.0027517198054468608 -0.029319791370752923 0.043695199840511914 0.083541694807877556 0.015347179328011443 -0.028790250204289367 -0.099217570104222469 -0.0022072689999685109
|
||||||
|
leaf_weight=937.29022094607353 417.85833202302456 320.03798474371433 31.915322333574295 449.0833810120821 218.10735833644867 39.50090055167675 374.63410261273384
|
||||||
|
leaf_count=4582 1898 1642 157 2211 1027 181 1742
|
||||||
|
internal_value=-0.000829778 0.0120602 9.06525e-05 0.0271434 -0.0221677 -0.0353586 -0.0119891
|
||||||
|
internal_weight=2788.43 1738.33 969.206 769.121 1050.1 457.359 592.741
|
||||||
|
internal_count=13440 8592 4739 3853 4848 2079 2769
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=5
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=51 50 35 143 44 147 11
|
||||||
|
split_gain=63.712 19.0005 13.7227 11.8206 10.6018 10.4763 6.84163
|
||||||
|
threshold=1.2550000000000001 1.4650000000000001 5.035000000000001 -1.7974999999999997 7.2550000000000008 0.47199397614381194 2.6904761904761911
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 2 -1 6 -5 -3 -2
|
||||||
|
right_child=3 5 -4 4 -6 -7 -8
|
||||||
|
leaf_value=0.0047544573525090221 -0.065940592898403594 0.046851958603355899 0.063639968219378742 -0.028402060075216558 -0.0037183287940315865 -0.010933729592520421 -0.2419531318087022
|
||||||
|
leaf_weight=1547.0932241082191 6.1367039680480939 207.7856714874506 44.20663620531559 674.41967558860779 262.60369572043419 40.760551080107689 3.9397892653942108
|
||||||
|
leaf_count=7584 28 1099 222 3053 1221 215 18
|
||||||
|
internal_value=-0.000729499 0.0105766 0.00639068 -0.0226927 -0.0214845 0.0373753 -0.134921
|
||||||
|
internal_weight=2786.95 1839.85 1591.3 947.1 937.023 248.546 10.0765
|
||||||
|
internal_count=13440 9120 7806 4320 4274 1314 46
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=6
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=41 130 54 48 99 34 105
|
||||||
|
split_gain=42.6482 15.4832 11.8244 11.5616 10.5481 8.08864 5.28375
|
||||||
|
threshold=1.9950000000000003 2.1835000000000004 1.6950000000000001 2.0250000000000004 0.13392857142857142 2.1550000000000007 1.0765000000000002
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 3 4 -1 -2 -3 -4
|
||||||
|
right_child=2 5 6 -5 -6 -7 -8
|
||||||
|
leaf_value=-0.012930103603477631 -0.025837088447404372 0.009985288944886676 0.093598551064641447 0.0827918792790409 0.017739499999769957 0.067684395437451708 -0.011462427181900188
|
||||||
|
leaf_weight=1452.7631230950356 63.837418377399445 116.17519751191139 30.260349631309509 13.827319353818892 1098.0612086355686 34.140560820698738 6.2758191227912894
|
||||||
|
leaf_count=6763 321 560 163 70 5525 162 34
|
||||||
|
internal_value=0.00228156 -0.00876197 0.0171813 -0.0120271 0.0153451 0.0230937 0.0755539
|
||||||
|
internal_weight=2815.34 1616.91 1198.43 1466.59 1161.9 150.316 36.5362
|
||||||
|
internal_count=13598 7555 6043 6833 5846 722 197
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=7
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=41 135 130 21 53 102 16
|
||||||
|
split_gain=34.421 15.4189 13.9177 13.4109 11.0563 13.2179 9.32957
|
||||||
|
threshold=1.9950000000000003 -0.78349999999999997 2.1340000000000003 0.4642857142857143 2.0250000000000004 2.1120000000000005 1.5000000000000002
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 3 -3 -1 6 -6 -2
|
||||||
|
right_child=4 2 -4 -5 5 -7 -8
|
||||||
|
leaf_value=-0.039029586512136658 0.021256889774663217 -0.0093694924607743823 0.024219953555788796 -0.18450744298912586 0.010656362766355395 -0.067587490182026186 0.059808579820180507
|
||||||
|
leaf_weight=29.468837857246399 324.64188092947006 1435.6618839651346 147.77664601802826 8.9744612574577314 753.81818389892578 24.195777088403702 86.313260063529015
|
||||||
|
leaf_count=138 1721 6659 716 42 3733 122 467
|
||||||
|
internal_value=0.00205658 -0.00781819 -0.00623458 -0.0730278 0.0155268 0.00822224 0.0293551
|
||||||
|
internal_weight=2810.85 1621.88 1583.44 38.4433 1188.97 778.014 410.955
|
||||||
|
internal_count=13598 7555 7375 180 6043 3855 2188
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=8
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=86 41 30 92 147 8 85
|
||||||
|
split_gain=36.407 25.9777 15.256 11.9724 10.8984 10.2187 7.72256
|
||||||
|
threshold=3.2679487179487183 1.8750000000000002 0.46841755319148942 -0.76249999999999984 0.40846280364372473 1.1083333333333336 -0.021724137931034445
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 2 -1 -3 5 -2 -6
|
||||||
|
right_child=4 3 -4 -5 6 -7 -8
|
||||||
|
leaf_value=-0.012159457825842523 0.064307005786210347 -0.085506751396820332 -0.10592968794102031 0.0081406001340509019 0.027805156010338752 -0.1311253894779951 0.074917050140623179
|
||||||
|
leaf_weight=1030.2416722476482 5.0686567574739438 14.960604444146155 19.18836584687233 1572.8768468499184 63.189212292432785 6.7883874922990799 94.08995346724987
|
||||||
|
leaf_count=4724 25 75 92 7835 328 34 485
|
||||||
|
internal_value=0.00185481 -0.00115146 -0.0138749 0.00725775 0.0487278 -0.0475971 0.055992
|
||||||
|
internal_weight=2806.4 2637.27 1049.43 1587.84 169.136 11.857 157.279
|
||||||
|
internal_count=13598 12726 4816 7910 872 59 813
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=9
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=49 150 52 133 30 91 30
|
||||||
|
split_gain=26.3296 13.6848 11.0511 10.5586 10.2017 14.0051 13.9274
|
||||||
|
threshold=2.7850000000000006 0.60942003008724055 2.9650000000000003 2.7320000000000007 0.10822072072072071 -0.0024999999999999497 0.12681311751103638
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 3 -3 -1 5 -2 -6
|
||||||
|
right_child=4 2 -4 -5 6 -7 -8
|
||||||
|
leaf_value=0.0056197323214787877 0.0092359089138059399 0.013793895571876906 0.055269467591862222 -0.056030521488072138 0.020769131467870516 -0.044189842169712931 -0.012941111969465513
|
||||||
|
leaf_weight=1335.4049420952797 73.188210651278496 194.0794630497694 108.95535556972027 30.86374768614769 165.2346598058939 196.06340071558952 684.92604845762253
|
||||||
|
leaf_count=6712 329 987 589 157 747 879 3130
|
||||||
|
internal_value=0.000378046 0.00867093 0.0287076 0.00422669 -0.0119885 -0.0296678 -0.00638913
|
||||||
|
internal_weight=2788.72 1669.3 303.035 1366.27 1119.41 269.252 850.161
|
||||||
|
internal_count=13530 8445 1576 6869 5085 1208 3877
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=10
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=86 41 0 6 110 102 53
|
||||||
|
split_gain=38.5149 20.3558 13.2957 10.1636 9.93058 14.9217 6.02783
|
||||||
|
threshold=3.0790020790020796 1.925 1413.5914823844723 1484.8073996434571 2.9500000000000006 0.65050000000000019 2.2150000000000003
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 2 -1 -3 6 -6 -2
|
||||||
|
right_child=4 3 -4 -5 5 -7 -8
|
||||||
|
leaf_value=0.0140954684441122 0.085154679849317738 0.026410531501952182 -0.017501548280296479 0.0014621478522681489 -0.046636790759956186 0.037447698249607933 0.031794502065436499
|
||||||
|
leaf_weight=167.52074213325977 60.752241030335426 211.7988056242466 1059.5275938510895 1090.8869259208441 27.780392900109291 130.96362222731113 37.02421498298645
|
||||||
|
leaf_count=765 323 1076 4848 5512 140 685 181
|
||||||
|
internal_value=0.000347101 -0.00355495 -0.0131877 0.00551857 0.0388267 0.0227309 0.0649542
|
||||||
|
internal_weight=2786.25 2529.73 1227.05 1302.69 256.52 158.744 97.7765
|
||||||
|
internal_count=13530 12201 5613 6588 1329 825 504
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=11
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=86 122 0 132 136 148 145
|
||||||
|
split_gain=31.5628 19.7563 17.5348 15.2483 8.699 11.6526 8.53686
|
||||||
|
threshold=3.0790020790020796 1.0250000000000001 1444.5595683182339 0.68350000000000011 11.950000000000001 0.25070180469638537 0.63955000000000006
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 2 -1 -3 6 -6 -2
|
||||||
|
right_child=4 3 -4 -5 5 -7 -8
|
||||||
|
leaf_value=-0.0029563172992086786 0.032749371502154893 -0.027078470578097272 -0.04142343191974563 0.004355282116605525 0.042836068356502124 -0.043229223026257771 0.082015555649337976
|
||||||
|
leaf_weight=268.76511310040951 128.29142379760742 184.50364246964455 247.01660700142384 1831.7398000508547 37.845243006944656 31.138597756624222 54.413731098175049
|
||||||
|
leaf_count=1259 680 882 1128 8932 205 158 286
|
||||||
|
internal_value=0.000321355 -0.0031776 -0.0213793 0.00147871 0.0355201 0.00398648 0.0474254
|
||||||
|
internal_weight=2783.71 2532.03 515.782 2016.24 251.689 68.9838 182.705
|
||||||
|
internal_count=13530 12201 2387 9814 1329 363 966
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=12
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=86 41 94 4 100 132 111
|
||||||
|
split_gain=16.7583 14.9692 11.4051 9.36529 9.15568 6.8883 6.86331
|
||||||
|
threshold=3.2679487179487183 2.5250000000000004 19.050000000000004 1454.7040164610194 2.1000000000000005 2.5855000000000006 1.6500000000000001
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 2 -1 4 -2 -3 -5
|
||||||
|
right_child=3 5 -4 6 -6 -7 -8
|
||||||
|
leaf_value=-0.0077031612935488866 -0.037300665068035477 0.045270021664037818 0.0069515620157151858 0.08783804546768309 0.1145092464596736 -0.063294467679354607 0.032433508236858831
|
||||||
|
leaf_weight=1642.7547204941511 28.476281866431236 95.693837076425552 889.01127083599567 33.729012683033943 5.0763863474130622 6.7911695241928092 86.767844557762146
|
||||||
|
leaf_count=7824 156 540 4317 188 29 38 478
|
||||||
|
internal_value=0.000977474 -0.000976496 -0.00255725 0.0343884 -0.0143067 0.0380708 0.0479478
|
||||||
|
internal_weight=2788.3 2634.25 2531.77 154.05 33.5527 102.485 120.497
|
||||||
|
internal_count=13570 12719 12141 851 185 578 666
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=13
|
||||||
|
num_leaves=5
|
||||||
|
num_cat=0
|
||||||
|
split_feature=49 91 105 52
|
||||||
|
split_gain=12.5399 11.9283 13.2239 11.4266
|
||||||
|
threshold=6.7950000000000008 0.46333333333333332 0.66550000000000009 3.1450000000000005
|
||||||
|
decision_type=2 2 2 2
|
||||||
|
left_child=1 3 -3 -1
|
||||||
|
right_child=-2 2 -4 -5
|
||||||
|
leaf_value=-0.00096173862485333158 -0.18852641170062942 -0.26944729151735436 0.0083924991906715318 0.019698628791158867
|
||||||
|
leaf_weight=2444.542382568121 3.7820855826139441 3.7145474255084983 3.7179097086191177 330.02280321717262
|
||||||
|
leaf_count=11674 16 18 18 1844
|
||||||
|
internal_value=0.000884212 0.00114235 -0.13063 0.00149578
|
||||||
|
internal_weight=2785.78 2782 7.43246 2774.57
|
||||||
|
internal_count=13570 13554 36 13518
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=14
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=35 136 1 3 120 119 137
|
||||||
|
split_gain=12.9995 12.1396 9.67922 10.2069 8.87434 8.76233 7.82142
|
||||||
|
threshold=3.4050000000000007 3.1500000000000008 1408.1043210310934 1436.2136975970254 1.4145000000000001 0.55000000000000016 12.850000000000003
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 5 3 -2 -3 -1 -4
|
||||||
|
right_child=2 4 6 -5 -6 -7 -8
|
||||||
|
leaf_value=-0.065982224130305259 -0.028897601514020019 -0.010800039930687538 0.014598348000302748 0.051779760894765055 0.0040416852382515198 0.035952394418601007 -0.011457004864636652
|
||||||
|
leaf_weight=9.93890532851219 20.277691304683685 1238.979572609067 441.32176646590233 106.29307742416859 676.56466819345951 115.69292894005775 174.66667002439499
|
||||||
|
leaf_count=46 107 5755 2341 568 3282 548 923
|
||||||
|
internal_value=0.000796137 -0.00349957 0.0126042 0.0388534 -0.00555799 0.0278839 0.00721016
|
||||||
|
internal_weight=2783.74 2041.18 742.559 126.571 1915.54 125.632 615.988
|
||||||
|
internal_count=13570 9631 3939 675 9037 594 3264
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=15
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=94 53 50 125 104 49 120
|
||||||
|
split_gain=15.421 19.7004 11.5702 10.8982 8.46618 7.68903 0.284565
|
||||||
|
threshold=17.550000000000004 3.5150000000000001 2.0050000000000003 0.45000000000000007 0.45750000000000007 1.8950000000000002 2.4365000000000001
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=2 5 3 -1 -3 -2 -4
|
||||||
|
right_child=1 4 6 -5 -6 -7 -8
|
||||||
|
leaf_value=-0.040237205117941127 0.029193543717025244 -0.027898057080941927 0.13173751892789104 -0.0049749588986612815 -0.15821400423700094 0.0070086816806797644 0.089170490566897243
|
||||||
|
leaf_weight=101.41680394113064 210.2422444075346 11.58236499130726 5.4282936453819257 1551.7522683441639 10.168696627020834 879.85487067699432 2.6328659802675247
|
||||||
|
leaf_count=475 1114 49 33 7519 43 4276 17
|
||||||
|
internal_value=-0.000172415 0.00932761 -0.00653072 -0.00713841 -0.0888634 0.0112876 0.117955
|
||||||
|
internal_weight=2773.08 1111.85 1661.23 1653.17 21.7511 1090.1 8.06116
|
||||||
|
internal_count=13526 5482 8044 7994 92 5390 50
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=16
|
||||||
|
num_leaves=7
|
||||||
|
num_cat=0
|
||||||
|
split_feature=54 49 149 143 133 120
|
||||||
|
split_gain=13.5064 12.5454 12.7609 9.52104 4.64479 6.69198
|
||||||
|
threshold=1.6950000000000001 4.1950000000000012 0.53851874003189804 -2.5639999999999996 1.2110000000000001 3.0500000000000003
|
||||||
|
decision_type=2 2 2 2 2 2
|
||||||
|
left_child=1 3 -3 -1 -2 -6
|
||||||
|
right_child=4 2 -4 -5 5 -7
|
||||||
|
leaf_value=-0.11165723984306615 -0.022805170561939463 -0.034049153155287885 0.071318390164509041 0.0013999129723307169 0.11023664759120146 -0.064625521974505357
|
||||||
|
leaf_weight=8.1074528247117978 4.7248373478651073 177.6567175835371 13.41981780529022 2544.4961924999952 20.898206591606144 2.6760432869195929
|
||||||
|
leaf_count=41 29 758 58 12491 132 17
|
||||||
|
internal_value=-0.000148839 -0.000887801 -0.0266458 0.00104042 0.0714722 0.0903692
|
||||||
|
internal_weight=2771.98 2743.68 191.077 2552.6 28.2991 23.5742
|
||||||
|
internal_count=13526 13348 816 12532 178 149
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=17
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=86 89 86 49 89 92 95
|
||||||
|
split_gain=12.3529 16.6857 29.867 13.2745 12.903 19.095 7.28162
|
||||||
|
threshold=2.9298029556650254 1.0000000180025095e-35 1.8603896103896107 3.3850000000000002 0.27000000000000007 -0.62124999999999986 8.25
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 3 -3 -1 6 -6 -2
|
||||||
|
right_child=4 2 -4 -5 5 -7 -8
|
||||||
|
leaf_value=0.0076740310795042049 0.058197093639699833 -0.094247277907232085 -0.010401082561217358 -0.014939641022089629 -0.10188514738956803 0.012348640807380216 -0.023647947189664047
|
||||||
|
leaf_weight=1310.5064302459359 93.891582764685154 49.551189616322517 670.03426378965378 359.25059229135513 16.932199478149414 257.1773796081543 13.500689059495924
|
||||||
|
leaf_count=6543 499 228 3182 1562 87 1350 75
|
||||||
|
internal_value=-0.000128236 -0.00290891 -0.016176 0.00280861 0.0172867 0.00528897 0.0479069
|
||||||
|
internal_weight=2770.84 2389.34 719.585 1669.76 381.502 274.11 107.392
|
||||||
|
internal_count=13526 11515 3410 8105 2011 1437 574
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=18
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=149 56 148 55 148 53 92
|
||||||
|
split_gain=15.7381 11.9383 11.3441 10.9087 9.49514 8.82734 5.7139
|
||||||
|
threshold=0.53433908520280893 1.7550000000000001 0.26796584848230992 1.905 0.24185130950380487 2.1250000000000004 -0.0099999999999999482
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 4 -3 5 -1 -2 -5
|
||||||
|
right_child=3 2 -4 6 -6 -7 -8
|
||||||
|
leaf_value=-0.054435660661113758 0.0153280247340685 0.02819107947162831 -0.017585503842290271 -0.01840079708748131 -0.010724207322160621 -0.0015876644117591623 0.10180483948952145
|
||||||
|
leaf_weight=56.825720146298409 617.56049958616495 165.87729875743389 91.08600726723671 5.4966678321361568 1074.6435647159815 732.60994145274162 19.602076262235641
|
||||||
|
leaf_count=283 3334 829 448 27 4917 3565 97
|
||||||
|
internal_value=-0.000486987 -0.00831442 0.0119646 0.00741537 -0.01292 0.00614953 0.0754826
|
||||||
|
internal_weight=2763.7 1388.43 256.963 1375.27 1131.47 1350.17 25.0987
|
||||||
|
internal_count=13500 6477 1277 7023 5200 6899 124
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=19
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=149 55 135 1 27 115 54
|
||||||
|
split_gain=12.6285 9.13776 8.91602 12.9607 10.4883 7.46851 5.43256
|
||||||
|
threshold=0.53433908520280893 1.905 0.30550000000000005 1494.2870431281676 0.50845238095238099 2.3665000000000007 1.3650000000000004
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=2 5 3 -1 -4 -2 -3
|
||||||
|
right_child=1 6 4 -5 -6 -7 -8
|
||||||
|
leaf_value=0.00092966247827827358 0.0028048803388890822 0.099877401856329082 -0.0069739024068449437 -0.021042388628781803 0.03967412519492558 0.027656530085268364 -0.011168774035797255
|
||||||
|
leaf_weight=536.86709239333868 1198.4237125739455 17.76616628468037 128.78820982575417 638.33134125173092 88.204329490661621 147.51364935934544 6.5457842200994483
|
||||||
|
leaf_count=2501 6137 84 598 2961 417 762 40
|
||||||
|
internal_value=-0.000430022 0.0066729 -0.007421 -0.0110049 0.0119887 0.00552878 0.0699864
|
||||||
|
internal_weight=2762.44 1370.25 1392.19 1175.2 216.993 1345.94 24.312
|
||||||
|
internal_count=13500 7023 6477 5462 1015 6899 124
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=20
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=86 29 98 85 111 54 1
|
||||||
|
split_gain=13.4852 11.6743 11.2269 10.3561 7.51975 9.02896 6.85752
|
||||||
|
threshold=3.3717607973421928 3.8452380952380958 0.53589743589743599 -0.45393665158371038 1.7500000000000002 1.3250000000000004 1430.9302281483838
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 2 -1 -3 6 -6 -2
|
||||||
|
right_child=4 3 -4 -5 5 -7 -8
|
||||||
|
leaf_value=0.010161271773601144 -0.030831897558424644 -0.065476683381506764 -0.016436452248208454 0.004566632375329463 -0.017458853996767588 0.051773327327659352 0.10280712840651235
|
||||||
|
leaf_weight=220.18627671897411 5.0186129659414318 23.250052616000175 793.86604422330856 1612.9528871029615 39.005949392914772 43.020874515175819 24.570655010640621
|
||||||
|
leaf_count=1065 29 113 3791 7879 209 264 150
|
||||||
|
internal_value=-0.000380007 -0.0018746 -0.0106611 0.00357096 0.0351053 0.0188533 0.0801381
|
||||||
|
internal_weight=2761.87 2650.26 1014.05 1636.2 111.616 82.0268 29.5893
|
||||||
|
internal_count=13500 12848 4856 7992 652 473 179
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=21
|
||||||
|
num_leaves=7
|
||||||
|
num_cat=0
|
||||||
|
split_feature=96 132 136 141 123 120
|
||||||
|
split_gain=13.2003 16.5388 14.2713 13.2653 11.1928 9.3524
|
||||||
|
threshold=4.5000000000000009 0.64600000000000013 7.8500000000000005 -2.3269999999999995 0.73000000000000009 3.1835000000000004
|
||||||
|
decision_type=2 2 2 2 2 2
|
||||||
|
left_child=1 2 -1 -2 -3 -5
|
||||||
|
right_child=3 4 -4 5 -6 -7
|
||||||
|
leaf_value=-0.060960557629992744 -0.18516760103419116 0.033438636082733196 -0.0037890386549494811 0.011554321509567651 -0.0045660462097220139 -0.095189759824081052
|
||||||
|
leaf_weight=104.0578725785017 3.772067964076995 88.859501846134663 87.140555322170258 867.02598301321268 1593.5797092542052 8.9989516139030439
|
||||||
|
leaf_count=484 19 416 405 4401 7693 51
|
||||||
|
internal_value=-0.000914735 -0.00585967 -0.0349056 0.00961608 -0.00255862 0.0104568
|
||||||
|
internal_weight=2753.43 1873.64 191.198 879.797 1682.44 876.025
|
||||||
|
internal_count=13469 8998 889 4471 8109 4452
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=22
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=86 96 132 53 17 141 14
|
||||||
|
split_gain=11.7147 10.9619 13.1395 10.1877 3.25091 5.30827 0.81688
|
||||||
|
threshold=3.9466666666666668 4.5000000000000009 0.64600000000000013 2.0250000000000004 1.0000000180025095e-35 0.45950000000000008 0.63333333333333341
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 2 -1 -3 5 -2 -6
|
||||||
|
right_child=4 3 -4 -5 6 -7 -8
|
||||||
|
leaf_value=-0.03177439277102298 0.091437039897303479 0.024857814401883283 -0.0029740838488449607 0.00058337476930965298 0.07050981561257999 -0.054418786094624118 0.13381725959363758
|
||||||
|
leaf_weight=191.83759662508965 7.081265255808832 274.07831323891878 1669.0744777023792 596.54252921044827 3.1656967699527723 4.3793987929821014 7.6569998264312744
|
||||||
|
leaf_count=880 41 1511 8020 2927 18 26 46
|
||||||
|
internal_value=-0.000813155 -0.00142725 -0.00594319 0.00822535 0.0744319 0.0357031 0.115377
|
||||||
|
internal_weight=2753.82 2731.53 1860.91 870.621 22.2834 11.4607 10.8227
|
||||||
|
internal_count=13469 13338 8900 4438 131 67 64
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=23
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=54 86 91 40 130 51 10
|
||||||
|
split_gain=12.222 10.6549 10.0211 7.99429 8.88031 6.65012 3.52018
|
||||||
|
threshold=1.5750000000000004 3.9115384615384619 0.46333333333333332 1.4550000000000003 3.4720000000000004 1.0650000000000002 1.2583333333333335
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 2 -1 4 -2 -5 -3
|
||||||
|
right_child=3 6 -4 5 -6 -7 -8
|
||||||
|
leaf_value=-0.0022469666970611943 0.016170707495608474 0.01400989076087111 -0.12852821652405796 0.092762096676041614 -0.16668567356812367 0.014555154480083921 0.10191215472125625
|
||||||
|
leaf_weight=2637.7453966140747 32.849811799824238 7.6601853668689754 6.834140643477439 32.402883179485798 3.1530902385711661 18.586706772446632 13.987728200852869
|
||||||
|
leaf_count=12765 209 44 31 200 20 112 88
|
||||||
|
internal_value=-0.000723185 -0.00197755 -0.00257376 0.0377177 0.000116917 0.0642621 0.0708273
|
||||||
|
internal_weight=2753.22 2666.23 2644.58 86.9925 36.0029 50.9896 21.6479
|
||||||
|
internal_count=13469 12928 12796 541 229 312 132
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=24
|
||||||
|
num_leaves=7
|
||||||
|
num_cat=0
|
||||||
|
split_feature=49 137 127 10 121 40
|
||||||
|
split_gain=12.6198 16.4964 12.4085 9.96103 9.53044 3.42942
|
||||||
|
threshold=3.3850000000000002 2.8500000000000001 1.4365000000000003 4.3000000000000007 2.7750000000000004 2.7850000000000006
|
||||||
|
decision_type=2 2 2 2 2 2
|
||||||
|
left_child=3 5 -3 4 -1 -2
|
||||||
|
right_child=1 2 -4 -5 -6 -7
|
||||||
|
leaf_value=0.0033265147337535523 -0.2293764266460791 -0.0035570344953408817 -0.040820787979045939 -0.15680120567767367 0.077284263807364459 -0.095337183505289247
|
||||||
|
leaf_weight=2143.9148783534765 3.9466704875230771 459.63925896584988 123.04180367290974 4.1842633336782447 19.085369817912579 4.4060309380292892
|
||||||
|
leaf_count=10807 17 1977 532 22 100 19
|
||||||
|
internal_value=-1.32262e-05 -0.0135124 -0.0114264 0.00366831 0.00397942 -0.158858
|
||||||
|
internal_weight=2758.22 591.034 582.681 2167.18 2163 8.3527
|
||||||
|
internal_count=13474 2545 2509 10929 10907 36
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=25
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=49 6 94 56 127 104 7
|
||||||
|
split_gain=10.0943 10.6231 11.9381 10.4719 9.83816 10.0485 9.11168
|
||||||
|
threshold=3.3850000000000002 1485.1782059621762 17.550000000000004 2.1050000000000004 1.4365000000000003 0.42950000000000005 3.0523414722088096
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 3 -3 -1 6 -6 -2
|
||||||
|
right_child=4 2 -4 -5 5 -7 -8
|
||||||
|
leaf_value=0.014478237478344286 -0.015463014973786505 -0.0073632514981839545 0.0096110031081186563 0.078530598053871026 -0.0086524748202200501 -0.067456935030922358 0.015332839885013407
|
||||||
|
leaf_weight=308.73068219423294 309.28241093456745 1017.4353533536196 807.05070595443249 30.452116876840591 63.547168910503387 62.713204026222229 157.49458535015583
|
||||||
|
leaf_count=1561 1327 5053 4143 172 271 269 678
|
||||||
|
internal_value=-7.78723e-06 0.00329399 0.000145221 0.0202309 -0.012054 -0.0378634 -0.00507213
|
||||||
|
internal_weight=2756.71 2163.67 1824.49 339.183 593.037 126.26 466.777
|
||||||
|
internal_count=13474 10929 9196 1733 2545 540 2005
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=26
|
||||||
|
num_leaves=7
|
||||||
|
num_cat=0
|
||||||
|
split_feature=86 78 86 86 106 45
|
||||||
|
split_gain=11.0807 19.2113 13.2975 16.5366 9.93615 9.16974
|
||||||
|
threshold=2.6909814323607431 3.2071428571428577 1.0000000180025095e-35 1.8603896103896107 0.59050000000000014 1.1950000000000001
|
||||||
|
decision_type=2 2 2 2 2 2
|
||||||
|
left_child=2 4 5 -4 -2 -1
|
||||||
|
right_child=1 -3 3 -5 -6 -7
|
||||||
|
leaf_value=0.0057285473288771786 0.034425187503696976 -0.17261249206353166 -0.072289780038289356 -0.011539802081962551 0.0051253977786566941 -0.012137044156937154
|
||||||
|
leaf_weight=1235.6497117057443 188.36661138385534 5.9902653545141211 54.218099623918533 475.07240612059832 377.99835128337145 417.49042452871799
|
||||||
|
leaf_count=6255 973 33 239 2206 1968 1800
|
||||||
|
internal_value=-1.60817e-06 0.0129056 -0.00338664 -0.0177639 0.0148706 0.00121666
|
||||||
|
internal_weight=2754.79 572.355 2182.43 529.291 566.365 1653.14
|
||||||
|
internal_count=13474 2974 10500 2445 2941 8055
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=27
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=148 141 115 107 104 4 134
|
||||||
|
split_gain=10.1298 10.8135 12.2053 9.7232 15.8813 8.97442 7.29505
|
||||||
|
threshold=0.17399267399267399 -0.79299999999999993 1.2250000000000003 0.40950000000000003 0.41250000000000003 1460.7202799166059 -0.30549999999999994
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=3 5 -3 6 -5 -2 -1
|
||||||
|
right_child=1 2 -4 4 -6 -7 -8
|
||||||
|
leaf_value=-0.10259253098907423 -0.03269054108208802 -0.0021082423175915925 0.015308582355162925 -0.13734624687852556 0.036154293999346325 -0.0035202193944307817 0.042506627852751083
|
||||||
|
leaf_weight=4.9914454817771938 183.7718341127038 1603.1649219617248 600.83727415651083 20.186357498168949 7.9962391257286063 304.1783049851656 15.20464117079973
|
||||||
|
leaf_count=25 894 7830 2977 102 43 1483 78
|
||||||
|
internal_value=-0.0013178 -0.00046824 0.00263984 -0.0485807 -0.0881234 -0.0145068 0.00661435
|
||||||
|
internal_weight=2740.33 2691.95 2204 48.3787 28.1826 487.95 20.1961
|
||||||
|
internal_count=13432 13184 10807 248 145 2377 103
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=28
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=86 134 41 106 29 91 3
|
||||||
|
split_gain=10.2371 10.3112 10.5364 10.1993 11.3955 9.81442 8.99213
|
||||||
|
threshold=2.864250614250615 -0.43849999999999995 2.1050000000000004 0.95450000000000013 1.3875000000000002 -0.0054166666666666486 1670.9226550788155
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=3 2 -2 5 -5 -1 -3
|
||||||
|
right_child=1 6 -4 4 -6 -7 -8
|
||||||
|
leaf_value=-0.015667034131642239 -0.063328583368563382 0.021380817595676553 0.036600112461665557 -0.21945686012767968 -0.026560041934415114 0.0014656039323343243 -0.12083840209161807
|
||||||
|
leaf_weight=461.02843705564737 34.460375130176544 373.77398503571749 17.162777505815029 3.4011466801166526 135.53743974119425 1711.2739861980081 4.8830340132117263
|
||||||
|
leaf_count=2173 176 1994 103 17 658 8282 29
|
||||||
|
internal_value=-0.0011736 0.0135866 -0.0301054 -0.00392153 -0.0312966 -0.00217051 0.0195438
|
||||||
|
internal_weight=2741.52 430.28 51.6232 2311.24 138.939 2172.3 378.657
|
||||||
|
internal_count=13432 2302 279 11130 675 10455 2023
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=29
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=12 84 115 141 136 11 110
|
||||||
|
split_gain=9.65816 11.3219 10.1518 11.5361 10.0734 9.44977 6.86501
|
||||||
|
threshold=1.0000000180025095e-35 0.017970779220779203 1.2915000000000003 -0.60349999999999981 3.6500000000000008 2.1083333333333338 27.750000000000004
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 6 4 -4 -2 -3 -1
|
||||||
|
right_child=2 5 3 -5 -6 -7 -8
|
||||||
|
leaf_value=0.01695486197013276 0.018272032851518873 -0.047853351303007219 -0.020306195413698006 0.015936397489881831 -0.011004436565708025 0.099082325881264394 -0.086337197330871959
|
||||||
|
leaf_weight=520.42061326652765 139.83185759186745 50.192012257874012 122.51054417341948 430.93686553835869 1465.7739738970995 5.2428159564733496 7.0750899761915198
|
||||||
|
leaf_count=2585 694 257 602 2140 7090 29 35
|
||||||
|
internal_value=-0.00104481 0.0108592 -0.00425885 0.00791357 -0.00845466 -0.0339422 0.0155679
|
||||||
|
internal_weight=2741.98 582.931 2159.05 553.447 1605.61 55.4348 527.496
|
||||||
|
internal_count=13432 2906 10526 2742 7784 286 2620
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=30
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=120 37 38 38 105 85 100
|
||||||
|
split_gain=12.0364 15.2453 11.9342 13.3835 10.0958 10.0578 10.0546
|
||||||
|
threshold=1.4145000000000001 0.42084520042422408 0.23906113829447367 0.14593794095256588 1.1225000000000003 -0.37141065830721004 1.3650000000000002
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=2 6 3 -1 -3 -4 -2
|
||||||
|
right_child=1 4 5 -5 -6 -7 -8
|
||||||
|
leaf_value=-0.12038760226397151 -0.0090962232080863334 0.0034107878159782353 -0.060847190395801561 0.022337300771774038 -0.044228760615057698 -0.0060312321358531873 0.030222541925148897
|
||||||
|
leaf_weight=7.3577561527490607 84.787891268730164 592.17002998292446 37.370823763310909 228.1118380650878 52.602927520871162 1330.5593820437789 423.39983003586531
|
||||||
|
leaf_count=43 418 3057 171 1205 280 6147 2165
|
||||||
|
internal_value=0.00204154 0.0101633 -0.00379863 0.0178729 -0.00047641 -0.00752917 0.0236624
|
||||||
|
internal_weight=2756.36 1152.96 1603.4 235.47 644.773 1367.93 508.188
|
||||||
|
internal_count=13486 5920 7566 1248 3337 6318 2583
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=31
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=86 86 86 1 127 31 122
|
||||||
|
split_gain=10.4188 10.4465 11.9432 10.3703 15.906 10.0392 7.58651
|
||||||
|
threshold=2.6939799331103687 1.0000000180025095e-35 1.8603896103896107 1467.9553804385575 2.1340000000000003 0.22980739360049704 2.3515000000000006
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=1 6 -3 5 -5 -2 -1
|
||||||
|
right_child=3 2 -4 4 -6 -7 -8
|
||||||
|
leaf_value=0.0014256124570572787 0.0018941270616234518 -0.058645654322910731 -0.0086447877444392647 0.02733676763309234 -0.12590863729503893 -0.082423971345859881 0.042831761918242235
|
||||||
|
leaf_weight=1608.7813730537891 166.28092505782843 58.273459360003471 473.13907171785831 372.2649027556181 7.4961845725774756 16.887378051877022 49.535993173718452
|
||||||
|
leaf_count=7823 854 251 2181 1963 43 94 277
|
||||||
|
internal_value=0.00183871 -0.00141235 -0.0141287 0.0144848 0.0243088 -0.0058835 0.0026627
|
||||||
|
internal_weight=2752.66 2189.73 531.413 562.929 379.761 183.168 1658.32
|
||||||
|
internal_count=13486 10532 2432 2954 2006 948 8100
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=32
|
||||||
|
num_leaves=8
|
||||||
|
num_cat=0
|
||||||
|
split_feature=93 144 112 94 104 93 120
|
||||||
|
split_gain=10.1721 16.1941 11.2364 13.1765 9.78364 8.96284 8.48134
|
||||||
|
threshold=20.550000000000004 0.013450000000000002 0.22750000000000004 5.5500000000000007 1.2865000000000002 25.050000000000004 2.0500000000000003
|
||||||
|
decision_type=2 2 2 2 2 2 2
|
||||||
|
left_child=2 4 6 -4 -2 -3 -1
|
||||||
|
right_child=1 5 3 -5 -6 -7 -8
|
||||||
|
leaf_value=0.0034609471658556285 0.020050548549636428 -0.009082334773132807 -0.11004659616173273 -0.007594432301873808 -0.021486441758403186 -0.13291664093499478 0.038221762386595907
|
||||||
|
leaf_weight=820.33589915931225 594.67776323109865 13.120999380946161 13.791079476475714 1142.1561977639794 68.70460732281208 12.293409973382948 84.046657353639603
|
||||||
|
leaf_count=3903 3054 71 65 5495 382 70 446
|
||||||
|
internal_value=0.0016558 0.0126202 -0.00200979 -0.00881763 0.0157484 -0.0690103 0.00669173
|
||||||
|
internal_weight=2749.13 688.797 2060.33 1155.95 663.382 25.4144 904.383
|
||||||
|
internal_count=13486 3577 9909 5560 3436 141 4349
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=33
|
||||||
|
num_leaves=5
|
||||||
|
num_cat=0
|
||||||
|
split_feature=91 141 123 7
|
||||||
|
split_gain=9.64033 9.54985 10.2025 8.96435
|
||||||
|
threshold=0.46333333333333332 -0.77399999999999991 2.2565000000000004 33.104396552584838
|
||||||
|
decision_type=2 2 2 2
|
||||||
|
left_child=1 3 -3 -1
|
||||||
|
right_child=-2 2 -4 -5
|
||||||
|
leaf_value=-0.015732035707484552 -0.12133869515037762 0.0038526132779362976 0.057630556320633561 0.031446003016811871
|
||||||
|
leaf_weight=450.80555958300829 6.9056807309389105 2188.2216669544578 38.992827542126179 48.440718069672585
|
||||||
|
leaf_count=2162 31 10769 213 250
|
||||||
|
internal_value=0.00156231 0.00187402 0.00479437 -0.011154
|
||||||
|
internal_weight=2733.37 2726.46 2227.21 499.246
|
||||||
|
internal_count=13425 13394 10982 2412
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
Tree=34
|
||||||
|
num_leaves=5
|
||||||
|
num_cat=0
|
||||||
|
split_feature=45 98 80 123
|
||||||
|
split_gain=8.19305 8.37131 12.6079 10.3403
|
||||||
|
threshold=1.6150000000000004 0.58114035087719318 0.043836402184014855 2.1715000000000004
|
||||||
|
decision_type=2 2 2 2
|
||||||
|
left_child=1 3 -3 -1
|
||||||
|
right_child=-2 2 -4 -5
|
||||||
|
leaf_value=0.008356015193296689 -0.14816646007318571 -0.033602776052007143 0.00019618273212945178 0.070940775625300892
|
||||||
|
leaf_weight=749.49989224970341 3.9628616422414771 128.32899699360132 1819.463518589735 29.807201541960239
|
||||||
|
leaf_count=3713 16 704 8830 162
|
||||||
|
internal_value=0.00140384 0.0016217 -0.00203079 0.0107506
|
||||||
|
internal_weight=2731.06 2727.1 1947.79 779.307
|
||||||
|
internal_count=13425 13409 9534 3875
|
||||||
|
is_linear=0
|
||||||
|
shrinkage=0.104222
|
||||||
|
|
||||||
|
|
||||||
|
end of trees
|
||||||
|
|
||||||
|
feature_importances:
|
||||||
|
Column_86=18
|
||||||
|
Column_49=9
|
||||||
|
Column_53=8
|
||||||
|
Column_41=6
|
||||||
|
Column_54=6
|
||||||
|
Column_120=6
|
||||||
|
Column_141=6
|
||||||
|
Column_45=5
|
||||||
|
Column_91=5
|
||||||
|
Column_104=5
|
||||||
|
Column_1=4
|
||||||
|
Column_94=4
|
||||||
|
Column_96=4
|
||||||
|
Column_132=4
|
||||||
|
Column_136=4
|
||||||
|
Column_148=4
|
||||||
|
Column_3=3
|
||||||
|
Column_4=3
|
||||||
|
Column_6=3
|
||||||
|
Column_11=3
|
||||||
|
Column_30=3
|
||||||
|
Column_35=3
|
||||||
|
Column_38=3
|
||||||
|
Column_48=3
|
||||||
|
Column_50=3
|
||||||
|
Column_85=3
|
||||||
|
Column_92=3
|
||||||
|
Column_105=3
|
||||||
|
Column_115=3
|
||||||
|
Column_123=3
|
||||||
|
Column_127=3
|
||||||
|
Column_130=3
|
||||||
|
Column_133=3
|
||||||
|
Column_149=3
|
||||||
|
Column_150=3
|
||||||
|
Column_0=2
|
||||||
|
Column_7=2
|
||||||
|
Column_10=2
|
||||||
|
Column_16=2
|
||||||
|
Column_29=2
|
||||||
|
Column_40=2
|
||||||
|
Column_44=2
|
||||||
|
Column_51=2
|
||||||
|
Column_52=2
|
||||||
|
Column_55=2
|
||||||
|
Column_56=2
|
||||||
|
Column_89=2
|
||||||
|
Column_93=2
|
||||||
|
Column_98=2
|
||||||
|
Column_100=2
|
||||||
|
Column_102=2
|
||||||
|
Column_106=2
|
||||||
|
Column_110=2
|
||||||
|
Column_111=2
|
||||||
|
Column_122=2
|
||||||
|
Column_134=2
|
||||||
|
Column_135=2
|
||||||
|
Column_137=2
|
||||||
|
Column_143=2
|
||||||
|
Column_144=2
|
||||||
|
Column_147=2
|
||||||
|
Column_8=1
|
||||||
|
Column_12=1
|
||||||
|
Column_14=1
|
||||||
|
Column_17=1
|
||||||
|
Column_21=1
|
||||||
|
Column_27=1
|
||||||
|
Column_28=1
|
||||||
|
Column_31=1
|
||||||
|
Column_34=1
|
||||||
|
Column_37=1
|
||||||
|
Column_39=1
|
||||||
|
Column_46=1
|
||||||
|
Column_47=1
|
||||||
|
Column_78=1
|
||||||
|
Column_80=1
|
||||||
|
Column_84=1
|
||||||
|
Column_95=1
|
||||||
|
Column_99=1
|
||||||
|
Column_107=1
|
||||||
|
Column_112=1
|
||||||
|
Column_119=1
|
||||||
|
Column_121=1
|
||||||
|
Column_125=1
|
||||||
|
Column_126=1
|
||||||
|
Column_145=1
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
[boosting: gbdt]
|
||||||
|
[objective: binary]
|
||||||
|
[metric: binary_logloss]
|
||||||
|
[tree_learner: serial]
|
||||||
|
[device_type: cpu]
|
||||||
|
[data_sample_strategy: bagging]
|
||||||
|
[data: ]
|
||||||
|
[valid: ]
|
||||||
|
[num_iterations: 1500]
|
||||||
|
[learning_rate: 0.104222]
|
||||||
|
[num_leaves: 8]
|
||||||
|
[num_threads: 4]
|
||||||
|
[seed: 42]
|
||||||
|
[deterministic: 0]
|
||||||
|
[force_col_wise: 0]
|
||||||
|
[force_row_wise: 0]
|
||||||
|
[histogram_pool_size: -1]
|
||||||
|
[max_depth: 3]
|
||||||
|
[min_data_in_leaf: 17]
|
||||||
|
[min_sum_hessian_in_leaf: 0.001]
|
||||||
|
[bagging_fraction: 0.709098]
|
||||||
|
[pos_bagging_fraction: 1]
|
||||||
|
[neg_bagging_fraction: 1]
|
||||||
|
[bagging_freq: 3]
|
||||||
|
[bagging_seed: 400]
|
||||||
|
[bagging_by_query: 0]
|
||||||
|
[feature_fraction: 0.58888]
|
||||||
|
[feature_fraction_bynode: 1]
|
||||||
|
[feature_fraction_seed: 30056]
|
||||||
|
[extra_trees: 0]
|
||||||
|
[extra_seed: 12879]
|
||||||
|
[early_stopping_round: 0]
|
||||||
|
[early_stopping_min_delta: 0]
|
||||||
|
[first_metric_only: 0]
|
||||||
|
[max_delta_step: 0]
|
||||||
|
[lambda_l1: 7.81041e-07]
|
||||||
|
[lambda_l2: 0.00942891]
|
||||||
|
[linear_lambda: 0]
|
||||||
|
[min_gain_to_split: 0]
|
||||||
|
[drop_rate: 0.1]
|
||||||
|
[max_drop: 50]
|
||||||
|
[skip_drop: 0.5]
|
||||||
|
[xgboost_dart_mode: 0]
|
||||||
|
[uniform_drop: 0]
|
||||||
|
[drop_seed: 17869]
|
||||||
|
[top_rate: 0.2]
|
||||||
|
[other_rate: 0.1]
|
||||||
|
[min_data_per_group: 100]
|
||||||
|
[max_cat_threshold: 32]
|
||||||
|
[cat_l2: 10]
|
||||||
|
[cat_smooth: 10]
|
||||||
|
[max_cat_to_onehot: 4]
|
||||||
|
[top_k: 20]
|
||||||
|
[monotone_constraints: ]
|
||||||
|
[monotone_constraints_method: basic]
|
||||||
|
[monotone_penalty: 0]
|
||||||
|
[feature_contri: ]
|
||||||
|
[forcedsplits_filename: ]
|
||||||
|
[refit_decay_rate: 0.9]
|
||||||
|
[cegb_tradeoff: 1]
|
||||||
|
[cegb_penalty_split: 0]
|
||||||
|
[cegb_penalty_feature_lazy: ]
|
||||||
|
[cegb_penalty_feature_coupled: ]
|
||||||
|
[path_smooth: 0]
|
||||||
|
[interaction_constraints: ]
|
||||||
|
[verbosity: -1]
|
||||||
|
[saved_feature_importance_type: 0]
|
||||||
|
[use_quantized_grad: 0]
|
||||||
|
[num_grad_quant_bins: 4]
|
||||||
|
[quant_train_renew_leaf: 0]
|
||||||
|
[stochastic_rounding: 1]
|
||||||
|
[linear_tree: 0]
|
||||||
|
[max_bin: 255]
|
||||||
|
[max_bin_by_feature: ]
|
||||||
|
[min_data_in_bin: 3]
|
||||||
|
[bin_construct_sample_cnt: 200000]
|
||||||
|
[data_random_seed: 175]
|
||||||
|
[is_enable_sparse: 1]
|
||||||
|
[enable_bundle: 1]
|
||||||
|
[use_missing: 1]
|
||||||
|
[zero_as_missing: 0]
|
||||||
|
[feature_pre_filter: 1]
|
||||||
|
[pre_partition: 0]
|
||||||
|
[two_round: 0]
|
||||||
|
[header: 0]
|
||||||
|
[label_column: ]
|
||||||
|
[weight_column: ]
|
||||||
|
[group_column: ]
|
||||||
|
[ignore_column: ]
|
||||||
|
[categorical_feature: ]
|
||||||
|
[forcedbins_filename: ]
|
||||||
|
[precise_float_parser: 0]
|
||||||
|
[parser_config_file: ]
|
||||||
|
[objective_seed: 16083]
|
||||||
|
[num_class: 1]
|
||||||
|
[is_unbalance: 0]
|
||||||
|
[scale_pos_weight: 1]
|
||||||
|
[sigmoid: 1]
|
||||||
|
[boost_from_average: 1]
|
||||||
|
[reg_sqrt: 0]
|
||||||
|
[alpha: 0.9]
|
||||||
|
[fair_c: 1]
|
||||||
|
[poisson_max_delta_step: 0.7]
|
||||||
|
[tweedie_variance_power: 1.5]
|
||||||
|
[lambdarank_truncation_level: 30]
|
||||||
|
[lambdarank_norm: 1]
|
||||||
|
[label_gain: ]
|
||||||
|
[lambdarank_position_bias_regularization: 0]
|
||||||
|
[eval_at: ]
|
||||||
|
[multi_error_top_k: 1]
|
||||||
|
[auc_mu_weights: ]
|
||||||
|
[num_machines: 1]
|
||||||
|
[local_listen_port: 12400]
|
||||||
|
[time_out: 120]
|
||||||
|
[machine_list_filename: ]
|
||||||
|
[machines: ]
|
||||||
|
[gpu_platform_id: -1]
|
||||||
|
[gpu_device_id: -1]
|
||||||
|
[gpu_use_dp: 0]
|
||||||
|
[num_gpu: 1]
|
||||||
|
|
||||||
|
end of parameters
|
||||||
|
|
||||||
|
pandas_categorical:null
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,735 @@
|
|||||||
|
"""
|
||||||
|
V25 Ensemble Predictor - NO TARGET LEAKAGE
|
||||||
|
===========================================
|
||||||
|
Multi-model ensemble for match prediction using XGBoost and LightGBM.
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- 73 engineered features (NO target leakage)
|
||||||
|
- Market-specific models (MS, OU25, BTTS)
|
||||||
|
- Weighted ensemble predictions
|
||||||
|
- Value bet detection
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
|
from typing import Dict, List, Optional, Any
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
|
import xgboost as xgb
|
||||||
|
import lightgbm as lgb
|
||||||
|
|
||||||
|
import sys
|
||||||
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
try:
|
||||||
|
from config.config_loader import get_config as _get_cfg
|
||||||
|
except ImportError:
|
||||||
|
_get_cfg = None # type: ignore[assignment]
|
||||||
|
|
||||||
|
# CatBoost is optional
|
||||||
|
try:
|
||||||
|
from catboost import CatBoostClassifier
|
||||||
|
CATBOOST_AVAILABLE = True
|
||||||
|
except ImportError:
|
||||||
|
CatBoostClassifier = None
|
||||||
|
CATBOOST_AVAILABLE = False
|
||||||
|
|
||||||
|
# Paths
|
||||||
|
MODELS_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'v25')
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class MarketPrediction:
|
||||||
|
"""Prediction for a single betting market."""
|
||||||
|
market_type: str
|
||||||
|
pick: str
|
||||||
|
probability: float
|
||||||
|
confidence: float
|
||||||
|
odds: float = 0.0
|
||||||
|
is_value_bet: bool = False
|
||||||
|
edge: float = 0.0
|
||||||
|
|
||||||
|
def to_dict(self) -> dict:
|
||||||
|
return {
|
||||||
|
'market_type': self.market_type,
|
||||||
|
'pick': self.pick,
|
||||||
|
'probability': round(self.probability * 100, 1),
|
||||||
|
'confidence': round(self.confidence, 1),
|
||||||
|
'odds': self.odds,
|
||||||
|
'is_value_bet': self.is_value_bet,
|
||||||
|
'edge': round(self.edge * 100, 1),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ValueBet:
|
||||||
|
"""Detected value bet opportunity."""
|
||||||
|
market_type: str
|
||||||
|
pick: str
|
||||||
|
probability: float
|
||||||
|
odds: float
|
||||||
|
edge: float
|
||||||
|
confidence: float
|
||||||
|
|
||||||
|
def to_dict(self) -> dict:
|
||||||
|
return {
|
||||||
|
'market_type': self.market_type,
|
||||||
|
'pick': self.pick,
|
||||||
|
'probability': round(self.probability * 100, 1),
|
||||||
|
'odds': self.odds,
|
||||||
|
'edge': round(self.edge * 100, 1),
|
||||||
|
'confidence': round(self.confidence, 1),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class MatchPrediction:
|
||||||
|
"""Complete match prediction with all markets."""
|
||||||
|
match_id: str
|
||||||
|
home_team: str
|
||||||
|
away_team: str
|
||||||
|
|
||||||
|
# MS predictions
|
||||||
|
home_prob: float = 0.0
|
||||||
|
draw_prob: float = 0.0
|
||||||
|
away_prob: float = 0.0
|
||||||
|
ms_pick: str = ''
|
||||||
|
ms_confidence: float = 0.0
|
||||||
|
|
||||||
|
# OU25 predictions
|
||||||
|
over_prob: float = 0.0
|
||||||
|
under_prob: float = 0.0
|
||||||
|
ou25_pick: str = ''
|
||||||
|
ou25_confidence: float = 0.0
|
||||||
|
|
||||||
|
# BTTS predictions
|
||||||
|
btts_yes_prob: float = 0.0
|
||||||
|
btts_no_prob: float = 0.0
|
||||||
|
btts_pick: str = ''
|
||||||
|
btts_confidence: float = 0.0
|
||||||
|
|
||||||
|
# Value bets
|
||||||
|
value_bets: List[ValueBet] = field(default_factory=list)
|
||||||
|
|
||||||
|
def to_dict(self) -> dict:
|
||||||
|
return {
|
||||||
|
'match_id': self.match_id,
|
||||||
|
'home_team': self.home_team,
|
||||||
|
'away_team': self.away_team,
|
||||||
|
'ms': {
|
||||||
|
'home_prob': round(self.home_prob * 100, 1),
|
||||||
|
'draw_prob': round(self.draw_prob * 100, 1),
|
||||||
|
'away_prob': round(self.away_prob * 100, 1),
|
||||||
|
'pick': self.ms_pick,
|
||||||
|
'confidence': round(self.ms_confidence, 1),
|
||||||
|
},
|
||||||
|
'ou25': {
|
||||||
|
'over_prob': round(self.over_prob * 100, 1),
|
||||||
|
'under_prob': round(self.under_prob * 100, 1),
|
||||||
|
'pick': self.ou25_pick,
|
||||||
|
'confidence': round(self.ou25_confidence, 1),
|
||||||
|
},
|
||||||
|
'btts': {
|
||||||
|
'yes_prob': round(self.btts_yes_prob * 100, 1),
|
||||||
|
'no_prob': round(self.btts_no_prob * 100, 1),
|
||||||
|
'pick': self.btts_pick,
|
||||||
|
'confidence': round(self.btts_confidence, 1),
|
||||||
|
},
|
||||||
|
'value_bets': [vb.to_dict() for vb in self.value_bets],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class V25Predictor:
|
||||||
|
"""
|
||||||
|
V25 Ensemble Predictor - NO TARGET LEAKAGE
|
||||||
|
|
||||||
|
Uses market-specific XGBoost and LightGBM models.
|
||||||
|
Each market (MS, OU25, BTTS) has its own trained models.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Feature columns — loaded dynamically from feature_cols.json to stay
|
||||||
|
# in sync with the trained models. The hardcoded list below is only a
|
||||||
|
# fallback in case the JSON file is missing.
|
||||||
|
_FALLBACK_FEATURE_COLS = [
|
||||||
|
# ELO Features (8)
|
||||||
|
'home_overall_elo', 'away_overall_elo', 'elo_diff',
|
||||||
|
'home_home_elo', 'away_away_elo',
|
||||||
|
'home_form_elo', 'away_form_elo', 'form_elo_diff',
|
||||||
|
|
||||||
|
# Form Features (12)
|
||||||
|
'home_goals_avg', 'home_conceded_avg',
|
||||||
|
'away_goals_avg', 'away_conceded_avg',
|
||||||
|
'home_clean_sheet_rate', 'away_clean_sheet_rate',
|
||||||
|
'home_scoring_rate', 'away_scoring_rate',
|
||||||
|
'home_winning_streak', 'away_winning_streak',
|
||||||
|
'home_unbeaten_streak', 'away_unbeaten_streak',
|
||||||
|
|
||||||
|
# H2H Features (6)
|
||||||
|
'h2h_total_matches', 'h2h_home_win_rate', 'h2h_draw_rate',
|
||||||
|
'h2h_avg_goals', 'h2h_btts_rate', 'h2h_over25_rate',
|
||||||
|
|
||||||
|
# Team Stats Features (8)
|
||||||
|
'home_avg_possession', 'away_avg_possession',
|
||||||
|
'home_avg_shots_on_target', 'away_avg_shots_on_target',
|
||||||
|
'home_shot_conversion', 'away_shot_conversion',
|
||||||
|
'home_avg_corners', 'away_avg_corners',
|
||||||
|
|
||||||
|
# Odds Features (24)
|
||||||
|
'odds_ms_h', 'odds_ms_d', 'odds_ms_a',
|
||||||
|
'implied_home', 'implied_draw', 'implied_away',
|
||||||
|
'odds_ht_ms_h', 'odds_ht_ms_d', 'odds_ht_ms_a',
|
||||||
|
'odds_ou05_o', 'odds_ou05_u',
|
||||||
|
'odds_ou15_o', 'odds_ou15_u',
|
||||||
|
'odds_ou25_o', 'odds_ou25_u',
|
||||||
|
'odds_ou35_o', 'odds_ou35_u',
|
||||||
|
'odds_ht_ou05_o', 'odds_ht_ou05_u',
|
||||||
|
'odds_ht_ou15_o', 'odds_ht_ou15_u',
|
||||||
|
'odds_btts_y', 'odds_btts_n',
|
||||||
|
|
||||||
|
# Odds Presence Flags (20)
|
||||||
|
'odds_ms_h_present', 'odds_ms_d_present', 'odds_ms_a_present',
|
||||||
|
'odds_ht_ms_h_present', 'odds_ht_ms_d_present', 'odds_ht_ms_a_present',
|
||||||
|
'odds_ou05_o_present', 'odds_ou05_u_present',
|
||||||
|
'odds_ou15_o_present', 'odds_ou15_u_present',
|
||||||
|
'odds_ou25_o_present', 'odds_ou25_u_present',
|
||||||
|
'odds_ou35_o_present', 'odds_ou35_u_present',
|
||||||
|
'odds_ht_ou05_o_present', 'odds_ht_ou05_u_present',
|
||||||
|
'odds_ht_ou15_o_present', 'odds_ht_ou15_u_present',
|
||||||
|
'odds_btts_y_present', 'odds_btts_n_present',
|
||||||
|
|
||||||
|
# League Features (4)
|
||||||
|
'home_xga', 'away_xga',
|
||||||
|
'league_avg_goals', 'league_zero_goal_rate',
|
||||||
|
|
||||||
|
# Upset Engine (4)
|
||||||
|
'upset_atmosphere', 'upset_motivation', 'upset_fatigue', 'upset_potential',
|
||||||
|
|
||||||
|
# Referee Engine (5)
|
||||||
|
'referee_home_bias', 'referee_avg_goals', 'referee_cards_total',
|
||||||
|
'referee_avg_yellow', 'referee_experience',
|
||||||
|
|
||||||
|
# Momentum Engine (3)
|
||||||
|
'home_momentum_score', 'away_momentum_score', 'momentum_diff',
|
||||||
|
|
||||||
|
# Squad Features (9)
|
||||||
|
'home_squad_quality', 'away_squad_quality', 'squad_diff',
|
||||||
|
'home_key_players', 'away_key_players',
|
||||||
|
'home_missing_impact', 'away_missing_impact',
|
||||||
|
'home_goals_form', 'away_goals_form',
|
||||||
|
]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _load_feature_cols() -> list:
|
||||||
|
"""Load feature columns from feature_cols.json, falling back to hardcoded list."""
|
||||||
|
feature_json = os.path.join(MODELS_DIR, 'feature_cols.json')
|
||||||
|
try:
|
||||||
|
if os.path.exists(feature_json):
|
||||||
|
with open(feature_json, 'r', encoding='utf-8') as f:
|
||||||
|
cols = json.load(f)
|
||||||
|
if isinstance(cols, list) and len(cols) > 0:
|
||||||
|
print(f"[V25] Loaded {len(cols)} feature columns from feature_cols.json")
|
||||||
|
return cols
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[V25] Warning: could not load feature_cols.json: {e}")
|
||||||
|
print(f"[V25] Using fallback feature columns ({len(V25Predictor._FALLBACK_FEATURE_COLS)} features)")
|
||||||
|
return V25Predictor._FALLBACK_FEATURE_COLS
|
||||||
|
|
||||||
|
# Model weights for ensemble (overridden from config in __init__)
|
||||||
|
DEFAULT_WEIGHTS = {
|
||||||
|
'xgb': 0.50,
|
||||||
|
'lgb': 0.50,
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, models_dir: Optional[str] = None):
|
||||||
|
"""
|
||||||
|
Initialize V25 Predictor.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
models_dir: Directory containing model files. Defaults to v25/ directory.
|
||||||
|
"""
|
||||||
|
self.models_dir = models_dir or MODELS_DIR
|
||||||
|
self.models = {} # market -> {'xgb': model, 'lgb': model}
|
||||||
|
self._loaded = False
|
||||||
|
self.FEATURE_COLS = self._load_feature_cols()
|
||||||
|
# Load weights from config (falls back to class default 0.50/0.50)
|
||||||
|
if _get_cfg is not None:
|
||||||
|
try:
|
||||||
|
cfg = _get_cfg()
|
||||||
|
self.DEFAULT_WEIGHTS = {
|
||||||
|
'xgb': float(cfg.get('model_ensemble.xgb_weight', 0.50)),
|
||||||
|
'lgb': float(cfg.get('model_ensemble.lgb_weight', 0.50)),
|
||||||
|
}
|
||||||
|
except Exception:
|
||||||
|
pass # keep class-level defaults
|
||||||
|
|
||||||
|
# All trained market models available in V25
|
||||||
|
ALL_MARKETS = [
|
||||||
|
'ms', 'ou25', 'btts', # Core markets
|
||||||
|
'ou15', 'ou35', # Additional OU lines
|
||||||
|
'ht_result', 'ht_ou05', 'ht_ou15', # HT markets
|
||||||
|
'htft', # HT/FT combo
|
||||||
|
'cards_ou45', # Cards market
|
||||||
|
'handicap_ms', # Handicap
|
||||||
|
'odd_even', # Odd/Even goals
|
||||||
|
]
|
||||||
|
|
||||||
|
# Multi-class markets (output > 2 classes)
|
||||||
|
MULTICLASS_MARKETS = {'ms', 'ht_result', 'htft', 'handicap_ms'}
|
||||||
|
|
||||||
|
def load_models(self) -> bool:
|
||||||
|
"""Load all market-specific models from disk."""
|
||||||
|
try:
|
||||||
|
loaded_count = 0
|
||||||
|
|
||||||
|
for market in self.ALL_MARKETS:
|
||||||
|
self.models[market] = {}
|
||||||
|
|
||||||
|
# Load XGBoost (read content in Python to avoid non-ASCII path issues)
|
||||||
|
xgb_path = os.path.join(self.models_dir, f'xgb_v25_{market}.json')
|
||||||
|
if os.path.exists(xgb_path) and os.path.getsize(xgb_path) > 0:
|
||||||
|
with open(xgb_path, 'r', encoding='utf-8') as f:
|
||||||
|
xgb_content = f.read()
|
||||||
|
booster = xgb.Booster()
|
||||||
|
booster.load_model(bytearray(xgb_content, 'utf-8'))
|
||||||
|
# Corruption detection: verify model can run a dummy prediction
|
||||||
|
try:
|
||||||
|
_dummy = pd.DataFrame([{col: 0.0 for col in self.FEATURE_COLS}])
|
||||||
|
booster.predict(xgb.DMatrix(_dummy))
|
||||||
|
self.models[market]['xgb'] = booster
|
||||||
|
loaded_count += 1
|
||||||
|
except Exception as _ce:
|
||||||
|
print(f"[V25] ⚠️ XGB model for {market} failed integrity check: {_ce} — skipping")
|
||||||
|
|
||||||
|
# Load LightGBM (read content in Python to avoid non-ASCII path issues)
|
||||||
|
lgb_path = os.path.join(self.models_dir, f'lgb_v25_{market}.txt')
|
||||||
|
if os.path.exists(lgb_path) and os.path.getsize(lgb_path) > 0:
|
||||||
|
with open(lgb_path, 'r', encoding='utf-8') as f:
|
||||||
|
model_str = f.read()
|
||||||
|
lgb_model = lgb.Booster(model_str=model_str)
|
||||||
|
# Corruption detection: verify model can run a dummy prediction
|
||||||
|
try:
|
||||||
|
_dummy = pd.DataFrame([{col: 0.0 for col in self.FEATURE_COLS}])
|
||||||
|
lgb_model.predict(_dummy)
|
||||||
|
self.models[market]['lgb'] = lgb_model
|
||||||
|
loaded_count += 1
|
||||||
|
except Exception as _ce:
|
||||||
|
print(f"[V25] ⚠️ LGB model for {market} failed integrity check: {_ce} — skipping")
|
||||||
|
|
||||||
|
# Remove empty entries
|
||||||
|
if not self.models[market]:
|
||||||
|
del self.models[market]
|
||||||
|
|
||||||
|
print(f"[V25] Loaded {loaded_count} model files across {len(self.models)} markets: {list(self.models.keys())}")
|
||||||
|
self._loaded = loaded_count > 0
|
||||||
|
return self._loaded
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[ERROR] Error loading models: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _ensure_loaded(self):
|
||||||
|
"""Ensure models are loaded before prediction."""
|
||||||
|
if not self._loaded:
|
||||||
|
if not self.load_models():
|
||||||
|
raise RuntimeError("Failed to load V25 models")
|
||||||
|
|
||||||
|
def readiness_summary(self) -> Dict[str, Any]:
|
||||||
|
"""Return per-market model status for health check endpoint."""
|
||||||
|
if not self._loaded:
|
||||||
|
self.load_models()
|
||||||
|
market_status = {}
|
||||||
|
for market in self.ALL_MARKETS:
|
||||||
|
m = self.models.get(market, {})
|
||||||
|
market_status[market] = {
|
||||||
|
"xgb": "xgb" in m,
|
||||||
|
"lgb": "lgb" in m,
|
||||||
|
"ready": bool(m),
|
||||||
|
}
|
||||||
|
loaded_markets = [k for k, v in market_status.items() if v["ready"]]
|
||||||
|
return {
|
||||||
|
"fully_loaded": len(loaded_markets) == len(self.ALL_MARKETS),
|
||||||
|
"loaded_markets": loaded_markets,
|
||||||
|
"missing_markets": [m for m in self.ALL_MARKETS if m not in loaded_markets],
|
||||||
|
"weights": self.DEFAULT_WEIGHTS,
|
||||||
|
}
|
||||||
|
|
||||||
|
def _prepare_features(self, features: Dict[str, float]) -> pd.DataFrame:
|
||||||
|
"""Prepare feature vector for prediction."""
|
||||||
|
X = pd.DataFrame([{col: features.get(col, 0.0) for col in self.FEATURE_COLS}])
|
||||||
|
return X
|
||||||
|
|
||||||
|
def predict_ms(self, features: Dict[str, float]) -> tuple:
|
||||||
|
"""
|
||||||
|
Predict match result (1X2).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(home_prob, draw_prob, away_prob)
|
||||||
|
"""
|
||||||
|
self._ensure_loaded()
|
||||||
|
|
||||||
|
X = self._prepare_features(features)
|
||||||
|
probs = []
|
||||||
|
|
||||||
|
# XGBoost
|
||||||
|
if 'xgb' in self.models.get('ms', {}):
|
||||||
|
dmat = xgb.DMatrix(X)
|
||||||
|
xgb_proba = self.models['ms']['xgb'].predict(dmat)
|
||||||
|
if len(xgb_proba.shape) == 1:
|
||||||
|
xgb_proba = np.array([xgb_proba])
|
||||||
|
probs.append(xgb_proba[0] * self.DEFAULT_WEIGHTS['xgb'])
|
||||||
|
|
||||||
|
# LightGBM
|
||||||
|
if 'lgb' in self.models.get('ms', {}):
|
||||||
|
lgb_proba = self.models['ms']['lgb'].predict(X)
|
||||||
|
if len(lgb_proba.shape) == 2:
|
||||||
|
probs.append(lgb_proba[0] * self.DEFAULT_WEIGHTS['lgb'])
|
||||||
|
|
||||||
|
if not probs:
|
||||||
|
return 0.33, 0.33, 0.33
|
||||||
|
|
||||||
|
ensemble_proba = np.sum(probs, axis=0)
|
||||||
|
ensemble_proba = ensemble_proba / ensemble_proba.sum()
|
||||||
|
|
||||||
|
return float(ensemble_proba[0]), float(ensemble_proba[1]), float(ensemble_proba[2])
|
||||||
|
|
||||||
|
def predict_ou25(self, features: Dict[str, float]) -> tuple:
|
||||||
|
"""
|
||||||
|
Predict Over/Under 2.5 goals.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(over_prob, under_prob)
|
||||||
|
"""
|
||||||
|
self._ensure_loaded()
|
||||||
|
|
||||||
|
X = self._prepare_features(features)
|
||||||
|
probs = []
|
||||||
|
|
||||||
|
# XGBoost
|
||||||
|
if 'xgb' in self.models.get('ou25', {}):
|
||||||
|
dmat = xgb.DMatrix(X)
|
||||||
|
xgb_proba = self.models['ou25']['xgb'].predict(dmat)
|
||||||
|
if isinstance(xgb_proba, np.ndarray) and len(xgb_proba.shape) == 1:
|
||||||
|
probs.append(xgb_proba[0])
|
||||||
|
|
||||||
|
# LightGBM
|
||||||
|
if 'lgb' in self.models.get('ou25', {}):
|
||||||
|
lgb_proba = self.models['ou25']['lgb'].predict(X)
|
||||||
|
if isinstance(lgb_proba, np.ndarray):
|
||||||
|
probs.append(lgb_proba[0])
|
||||||
|
|
||||||
|
if not probs:
|
||||||
|
return 0.5, 0.5
|
||||||
|
|
||||||
|
# Average probability
|
||||||
|
avg_prob = np.mean(probs)
|
||||||
|
|
||||||
|
return float(avg_prob), float(1 - avg_prob)
|
||||||
|
|
||||||
|
def predict_btts(self, features: Dict[str, float]) -> tuple:
|
||||||
|
"""
|
||||||
|
Predict Both Teams To Score.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(yes_prob, no_prob)
|
||||||
|
"""
|
||||||
|
self._ensure_loaded()
|
||||||
|
|
||||||
|
X = self._prepare_features(features)
|
||||||
|
probs = []
|
||||||
|
|
||||||
|
# XGBoost
|
||||||
|
if 'xgb' in self.models.get('btts', {}):
|
||||||
|
dmat = xgb.DMatrix(X)
|
||||||
|
xgb_proba = self.models['btts']['xgb'].predict(dmat)
|
||||||
|
if isinstance(xgb_proba, np.ndarray) and len(xgb_proba.shape) == 1:
|
||||||
|
probs.append(xgb_proba[0])
|
||||||
|
|
||||||
|
# LightGBM
|
||||||
|
if 'lgb' in self.models.get('btts', {}):
|
||||||
|
lgb_proba = self.models['btts']['lgb'].predict(X)
|
||||||
|
if isinstance(lgb_proba, np.ndarray):
|
||||||
|
probs.append(lgb_proba[0])
|
||||||
|
|
||||||
|
if not probs:
|
||||||
|
return 0.5, 0.5
|
||||||
|
|
||||||
|
# Average probability
|
||||||
|
avg_prob = np.mean(probs)
|
||||||
|
|
||||||
|
return float(avg_prob), float(1 - avg_prob)
|
||||||
|
|
||||||
|
def predict_market(self, market: str, features: Dict[str, float]) -> Optional[np.ndarray]:
|
||||||
|
"""
|
||||||
|
Generic prediction for any loaded market.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
market: Market key (e.g. 'ht_result', 'htft', 'cards_ou45')
|
||||||
|
features: Feature dictionary.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
numpy array of probabilities.
|
||||||
|
For binary markets: [positive_prob]
|
||||||
|
For multi-class markets: [class0_prob, class1_prob, ...]
|
||||||
|
"""
|
||||||
|
self._ensure_loaded()
|
||||||
|
|
||||||
|
if market not in self.models:
|
||||||
|
return None
|
||||||
|
|
||||||
|
X = self._prepare_features(features)
|
||||||
|
probs = []
|
||||||
|
weights = []
|
||||||
|
is_multiclass = market in self.MULTICLASS_MARKETS
|
||||||
|
|
||||||
|
# XGBoost
|
||||||
|
if 'xgb' in self.models[market]:
|
||||||
|
dmat = xgb.DMatrix(X)
|
||||||
|
xgb_proba = self.models[market]['xgb'].predict(dmat)
|
||||||
|
if isinstance(xgb_proba, np.ndarray):
|
||||||
|
if is_multiclass and len(xgb_proba.shape) == 2:
|
||||||
|
probs.append(xgb_proba[0])
|
||||||
|
elif is_multiclass and len(xgb_proba.shape) == 1:
|
||||||
|
probs.append(xgb_proba)
|
||||||
|
else:
|
||||||
|
probs.append(np.array([xgb_proba[0]]))
|
||||||
|
weights.append(self.DEFAULT_WEIGHTS['xgb'])
|
||||||
|
|
||||||
|
# LightGBM
|
||||||
|
if 'lgb' in self.models[market]:
|
||||||
|
lgb_proba = self.models[market]['lgb'].predict(X)
|
||||||
|
if isinstance(lgb_proba, np.ndarray):
|
||||||
|
if is_multiclass and len(lgb_proba.shape) == 2:
|
||||||
|
probs.append(lgb_proba[0])
|
||||||
|
elif is_multiclass and len(lgb_proba.shape) == 1:
|
||||||
|
probs.append(lgb_proba)
|
||||||
|
else:
|
||||||
|
probs.append(np.array([lgb_proba[0]]))
|
||||||
|
weights.append(self.DEFAULT_WEIGHTS['lgb'])
|
||||||
|
|
||||||
|
if not probs:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Weighted average
|
||||||
|
if len(probs) == 1:
|
||||||
|
return probs[0]
|
||||||
|
|
||||||
|
total_w = sum(weights[:len(probs)])
|
||||||
|
result = np.zeros_like(probs[0])
|
||||||
|
for p, w in zip(probs, weights):
|
||||||
|
result += p * (w / total_w)
|
||||||
|
|
||||||
|
# Normalize multi-class
|
||||||
|
if is_multiclass and result.sum() > 0:
|
||||||
|
result = result / result.sum()
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def has_market(self, market: str) -> bool:
|
||||||
|
"""Check if a specific market model is loaded."""
|
||||||
|
return market in self.models
|
||||||
|
|
||||||
|
def predict_match(
|
||||||
|
self,
|
||||||
|
match_id: str,
|
||||||
|
home_team: str,
|
||||||
|
away_team: str,
|
||||||
|
features: Dict[str, float],
|
||||||
|
odds: Optional[Dict[str, float]] = None,
|
||||||
|
) -> MatchPrediction:
|
||||||
|
"""
|
||||||
|
Predict all markets for a match.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
match_id: Match identifier.
|
||||||
|
home_team: Home team name.
|
||||||
|
away_team: Away team name.
|
||||||
|
features: Feature dictionary.
|
||||||
|
odds: Optional odds dictionary for value bet detection.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
MatchPrediction object.
|
||||||
|
"""
|
||||||
|
# Get predictions for each market
|
||||||
|
home_prob, draw_prob, away_prob = self.predict_ms(features)
|
||||||
|
over_prob, under_prob = self.predict_ou25(features)
|
||||||
|
btts_yes_prob, btts_no_prob = self.predict_btts(features)
|
||||||
|
|
||||||
|
# Determine picks
|
||||||
|
ms_probs = {'1': home_prob, 'X': draw_prob, '2': away_prob}
|
||||||
|
ms_pick = max(ms_probs, key=ms_probs.__getitem__)
|
||||||
|
ms_confidence = ms_probs[ms_pick] * 100
|
||||||
|
|
||||||
|
ou25_probs = {'Over': over_prob, 'Under': under_prob}
|
||||||
|
ou25_pick = max(ou25_probs, key=ou25_probs.__getitem__)
|
||||||
|
ou25_confidence = ou25_probs[ou25_pick] * 100
|
||||||
|
|
||||||
|
btts_probs = {'Yes': btts_yes_prob, 'No': btts_no_prob}
|
||||||
|
btts_pick = max(btts_probs, key=btts_probs.__getitem__)
|
||||||
|
btts_confidence = btts_probs[btts_pick] * 100
|
||||||
|
|
||||||
|
# Create prediction
|
||||||
|
prediction = MatchPrediction(
|
||||||
|
match_id=match_id,
|
||||||
|
home_team=home_team,
|
||||||
|
away_team=away_team,
|
||||||
|
home_prob=home_prob,
|
||||||
|
draw_prob=draw_prob,
|
||||||
|
away_prob=away_prob,
|
||||||
|
ms_pick=ms_pick,
|
||||||
|
ms_confidence=ms_confidence,
|
||||||
|
over_prob=over_prob,
|
||||||
|
under_prob=under_prob,
|
||||||
|
ou25_pick=ou25_pick,
|
||||||
|
ou25_confidence=ou25_confidence,
|
||||||
|
btts_yes_prob=btts_yes_prob,
|
||||||
|
btts_no_prob=btts_no_prob,
|
||||||
|
btts_pick=btts_pick,
|
||||||
|
btts_confidence=btts_confidence,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Detect value bets
|
||||||
|
if odds:
|
||||||
|
prediction.value_bets = self._detect_value_bets(
|
||||||
|
prediction, odds, home_prob, draw_prob, away_prob,
|
||||||
|
over_prob, under_prob, btts_yes_prob, btts_no_prob
|
||||||
|
)
|
||||||
|
|
||||||
|
return prediction
|
||||||
|
|
||||||
|
def _detect_value_bets(
|
||||||
|
self,
|
||||||
|
prediction: MatchPrediction,
|
||||||
|
odds: Dict[str, float],
|
||||||
|
home_prob: float,
|
||||||
|
draw_prob: float,
|
||||||
|
away_prob: float,
|
||||||
|
over_prob: float,
|
||||||
|
under_prob: float,
|
||||||
|
btts_yes_prob: float,
|
||||||
|
btts_no_prob: float,
|
||||||
|
) -> List[ValueBet]:
|
||||||
|
"""Detect value bets based on model vs market odds."""
|
||||||
|
value_bets = []
|
||||||
|
# Market-specific minimum edge thresholds
|
||||||
|
# MS: higher variance → require more edge
|
||||||
|
# OU/BTTS: binary markets → tighter edge acceptable
|
||||||
|
EDGE_THRESHOLDS = {
|
||||||
|
'MS': 0.06,
|
||||||
|
'OU25': 0.04,
|
||||||
|
'BTTS': 0.04,
|
||||||
|
}
|
||||||
|
ms_edge = EDGE_THRESHOLDS['MS']
|
||||||
|
ou_edge = EDGE_THRESHOLDS['OU25']
|
||||||
|
btts_edge = EDGE_THRESHOLDS['BTTS']
|
||||||
|
|
||||||
|
# MS value bets
|
||||||
|
if 'ms_h' in odds and odds['ms_h'] > 0:
|
||||||
|
implied = 1 / odds['ms_h']
|
||||||
|
edge = home_prob - implied
|
||||||
|
if edge > ms_edge:
|
||||||
|
value_bets.append(ValueBet(
|
||||||
|
market_type='MS',
|
||||||
|
pick='1',
|
||||||
|
probability=home_prob,
|
||||||
|
odds=odds['ms_h'],
|
||||||
|
edge=edge,
|
||||||
|
confidence=home_prob * 100,
|
||||||
|
))
|
||||||
|
|
||||||
|
if 'ms_d' in odds and odds['ms_d'] > 0:
|
||||||
|
implied = 1 / odds['ms_d']
|
||||||
|
edge = draw_prob - implied
|
||||||
|
if edge > ms_edge:
|
||||||
|
value_bets.append(ValueBet(
|
||||||
|
market_type='MS',
|
||||||
|
pick='X',
|
||||||
|
probability=draw_prob,
|
||||||
|
odds=odds['ms_d'],
|
||||||
|
edge=edge,
|
||||||
|
confidence=draw_prob * 100,
|
||||||
|
))
|
||||||
|
|
||||||
|
if 'ms_a' in odds and odds['ms_a'] > 0:
|
||||||
|
implied = 1 / odds['ms_a']
|
||||||
|
edge = away_prob - implied
|
||||||
|
if edge > ms_edge:
|
||||||
|
value_bets.append(ValueBet(
|
||||||
|
market_type='MS',
|
||||||
|
pick='2',
|
||||||
|
probability=away_prob,
|
||||||
|
odds=odds['ms_a'],
|
||||||
|
edge=edge,
|
||||||
|
confidence=away_prob * 100,
|
||||||
|
))
|
||||||
|
|
||||||
|
# OU25 value bets
|
||||||
|
if 'ou25_o' in odds and odds['ou25_o'] > 0:
|
||||||
|
implied = 1 / odds['ou25_o']
|
||||||
|
edge = over_prob - implied
|
||||||
|
if edge > ou_edge:
|
||||||
|
value_bets.append(ValueBet(
|
||||||
|
market_type='OU25',
|
||||||
|
pick='Over',
|
||||||
|
probability=over_prob,
|
||||||
|
odds=odds['ou25_o'],
|
||||||
|
edge=edge,
|
||||||
|
confidence=over_prob * 100,
|
||||||
|
))
|
||||||
|
|
||||||
|
if 'ou25_u' in odds and odds['ou25_u'] > 0:
|
||||||
|
implied = 1 / odds['ou25_u']
|
||||||
|
edge = under_prob - implied
|
||||||
|
if edge > ou_edge:
|
||||||
|
value_bets.append(ValueBet(
|
||||||
|
market_type='OU25',
|
||||||
|
pick='Under',
|
||||||
|
probability=under_prob,
|
||||||
|
odds=odds['ou25_u'],
|
||||||
|
edge=edge,
|
||||||
|
confidence=under_prob * 100,
|
||||||
|
))
|
||||||
|
|
||||||
|
# BTTS value bets
|
||||||
|
if 'btts_y' in odds and odds['btts_y'] > 0:
|
||||||
|
implied = 1 / odds['btts_y']
|
||||||
|
edge = btts_yes_prob - implied
|
||||||
|
if edge > btts_edge:
|
||||||
|
value_bets.append(ValueBet(
|
||||||
|
market_type='BTTS',
|
||||||
|
pick='Yes',
|
||||||
|
probability=btts_yes_prob,
|
||||||
|
odds=odds['btts_y'],
|
||||||
|
edge=edge,
|
||||||
|
confidence=btts_yes_prob * 100,
|
||||||
|
))
|
||||||
|
|
||||||
|
if 'btts_n' in odds and odds['btts_n'] > 0:
|
||||||
|
implied = 1 / odds['btts_n']
|
||||||
|
edge = btts_no_prob - implied
|
||||||
|
if edge > btts_edge:
|
||||||
|
value_bets.append(ValueBet(
|
||||||
|
market_type='BTTS',
|
||||||
|
pick='No',
|
||||||
|
probability=btts_no_prob,
|
||||||
|
odds=odds['btts_n'],
|
||||||
|
edge=edge,
|
||||||
|
confidence=btts_no_prob * 100,
|
||||||
|
))
|
||||||
|
|
||||||
|
return value_bets
|
||||||
|
|
||||||
|
|
||||||
|
# Singleton instance
|
||||||
|
_v25_predictor: Optional[V25Predictor] = None
|
||||||
|
|
||||||
|
|
||||||
|
def get_v25_predictor() -> V25Predictor:
|
||||||
|
"""Get or create V25 predictor instance."""
|
||||||
|
global _v25_predictor
|
||||||
|
if _v25_predictor is None:
|
||||||
|
_v25_predictor = V25Predictor()
|
||||||
|
_v25_predictor.load_models()
|
||||||
|
return _v25_predictor
|
||||||
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user