Download src/models/tree_models.py from Ypeng12/quant-ai: direct link, hf CLI and curl.
- Browser
- Download file 5.45 kB
-
https://huggingface.co/spaces/Ypeng12/quant-ai/resolve/main/src/models/tree_models.py
- Command line
-
hf download hf://spaces/Ypeng12/quant-ai/src/models/tree_models.py
-
curl -L -o tree_models.py https://huggingface.co/spaces/Ypeng12/quant-ai/resolve/main/src/models/tree_models.py
5.45 kB
| import pandas as pd | |
| import numpy as np | |
| from typing import List, Optional, Dict, Any | |
| class LightGBMModel: | |
| """ | |
| Tree Model 1: LightGBM Regressor / Ranker with constrained depth to prevent overfitting. | |
| Falls back gracefully to sklearn HistGradientBoostingRegressor if lightgbm is not installed. | |
| """ | |
| def __init__( | |
| self, | |
| max_depth: int = 3, | |
| num_leaves: int = 7, | |
| learning_rate: float = 0.01, | |
| n_estimators: int = 500, | |
| mode: str = "regressor", | |
| ): | |
| self.max_depth = max_depth | |
| self.num_leaves = num_leaves | |
| self.learning_rate = learning_rate | |
| self.n_estimators = n_estimators | |
| self.mode = mode | |
| self.model = None | |
| def fit(self, df: pd.DataFrame, feature_cols: List[str], target_col: str): | |
| clean_df = df[feature_cols + [target_col, "date"]].dropna() | |
| if len(clean_df) < 50: | |
| return | |
| X = clean_df[feature_cols] | |
| y = clean_df[target_col] | |
| try: | |
| import lightgbm as lgb | |
| if self.mode == "ranker": | |
| clean_df = clean_df.sort_values("date") | |
| group_sizes = clean_df.groupby("date").size().values | |
| y_quant = clean_df.groupby("date")[target_col].transform( | |
| lambda s: pd.qcut(s.rank(method="first"), 5, labels=False) | |
| ) | |
| self.model = lgb.LGBMRanker( | |
| max_depth=self.max_depth, | |
| num_leaves=self.num_leaves, | |
| learning_rate=self.learning_rate, | |
| n_estimators=self.n_estimators, | |
| subsample=0.7, | |
| colsample_bytree=0.7, | |
| random_state=42, | |
| verbosity=-1, | |
| ) | |
| self.model.fit(clean_df[feature_cols], y_quant, group=group_sizes) | |
| else: | |
| self.model = lgb.LGBMRegressor( | |
| max_depth=self.max_depth, | |
| num_leaves=self.num_leaves, | |
| learning_rate=self.learning_rate, | |
| n_estimators=self.n_estimators, | |
| subsample=0.7, | |
| colsample_bytree=0.7, | |
| random_state=42, | |
| verbosity=-1, | |
| ) | |
| self.model.fit(X, y) | |
| except ImportError: | |
| # Fallback to sklearn HistGradientBoostingRegressor | |
| from sklearn.ensemble import HistGradientBoostingRegressor | |
| self.model = HistGradientBoostingRegressor( | |
| max_depth=self.max_depth, | |
| learning_rate=self.learning_rate, | |
| max_iter=min(200, self.n_estimators), | |
| random_state=42, | |
| ) | |
| self.model.fit(X, y) | |
| def predict(self, df: pd.DataFrame, feature_cols: List[str]) -> pd.Series: | |
| if self.model is None: | |
| return pd.Series(0.0, index=df.index) | |
| X = df[feature_cols].fillna(0.0) | |
| preds = self.model.predict(X) | |
| return pd.Series(preds, index=df.index) | |
| def feature_importances(self, feature_cols: List[str]) -> Dict[str, float]: | |
| if self.model is None: | |
| return {} | |
| if hasattr(self.model, "feature_importances_"): | |
| imp = self.model.feature_importances_ | |
| total = float(imp.sum()) + 1e-8 | |
| return {f: float(i / total) for f, i in zip(feature_cols, imp)} | |
| return {f: 1.0 / len(feature_cols) for f in feature_cols} | |
| class XGBoostModel: | |
| """ | |
| Tree Model 2: XGBoost Regressor with L2 regularization. | |
| Falls back gracefully to sklearn GradientBoostingRegressor if xgboost is not installed. | |
| """ | |
| def __init__( | |
| self, | |
| max_depth: int = 3, | |
| learning_rate: float = 0.01, | |
| n_estimators: int = 500, | |
| reg_lambda: float = 1.0, | |
| ): | |
| self.max_depth = max_depth | |
| self.learning_rate = learning_rate | |
| self.n_estimators = n_estimators | |
| self.reg_lambda = reg_lambda | |
| self.model = None | |
| def fit(self, df: pd.DataFrame, feature_cols: List[str], target_col: str): | |
| clean_df = df[feature_cols + [target_col]].dropna() | |
| if len(clean_df) < 50: | |
| return | |
| X = clean_df[feature_cols] | |
| y = clean_df[target_col] | |
| try: | |
| import xgboost as xgb | |
| self.model = xgb.XGBRegressor( | |
| max_depth=self.max_depth, | |
| learning_rate=self.learning_rate, | |
| n_estimators=self.n_estimators, | |
| reg_lambda=self.reg_lambda, | |
| subsample=0.7, | |
| colsample_bytree=0.7, | |
| random_state=42, | |
| verbosity=0, | |
| ) | |
| self.model.fit(X, y) | |
| except ImportError: | |
| from sklearn.ensemble import GradientBoostingRegressor | |
| self.model = GradientBoostingRegressor( | |
| max_depth=self.max_depth, | |
| learning_rate=self.learning_rate, | |
| n_estimators=min(200, self.n_estimators), | |
| subsample=0.7, | |
| random_state=42, | |
| ) | |
| self.model.fit(X, y) | |
| def predict(self, df: pd.DataFrame, feature_cols: List[str]) -> pd.Series: | |
| if self.model is None: | |
| return pd.Series(0.0, index=df.index) | |
| X = df[feature_cols].fillna(0.0) | |
| preds = self.model.predict(X) | |
| return pd.Series(preds, index=df.index) | |