Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ env/
# Testing
.pytest_cache/
.coverage
coverage.xml
htmlcov/
.tox/

Expand All @@ -53,6 +54,7 @@ dist/

# Notebooks
.ipynb_checkpoints/
*.ipynb

# OS
.DS_Store
Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ repos:
language: system
types: [python]
pass_filenames: false
entry: uv run ruff check src/ configs/ scripts/ --fix --exclude src/leap/_version.py
entry: uv run ruff check src/leap/ configs/ scripts/ --fix --exclude src/leap/_version.py
- id: mypy
name: Static type checking using mypy
language: system
types: [python]
pass_filenames: false
entry: uv run mypy src/ configs/ --exclude src/leap/_version.py
entry: uv run mypy src/leap/ configs/ --exclude src/leap/_version.py
- id: pydoclint
name: Docstring linting with pydoclint
language: system
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: help install checks testing clean
.PHONY: help install checks tests clean

UV_VERSION := 0.8.23

Expand Down Expand Up @@ -38,7 +38,7 @@ checks: ## Run pre-commit checks on all files
@echo "🔍 Running checks..."
@PIP_INDEX_URL=https://pypi.org/simple PIP_EXTRA_INDEX_URL="" uv run pre-commit run --all-files

testing: ## Run tests with coverage
tests: ## Run tests with coverage
@echo "🧪 Running tests..."
@uv run pytest src/tests/ -vv

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Run quality checks before committing:

```bash
make checks # Run pre-commit hooks (linting, formatting, type checking)
make testing # Run tests with coverage
make tests # Run tests with coverage
```

## Usage
Expand Down
2 changes: 1 addition & 1 deletion badges/cov_badge.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
104 changes: 104 additions & 0 deletions configs/config_perturbation_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
"""Define perturbation model parameters."""

PRED_MODEL_NAME: dict[str, str] = {
"mae_pp_tdnn": "dnn_regressor",
"mae_pp_mlp": "mlp_regressor",
"mae_pp_lgbm": "lgbm_regressor",
"mae_ps_knn": "knn_regressor",
"mae_ps_mlp": "mlp_regressor_small",
"mae_ps_lgbm": "lgbm_regressor_small",
"mae_ps_enet": "elastic_net_regressor",
}

PRED_MODEL_TYPE: dict[str, str] = {
"mae_pp_tdnn": "pan_perturbation",
"mae_pp_mlp": "pan_perturbation",
"mae_pp_lgbm": "pan_perturbation",
"mae_ps_knn": "multi_label",
"mae_ps_mlp": "perturbation_specific",
"mae_ps_lgbm": "perturbation_specific",
"mae_ps_enet": "perturbation_specific",
}

RPZ_MODEL_NAME: dict[str, str] = {
"mae_pp_tdnn": "mae",
"mae_pp_mlp": "mae",
"mae_pp_lgbm": "mae",
"mae_ps_knn": "mae",
"mae_ps_mlp": "mae",
"mae_ps_lgbm": "mae",
"mae_ps_enet": "mae",
}

USE_TRAINED_PREPROCESSOR: dict[str, bool] = {
"mae_pp_tdnn": True,
"mae_pp_mlp": True,
"mae_pp_lgbm": True,
"mae_ps_knn": True,
"mae_ps_mlp": True,
"mae_ps_lgbm": True,
"mae_ps_enet": True,
}


USE_TRAINED_RPZ: dict[str, bool] = {
"mae_pp_tdnn": True,
"mae_pp_mlp": True,
"mae_pp_lgbm": True,
"mae_ps_knn": True,
"mae_ps_mlp": True,
"mae_ps_lgbm": True,
"mae_ps_enet": True,
}

# IMPORTANT: in LEAP we actually use depmap_gdsc_pdx (using all available data)
PRETRAINED_DATA: dict[str, str] = {
"mae_pp_tdnn": "depmap",
"mae_pp_mlp": "depmap",
"mae_pp_lgbm": "depmap",
"mae_ps_knn": "depmap",
"mae_ps_mlp": "depmap",
"mae_ps_lgbm": "depmap",
"mae_ps_enet": "depmap",
}


ENSEMBLING: dict[str, bool] = {
"mae_pp_tdnn": True,
"mae_pp_mlp": True,
"mae_pp_lgbm": True,
"mae_ps_knn": True,
"mae_ps_mlp": True,
"mae_ps_lgbm": True,
"mae_ps_enet": True,
}

ENSEMBLING_SAVE_MODELS_TO_DISK: dict[str, bool] = {
"mae_pp_tdnn": True,
"mae_pp_mlp": True,
"mae_pp_lgbm": True,
"mae_ps_knn": False,
"mae_ps_mlp": False,
"mae_ps_lgbm": False,
"mae_ps_enet": False,
}

USE_RAY: dict[str, bool] = {
"mae_pp_tdnn": False,
"mae_pp_mlp": False,
"mae_pp_lgbm": False,
"mae_ps_knn": False,
"mae_ps_mlp": True,
"mae_ps_lgbm": True,
"mae_ps_enet": True,
}

RAY_REMOTE_PARAMS: dict[str, dict | None] = {
"mae_pp_tdnn": None,
"mae_pp_mlp": None,
"mae_pp_lgbm": None,
"mae_ps_knn": None,
"mae_ps_mlp": {"num_cpus": 1, "num_gpus": 0.05},
"mae_ps_lgbm": {"num_cpus": 8},
"mae_ps_enet": {"num_cpus": 1},
}
210 changes: 210 additions & 0 deletions configs/config_regression_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
"""Define configs for regression models to use in the pipeline."""

from ml_collections import config_dict

from leap.regression_models import ElasticNet, KnnRegressor, LGBMRegressor, TorchMLPRegressor
from leap.regression_models.utils import AlphaGridElasticNet


REGRESSION_MODEL: dict[str, config_dict.ConfigDict] = {
"knn_regressor": config_dict.ConfigDict(
{
"_target_": KnnRegressor,
"n_sample_neighbors": 5, # default
"weights": "uniform", # default
"n_jobs": 30,
}
),
"elastic_net_regressor": config_dict.ConfigDict(
{
"_target_": ElasticNet,
"l1_ratio": 1.0,
}
),
"lgbm_regressor": config_dict.ConfigDict(
{
"_target_": LGBMRegressor,
"subsample_for_bin": 400000,
"num_leaves": 4000,
"min_split_gain": 0,
"min_child_weight": 0.01,
"min_child_samples": 5,
"max_depth": 20,
"learning_rate": 0.03,
"reg_lambda": 0,
"reg_alpha": 1,
"colsample_bytree": 0.8,
"n_estimators": 500,
"subsample": 1,
"random_state": 0,
"n_jobs": 50, # launch two in // on large vm
"verbose": -1,
}
),
"lgbm_regressor_small": config_dict.ConfigDict(
{
# Comment every time the default is changed
"_target_": LGBMRegressor,
"boosting_type": "gbdt",
"num_leaves": 31,
"max_depth": 10, # After small grid, systematically better default is -1
"learning_rate": 0.01, # TO TUNE, but 0.01 works well. default is 0.1
"n_estimators": 400, # Default is 100, but 400 is better
"subsample_for_bin": 200000,
"objective": None,
"class_weight": None,
"min_split_gain": 0,
"min_child_weight": 1e-3,
"min_child_samples": (5), # Tuning it is the next best thing to do, default 20
"subsample": 1,
"subsample_freq": 0,
"colsample_bytree": 0.1, # TO TUNE, much better when small, default is 1.0
"reg_alpha": 1, # After small grid, better when 1, default is 0
"reg_lambda": 1, # After small grid, marginally better when 1, default is 0
"random_state": 0, # for reproducibility
"n_jobs": 8, # small model so we can use less cores
"verbose": -1, # disable prints
}
),
"mlp_regressor": config_dict.ConfigDict(
{
"_target_": TorchMLPRegressor,
"hidden_layer_sizes": (512, 256, 128, 64, 32, 16),
"activation": "relu",
"learning_rate_init": 0.001,
"max_epochs": 200,
"batch_size": 2048,
"dropout_rate": 0.2, # Best based on tests on 1a-small
"random_seed": 0,
"early_stopping_use": True,
"early_stopping_split": 0.2,
"early_stopping_patience": 20,
"early_stopping_delta": 0.001,
"optimizer_type": "adam",
"weight_decay": 1e-5,
"learning_rate_scheduler": True, # Best based on tests on 1a-small
"scheduler_factor": 0.1,
# If the threshold is the same as the delta,
# this needs to be smaller than the patience of the early stopping
"scheduler_patience": 10,
"scheduler_threshold": 0.001,
"metric": "spearman",
"scaler_name": "robust",
"loss_function_name": "spearman",
}
),
"mlp_regressor_small": config_dict.ConfigDict(
{
"_target_": TorchMLPRegressor,
"hidden_layer_sizes": (20, 20),
"activation": "relu",
"learning_rate_init": 0.001,
"max_epochs": 200,
"batch_size": 2048,
"dropout_rate": 0.2, # Best based on tests on 1a-small
"random_seed": 0,
"early_stopping_use": True,
"early_stopping_split": 0.2,
"early_stopping_patience": 20,
"early_stopping_delta": 0.001,
"optimizer_type": "adam",
"weight_decay": 1e-5,
"learning_rate_scheduler": True, # Best based on tests on 1a-small
"scheduler_factor": 0.1,
# If the threshold is the same as the delta,
# this needs to be smaller than the patience of the early stopping
"scheduler_patience": 10,
"scheduler_threshold": 0.001,
"metric": "spearman",
"scaler_name": "robust",
"loss_function_name": "spearman",
}
),
# For the ETL tDNN paper comparison
"dnn_regressor": config_dict.ConfigDict(
{
"_target_": TorchMLPRegressor,
"hidden_layer_sizes": (250, 125, 60, 30),
"activation": "relu",
# "The learning rate was initialized at 0.001"
"learning_rate_init": 0.001,
# "otherwise the full learning process would take 100 epochs"
"max_epochs": 100,
"batch_size": 2048,
"dropout_rate": 0.0,
"random_seed": 0,
# "The learning process would be early stopped if the reduction of
# validation loss was smaller than 0.00001 in 20 epochs"
"early_stopping_use": True,
"early_stopping_split": 0.2,
"early_stopping_patience": 20,
"early_stopping_delta": 0.00001,
# "The Adam optimizer was used with default setting for model learning"
"optimizer_type": "adam",
"weight_decay": 1e-5,
# "The learning rate [...] was reduced by a factor of 10 if the reduction of
# validation loss was smaller than 0.00001 in 10 epochs."
"learning_rate_scheduler": True,
"scheduler_factor": 0.1,
"scheduler_patience": 10,
"scheduler_threshold": 0.00001,
"metric": "mse", # In the ETL paper (tDNN) it's the mse (loss)
"scaler_name": "standard",
"loss_function_name": "mse",
}
),
}

HPT_TUNING_PARAM_GRID: dict[str, config_dict.ConfigDict | None] = {
"knn_regressor": None,
"elastic_net_regressor": config_dict.ConfigDict(
{
"alpha": config_dict.ConfigDict(
{
"_target_": AlphaGridElasticNet,
"alpha_min_ratio": 1e-3,
"n_alphas": 10,
}
),
}
),
"lgbm_regressor": config_dict.ConfigDict(
{
"reg_alpha": [0, 1],
# log-spaced between 1e-2 and 2e-1, rounded to the first non-zero decimal
"learning_rate": [0.01, 0.02, 0.04, 0.09, 0.2],
}
),
"lgbm_regressor_small": config_dict.ConfigDict(
{
"learning_rate": [0.005, 0.01],
"colsample_bytree": [0.05, 0.1, 0.15, 0.2, 0.25],
}
),
"mlp_regressor": config_dict.ConfigDict(
{
# log-spaced between 5e-4 and 1e-2, rounded to the first non-zero decimal
"learning_rate_init": [0.0005, 0.001, 0.002, 0.005, 0.01],
"batch_size": [2048, 8192],
}
),
"mlp_regressor_small": config_dict.ConfigDict(
{
# log-spaced between 5e-4 and 1e-2, rounded to the first non-zero decimal
"learning_rate_init": [0.0005, 0.001, 0.002, 0.005, 0.01],
"hidden_layer_sizes": [
(20,),
(20, 20),
],
}
),
"dnn_regressor": config_dict.ConfigDict(
{
# This correspond to the HPT done in the ETL paper (tDNN)
# "In the analysis, the dropout rate was selected among 0, 0.1, 0.25, 0.45,
# and 0.7 by minimizing the validation loss. It was the only hyperparameter
# optimized in the model learning process.""
"dropout_rate": [0, 0.1, 0.25, 0.45, 0.7],
}
),
}
Loading
Loading