From 167e051c3a66d20ad523f55dbd2e67423c8f7e29 Mon Sep 17 00:00:00 2001 From: xzy Date: Sat, 13 Jan 2024 21:53:24 +0800 Subject: [PATCH 001/168] add_transform_test --- dance/transforms/graph/resept_graph.py | 5 +++-- dance/transforms/sc3_feature.py | 2 +- test_automl/sweep-config.yaml | 21 +++++++++++++++++++++ tests/transforms/test_RESPETGraph.py | 19 +++++++++++++++++++ tests/transforms/test_SC3Feature.py | 22 ++++++++++++++++++++++ tests/transforms/test_TangramFeature.py | 22 ++++++++++++++++++++++ tests/transforms/test_celltypeNums.py | 19 +++++++++++++++++++ 7 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 test_automl/sweep-config.yaml create mode 100644 tests/transforms/test_RESPETGraph.py create mode 100644 tests/transforms/test_SC3Feature.py create mode 100644 tests/transforms/test_TangramFeature.py create mode 100644 tests/transforms/test_celltypeNums.py diff --git a/dance/transforms/graph/resept_graph.py b/dance/transforms/graph/resept_graph.py index 9ff8fb7a2..ea16bb3d9 100644 --- a/dance/transforms/graph/resept_graph.py +++ b/dance/transforms/graph/resept_graph.py @@ -19,11 +19,11 @@ class RESEPTGraph(BaseTransform): """ - def __init__(self, fiducial_diameter_fullres=144.56835055243283, tissue_hires_scalef=0.150015, **kwargs): + def __init__(self, fiducial_diameter_fullres=144.56835055243283, tissue_hires_scalef=0.150015,n_neighbors: int = 15,**kwargs): super().__init__(**kwargs) self.fiducial_diameter_fullres = fiducial_diameter_fullres self.tissue_hires_scalef = tissue_hires_scalef - + self.n_neighbors=n_neighbors def scale_to_RGB(self, channel, truncated_percent): truncated_down = np.percentile(channel, truncated_percent) truncated_up = np.percentile(channel, 100 - truncated_percent) @@ -34,6 +34,7 @@ def scale_to_RGB(self, channel, truncated_percent): def __call__(self, data: Data) -> Data: xy_pixel = data.get_feature(return_type="numpy", channel="spatial_pixel", channel_type="obsm") + sc.pp.neighbors(data.data,n_neighbors=self.n_neighbors) sc.tl.umap(data.data, n_components=3) X_transform = data.get_feature(return_type="numpy", channel="X_umap", channel_type="obsm") X_transform[:, 0] = self.scale_to_RGB(X_transform[:, 0], 100) diff --git a/dance/transforms/sc3_feature.py b/dance/transforms/sc3_feature.py index ebda74ee2..bf9d88d02 100644 --- a/dance/transforms/sc3_feature.py +++ b/dance/transforms/sc3_feature.py @@ -86,5 +86,5 @@ def __call__(self, data): sim_matrix_all = np.array(sim_matrix_all) sim_matrix_mean = np.mean(sim_matrix_all, axis=0) - data.data.uns[self.out] = sim_matrix_mean + data.data.obsm[self.out] = sim_matrix_mean return data diff --git a/test_automl/sweep-config.yaml b/test_automl/sweep-config.yaml new file mode 100644 index 000000000..c81ce31ae --- /dev/null +++ b/test_automl/sweep-config.yaml @@ -0,0 +1,21 @@ +job: xzy11632/pytorch-cell_type_annotation_ACTINN_function_new/job-source-pytorch-cell_type_annotation_ACTINN_function_new-test_automl_test_automl_fun_job.py:latest +metric: + goal: maximize + name: scores +run_cap: 20 +scheduler: + job: xzy11632/pytorch-cell_type_annotation_ACTINN_function_new/job-OptunaScheduler:latest + num_workers: 2 + docker_image: r:fcf2b32f + resource_args: + local-container: + env-file: "/home/zyxing/dance/web-variables.env" + settings: + optuna_source: xzy11632/pytorch-cell_type_annotation_ACTINN_function_new/optuna-config:latest + optuna_source_filename: test_automl/optuna_wandb.py + pruner: + args: + n_min_trials: 1 + n_startup_trials: 2 + percentile: 0.25 + type: PercentilePruner diff --git a/tests/transforms/test_RESPETGraph.py b/tests/transforms/test_RESPETGraph.py new file mode 100644 index 000000000..1e292cc77 --- /dev/null +++ b/tests/transforms/test_RESPETGraph.py @@ -0,0 +1,19 @@ +from dance.transforms.graph import RESEPTGraph +import numpy as np +from anndata import AnnData +from dance.data import Data +import pytest +import pandas as pd +SEED=123 + +def test_RESPET_GRAPH(): + num_cells = 100 + num_genes = 500 + gene_expression = np.random.default_rng(seed=SEED).random((num_cells, num_genes)) + adata = AnnData(X=gene_expression) + random_df = pd.DataFrame(np.random.default_rng(seed=SEED).integers(1,10000,size=(num_cells, 2)), columns=["x_pixel", "y_pixel"],index=adata.obs_names) + adata.obsm['spatial_pixel']=random_df + data=Data(adata.copy()) + RESEPTgraph=RESEPTGraph() + RESEPTgraph(data) + assert data.data.uns['RESEPTGraph'].shape==(2000,2000,3) diff --git a/tests/transforms/test_SC3Feature.py b/tests/transforms/test_SC3Feature.py new file mode 100644 index 000000000..c73beb3fa --- /dev/null +++ b/tests/transforms/test_SC3Feature.py @@ -0,0 +1,22 @@ +from dance.transforms import SC3Feature +import numpy as np +from anndata import AnnData +from dance.data import Data +import pytest + +SEED = 123 + + +@pytest.fixture +def toy_data(): + x = np.random.default_rng(SEED).random((5, 3)) + adata = AnnData(X=x, dtype=np.float32) + data = Data(adata.copy()) + return adata, data + +def test_sc3_feature(toy_data): + adata,data = toy_data + sc3feature=SC3Feature() + data=sc3feature(data) + sc3_feature=data.get_feature(return_type="numpy", channel="SC3Feature", channel_type="obsm") + assert sc3_feature.shape[0]==data.shape[0] diff --git a/tests/transforms/test_TangramFeature.py b/tests/transforms/test_TangramFeature.py new file mode 100644 index 000000000..573200746 --- /dev/null +++ b/tests/transforms/test_TangramFeature.py @@ -0,0 +1,22 @@ +from dance.transforms import TangramFeature +import numpy as np +from anndata import AnnData +from dance.data import Data +import pytest + +SEED = 123 + + +@pytest.fixture +def toy_data(): + x = np.random.default_rng(SEED).random((5, 3)) + adata = AnnData(X=x, dtype=np.float32) + data = Data(adata.copy()) + return adata, data + +def test_tangram_feature(toy_data): + adata, data = toy_data + tangramFeature=TangramFeature() + data=tangramFeature(data) + tangram_feature=data.get_feature(return_type="numpy", channel="TangramFeature", channel_type="obs") + assert np.sum(tangram_feature)==1 diff --git a/tests/transforms/test_celltypeNums.py b/tests/transforms/test_celltypeNums.py new file mode 100644 index 000000000..bd7cf53b8 --- /dev/null +++ b/tests/transforms/test_celltypeNums.py @@ -0,0 +1,19 @@ +from dance.transforms import CellTypeNums +import numpy as np +from anndata import AnnData +from dance.data import Data +import pytest +import numpy as np +SEED = 123 +def test_cell_type_nums(): + np.random.seed() + num_cells = 100 + num_genes = 500 + gene_expression = np.random.default_rng(seed=SEED).random((num_cells, num_genes)) + cell_types = np.random.default_rng(seed=SEED).choice(['Type_A', 'Type_B', 'Type_C'], num_cells) + adata = AnnData(X=gene_expression, obs={'cellType': cell_types}) + data = Data(adata.copy()) + data=CellTypeNums()(data) + cell_type_nums=data.get_feature(return_type="numpy", channel="CellTypeNums", channel_type="uns") + return cell_type_nums.shape[0]==len(np.unique(cell_types)) + From 1d34dcfcf7c6331810eee6ca06941e508c02981a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 13 Jan 2024 13:57:50 +0000 Subject: [PATCH 002/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dance/transforms/graph/resept_graph.py | 8 +++++--- test_automl/sweep-config.yaml | 4 ++-- tests/transforms/test_RESPETGraph.py | 23 ++++++++++++++--------- tests/transforms/test_SC3Feature.py | 16 +++++++++------- tests/transforms/test_TangramFeature.py | 14 ++++++++------ tests/transforms/test_celltypeNums.py | 16 +++++++++------- 6 files changed, 47 insertions(+), 34 deletions(-) diff --git a/dance/transforms/graph/resept_graph.py b/dance/transforms/graph/resept_graph.py index ea16bb3d9..21652daf8 100644 --- a/dance/transforms/graph/resept_graph.py +++ b/dance/transforms/graph/resept_graph.py @@ -19,11 +19,13 @@ class RESEPTGraph(BaseTransform): """ - def __init__(self, fiducial_diameter_fullres=144.56835055243283, tissue_hires_scalef=0.150015,n_neighbors: int = 15,**kwargs): + def __init__(self, fiducial_diameter_fullres=144.56835055243283, tissue_hires_scalef=0.150015, + n_neighbors: int = 15, **kwargs): super().__init__(**kwargs) self.fiducial_diameter_fullres = fiducial_diameter_fullres self.tissue_hires_scalef = tissue_hires_scalef - self.n_neighbors=n_neighbors + self.n_neighbors = n_neighbors + def scale_to_RGB(self, channel, truncated_percent): truncated_down = np.percentile(channel, truncated_percent) truncated_up = np.percentile(channel, 100 - truncated_percent) @@ -34,7 +36,7 @@ def scale_to_RGB(self, channel, truncated_percent): def __call__(self, data: Data) -> Data: xy_pixel = data.get_feature(return_type="numpy", channel="spatial_pixel", channel_type="obsm") - sc.pp.neighbors(data.data,n_neighbors=self.n_neighbors) + sc.pp.neighbors(data.data, n_neighbors=self.n_neighbors) sc.tl.umap(data.data, n_components=3) X_transform = data.get_feature(return_type="numpy", channel="X_umap", channel_type="obsm") X_transform[:, 0] = self.scale_to_RGB(X_transform[:, 0], 100) diff --git a/test_automl/sweep-config.yaml b/test_automl/sweep-config.yaml index c81ce31ae..adea93e7a 100644 --- a/test_automl/sweep-config.yaml +++ b/test_automl/sweep-config.yaml @@ -6,11 +6,11 @@ run_cap: 20 scheduler: job: xzy11632/pytorch-cell_type_annotation_ACTINN_function_new/job-OptunaScheduler:latest num_workers: 2 - docker_image: r:fcf2b32f + docker_image: r:fcf2b32f resource_args: local-container: env-file: "/home/zyxing/dance/web-variables.env" - settings: + settings: optuna_source: xzy11632/pytorch-cell_type_annotation_ACTINN_function_new/optuna-config:latest optuna_source_filename: test_automl/optuna_wandb.py pruner: diff --git a/tests/transforms/test_RESPETGraph.py b/tests/transforms/test_RESPETGraph.py index 1e292cc77..4b478ec45 100644 --- a/tests/transforms/test_RESPETGraph.py +++ b/tests/transforms/test_RESPETGraph.py @@ -1,19 +1,24 @@ -from dance.transforms.graph import RESEPTGraph import numpy as np +import pandas as pd +import pytest from anndata import AnnData + from dance.data import Data -import pytest -import pandas as pd -SEED=123 +from dance.transforms.graph import RESEPTGraph + +SEED = 123 + def test_RESPET_GRAPH(): num_cells = 100 num_genes = 500 gene_expression = np.random.default_rng(seed=SEED).random((num_cells, num_genes)) adata = AnnData(X=gene_expression) - random_df = pd.DataFrame(np.random.default_rng(seed=SEED).integers(1,10000,size=(num_cells, 2)), columns=["x_pixel", "y_pixel"],index=adata.obs_names) - adata.obsm['spatial_pixel']=random_df - data=Data(adata.copy()) - RESEPTgraph=RESEPTGraph() + random_df = pd.DataFrame( + np.random.default_rng(seed=SEED).integers(1, 10000, size=(num_cells, 2)), columns=["x_pixel", "y_pixel"], + index=adata.obs_names) + adata.obsm['spatial_pixel'] = random_df + data = Data(adata.copy()) + RESEPTgraph = RESEPTGraph() RESEPTgraph(data) - assert data.data.uns['RESEPTGraph'].shape==(2000,2000,3) + assert data.data.uns['RESEPTGraph'].shape == (2000, 2000, 3) diff --git a/tests/transforms/test_SC3Feature.py b/tests/transforms/test_SC3Feature.py index c73beb3fa..c64bf209f 100644 --- a/tests/transforms/test_SC3Feature.py +++ b/tests/transforms/test_SC3Feature.py @@ -1,8 +1,9 @@ -from dance.transforms import SC3Feature import numpy as np +import pytest from anndata import AnnData + from dance.data import Data -import pytest +from dance.transforms import SC3Feature SEED = 123 @@ -14,9 +15,10 @@ def toy_data(): data = Data(adata.copy()) return adata, data + def test_sc3_feature(toy_data): - adata,data = toy_data - sc3feature=SC3Feature() - data=sc3feature(data) - sc3_feature=data.get_feature(return_type="numpy", channel="SC3Feature", channel_type="obsm") - assert sc3_feature.shape[0]==data.shape[0] + adata, data = toy_data + sc3feature = SC3Feature() + data = sc3feature(data) + sc3_feature = data.get_feature(return_type="numpy", channel="SC3Feature", channel_type="obsm") + assert sc3_feature.shape[0] == data.shape[0] diff --git a/tests/transforms/test_TangramFeature.py b/tests/transforms/test_TangramFeature.py index 573200746..4be8968e5 100644 --- a/tests/transforms/test_TangramFeature.py +++ b/tests/transforms/test_TangramFeature.py @@ -1,8 +1,9 @@ -from dance.transforms import TangramFeature import numpy as np +import pytest from anndata import AnnData + from dance.data import Data -import pytest +from dance.transforms import TangramFeature SEED = 123 @@ -14,9 +15,10 @@ def toy_data(): data = Data(adata.copy()) return adata, data + def test_tangram_feature(toy_data): adata, data = toy_data - tangramFeature=TangramFeature() - data=tangramFeature(data) - tangram_feature=data.get_feature(return_type="numpy", channel="TangramFeature", channel_type="obs") - assert np.sum(tangram_feature)==1 + tangramFeature = TangramFeature() + data = tangramFeature(data) + tangram_feature = data.get_feature(return_type="numpy", channel="TangramFeature", channel_type="obs") + assert np.sum(tangram_feature) == 1 diff --git a/tests/transforms/test_celltypeNums.py b/tests/transforms/test_celltypeNums.py index bd7cf53b8..18c7c5817 100644 --- a/tests/transforms/test_celltypeNums.py +++ b/tests/transforms/test_celltypeNums.py @@ -1,10 +1,13 @@ -from dance.transforms import CellTypeNums import numpy as np +import pytest from anndata import AnnData + from dance.data import Data -import pytest -import numpy as np +from dance.transforms import CellTypeNums + SEED = 123 + + def test_cell_type_nums(): np.random.seed() num_cells = 100 @@ -13,7 +16,6 @@ def test_cell_type_nums(): cell_types = np.random.default_rng(seed=SEED).choice(['Type_A', 'Type_B', 'Type_C'], num_cells) adata = AnnData(X=gene_expression, obs={'cellType': cell_types}) data = Data(adata.copy()) - data=CellTypeNums()(data) - cell_type_nums=data.get_feature(return_type="numpy", channel="CellTypeNums", channel_type="uns") - return cell_type_nums.shape[0]==len(np.unique(cell_types)) - + data = CellTypeNums()(data) + cell_type_nums = data.get_feature(return_type="numpy", channel="CellTypeNums", channel_type="uns") + return cell_type_nums.shape[0] == len(np.unique(cell_types)) From cab672d93b52eda9829531599d165fbf6bc63f2e Mon Sep 17 00:00:00 2001 From: xzy Date: Sat, 13 Jan 2024 22:18:01 +0800 Subject: [PATCH 003/168] automl_demo --- test_automl/optuna_scheduler.py | 805 +++++++++++++++++++++++++++++ test_automl/optuna_wandb.py | 159 ++++++ test_automl/test_automl_fun_2.py | 54 ++ test_automl/test_automl_fun_job.py | 175 +++++++ test_automl/test_automl_step2.py | 145 ++++++ test_automl/web-variables.env | 2 + 6 files changed, 1340 insertions(+) create mode 100644 test_automl/optuna_scheduler.py create mode 100644 test_automl/optuna_wandb.py create mode 100644 test_automl/test_automl_fun_2.py create mode 100644 test_automl/test_automl_fun_job.py create mode 100644 test_automl/test_automl_step2.py create mode 100644 test_automl/web-variables.env diff --git a/test_automl/optuna_scheduler.py b/test_automl/optuna_scheduler.py new file mode 100644 index 000000000..a84cf1d09 --- /dev/null +++ b/test_automl/optuna_scheduler.py @@ -0,0 +1,805 @@ +import argparse +import base64 +import logging +import os +import signal +import traceback +from collections import defaultdict +from dataclasses import dataclass +from enum import Enum +from importlib.machinery import SourceFileLoader +from types import ModuleType +from typing import Any, Dict, List, Optional, Tuple + +import click +import optuna +import wandb +from wandb.apis.internal import Api +from wandb.apis.public import Api as PublicApi +from wandb.apis.public import QueuedRun, Run +from wandb.sdk.artifacts.artifact import Artifact +from wandb.sdk.launch.sweeps import SchedulerError +from wandb.sdk.launch.sweeps.scheduler import RunState, Scheduler, SweepRun + +logger = logging.getLogger(__name__) +optuna.logging.set_verbosity(optuna.logging.WARNING) + +LOG_PREFIX = f"{click.style('optuna sched:', fg='bright_blue')} " + + +class OptunaComponents(Enum): + main_file = "optuna_wandb.py" + storage = "optuna.db" + study = "optuna-study" + pruner = "optuna-pruner" + sampler = "optuna-sampler" + + +@dataclass +class OptunaRun: + num_metrics: int + trial: optuna.Trial + sweep_run: SweepRun + + +@dataclass +class Metric: + name: str + direction: optuna.study.StudyDirection + + +def setup_scheduler(scheduler: Scheduler, **kwargs): + """Setup a run to log a scheduler job. + + If this job is triggered using a sweep config, it will become a sweep scheduler, + automatically managing a launch sweep Otherwise, we just log the code, creating a + job that can be inserted into a sweep config. + + """ + + parser = argparse.ArgumentParser() + parser.add_argument("--project", type=str, default=kwargs.get("project")) + parser.add_argument("--entity", type=str, default=kwargs.get("entity")) + parser.add_argument("--num_workers", type=int, default=1) + parser.add_argument("--name", type=str, default=f"job-{scheduler.__name__}") + cli_args = parser.parse_args() + + settings = {"job_name": cli_args.name, "job_source": "artifact"} + run = wandb.init( + settings=settings, + project=cli_args.project, + entity=cli_args.entity, + ) + config = run.config + args = config.get("sweep_args", {}) + + if not args or not args.get("sweep_id"): + # when the config has no sweep args, this is being run directly from CLI + # and not in a sweep. Just log the code and return + if not os.getenv("WANDB_DOCKER"): + # if not docker, log the code to a git or code artifact + run.log_code(root=os.path.dirname(__file__)) + run.finish() + return + + if cli_args.num_workers: # override + kwargs.update({"num_workers": cli_args.num_workers}) + + _scheduler = scheduler(Api(), run=run, **args, **kwargs) + _scheduler.start() + + +class OptunaScheduler(Scheduler): + OPT_TIMEOUT = 2 + MAX_MISCONFIGURED_RUNS = 3 + + def __init__( + self, + api: Api, + *args: Optional[Any], + **kwargs: Optional[Any], + ): + super().__init__(api, *args, **kwargs) + # Optuna + self._study: Optional[optuna.study.Study] = None + self._storage_path: Optional[str] = None + self._trial_func = self._make_trial + self._optuna_runs: Dict[str, OptunaRun] = {} + + # Load optuna args from kwargs then check wandb run config + self._optuna_config = kwargs.get("settings") + if not self._optuna_config: + self._optuna_config = self._wandb_run.config.get("settings", {}) + + self._metric_defs = self._get_metric_names_and_directions() + + # if metric is misconfigured, increment, stop sweep if 3 consecutive fails + self._num_misconfigured_runs = 0 + + @property + def study(self) -> optuna.study.Study: + if not self._study: + raise SchedulerError("Optuna study=None before scheduler.start") + return self._study + + @property + def study_name(self) -> str: + if not self._study: + return f"optuna-study-{self._sweep_id}" + optuna_study_name: str = self.study.study_name + return optuna_study_name + + @property + def is_multi_objective(self) -> bool: + return len(self._metric_defs) > 1 + + @property + def study_string(self) -> str: + msg = f"{LOG_PREFIX}{'Loading' if self._wandb_run.resumed else 'Creating'}" + msg += f" optuna study: {self.study_name} " + msg += f"[storage:{self.study._storage.__class__.__name__}" + if not self.is_multi_objective: + msg += f", direction: {self._metric_defs[0].direction.name.capitalize()}" + else: + msg += ", directions: " + for metric in self._metric_defs: + msg += f"{metric.name}:{metric.direction.name.capitalize()}, " + msg = msg[:-2] + msg += f", pruner:{self.study.pruner.__class__.__name__}" + msg += f", sampler:{self.study.sampler.__class__.__name__}]" + return msg + + @property + def formatted_trials(self) -> str: + """Print out the last 10 trials from the current optuna study. + + Shows the run_id/run_state/total_metrics/last_metric. Returns a string with + whitespace. + + """ + if not self._study or len(self.study.trials) == 0: + return "" + + trial_strs = [] + for trial in self.study.trials: + if not trial.values: + continue + + run_id = trial.user_attrs["run_id"] + best: str = "" + if not self.is_multi_objective: + vals = list(trial.intermediate_values.values()) + if len(vals) > 0: + if self.study.direction == optuna.study.StudyDirection.MINIMIZE: + best = f"{round(min(vals), 5)}" + elif self.study.direction == optuna.study.StudyDirection.MAXIMIZE: + best = f"{round(max(vals), 5)}" + trial_strs += [ + f"\t[trial-{trial.number + 1}] run: {run_id}, state: " + f"{trial.state.name}, num-metrics: {len(vals)}, best: {best}" + ] + else: # multi-objective optimization, only 1 metric logged in study + if len(trial.values) != len(self._metric_defs): + wandb.termwarn(f"{LOG_PREFIX}Number of logged metrics ({trial.values})" + " does not match number of metrics defined " + f"({self._metric_defs}). Specify metrics for optimization" + " in the scheduler.settings.metrics portion of the sweep config") + continue + + for val, metric in zip(trial.values, self._metric_defs): + direction = metric.direction.name.capitalize() + best += f"{metric.name} ({direction}):" + best += f"{round(val, 5)}, " + + # trim trailing comma and space + best = best[:-2] + trial_strs += [ + f"\t[trial-{trial.number + 1}] run: {run_id}, state: " + f"{trial.state.name}, best: {best}" + ] + + return "\n".join(trial_strs[-10:]) # only print out last 10 + + def _get_metric_names_and_directions(self) -> List[Metric]: + """Helper to configure dict of at least one metric. + + Dict contains the metric names as keys, with the optimization direction (or + goal) as the value (type: optuna.study.StudyDirection) + + """ + # if single-objective, just top level metric is set + if self._sweep_config.get("metric"): + direction = (optuna.study.StudyDirection.MINIMIZE if self._sweep_config["metric"]["goal"] == "minimize" else + optuna.study.StudyDirection.MAXIMIZE) + metric = Metric(name=self._sweep_config["metric"]["name"], direction=direction) + return [metric] + + # multi-objective optimization + metric_defs = [] + for metric in self._optuna_config.get("metrics", []): + if not metric.get("name"): + raise SchedulerError("Optuna metric missing name") + if not metric.get("goal"): + raise SchedulerError("Optuna metric missing goal") + + direction = (optuna.study.StudyDirection.MINIMIZE + if metric["goal"] == "minimize" else optuna.study.StudyDirection.MAXIMIZE) + metric_defs += [Metric(name=metric["name"], direction=direction)] + + if len(metric_defs) == 0: + raise SchedulerError("Zero metrics found in the top level 'metric' section " + "and multi-objective metric section scheduler.settings.metrics") + + return metric_defs + + def _validate_optuna_study(self, study: optuna.Study) -> Optional[str]: + """Accepts an optuna study, runs validation. + + Returns an error string if validation fails + + """ + if len(study.trials) > 0: + wandb.termlog(f"{LOG_PREFIX}User provided study has prior trials") + + if study.user_attrs: + wandb.termwarn(f"{LOG_PREFIX}user_attrs are ignored from provided study:" + f" ({study.user_attrs})") + + if study._storage is not None: + wandb.termlog(f"{LOG_PREFIX}User provided study has storage:{study._storage}") + + return None + + def _load_optuna_classes( + self, + filepath: str, + ) -> Tuple[ + Optional[optuna.Study], + Optional[optuna.pruners.BasePruner], + Optional[optuna.samplers.BaseSampler], + ]: + """Loads custom optuna classes from user-supplied artifact. + + Returns: + study: a custom optuna study object created by the user + pruner: a custom optuna pruner supplied by user + sampler: a custom optuna sampler supplied by user + + """ + mod, err = _get_module("optuna", filepath) + if not mod: + raise SchedulerError(f"Failed to load optuna from path {filepath} with error: {err}") + + # Set custom optuna trial creation method + try: + self._objective_func = mod.objective + self._trial_func = self._make_trial_from_objective + except AttributeError: + pass + + try: + study = mod.study() + val_error: Optional[str] = self._validate_optuna_study(study) + wandb.termlog(f"{LOG_PREFIX}User provided study, ignoring pruner and sampler") + if val_error: + raise SchedulerError(err) + return study, None, None + except AttributeError: + pass + + pruner, sampler = None, None + try: + pruner = mod.pruner() + except AttributeError: + pass + + try: + sampler = mod.sampler() + except AttributeError: + pass + + return None, pruner, sampler + + def _get_and_download_artifact(self, component: OptunaComponents) -> Optional[str]: + """Finds and downloads an artifact, returns name of downloaded artifact.""" + try: + artifact_name = f"{self._entity}/{self._project}/{component.name}:latest" + component_artifact: Artifact = self._wandb_run.use_artifact(artifact_name) + path = component_artifact.download() + + storage_files = os.listdir(path) + if component.value in storage_files: + if path.startswith("./"): # TODO(gst): robust way of handling this + path = path[2:] + wandb.termlog(f"{LOG_PREFIX}Loaded storage from artifact: {artifact_name}") + return f"{path}/{component.value}" + except wandb.errors.CommError as e: + raise SchedulerError(str(e)) + except Exception as e: + raise SchedulerError(str(e)) + + return None + + def _load_file_from_artifact(self, artifact_name: str) -> str: + wandb.termlog(f"{LOG_PREFIX}User set optuna.artifact, attempting download.") + + # load user-set optuna class definition file + artifact = self._wandb_run.use_artifact(artifact_name, type="optuna") + if not artifact: + raise SchedulerError(f"Failed to load artifact: {artifact_name}") + + path = artifact.download() + optuna_filepath = self._optuna_config.get("optuna_source_filename", OptunaComponents.main_file.value) + return f"{path}/{optuna_filepath}" + + def _try_make_existing_objects( + self, optuna_source: Optional[str] + ) -> Tuple[ + Optional[optuna.Study], + Optional[optuna.pruners.BasePruner], + Optional[optuna.samplers.BaseSampler], + ]: + if not optuna_source: + return None, None, None + + optuna_file = None + if ":" in optuna_source: + optuna_file = self._load_file_from_artifact(optuna_source) + elif ".py" in optuna_source: # raw filepath + optuna_file = optuna_source + else: + raise SchedulerError(f"Provided optuna_source='{optuna_source}' not python file or artifact") + + return self._load_optuna_classes(optuna_file) + + def _load_optuna(self) -> None: + """If our run was resumed, attempt to restore optuna artifacts from run state. + + Create an optuna study with a sqlite backened for loose state management + + """ + study, pruner, sampler = self._try_make_existing_objects(self._optuna_config.get("optuna_source")) + + existing_storage = None + if self._wandb_run.resumed or self._kwargs.get("resumed"): + existing_storage = self._get_and_download_artifact(OptunaComponents.storage) + + if study: # user provided a valid study in downloaded artifact + if existing_storage: + wandb.termwarn(f"{LOG_PREFIX}Resuming state unsupported with user-provided study") + self._study = study + wandb.termlog(self.study_string) + return + # making a new study + + if pruner: + wandb.termlog(f"{LOG_PREFIX}Loaded pruner ({pruner.__class__.__name__})") + else: + pruner_args = self._optuna_config.get("pruner", {}) + if pruner_args: + pruner = load_optuna_pruner(pruner_args["type"], pruner_args.get("args")) + wandb.termlog(f"{LOG_PREFIX}Loaded pruner ({pruner.__class__.__name__})") + else: + wandb.termlog(f"{LOG_PREFIX}No pruner args, defaulting to MedianPruner") + + if sampler: + wandb.termlog(f"{LOG_PREFIX}Loaded sampler ({sampler.__class__.__name__})") + else: + sampler_args = self._optuna_config.get("sampler", {}) + if sampler_args: + sampler = load_optuna_sampler(sampler_args["type"], sampler_args.get("args")) + wandb.termlog(f"{LOG_PREFIX}Loaded sampler ({sampler.__class__.__name__})") + else: + wandb.termlog(f"{LOG_PREFIX}No sampler args, defaulting to TPESampler") + + self._storage_path = existing_storage or OptunaComponents.storage.value + directions = [metric.direction for metric in self._metric_defs] + if len(directions) == 1: + self._study = optuna.create_study( + study_name=self.study_name, + storage=f"sqlite:///{self._storage_path}", + pruner=pruner, + sampler=sampler, + load_if_exists=True, + direction=directions[0], + ) + else: # multi-objective optimization + self._study = optuna.create_study( + study_name=self.study_name, + storage=f"sqlite:///{self._storage_path}", + pruner=pruner, + sampler=sampler, + load_if_exists=True, + directions=directions, + ) + wandb.termlog(self.study_string) + + if existing_storage: + wandb.termlog(f"{LOG_PREFIX}Loaded prior runs ({len(self.study.trials)}) from " + f"storage ({existing_storage})\n {self.formatted_trials}") + + return + + def _load_state(self) -> None: + """Called when Scheduler class invokes start(). + + Load optuna study sqlite data from an artifact in controller run. + + """ + self._load_optuna() + + def _save_state(self) -> None: + """Called when Scheduler class invokes exit(). + + Save optuna study, or sqlite data to an artifact in the scheduler run + + """ + if not self._study or self._storage_path: # nothing to save + return None + + artifact_name = f"{OptunaComponents.storage.name}-{self._sweep_id}" + artifact = wandb.Artifact(artifact_name, type="optuna") + artifact.add_file(self._storage_path) + self._wandb_run.log_artifact(artifact) + + if self._study: + wandb.termlog(f"{LOG_PREFIX}Saved study with trials:\n{self.formatted_trials}") + return + + def _get_next_sweep_run(self, worker_id: int) -> Optional[SweepRun]: + """Called repeatedly in the polling loop, whenever a worker is available.""" + config, trial = self._trial_func() + run: dict = self._api.upsert_run( + project=self._project, + entity=self._entity, + sweep_name=self._sweep_id, + config=config, + )[0] + srun = SweepRun( + id=_encode(run["id"]), + args=config, + worker_id=worker_id, + ) + self._optuna_runs[srun.id] = OptunaRun( + num_metrics=0, + trial=trial, + sweep_run=srun, + ) + self._optuna_runs[srun.id].trial.set_user_attr("run_id", srun.id) + + wandb.termlog(f"{LOG_PREFIX}Starting new run ({srun.id}) with params: {trial.params}") + if self.formatted_trials: + wandb.termlog(f"{LOG_PREFIX}Study state:\n{self.formatted_trials}") + + return srun + + def _get_run_history(self, run_id: str) -> List[int]: + """Gets logged metric history for a given run_id.""" + if run_id not in self._runs: + logger.debug(f"Cant get history for run {run_id} not in self.runs") + return [] + + queued_run: Optional[QueuedRun] = self._runs[run_id].queued_run + if not queued_run or queued_run.state == "pending": + return [] + + try: + api_run: Run = self._public_api.run(f"{queued_run.entity}/{queued_run.project}/{run_id}") + except Exception as e: + logger.debug(f"Failed to poll run from public api: {str(e)}") + return [] + + names = [metric.name for metric in self._metric_defs] + history = api_run.scan_history(keys=names + ["_step"]) + metrics = [] + for log in history: + if self.is_multi_objective: + metrics += [tuple(log.get(key) for key in names)] + else: + metrics += [log.get(names[0])] + + if len(metrics) == 0 and api_run.lastHistoryStep > -1: + logger.debug("No metrics, but lastHistoryStep exists") + wandb.termwarn(f"{LOG_PREFIX}Detected logged metrics, but none matching " + + f"provided metric name(s): '{names}'") + + return metrics + + def _poll_run(self, orun: OptunaRun) -> bool: + """Polls metrics for a run, returns true if finished.""" + metrics = self._get_run_history(orun.sweep_run.id) + if not self.is_multi_objective: # can't report to trial when multi + for i, metric_val in enumerate(metrics[orun.num_metrics:]): + logger.debug(f"{orun.sweep_run.id} (step:{i+orun.num_metrics}) {metrics}") + prev = orun.trial._cached_frozen_trial.intermediate_values + if orun.num_metrics + i not in prev: + orun.trial.report(metric_val, orun.num_metrics + i) + + if orun.trial.should_prune(): + wandb.termlog(f"{LOG_PREFIX}Optuna pruning run: {orun.sweep_run.id}") + self.study.tell(orun.trial, state=optuna.trial.TrialState.PRUNED) + self._stop_run(orun.sweep_run.id) + return True + + orun.num_metrics = len(metrics) + + # run still running + if self._runs[orun.sweep_run.id].state.is_alive: + return False + + # run is complete + prev_metrics = orun.trial._cached_frozen_trial.intermediate_values + if (self._runs[orun.sweep_run.id].state == RunState.FINISHED and len(prev_metrics) == 0 + and not self.is_multi_objective): + # run finished correctly, but never logged a metric + wandb.termwarn(f"{LOG_PREFIX}Run ({orun.sweep_run.id}) never logged metric: " + + f"'{self._metric_defs[0].name}'. Check your sweep " + "config and training script.") + self._num_misconfigured_runs += 1 + self.study.tell(orun.trial, state=optuna.trial.TrialState.FAIL) + + if self._num_misconfigured_runs >= self.MAX_MISCONFIGURED_RUNS: + raise SchedulerError(f"Too many misconfigured runs ({self._num_misconfigured_runs})," + " stopping sweep early") + + # Delete run in Scheduler memory, freeing up worker + del self._runs[orun.sweep_run.id] + + return True + + if self.is_multi_objective: + last_value = tuple(metrics[-1]) + else: + last_value = prev_metrics[orun.num_metrics - 1] + + self._num_misconfigured_runs = 0 # only count consecutive + self.study.tell( + trial=orun.trial, + state=optuna.trial.TrialState.COMPLETE, + values=last_value, + ) + wandb.termlog(f"{LOG_PREFIX}Completing trial for run ({orun.sweep_run.id}) " + f"[last metric{'s' if self.is_multi_objective else ''}: {last_value}" + f", total: {orun.num_metrics}]") + + # Delete run in Scheduler memory, freeing up worker + del self._runs[orun.sweep_run.id] + + return True + + def _poll_running_runs(self) -> None: + """Iterates through runs, getting metrics, reporting to optuna. + + Returns list of runs optuna marked as PRUNED, to be deleted + + """ + to_kill = [] + for run_id, orun in self._optuna_runs.items(): + run_finished = self._poll_run(orun) + if run_finished: + wandb.termlog(f"{LOG_PREFIX}Run: {run_id} finished.") + logger.debug(f"Finished run, study state: {self.study.trials}") + to_kill += [run_id] + + for r in to_kill: + del self._optuna_runs[r] + + def _make_trial(self) -> Tuple[Dict[str, Any], optuna.Trial]: + """Use a wandb.config to create an optuna trial.""" + trial = self.study.ask() + config: Dict[str, Dict[str, Any]] = defaultdict(dict) + for param, extras in self._sweep_config["parameters"].items(): + if extras.get("values"): + config[param]["value"] = trial.suggest_categorical(param, extras["values"]) + elif extras.get("value"): + config[param]["value"] = trial.suggest_categorical(param, [extras["value"]]) + elif isinstance(extras.get("min"), float): + if not extras.get("max"): + raise SchedulerError("Error converting config. 'min' requires 'max'") + log = extras.get("log", False) + step = extras.get("step") + config[param]["value"] = trial.suggest_float(param, extras["min"], extras["max"], log=log, step=step) + elif isinstance(extras.get("min"), int): + if not extras.get("max"): + raise SchedulerError("Error converting config. 'min' requires 'max'") + log = extras.get("log", False) + step = extras.get("step") + if step: + config[param]["value"] = trial.suggest_int(param, extras["min"], extras["max"], log=log, step=step) + else: + config[param]["value"] = trial.suggest_int(param, extras["min"], extras["max"], log=log) + else: + logger.debug(f"Unknown parameter type: param={param}, val={extras}") + raise SchedulerError(f"Error converting config. Unknown parameter type: param={param}, val={extras}") + return config, trial + + def _make_trial_from_objective(self) -> Tuple[Dict[str, Any], optuna.Trial]: + """Turn a user-provided MOCK objective func into wandb params. + + This enables pythonic search spaces. + MOCK: does not actually train, only configures params. + + First creates a copy of our real study, quarantined from fake metrics + + Then calls optuna optimize on the copy study, passing in the + loaded-from-user objective function with an aggresive timeout: + ensures the model does not actually train. + + Retrieves created mock-trial from study copy and formats params for wandb + + Finally, ask our real study for a trial with fixed distributions + + Returns wandb formatted config and optuna trial from real study + + """ + wandb.termlog(f"{LOG_PREFIX}Making trial params from objective func," + " ignoring sweep config parameters") + study_copy = optuna.create_study() + study_copy.add_trials(self.study.trials) + + # Signal handler to raise error if objective func takes too long + def handler(signum: Any, frame: Any) -> None: + raise TimeoutError("Passed optuna objective function only creates parameter config." + f" Do not train; must execute in {self.OPT_TIMEOUT} seconds. See docs.") + + signal.signal(signal.SIGALRM, handler) + signal.alarm(self.OPT_TIMEOUT) + # run mock objective func to parse pythonic search space + study_copy.optimize(self._objective_func, n_trials=1) + signal.alarm(0) # disable alarm + + # now ask the study to create a new active trial from the distributions provided + new_trial = self.study.ask(fixed_distributions=study_copy.trials[-1].distributions) + # convert from optuna-type param config to wandb-type param config + config: Dict[str, Dict[str, Any]] = defaultdict(dict) + for param, value in new_trial.params.items(): + config[param]["value"] = value + + return config, new_trial + + def _poll(self) -> None: + self._poll_running_runs() + + def _exit(self) -> None: + pass + + def _cleanup_runs(self, runs_to_remove: List[str]) -> None: + logger.debug(f"[_cleanup_runs] not removing: {runs_to_remove}") + + +# External validation functions +def validate_optuna(public_api: PublicApi, settings_config: Dict[str, Any]) -> bool: + """Accepts a user provided optuna configuration. + + optuna library must be installed in scope, otherwise returns False. validates + sampler and pruner configuration args. validates artifact existence. + + """ + try: + import optuna # noqa: F401 + except ImportError: + wandb.termerror("Optuna must be installed to validate user-provided configuration." + f" Error: {traceback.format_exc()}") + return False + + if settings_config.get("pruner"): + if not validate_optuna_pruner(settings_config["pruner"]): + return False + + if settings_config.get("sampler"): + if not validate_optuna_sampler(settings_config["sampler"]): + return False + + if settings_config.get("artifact"): + try: + _ = public_api.artifact(settings_config["artifact"]) + except Exception as e: + if ":" not in settings_config["artifact"]: + wandb.termerror("No alias (ex. :latest) found in artifact name") + wandb.termerror(f"{e}") + return False + return True + + +def validate_optuna_pruner(args: Dict[str, Any]) -> bool: + if not args.get("type"): + wandb.termerror("key: 'type' is required") + return False + + try: + _ = load_optuna_pruner(args["type"], args.get("args")) + except Exception as e: + wandb.termerror(f"Error loading optuna pruner: {e}") + return False + return True + + +def validate_optuna_sampler(args: Dict[str, Any]) -> bool: + if not args.get("type"): + wandb.termerror("key: 'type' is required") + return False + + try: + _ = load_optuna_sampler(args["type"], args.get("args")) + except Exception as e: + wandb.termerror(f"Error loading optuna sampler: {e}") + return False + return True + + +def load_optuna_pruner( + type_: str, + args: Optional[Dict[str, Any]], +) -> optuna.pruners.BasePruner: + args = args or {} + if type_ == "NopPruner": + return optuna.pruners.NopPruner(**args) + elif type_ == "MedianPruner": + return optuna.pruners.MedianPruner(**args) + elif type_ == "HyperbandPruner": + return optuna.pruners.HyperbandPruner(**args) + elif type_ == "PatientPruner": + wandb.termerror("PatientPruner requires passing in a wrapped_pruner, which is not " + "supported through this simple config path. Please use the adv. " + "artifact upload path for this pruner, specified in the docs.") + return optuna.pruners.PatientPruner(**args) + elif type_ == "PercentilePruner": + return optuna.pruners.PercentilePruner(**args) + elif type_ == "SuccessiveHalvingPruner": + return optuna.pruners.SuccessiveHalvingPruner(**args) + elif type_ == "ThresholdPruner": + return optuna.pruners.ThresholdPruner(**args) + + raise Exception(f"Optuna pruner type: {type_} not supported") + + +def load_optuna_sampler( + type_: str, + args: Optional[Dict[str, Any]], +) -> optuna.samplers.BaseSampler: + args = args or {} + if type_ == "BruteForceSampler": + return optuna.samplers.BruteForceSampler(**args) + elif type_ == "CmaEsSampler": + return optuna.samplers.CmaEsSampler(**args) + elif type_ == "GridSampler": + return optuna.samplers.GridSampler(**args) + elif type_ == "IntersectionSearchSpace": + return optuna.samplers.IntersectionSearchSpace(**args) + elif type_ == "MOTPESampler": + return optuna.samplers.MOTPESampler(**args) + elif type_ == "NSGAIISampler": + return optuna.samplers.NSGAIISampler(**args) + elif type_ == "PartialFixedSampler": + wandb.termerror("PartialFixedSampler requires passing in a base_sampler, which is not " + "supported through this simple config path. Please use the adv. " + "artifact upload path for this sampler, specified in the docs.") + return optuna.samplers.PartialFixedSampler(**args) + elif type_ == "RandomSampler": + return optuna.samplers.RandomSampler(**args) + elif type_ == "TPESampler": + return optuna.samplers.TPESampler(**args) + elif type_ == "QMCSampler": + return optuna.samplers.QMCSampler(**args) + + raise Exception(f"Optuna sampler type: {type_} not supported") + + +def _encode(run_id: str) -> str: + """Helper to hash the run id for backend format.""" + return base64.b64decode(bytes(run_id.encode("utf-8"))).decode("utf-8").split(":")[2] + + +def _get_module(module_name: str, filepath: str) -> Tuple[Optional[ModuleType], Optional[str]]: + """Helper function that loads a python module from provided filepath.""" + try: + loader = SourceFileLoader(module_name, filepath) + mod = ModuleType(loader.name) + loader.exec_module(mod) + except Exception as e: + return None, str(e) + + return mod, None + + +# if __name__ == "__main__": +setup_scheduler(OptunaScheduler) diff --git a/test_automl/optuna_wandb.py b/test_automl/optuna_wandb.py new file mode 100644 index 000000000..ba0981620 --- /dev/null +++ b/test_automl/optuna_wandb.py @@ -0,0 +1,159 @@ +import json +import os +import sys + +import optuna +import scanpy as sc + +fun_list = ["log1p", "filter_gene_by_count"] +# import inspect + +# path= os.path.dirname(inspect.getfile(lambda: None)) +# path = os.path.join(path,"fun_list.json") # 拼接文件的路径 +# with open(path,"r") as file: +# loaded_data = json.load(file) +# fun_list = loaded_data["fun_list"] + +# print(path) +# from fun_list import fun_list +# from dance.transforms.cell_feature import CellPCA,CellSVD,WeightedFeaturePCA +# from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression +# from dance.transforms.interface import AnnDataTransform +# from dance.transforms.normalize import ScTransformR, ScaleFeature + + +def cell_pca(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + return {method_name + "n_components": trial.suggest_int(method_name + "n_components", 200, 5000)} + + + # return CellPCA(n_components=trial.suggest_int(method_name+"n_components",200,5000)) +def cell_weighted_pca(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + return {method_name + "n_components": trial.suggest_int(method_name + "n_components", 200, 5000)} + + + # return WeightedFeaturePCA(n_components=trial.suggest_int(method_name+"n_components",200,5000)) +def cell_svd(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + return {method_name + "n_components": trial.suggest_int(method_name + "n_components", 200, 5000)} + + + # return CellSVD(n_components=trial.suggest_int(method_name+"n_components",200,5000)) +def Filter_gene_by_regress_score(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + # return FilterGenesRegression(method=trial.suggest_categorical(method_name+"method",["enclasc","seurat3","scmap"]), + # num_genes=trial.suggest_int(method_name+"num_genes",5000,6000)) + return { + method_name + "method": trial.suggest_categorical(method_name + "method", ["enclasc", "seurat3", "scmap"]), + method_name + "num_genes": trial.suggest_int(method_name + "num_genes", 5000, 6000) + } + + +def highly_variable_genes(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + # return AnnDataTransform(sc.pp.highly_variable_genes,min_mean=trial.suggest_float(method_name+"min_mean",0.0025,0.03), + # max_mean=trial.suggest_float(method_name+"min_mean",1.5,4.5), + # min_disp=trial.suggest_float(method_name+"min_disp",0.25,0.75), + # span=trial.suggest_float(method_name+"span",0.2,1.0), + # n_bins=trial.suggest_int(method_name+"n_bins",10,30), + # flavor=trial.suggest_categorical(method_name+"flavor",['seurat', 'cell_ranger']) + # ) + return { + method_name + "min_mean": trial.suggest_float(method_name + "min_mean", 0.0025, 0.03), + method_name + "max_mean": trial.suggest_float(method_name + "min_mean", 1.5, 4.5), + method_name + "min_disp": trial.suggest_float(method_name + "min_disp", 0.25, 0.75), + method_name + "span": trial.suggest_float(method_name + "span", 0.2, 1.0), + method_name + "n_bins": trial.suggest_int(method_name + "n_bins", 10, 30), + method_name + "flavor": trial.suggest_categorical(method_name + "flavor", ['seurat', 'cell_ranger']) + } + + +def filter_gene_by_percentile(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + # return FilterGenesPercentile(min_val=trial.suggest_int(method_name+"min_val",1,10), + # max_val=trial.suggest_int(method_name+"max_val",90,99), + # mode=trial.suggest_categorical(method_name+"mode",["sum","var","cv","rv"])) + return { + method_name + "min_val": trial.suggest_int(method_name + "min_val", 1, 10), + method_name + "max_val": trial.suggest_int(method_name + "max_val", 90, 99), + method_name + "mode": trial.suggest_categorical(method_name + "mode", ["sum", "var", "cv", "rv"]) + } + + +def filter_gene_by_count(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + method = trial.suggest_categorical(method_name + "method", ['min_counts', 'min_cells', 'max_counts', 'max_cells']) + if method == "min_counts": + num = trial.suggest_int(method_name + "num", 2, 10) + if method == "min_cells": + num = trial.suggest_int(method_name + "num", 2, 10) + if method == "max_counts": + num = trial.suggest_int(method_name + "num", 500, 1000) + if method == "max_cells": + num = trial.suggest_int(method_name + "num", 500, 1000) + # return AnnDataTransform(sc.pp.filter_genes,method=num) + return {method_name + "method": method, method_name + "num": num} + + +def log1p(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + # return AnnDataTransform(sc.pp.log1p,base=trial.suggest_int(method_name+"base",2,10)) + return {method_name + "base": trial.suggest_int(method_name + "base", 2, 10)} + + +def scTransform(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + return {method_name + "min_cells": trial.suggest_int(method_name + "min_cells", 1, 10)} + + + # return ScTransformR(min_cells=trial.suggest_int(method_name+"min_cells",1,10)) +def scaleFeature(trial: optuna.Trial): #eps未优化 + method_name = str(sys._getframe().f_code.co_name) + "_" + # return ScaleFeature(mode=trial.suggest_categorical(method_name+"mode",["normalize", "standardize", "minmax", "l2"])) + return { + method_name + "mode": trial.suggest_categorical(method_name + "mode", + ["normalize", "standardize", "minmax", "l2"]) + } + + +def normalize_total(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + exclude_highly_expressed = trial.suggest_categorical(method_name + "exclude_highly_expressed", [False, True]) + + if exclude_highly_expressed: + max_fraction = trial.suggest_float(method_name + "max_fraction", 0.04, 0.1) + return { + method_name + "exclude_highly_expressed": + trial.suggest_categorical(method_name + "exclude_highly_expressed", [False, True]), + method_name + "max_fraction": + max_fraction + } + else: + return { + method_name + "exclude_highly_expressed": + trial.suggest_categorical(method_name + "exclude_highly_expressed", [False, True]) + } + # return AnnDataTransform(sc.pp.normalize_total,target_sum=trial.suggest_categorical(method_name+"target_sum",[1e4,1e5,1e6]),exclude_highly_expressed=exclude_highly_expressed,max_fraction=max_fraction) + + +# 从 JSON 文件中读取数据 + +parameter_config = None + + +def objective(trial): + # method_name=str(sys._getframe().f_code.co_name)+"_" + # exclude_highly_expressed=trial.suggest_categorical(method_name+"exclude_highly_expressed",[False,True]) + # if exclude_highly_expressed: + # max_fraction=trial.suggest_float(method_name+"max_fraction",0.04,0.1) + # print(exclude_highly_expressed) + # if exclude_highly_expressed: + # print(max_fraction) + global parameter_config + parameter_config = {} + for f_str in fun_list: + fun_i = eval(f_str) + parameter_config.update(fun_i(trial)) + # transforms.append(fun_i(trial)) + return -1 diff --git a/test_automl/test_automl_fun_2.py b/test_automl/test_automl_fun_2.py new file mode 100644 index 000000000..5aa693468 --- /dev/null +++ b/test_automl/test_automl_fun_2.py @@ -0,0 +1,54 @@ +import wandb +import yaml + +ARTIFACT_FILENAME = "/home/zyxing/dance/" +ARTIFACT_NAME = "optuna-config" + +PROJECT = "pytorch-cell_type_annotation_ACTINN_function_new" +ENTITY = "xzy11632" +QUEUE = "actinn" ## Put in a Launch queue you've created and started + + +def train(a): + pass + + +if __name__ == "__main__": + # """create and log artifact to wandb""" + run = wandb.init(project=PROJECT, entity=ENTITY) + artifact = wandb.Artifact(name=ARTIFACT_NAME, type='optuna') + artifact.add_dir(ARTIFACT_FILENAME) + run.log_artifact(artifact) + run.finish() +# config = { +# "metric": {"name": "scores", "goal": "maximize"}, +# "run_cap": 4, +# "job": "xzy11632/pytorch-cell_type_annotation_ACTINN_function_new/job-source-pytorch-cell_type_annotation_ACTINN_function_new-test_automl_test_automl_fun_job.py:v3",#思考一下 +# "scheduler": { +# "job": "xzy11632/pytorch-cell_type_annotation_ACTINN_function_new/job-OptunaScheduler:v4", +# "num_workers": 2, +# "settings": { +# "optuna_source": f"{ENTITY}/{PROJECT}/{artifact.wait().name}", +# "optuna_source_filename": ARTIFACT_FILENAME, +# "resource": "local-container", # required for scheduler jobs sourced from images + +# # optional sampler args +# "pruner": { +# "type": "PercentilePruner", +# "args": { +# "percentile": 0.25, +# "n_startup_trials": 2, +# "n_min_trials": 1, # min epochs before prune +# } +# } +# } +# }, +# # parameters are not needed when loading a conditional config from an artifact +# # "parameters": { +# # 'epochs': {'values': [5, 10, 15]}, +# # 'lr': {'max': 0.1, 'min': 0.0001} +# # } +# } +# # write config to file +# config_filename = "sweep-config.yaml" +# yaml.dump(config, open(config_filename, "w")) diff --git a/test_automl/test_automl_fun_job.py b/test_automl/test_automl_fun_job.py new file mode 100644 index 000000000..3d37b6524 --- /dev/null +++ b/test_automl/test_automl_fun_job.py @@ -0,0 +1,175 @@ +import os +import random +import sys + +import numpy as np +import scanpy as sc +import torch +import wandb +from optuna_wandb import fun_list +from test_automl_preprocess import fun2code_dict + +from dance.datasets.singlemodality import CellTypeAnnotationDataset +from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN +from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA +from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression +from dance.transforms.interface import AnnDataTransform +from dance.transforms.misc import Compose, SetConfig +from dance.transforms.normalize import ScaleFeature, ScTransformR +from dance.utils import set_seed + +device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu") + + +# import inspect +# path= os.path.dirname(inspect.getfile(lambda: None)) +# path = os.path.join(path,"fun_list.json") # 拼接文件的路径 +# with open(path,"r") as file: +# loaded_data = json.load(file) +# fun_list = loaded_data["fun_list"] +def cell_pca(parameter_config): + method_name = str(sys._getframe().f_code.co_name) + "_" + return CellPCA(n_components=parameter_config.get(method_name + "n_components")) + + +def cell_weighted_pca(parameter_config): + method_name = str(sys._getframe().f_code.co_name) + "_" + return WeightedFeaturePCA(n_components=parameter_config.get(method_name + "n_components")) + + +def cell_svd(parameter_config): + method_name = str(sys._getframe().f_code.co_name) + "_" + return CellSVD(n_components=parameter_config.get(method_name + "n_components")) + + +def Filter_gene_by_regress_score(parameter_config): + method_name = str(sys._getframe().f_code.co_name) + "_" + return FilterGenesRegression(method=parameter_config.get(method_name + "method"), + num_genes=parameter_config.get(method_name + "num_genes")) + + +def highly_variable_genes(parameter_config): + method_name = str(sys._getframe().f_code.co_name) + "_" + return AnnDataTransform(sc.pp.highly_variable_genes, min_mean=parameter_config.get(method_name + "min_mean"), + max_mean=parameter_config.get(method_name + "min_mean"), + min_disp=parameter_config.get(method_name + "min_disp"), + span=parameter_config.get(method_name + "span"), + n_bins=parameter_config.get(method_name + "n_bins"), + flavor=parameter_config.get(method_name + "flavor")) + + +def filter_gene_by_percentile(parameter_config): + method_name = str(sys._getframe().f_code.co_name) + "_" + return FilterGenesPercentile(min_val=parameter_config.get(method_name + "min_val"), + max_val=parameter_config.get(method_name + "max_val"), + mode=parameter_config.get(method_name + "mode")) + + +def filter_gene_by_count(parameter_config): + method_name = str(sys._getframe().f_code.co_name) + "_" + method = parameter_config.get(method_name + "method") + num = parameter_config.get(method_name + "num") + return AnnDataTransform(sc.pp.filter_genes, **{method: num}) + + +def log1p(parameter_config): + method_name = str(sys._getframe().f_code.co_name) + "_" + base = parameter_config.get(method_name + "base") + return AnnDataTransform(sc.pp.log1p, base=base) + + +def scTransform(parameter_config): + method_name = str(sys._getframe().f_code.co_name) + "_" + return ScTransformR(min_cells=parameter_config.get(method_name + "min_cells")) + + +def scaleFeature(parameter_config): #eps未优化 + method_name = str(sys._getframe().f_code.co_name) + "_" + return ScaleFeature(mode=parameter_config.get(method_name + "mode", ["normalize", "standardize", "minmax", "l2"])) + + +def normalize_total(parameter_config): + method_name = str(sys._getframe().f_code.co_name) + "_" + exclude_highly_expressed = parameter_config.get(method_name + "exclude_highly_expressed", [False, True]) + if exclude_highly_expressed: + max_fraction = parameter_config.get(method_name + "max_fraction") + return AnnDataTransform(sc.pp.normalize_total, target_sum=parameter_config.get(method_name + "target_sum"), + exclude_highly_expressed=exclude_highly_expressed, max_fraction=max_fraction) + else: + return AnnDataTransform(sc.pp.normalize_total, target_sum=parameter_config.get(method_name + "target_sum"), + exclude_highly_expressed=exclude_highly_expressed) + + +def run_training_run(): + settings = wandb.Settings(job_source="artifact") + run = wandb.init( + project="pytorch-cell_type_annotation_ACTINN_function_new", + settings=settings, + entity="xzy11632", + ) + + print("parameter_config") + parameter_config = dict(run.config) + print(parameter_config) + print("fun_list" + str(fun_list)) + + if len(parameter_config.keys()) != 0: + + parameters_dict = { + 'batch_size': 128, + "hidden_dims": [2000], + 'lambd': 0.005, + 'num_epochs': 50, + 'seed': 0, + 'num_runs': 1, + 'learning_rate': 0.0001 + } + parameter_config.update(parameters_dict) + transforms = [] + for f_str in fun_list: + fun_i = eval(f_str) + transforms.append(fun_i(parameter_config)) + print(transforms) + data_config = {"label_channel": "cell_type"} + feature_name = {"cell_svd", "cell_weighted_pca", "cell_pca"} & set(fun_list) + if feature_name: + data_config.update({"feature_channel": fun2code_dict[feature_name].name}) + + transforms.append(SetConfig(data_config)) + preprocessing_pipeline = Compose(*transforms, log_level="INFO") + + # preprocessing_pipeline = model.preprocessing_pipeline(normalize=args.normalize, filter_genes=not args.nofilter) + # Load data and perform necessary preprocessing + train_dataset = [753, 3285] + test_dataset = [2695] + tissue = "Brain" + species = "mouse" + dataloader = CellTypeAnnotationDataset(train_dataset=train_dataset, test_dataset=test_dataset, tissue=tissue, + species=species) + data = dataloader.load_data(transform=preprocessing_pipeline, cache=True) + + # Obtain training and testing data + x_train, y_train = data.get_train_data(return_type="torch") + x_test, y_test = data.get_test_data(return_type="torch") + x_train, y_train, x_test, y_test = x_train.float(), y_train.float(), x_test.float(), y_test.float() + # Train and evaluate models for several rounds + scores = [] + model = ACTINN(hidden_dims=parameter_config.get('hidden_dims'), lambd=parameter_config.get('lambd'), + device=device) + for seed in range(parameter_config.get('seed'), + parameter_config.get('seed') + parameter_config.get('num_runs')): + set_seed(seed) + + model.fit(x_train, y_train, seed=seed, lr=parameter_config.get('learning_rate'), + num_epochs=parameter_config.get('num_epochs'), batch_size=parameter_config.get('batch_size'), + print_cost=False) + scores.append(score := model.score(x_test, y_test)) + # print(f"{score=:.4f}") + # print(f"ACTINN {species} {tissue} {test_dataset}:") + # print(f"{scores}\n{np.mean(scores):.5f} +/- {np.std(scores):.5f}") + wandb.log({"scores": np.mean(scores)}) + run.log_code() + run.finish() + + +run_training_run() diff --git a/test_automl/test_automl_step2.py b/test_automl/test_automl_step2.py new file mode 100644 index 000000000..609958f96 --- /dev/null +++ b/test_automl/test_automl_step2.py @@ -0,0 +1,145 @@ +from functools import partial +from itertools import combinations + +import scanpy as sc +import wandb + +from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA +from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression +from dance.transforms.interface import AnnDataTransform +from dance.transforms.normalize import ScaleFeature, ScTransformR + +fun2code_dict = { + "normalize_total": AnnDataTransform(sc.pp.normalize_total, target_sum=1e4), + "log1p": AnnDataTransform(sc.pp.log1p, base=2), + "scaleFeature": ScaleFeature(split_names="ALL", mode="standardize"), + "scTransform": ScTransformR(mirror_index=1), + "filter_gene_by_count": AnnDataTransform(sc.pp.filter_genes, min_cells=1), + "filter_gene_by_percentile": FilterGenesPercentile(min_val=1, max_val=99, mode="sum"), + "highly_variable_genes": AnnDataTransform(sc.pp.highly_variable_genes), + "regress_out": AnnDataTransform(sc.pp.regress_out), + "Filter_gene_by_regress_score": FilterGenesRegression("enclasc"), + "cell_svd": CellSVD(), + "cell_weighted_pca": WeightedFeaturePCA(split_name="train"), + "cell_pca": CellPCA() +} + + +def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): + pipline2fun_dict = { + "normalize": { + "values": ["normalize_total", "log1p", "scaleFeature", "scTransform"] + }, + "gene_filter": { + "values": [ + "filter_gene_by_count", "filter_gene_by_percentile", "highly_variable_genes", + "Filter_gene_by_regress_score" + ] + }, + "gene_dim_reduction": { + "values": ["cell_svd", "cell_weighted_pca", "cell_pca"] + } + } + pipline2fun_dict = {key: pipline2fun_dict[key] for key in selected_keys} + count = 1 + for pipline_key, pipline_values in pipline2fun_dict.items(): + count *= len(pipline_values['values']) + parameters_dict = pipline2fun_dict + parameters_dict.update({ + 'batch_size': { + 'value': 128 + }, + "hidden_dims": { + 'value': [2000] + }, + 'lambd': { + 'value': 0.005 + }, + 'num_epochs': { + 'value': 50 + }, + 'seed': { + 'value': 0 + }, + 'num_runs': { + 'value': 1 + }, + 'learning_rate': { + 'value': 0.0001 + } + }) + sweep_config = {'method': 'grid'} + sweep_config['parameters'] = parameters_dict + metric = {'name': 'scores', 'goal': 'maximize'} + + sweep_config['metric'] = metric + sweep_id = wandb.sweep(sweep_config, project="pytorch-cell_type_annotation_ACTINN") + return sweep_id, count + + +import numpy as np +import torch + +from dance.datasets.singlemodality import CellTypeAnnotationDataset +from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN +from dance.transforms.misc import Compose, SetConfig +from dance.utils import set_seed + +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + + +def train(config=None): + with wandb.init(config=config): + config = wandb.config + if ("normalize" not in config.keys() or config.normalize + != "log1p") and ("gene_filter" in config.keys() and config.gene_filter == "highly_variable_genes"): + wandb.log({"scores": 0}) + return + model = ACTINN(hidden_dims=config.hidden_dims, lambd=config.lambd, device=device) + transforms = [] + transforms.append(fun2code_dict[config.normalize]) if "normalize" in config.keys() else None + transforms.append(fun2code_dict[config.gene_filter]) if "gene_filter" in config.keys() else None + transforms.append(fun2code_dict[config.gene_dim_reduction]) if "gene_dim_reduction" in config.keys() else None + data_config = {"label_channel": "cell_type"} + if "gene_dim_reduction" in config.keys(): + data_config.update({"feature_channel": fun2code_dict[config.gene_dim_reduction].name}) + transforms.append(SetConfig(data_config)) + preprocessing_pipeline = Compose(*transforms, log_level="INFO") + + # preprocessing_pipeline = model.preprocessing_pipeline(normalize=args.normalize, filter_genes=not args.nofilter) + # Load data and perform necessary preprocessing + train_dataset = [753, 3285] + test_dataset = [2695] + tissue = "Brain" + species = "mouse" + dataloader = CellTypeAnnotationDataset(train_dataset=train_dataset, test_dataset=test_dataset, tissue=tissue, + species=species) + data = dataloader.load_data(transform=preprocessing_pipeline, cache=False) + + # Obtain training and testing data + x_train, y_train = data.get_train_data(return_type="torch") + x_test, y_test = data.get_test_data(return_type="torch") + x_train, y_train, x_test, y_test = x_train.float(), y_train.float(), x_test.float(), y_test.float() + # Train and evaluate models for several rounds + scores = [] + for seed in range(config.seed, config.seed + config.num_runs): + set_seed(seed) + + model.fit(x_train, y_train, seed=seed, lr=config.learning_rate, num_epochs=config.num_epochs, + batch_size=config.batch_size, print_cost=False) + scores.append(score := model.score(x_test, y_test)) + # print(f"{score=:.4f}") + # print(f"ACTINN {species} {tissue} {test_dataset}:") + # print(f"{scores}\n{np.mean(scores):.5f} +/- {np.std(scores):.5f}") + wandb.log({"scores": np.mean(scores)}) + + +if __name__ == "__main__": + original_list = ["normalize", "gene_filter", "gene_dim_reduction"] + all_combinations = [combo for i in range(1, len(original_list) + 1) for combo in combinations(original_list, i)] + all_combinations.append([]) + for s_key in all_combinations: + s_list = list(s_key) + sweep_id, count = getSweepId(s_list) + print(s_list, count) + wandb.agent(sweep_id, train, count=count) diff --git a/test_automl/web-variables.env b/test_automl/web-variables.env new file mode 100644 index 000000000..be03597b4 --- /dev/null +++ b/test_automl/web-variables.env @@ -0,0 +1,2 @@ +http_proxy=http://211.87.232.112:20171 +https_proxy=http://211.87.232.112:20171 From f181e57339ab4efc66bde912a004b480f215837c Mon Sep 17 00:00:00 2001 From: xzy Date: Sat, 13 Jan 2024 22:25:29 +0800 Subject: [PATCH 004/168] change file location --- test_automl/optuna_scheduler.py => optuna_scheduler.py | 0 test_automl/web-variables.env => web-variables.env | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename test_automl/optuna_scheduler.py => optuna_scheduler.py (100%) rename test_automl/web-variables.env => web-variables.env (100%) diff --git a/test_automl/optuna_scheduler.py b/optuna_scheduler.py similarity index 100% rename from test_automl/optuna_scheduler.py rename to optuna_scheduler.py diff --git a/test_automl/web-variables.env b/web-variables.env similarity index 100% rename from test_automl/web-variables.env rename to web-variables.env From 61877042fd746b6d7f4cfc1a52f8e022a6937aaf Mon Sep 17 00:00:00 2001 From: xzy Date: Sun, 14 Jan 2024 10:25:23 +0800 Subject: [PATCH 005/168] update name --- test_automl/test_automl_fun_job.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/test_automl_fun_job.py b/test_automl/test_automl_fun_job.py index 3d37b6524..fda982391 100644 --- a/test_automl/test_automl_fun_job.py +++ b/test_automl/test_automl_fun_job.py @@ -7,7 +7,7 @@ import torch import wandb from optuna_wandb import fun_list -from test_automl_preprocess import fun2code_dict +from test_automl_step2 import fun2code_dict from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN From bdd3a18e952e871b924a90ad9633412999ed7020 Mon Sep 17 00:00:00 2001 From: xzy Date: Sun, 14 Jan 2024 11:00:06 +0800 Subject: [PATCH 006/168] add run.sh --- automl_fun.sh | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100755 automl_fun.sh diff --git a/automl_fun.sh b/automl_fun.sh new file mode 100755 index 000000000..756ce530a --- /dev/null +++ b/automl_fun.sh @@ -0,0 +1,6 @@ +cd ~/dance +python test_automl/test_automl_fun_job.py +python test_automl/test_automl_fun_2.py +cd ~ +python dance/optuna_scheduler.py --entity xzy11632 --project pytorch-cell_type_annotation_ACTINN_function_new +wandb launch-sweep dance/test_automl/sweep-config.yaml -e xzy11632 -p pytorch-cell_type_annotation_ACTINN_function_new -q tutorial-run-queue From 2dc212ca4763af26fdabc0ec24b6d7efc110917f Mon Sep 17 00:00:00 2001 From: xzy Date: Sun, 14 Jan 2024 11:29:22 +0800 Subject: [PATCH 007/168] update gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 72d98b0f8..f256fea8a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ __pycache__ *.egg* .DS_Store + +wandb From f207a0da7c33cbfb444e4dc0c7b3b3991be8a8be Mon Sep 17 00:00:00 2001 From: xzy Date: Wed, 17 Jan 2024 16:55:42 +0800 Subject: [PATCH 008/168] no docker --- .gitignore | 3 + test_automl/optuna_wandb_nocontainer_step3.py | 236 ++++++++++++++++++ test_automl/sweep-config.yaml | 2 +- web-variables.env | 4 +- 4 files changed, 242 insertions(+), 3 deletions(-) create mode 100644 test_automl/optuna_wandb_nocontainer_step3.py diff --git a/.gitignore b/.gitignore index f256fea8a..0ee87557d 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ __pycache__ .DS_Store wandb + + +test_automl/data diff --git a/test_automl/optuna_wandb_nocontainer_step3.py b/test_automl/optuna_wandb_nocontainer_step3.py new file mode 100644 index 000000000..31f05faeb --- /dev/null +++ b/test_automl/optuna_wandb_nocontainer_step3.py @@ -0,0 +1,236 @@ +import json +import os +import sys + +import numpy as np +import optuna +import scanpy as sc +import torch +from optuna.integration.wandb import WeightsAndBiasesCallback +from test_automl_step2 import fun2code_dict + +import wandb +from dance.datasets.singlemodality import CellTypeAnnotationDataset +from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN +from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA +from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression +from dance.transforms.interface import AnnDataTransform +from dance.transforms.misc import Compose, SetConfig +from dance.transforms.normalize import ScaleFeature, ScTransformR +from dance.utils import set_seed + +fun_list = ["log1p", "filter_gene_by_count"] +wandb_kwargs = {"project": "my-project"} +wandbc = WeightsAndBiasesCallback(wandb_kwargs=wandb_kwargs, as_multirun=True) +# import inspect + +# path= os.path.dirname(inspect.getfile(lambda: None)) +# path = os.path.join(path,"fun_list.json") # 拼接文件的路径 +# with open(path,"r") as file: +# loaded_data = json.load(file) +# fun_list = loaded_data["fun_list"] + +# print(path) +# from fun_list import fun_list +# from dance.transforms.cell_feature import CellPCA,CellSVD,WeightedFeaturePCA +# from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression +# from dance.transforms.interface import AnnDataTransform +# from dance.transforms.normalize import ScTransformR, ScaleFeature + + +def cell_pca(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + # return {method_name + "n_components": trial.suggest_int(method_name + "n_components", 200, 5000)} + return CellPCA(n_components=trial.suggest_int(method_name + "n_components", 200, 5000)) + + +def cell_weighted_pca(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + # return {method_name + "n_components": trial.suggest_int(method_name + "n_components", 200, 5000)} + + return WeightedFeaturePCA(n_components=trial.suggest_int(method_name + "n_components", 200, 5000)) + + +def cell_svd(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + # return {method_name + "n_components": trial.suggest_int(method_name + "n_components", 200, 5000)} + + return CellSVD(n_components=trial.suggest_int(method_name + "n_components", 200, 5000)) + + +def Filter_gene_by_regress_score(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + return FilterGenesRegression( + method=trial.suggest_categorical(method_name + "method", ["enclasc", "seurat3", "scmap"]), + num_genes=trial.suggest_int(method_name + "num_genes", 5000, 6000)) + # return { + # method_name + "method": trial.suggest_categorical(method_name + "method", ["enclasc", "seurat3", "scmap"]), + # method_name + "num_genes": trial.suggest_int(method_name + "num_genes", 5000, 6000) + # } + + +def highly_variable_genes(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + return AnnDataTransform(sc.pp.highly_variable_genes, min_mean=trial.suggest_float( + method_name + "min_mean", 0.0025, + 0.03), max_mean=trial.suggest_float(method_name + "min_mean", 1.5, + 4.5), min_disp=trial.suggest_float(method_name + "min_disp", 0.25, 0.75), + span=trial.suggest_float(method_name + "span", 0.2, + 1.0), n_bins=trial.suggest_int(method_name + "n_bins", 10, 30), + flavor=trial.suggest_categorical(method_name + "flavor", ['seurat', 'cell_ranger'])) + # return { + # method_name + "min_mean": trial.suggest_float(method_name + "min_mean", 0.0025, 0.03), + # method_name + "max_mean": trial.suggest_float(method_name + "min_mean", 1.5, 4.5), + # method_name + "min_disp": trial.suggest_float(method_name + "min_disp", 0.25, 0.75), + # method_name + "span": trial.suggest_float(method_name + "span", 0.2, 1.0), + # method_name + "n_bins": trial.suggest_int(method_name + "n_bins", 10, 30), + # method_name + "flavor": trial.suggest_categorical(method_name + "flavor", ['seurat', 'cell_ranger']) + # } + + +def filter_gene_by_percentile(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + return FilterGenesPercentile(min_val=trial.suggest_int(method_name + "min_val", 1, 10), + max_val=trial.suggest_int(method_name + "max_val", 90, 99), + mode=trial.suggest_categorical(method_name + "mode", ["sum", "var", "cv", "rv"])) + # return { + # method_name + "min_val": trial.suggest_int(method_name + "min_val", 1, 10), + # method_name + "max_val": trial.suggest_int(method_name + "max_val", 90, 99), + # method_name + "mode": trial.suggest_categorical(method_name + "mode", ["sum", "var", "cv", "rv"]) + # } + + +def filter_gene_by_count(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + method = trial.suggest_categorical(method_name + "method", ['min_counts', 'min_cells', 'max_counts', 'max_cells']) + if method == "min_counts": + num = trial.suggest_int(method_name + "num", 2, 10) + if method == "min_cells": + num = trial.suggest_int(method_name + "num", 2, 10) + if method == "max_counts": + num = trial.suggest_int(method_name + "num", 500, 1000) + if method == "max_cells": + num = trial.suggest_int(method_name + "num", 500, 1000) + return AnnDataTransform(sc.pp.filter_genes, **{method: num}) + # return {method_name + "method": method, method_name + "num": num} + + +def log1p(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + return AnnDataTransform(sc.pp.log1p, base=trial.suggest_int(method_name + "base", 2, 10)) + # return {method_name + "base": trial.suggest_int(method_name + "base", 2, 10)} + + +def scTransform(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + # return {method_name + "min_cells": trial.suggest_int(method_name + "min_cells", 1, 10)} + + return ScTransformR(min_cells=trial.suggest_int(method_name + "min_cells", 1, 10)) + + +def scaleFeature(trial: optuna.Trial): #eps未优化 + method_name = str(sys._getframe().f_code.co_name) + "_" + return ScaleFeature(mode=trial.suggest_categorical(method_name + + "mode", ["normalize", "standardize", "minmax", "l2"])) + # return { + # method_name + "mode": trial.suggest_categorical(method_name + "mode", + # ["normalize", "standardize", "minmax", "l2"]) + # } + + +def normalize_total(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + exclude_highly_expressed = trial.suggest_categorical(method_name + "exclude_highly_expressed", [False, True]) + + if exclude_highly_expressed: + max_fraction = trial.suggest_float(method_name + "max_fraction", 0.04, 0.1) + return AnnDataTransform(sc.pp.normalize_total, + target_sum=trial.suggest_categorical(method_name + "target_sum", [1e4, 1e5, 1e6]), + exclude_highly_expressed=exclude_highly_expressed, max_fraction=max_fraction) + # return { + # method_name + "exclude_highly_expressed": + # trial.suggest_categorical(method_name + "exclude_highly_expressed", [False, True]), + # method_name + "max_fraction": + # max_fraction + # } + else: + return AnnDataTransform(sc.pp.normalize_total, + target_sum=trial.suggest_categorical(method_name + "target_sum", [1e4, 1e5, 1e6]), + exclude_highly_expressed=exclude_highly_expressed, max_fraction=max_fraction) + # return { + # method_name + "exclude_highly_expressed": + # trial.suggest_categorical(method_name + "exclude_highly_expressed", [False, True]) + # } + + +# 从 JSON 文件中读取数据 + +# parameter_config = None + +device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu") + + +@wandbc.track_in_wandb() +def objective(trial): + # method_name=str(sys._getframe().f_code.co_name)+"_" + # exclude_highly_expressed=trial.suggest_categorical(method_name+"exclude_highly_expressed",[False,True]) + # if exclude_highly_expressed: + # max_fraction=trial.suggest_float(method_name+"max_fraction",0.04,0.1) + # print(exclude_highly_expressed) + # if exclude_highly_expressed: + # print(max_fraction) + # global parameter_config + # parameter_config = {} + transforms = [] + for f_str in fun_list: + fun_i = eval(f_str) + # parameter_config.update(fun_i(trial)) + transforms.append(fun_i(trial)) + parameters_dict = { + 'batch_size': 128, + "hidden_dims": [2000], + 'lambd': 0.005, + 'num_epochs': 50, + 'seed': 0, + 'num_runs': 1, + 'learning_rate': 0.0001 + } + data_config = {"label_channel": "cell_type"} + feature_name = {"cell_svd", "cell_weighted_pca", "cell_pca"} & set(fun_list) + if feature_name: + data_config.update({"feature_channel": fun2code_dict[feature_name].name}) + transforms.append(SetConfig(data_config)) + preprocessing_pipeline = Compose(*transforms, log_level="INFO") + train_dataset = [753, 3285] + test_dataset = [2695] + tissue = "Brain" + species = "mouse" + dataloader = CellTypeAnnotationDataset(train_dataset=train_dataset, test_dataset=test_dataset, tissue=tissue, + species=species, data_dir="./test_automl/data") + data = dataloader.load_data(transform=preprocessing_pipeline, cache=True) + + # Obtain training and testing data + x_train, y_train = data.get_train_data(return_type="torch") + x_test, y_test = data.get_test_data(return_type="torch") + x_train, y_train, x_test, y_test = x_train.float(), y_train.float(), x_test.float(), y_test.float() + # Train and evaluate models for several rounds + scores = [] + parameter_config = {} + parameter_config.update(parameters_dict) + model = ACTINN(hidden_dims=parameter_config.get('hidden_dims'), lambd=parameter_config.get('lambd'), device=device) + for seed in range(parameter_config.get('seed'), parameter_config.get('seed') + parameter_config.get('num_runs')): + set_seed(seed) + + model.fit(x_train, y_train, seed=seed, lr=parameter_config.get('learning_rate'), + num_epochs=parameter_config.get('num_epochs'), batch_size=parameter_config.get('batch_size'), + print_cost=False) + scores.append(score := model.score(x_test, y_test)) + # print(f"{score=:.4f}") + # print(f"ACTINN {species} {tissue} {test_dataset}:") + # print(f"{scores}\n{np.mean(scores):.5f} +/- {np.std(scores):.5f}") + wandb.log({"scores": np.mean(scores)}) + return np.mean(scores) + + +study = optuna.create_study() +study.optimize(objective, n_trials=10, callbacks=[wandbc]) diff --git a/test_automl/sweep-config.yaml b/test_automl/sweep-config.yaml index adea93e7a..c19c632da 100644 --- a/test_automl/sweep-config.yaml +++ b/test_automl/sweep-config.yaml @@ -6,7 +6,7 @@ run_cap: 20 scheduler: job: xzy11632/pytorch-cell_type_annotation_ACTINN_function_new/job-OptunaScheduler:latest num_workers: 2 - docker_image: r:fcf2b32f + docker_image: rdance_fcf2b32f.sif resource_args: local-container: env-file: "/home/zyxing/dance/web-variables.env" diff --git a/web-variables.env b/web-variables.env index be03597b4..61b1e0682 100644 --- a/web-variables.env +++ b/web-variables.env @@ -1,2 +1,2 @@ -http_proxy=http://211.87.232.112:20171 -https_proxy=http://211.87.232.112:20171 +http_proxy=http://121.250.209.147:7890 +https_proxy=http://121.250.209.147:7890 From a68558e63c32311595fb37afc6efeb56a3ddea0a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 17 Jan 2024 08:57:25 +0000 Subject: [PATCH 009/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/optuna_wandb_nocontainer_step3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/optuna_wandb_nocontainer_step3.py b/test_automl/optuna_wandb_nocontainer_step3.py index 31f05faeb..be6c466c0 100644 --- a/test_automl/optuna_wandb_nocontainer_step3.py +++ b/test_automl/optuna_wandb_nocontainer_step3.py @@ -6,10 +6,10 @@ import optuna import scanpy as sc import torch +import wandb from optuna.integration.wandb import WeightsAndBiasesCallback from test_automl_step2 import fun2code_dict -import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA From 40a7c01bceef780b053a39eea79ac375c0f52d5c Mon Sep 17 00:00:00 2001 From: xzy Date: Wed, 17 Jan 2024 22:17:26 +0800 Subject: [PATCH 010/168] Delete useless comments --- test_automl/optuna_wandb_nocontainer_step3.py | 76 +------------------ 1 file changed, 2 insertions(+), 74 deletions(-) diff --git a/test_automl/optuna_wandb_nocontainer_step3.py b/test_automl/optuna_wandb_nocontainer_step3.py index be6c466c0..583b9621f 100644 --- a/test_automl/optuna_wandb_nocontainer_step3.py +++ b/test_automl/optuna_wandb_nocontainer_step3.py @@ -1,15 +1,13 @@ -import json -import os import sys import numpy as np import optuna import scanpy as sc import torch -import wandb from optuna.integration.wandb import WeightsAndBiasesCallback from test_automl_step2 import fun2code_dict +import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA @@ -22,39 +20,20 @@ fun_list = ["log1p", "filter_gene_by_count"] wandb_kwargs = {"project": "my-project"} wandbc = WeightsAndBiasesCallback(wandb_kwargs=wandb_kwargs, as_multirun=True) -# import inspect - -# path= os.path.dirname(inspect.getfile(lambda: None)) -# path = os.path.join(path,"fun_list.json") # 拼接文件的路径 -# with open(path,"r") as file: -# loaded_data = json.load(file) -# fun_list = loaded_data["fun_list"] - -# print(path) -# from fun_list import fun_list -# from dance.transforms.cell_feature import CellPCA,CellSVD,WeightedFeaturePCA -# from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression -# from dance.transforms.interface import AnnDataTransform -# from dance.transforms.normalize import ScTransformR, ScaleFeature def cell_pca(trial: optuna.Trial): method_name = str(sys._getframe().f_code.co_name) + "_" - # return {method_name + "n_components": trial.suggest_int(method_name + "n_components", 200, 5000)} return CellPCA(n_components=trial.suggest_int(method_name + "n_components", 200, 5000)) def cell_weighted_pca(trial: optuna.Trial): method_name = str(sys._getframe().f_code.co_name) + "_" - # return {method_name + "n_components": trial.suggest_int(method_name + "n_components", 200, 5000)} - return WeightedFeaturePCA(n_components=trial.suggest_int(method_name + "n_components", 200, 5000)) def cell_svd(trial: optuna.Trial): method_name = str(sys._getframe().f_code.co_name) + "_" - # return {method_name + "n_components": trial.suggest_int(method_name + "n_components", 200, 5000)} - return CellSVD(n_components=trial.suggest_int(method_name + "n_components", 200, 5000)) @@ -63,10 +42,6 @@ def Filter_gene_by_regress_score(trial: optuna.Trial): return FilterGenesRegression( method=trial.suggest_categorical(method_name + "method", ["enclasc", "seurat3", "scmap"]), num_genes=trial.suggest_int(method_name + "num_genes", 5000, 6000)) - # return { - # method_name + "method": trial.suggest_categorical(method_name + "method", ["enclasc", "seurat3", "scmap"]), - # method_name + "num_genes": trial.suggest_int(method_name + "num_genes", 5000, 6000) - # } def highly_variable_genes(trial: optuna.Trial): @@ -78,14 +53,6 @@ def highly_variable_genes(trial: optuna.Trial): span=trial.suggest_float(method_name + "span", 0.2, 1.0), n_bins=trial.suggest_int(method_name + "n_bins", 10, 30), flavor=trial.suggest_categorical(method_name + "flavor", ['seurat', 'cell_ranger'])) - # return { - # method_name + "min_mean": trial.suggest_float(method_name + "min_mean", 0.0025, 0.03), - # method_name + "max_mean": trial.suggest_float(method_name + "min_mean", 1.5, 4.5), - # method_name + "min_disp": trial.suggest_float(method_name + "min_disp", 0.25, 0.75), - # method_name + "span": trial.suggest_float(method_name + "span", 0.2, 1.0), - # method_name + "n_bins": trial.suggest_int(method_name + "n_bins", 10, 30), - # method_name + "flavor": trial.suggest_categorical(method_name + "flavor", ['seurat', 'cell_ranger']) - # } def filter_gene_by_percentile(trial: optuna.Trial): @@ -93,11 +60,6 @@ def filter_gene_by_percentile(trial: optuna.Trial): return FilterGenesPercentile(min_val=trial.suggest_int(method_name + "min_val", 1, 10), max_val=trial.suggest_int(method_name + "max_val", 90, 99), mode=trial.suggest_categorical(method_name + "mode", ["sum", "var", "cv", "rv"])) - # return { - # method_name + "min_val": trial.suggest_int(method_name + "min_val", 1, 10), - # method_name + "max_val": trial.suggest_int(method_name + "max_val", 90, 99), - # method_name + "mode": trial.suggest_categorical(method_name + "mode", ["sum", "var", "cv", "rv"]) - # } def filter_gene_by_count(trial: optuna.Trial): @@ -112,19 +74,15 @@ def filter_gene_by_count(trial: optuna.Trial): if method == "max_cells": num = trial.suggest_int(method_name + "num", 500, 1000) return AnnDataTransform(sc.pp.filter_genes, **{method: num}) - # return {method_name + "method": method, method_name + "num": num} def log1p(trial: optuna.Trial): method_name = str(sys._getframe().f_code.co_name) + "_" return AnnDataTransform(sc.pp.log1p, base=trial.suggest_int(method_name + "base", 2, 10)) - # return {method_name + "base": trial.suggest_int(method_name + "base", 2, 10)} def scTransform(trial: optuna.Trial): method_name = str(sys._getframe().f_code.co_name) + "_" - # return {method_name + "min_cells": trial.suggest_int(method_name + "min_cells", 1, 10)} - return ScTransformR(min_cells=trial.suggest_int(method_name + "min_cells", 1, 10)) @@ -132,10 +90,6 @@ def scaleFeature(trial: optuna.Trial): #eps未优化 method_name = str(sys._getframe().f_code.co_name) + "_" return ScaleFeature(mode=trial.suggest_categorical(method_name + "mode", ["normalize", "standardize", "minmax", "l2"])) - # return { - # method_name + "mode": trial.suggest_categorical(method_name + "mode", - # ["normalize", "standardize", "minmax", "l2"]) - # } def normalize_total(trial: optuna.Trial): @@ -147,44 +101,21 @@ def normalize_total(trial: optuna.Trial): return AnnDataTransform(sc.pp.normalize_total, target_sum=trial.suggest_categorical(method_name + "target_sum", [1e4, 1e5, 1e6]), exclude_highly_expressed=exclude_highly_expressed, max_fraction=max_fraction) - # return { - # method_name + "exclude_highly_expressed": - # trial.suggest_categorical(method_name + "exclude_highly_expressed", [False, True]), - # method_name + "max_fraction": - # max_fraction - # } else: return AnnDataTransform(sc.pp.normalize_total, target_sum=trial.suggest_categorical(method_name + "target_sum", [1e4, 1e5, 1e6]), exclude_highly_expressed=exclude_highly_expressed, max_fraction=max_fraction) - # return { - # method_name + "exclude_highly_expressed": - # trial.suggest_categorical(method_name + "exclude_highly_expressed", [False, True]) - # } - -# 从 JSON 文件中读取数据 - -# parameter_config = None device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu") @wandbc.track_in_wandb() def objective(trial): - # method_name=str(sys._getframe().f_code.co_name)+"_" - # exclude_highly_expressed=trial.suggest_categorical(method_name+"exclude_highly_expressed",[False,True]) - # if exclude_highly_expressed: - # max_fraction=trial.suggest_float(method_name+"max_fraction",0.04,0.1) - # print(exclude_highly_expressed) - # if exclude_highly_expressed: - # print(max_fraction) - # global parameter_config - # parameter_config = {} + transforms = [] for f_str in fun_list: fun_i = eval(f_str) - # parameter_config.update(fun_i(trial)) transforms.append(fun_i(trial)) parameters_dict = { 'batch_size': 128, @@ -225,9 +156,6 @@ def objective(trial): num_epochs=parameter_config.get('num_epochs'), batch_size=parameter_config.get('batch_size'), print_cost=False) scores.append(score := model.score(x_test, y_test)) - # print(f"{score=:.4f}") - # print(f"ACTINN {species} {tissue} {test_dataset}:") - # print(f"{scores}\n{np.mean(scores):.5f} +/- {np.std(scores):.5f}") wandb.log({"scores": np.mean(scores)}) return np.mean(scores) From 94ac30eefa15eec7d2be491d81b8fb065492c0ea Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 17 Jan 2024 14:17:56 +0000 Subject: [PATCH 011/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/optuna_wandb_nocontainer_step3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/optuna_wandb_nocontainer_step3.py b/test_automl/optuna_wandb_nocontainer_step3.py index 583b9621f..c78e9ccd4 100644 --- a/test_automl/optuna_wandb_nocontainer_step3.py +++ b/test_automl/optuna_wandb_nocontainer_step3.py @@ -4,10 +4,10 @@ import optuna import scanpy as sc import torch +import wandb from optuna.integration.wandb import WeightsAndBiasesCallback from test_automl_step2 import fun2code_dict -import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA From 0c46c7f0c3bc263d924465433de2036ef6e60357 Mon Sep 17 00:00:00 2001 From: xzy Date: Wed, 17 Jan 2024 22:18:54 +0800 Subject: [PATCH 012/168] delete useless comments --- test_automl/test_automl_step2.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/test_automl/test_automl_step2.py b/test_automl/test_automl_step2.py index 609958f96..0c85e6f85 100644 --- a/test_automl/test_automl_step2.py +++ b/test_automl/test_automl_step2.py @@ -2,8 +2,8 @@ from itertools import combinations import scanpy as sc -import wandb +import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform @@ -105,9 +105,6 @@ def train(config=None): data_config.update({"feature_channel": fun2code_dict[config.gene_dim_reduction].name}) transforms.append(SetConfig(data_config)) preprocessing_pipeline = Compose(*transforms, log_level="INFO") - - # preprocessing_pipeline = model.preprocessing_pipeline(normalize=args.normalize, filter_genes=not args.nofilter) - # Load data and perform necessary preprocessing train_dataset = [753, 3285] test_dataset = [2695] tissue = "Brain" @@ -128,9 +125,6 @@ def train(config=None): model.fit(x_train, y_train, seed=seed, lr=config.learning_rate, num_epochs=config.num_epochs, batch_size=config.batch_size, print_cost=False) scores.append(score := model.score(x_test, y_test)) - # print(f"{score=:.4f}") - # print(f"ACTINN {species} {tissue} {test_dataset}:") - # print(f"{scores}\n{np.mean(scores):.5f} +/- {np.std(scores):.5f}") wandb.log({"scores": np.mean(scores)}) From 8ffdbdfec779e59eabe43bd0d729106f93678930 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 17 Jan 2024 14:23:43 +0000 Subject: [PATCH 013/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/test_automl_step2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/test_automl_step2.py b/test_automl/test_automl_step2.py index 0c85e6f85..97bda32e6 100644 --- a/test_automl/test_automl_step2.py +++ b/test_automl/test_automl_step2.py @@ -2,8 +2,8 @@ from itertools import combinations import scanpy as sc - import wandb + from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform From d56b317e00f03ce8174e527f5e6fbaedb408104d Mon Sep 17 00:00:00 2001 From: xzy Date: Wed, 17 Jan 2024 22:31:40 +0800 Subject: [PATCH 014/168] rename step2File --- test_automl/optuna_wandb_nocontainer_step3.py | 4 ++-- test_automl/test_automl_fun_job.py | 4 ++-- test_automl/{test_automl_step2.py => wandb_step2.py} | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename test_automl/{test_automl_step2.py => wandb_step2.py} (100%) diff --git a/test_automl/optuna_wandb_nocontainer_step3.py b/test_automl/optuna_wandb_nocontainer_step3.py index c78e9ccd4..08f4dec25 100644 --- a/test_automl/optuna_wandb_nocontainer_step3.py +++ b/test_automl/optuna_wandb_nocontainer_step3.py @@ -4,10 +4,9 @@ import optuna import scanpy as sc import torch -import wandb from optuna.integration.wandb import WeightsAndBiasesCallback -from test_automl_step2 import fun2code_dict +import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA @@ -16,6 +15,7 @@ from dance.transforms.misc import Compose, SetConfig from dance.transforms.normalize import ScaleFeature, ScTransformR from dance.utils import set_seed +from test_automl.wandb_step2 import fun2code_dict fun_list = ["log1p", "filter_gene_by_count"] wandb_kwargs = {"project": "my-project"} diff --git a/test_automl/test_automl_fun_job.py b/test_automl/test_automl_fun_job.py index fda982391..0a165fc36 100644 --- a/test_automl/test_automl_fun_job.py +++ b/test_automl/test_automl_fun_job.py @@ -5,10 +5,9 @@ import numpy as np import scanpy as sc import torch -import wandb from optuna_wandb import fun_list -from test_automl_step2 import fun2code_dict +import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA @@ -17,6 +16,7 @@ from dance.transforms.misc import Compose, SetConfig from dance.transforms.normalize import ScaleFeature, ScTransformR from dance.utils import set_seed +from test_automl.wandb_step2 import fun2code_dict device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu") diff --git a/test_automl/test_automl_step2.py b/test_automl/wandb_step2.py similarity index 100% rename from test_automl/test_automl_step2.py rename to test_automl/wandb_step2.py index 97bda32e6..0c85e6f85 100644 --- a/test_automl/test_automl_step2.py +++ b/test_automl/wandb_step2.py @@ -2,8 +2,8 @@ from itertools import combinations import scanpy as sc -import wandb +import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform From 4fbfc5d5dee2cbc0b415d4f4841846ba53d20d0c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 17 Jan 2024 14:32:17 +0000 Subject: [PATCH 015/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/optuna_wandb_nocontainer_step3.py | 2 +- test_automl/test_automl_fun_job.py | 2 +- test_automl/wandb_step2.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test_automl/optuna_wandb_nocontainer_step3.py b/test_automl/optuna_wandb_nocontainer_step3.py index 08f4dec25..a827e7b98 100644 --- a/test_automl/optuna_wandb_nocontainer_step3.py +++ b/test_automl/optuna_wandb_nocontainer_step3.py @@ -4,9 +4,9 @@ import optuna import scanpy as sc import torch +import wandb from optuna.integration.wandb import WeightsAndBiasesCallback -import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA diff --git a/test_automl/test_automl_fun_job.py b/test_automl/test_automl_fun_job.py index 0a165fc36..ed91c3de2 100644 --- a/test_automl/test_automl_fun_job.py +++ b/test_automl/test_automl_fun_job.py @@ -5,9 +5,9 @@ import numpy as np import scanpy as sc import torch +import wandb from optuna_wandb import fun_list -import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA diff --git a/test_automl/wandb_step2.py b/test_automl/wandb_step2.py index 0c85e6f85..97bda32e6 100644 --- a/test_automl/wandb_step2.py +++ b/test_automl/wandb_step2.py @@ -2,8 +2,8 @@ from itertools import combinations import scanpy as sc - import wandb + from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform From 2cb78e1fe32883ccbd8f77c02c9cd012d450bd8a Mon Sep 17 00:00:00 2001 From: xzy Date: Thu, 18 Jan 2024 09:22:14 +0800 Subject: [PATCH 016/168] delete unused comments --- test_automl/optuna_wandb.py | 47 +++---------------------------------- 1 file changed, 3 insertions(+), 44 deletions(-) diff --git a/test_automl/optuna_wandb.py b/test_automl/optuna_wandb.py index ba0981620..e94a18d53 100644 --- a/test_automl/optuna_wandb.py +++ b/test_automl/optuna_wandb.py @@ -6,20 +6,6 @@ import scanpy as sc fun_list = ["log1p", "filter_gene_by_count"] -# import inspect - -# path= os.path.dirname(inspect.getfile(lambda: None)) -# path = os.path.join(path,"fun_list.json") # 拼接文件的路径 -# with open(path,"r") as file: -# loaded_data = json.load(file) -# fun_list = loaded_data["fun_list"] - -# print(path) -# from fun_list import fun_list -# from dance.transforms.cell_feature import CellPCA,CellSVD,WeightedFeaturePCA -# from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression -# from dance.transforms.interface import AnnDataTransform -# from dance.transforms.normalize import ScTransformR, ScaleFeature def cell_pca(trial: optuna.Trial): @@ -27,23 +13,19 @@ def cell_pca(trial: optuna.Trial): return {method_name + "n_components": trial.suggest_int(method_name + "n_components", 200, 5000)} - # return CellPCA(n_components=trial.suggest_int(method_name+"n_components",200,5000)) def cell_weighted_pca(trial: optuna.Trial): method_name = str(sys._getframe().f_code.co_name) + "_" return {method_name + "n_components": trial.suggest_int(method_name + "n_components", 200, 5000)} - # return WeightedFeaturePCA(n_components=trial.suggest_int(method_name+"n_components",200,5000)) def cell_svd(trial: optuna.Trial): method_name = str(sys._getframe().f_code.co_name) + "_" return {method_name + "n_components": trial.suggest_int(method_name + "n_components", 200, 5000)} - # return CellSVD(n_components=trial.suggest_int(method_name+"n_components",200,5000)) def Filter_gene_by_regress_score(trial: optuna.Trial): method_name = str(sys._getframe().f_code.co_name) + "_" - # return FilterGenesRegression(method=trial.suggest_categorical(method_name+"method",["enclasc","seurat3","scmap"]), - # num_genes=trial.suggest_int(method_name+"num_genes",5000,6000)) + return { method_name + "method": trial.suggest_categorical(method_name + "method", ["enclasc", "seurat3", "scmap"]), method_name + "num_genes": trial.suggest_int(method_name + "num_genes", 5000, 6000) @@ -52,13 +34,7 @@ def Filter_gene_by_regress_score(trial: optuna.Trial): def highly_variable_genes(trial: optuna.Trial): method_name = str(sys._getframe().f_code.co_name) + "_" - # return AnnDataTransform(sc.pp.highly_variable_genes,min_mean=trial.suggest_float(method_name+"min_mean",0.0025,0.03), - # max_mean=trial.suggest_float(method_name+"min_mean",1.5,4.5), - # min_disp=trial.suggest_float(method_name+"min_disp",0.25,0.75), - # span=trial.suggest_float(method_name+"span",0.2,1.0), - # n_bins=trial.suggest_int(method_name+"n_bins",10,30), - # flavor=trial.suggest_categorical(method_name+"flavor",['seurat', 'cell_ranger']) - # ) + return { method_name + "min_mean": trial.suggest_float(method_name + "min_mean", 0.0025, 0.03), method_name + "max_mean": trial.suggest_float(method_name + "min_mean", 1.5, 4.5), @@ -71,9 +47,7 @@ def highly_variable_genes(trial: optuna.Trial): def filter_gene_by_percentile(trial: optuna.Trial): method_name = str(sys._getframe().f_code.co_name) + "_" - # return FilterGenesPercentile(min_val=trial.suggest_int(method_name+"min_val",1,10), - # max_val=trial.suggest_int(method_name+"max_val",90,99), - # mode=trial.suggest_categorical(method_name+"mode",["sum","var","cv","rv"])) + return { method_name + "min_val": trial.suggest_int(method_name + "min_val", 1, 10), method_name + "max_val": trial.suggest_int(method_name + "max_val", 90, 99), @@ -92,13 +66,11 @@ def filter_gene_by_count(trial: optuna.Trial): num = trial.suggest_int(method_name + "num", 500, 1000) if method == "max_cells": num = trial.suggest_int(method_name + "num", 500, 1000) - # return AnnDataTransform(sc.pp.filter_genes,method=num) return {method_name + "method": method, method_name + "num": num} def log1p(trial: optuna.Trial): method_name = str(sys._getframe().f_code.co_name) + "_" - # return AnnDataTransform(sc.pp.log1p,base=trial.suggest_int(method_name+"base",2,10)) return {method_name + "base": trial.suggest_int(method_name + "base", 2, 10)} @@ -107,10 +79,8 @@ def scTransform(trial: optuna.Trial): return {method_name + "min_cells": trial.suggest_int(method_name + "min_cells", 1, 10)} - # return ScTransformR(min_cells=trial.suggest_int(method_name+"min_cells",1,10)) def scaleFeature(trial: optuna.Trial): #eps未优化 method_name = str(sys._getframe().f_code.co_name) + "_" - # return ScaleFeature(mode=trial.suggest_categorical(method_name+"mode",["normalize", "standardize", "minmax", "l2"])) return { method_name + "mode": trial.suggest_categorical(method_name + "mode", ["normalize", "standardize", "minmax", "l2"]) @@ -134,26 +104,15 @@ def normalize_total(trial: optuna.Trial): method_name + "exclude_highly_expressed": trial.suggest_categorical(method_name + "exclude_highly_expressed", [False, True]) } - # return AnnDataTransform(sc.pp.normalize_total,target_sum=trial.suggest_categorical(method_name+"target_sum",[1e4,1e5,1e6]),exclude_highly_expressed=exclude_highly_expressed,max_fraction=max_fraction) - -# 从 JSON 文件中读取数据 parameter_config = None def objective(trial): - # method_name=str(sys._getframe().f_code.co_name)+"_" - # exclude_highly_expressed=trial.suggest_categorical(method_name+"exclude_highly_expressed",[False,True]) - # if exclude_highly_expressed: - # max_fraction=trial.suggest_float(method_name+"max_fraction",0.04,0.1) - # print(exclude_highly_expressed) - # if exclude_highly_expressed: - # print(max_fraction) global parameter_config parameter_config = {} for f_str in fun_list: fun_i = eval(f_str) parameter_config.update(fun_i(trial)) - # transforms.append(fun_i(trial)) return -1 From ba305ee04d0a85d12b7624d7160c1194f7bd5c7c Mon Sep 17 00:00:00 2001 From: xzy Date: Thu, 18 Jan 2024 09:23:15 +0800 Subject: [PATCH 017/168] delete unused comments --- test_automl/test_automl_fun_2.py | 40 ++------------------------------ 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/test_automl/test_automl_fun_2.py b/test_automl/test_automl_fun_2.py index 5aa693468..64cfa9093 100644 --- a/test_automl/test_automl_fun_2.py +++ b/test_automl/test_automl_fun_2.py @@ -1,6 +1,7 @@ -import wandb import yaml +import wandb + ARTIFACT_FILENAME = "/home/zyxing/dance/" ARTIFACT_NAME = "optuna-config" @@ -8,11 +9,6 @@ ENTITY = "xzy11632" QUEUE = "actinn" ## Put in a Launch queue you've created and started - -def train(a): - pass - - if __name__ == "__main__": # """create and log artifact to wandb""" run = wandb.init(project=PROJECT, entity=ENTITY) @@ -20,35 +16,3 @@ def train(a): artifact.add_dir(ARTIFACT_FILENAME) run.log_artifact(artifact) run.finish() -# config = { -# "metric": {"name": "scores", "goal": "maximize"}, -# "run_cap": 4, -# "job": "xzy11632/pytorch-cell_type_annotation_ACTINN_function_new/job-source-pytorch-cell_type_annotation_ACTINN_function_new-test_automl_test_automl_fun_job.py:v3",#思考一下 -# "scheduler": { -# "job": "xzy11632/pytorch-cell_type_annotation_ACTINN_function_new/job-OptunaScheduler:v4", -# "num_workers": 2, -# "settings": { -# "optuna_source": f"{ENTITY}/{PROJECT}/{artifact.wait().name}", -# "optuna_source_filename": ARTIFACT_FILENAME, -# "resource": "local-container", # required for scheduler jobs sourced from images - -# # optional sampler args -# "pruner": { -# "type": "PercentilePruner", -# "args": { -# "percentile": 0.25, -# "n_startup_trials": 2, -# "n_min_trials": 1, # min epochs before prune -# } -# } -# } -# }, -# # parameters are not needed when loading a conditional config from an artifact -# # "parameters": { -# # 'epochs': {'values': [5, 10, 15]}, -# # 'lr': {'max': 0.1, 'min': 0.0001} -# # } -# } -# # write config to file -# config_filename = "sweep-config.yaml" -# yaml.dump(config, open(config_filename, "w")) From dcf2cdd506bc9159037eebea60df2fc31556ffcf Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Jan 2024 01:23:36 +0000 Subject: [PATCH 018/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/test_automl_fun_2.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test_automl/test_automl_fun_2.py b/test_automl/test_automl_fun_2.py index 64cfa9093..9945cd7f5 100644 --- a/test_automl/test_automl_fun_2.py +++ b/test_automl/test_automl_fun_2.py @@ -1,6 +1,5 @@ -import yaml - import wandb +import yaml ARTIFACT_FILENAME = "/home/zyxing/dance/" ARTIFACT_NAME = "optuna-config" From cec3906de4c0da15fdcf658b5b741d2647eb7476 Mon Sep 17 00:00:00 2001 From: xzy Date: Thu, 18 Jan 2024 09:24:50 +0800 Subject: [PATCH 019/168] delete unused comments --- test_automl/test_automl_fun_job.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/test_automl/test_automl_fun_job.py b/test_automl/test_automl_fun_job.py index ed91c3de2..1069e9c5d 100644 --- a/test_automl/test_automl_fun_job.py +++ b/test_automl/test_automl_fun_job.py @@ -5,9 +5,9 @@ import numpy as np import scanpy as sc import torch -import wandb from optuna_wandb import fun_list +import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA @@ -21,12 +21,6 @@ device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu") -# import inspect -# path= os.path.dirname(inspect.getfile(lambda: None)) -# path = os.path.join(path,"fun_list.json") # 拼接文件的路径 -# with open(path,"r") as file: -# loaded_data = json.load(file) -# fun_list = loaded_data["fun_list"] def cell_pca(parameter_config): method_name = str(sys._getframe().f_code.co_name) + "_" return CellPCA(n_components=parameter_config.get(method_name + "n_components")) @@ -138,8 +132,6 @@ def run_training_run(): transforms.append(SetConfig(data_config)) preprocessing_pipeline = Compose(*transforms, log_level="INFO") - # preprocessing_pipeline = model.preprocessing_pipeline(normalize=args.normalize, filter_genes=not args.nofilter) - # Load data and perform necessary preprocessing train_dataset = [753, 3285] test_dataset = [2695] tissue = "Brain" @@ -164,9 +156,7 @@ def run_training_run(): num_epochs=parameter_config.get('num_epochs'), batch_size=parameter_config.get('batch_size'), print_cost=False) scores.append(score := model.score(x_test, y_test)) - # print(f"{score=:.4f}") - # print(f"ACTINN {species} {tissue} {test_dataset}:") - # print(f"{scores}\n{np.mean(scores):.5f} +/- {np.std(scores):.5f}") + wandb.log({"scores": np.mean(scores)}) run.log_code() run.finish() From f68e18135b028159ae212094f2f9a6c904a3fd1d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Jan 2024 01:26:04 +0000 Subject: [PATCH 020/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/test_automl_fun_job.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/test_automl_fun_job.py b/test_automl/test_automl_fun_job.py index 1069e9c5d..d1bfcd1e3 100644 --- a/test_automl/test_automl_fun_job.py +++ b/test_automl/test_automl_fun_job.py @@ -5,9 +5,9 @@ import numpy as np import scanpy as sc import torch +import wandb from optuna_wandb import fun_list -import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA From d23b3ed5aa805263f4acaed20d3e201de614dbe1 Mon Sep 17 00:00:00 2001 From: xzy Date: Thu, 18 Jan 2024 09:53:57 +0800 Subject: [PATCH 021/168] change parameter config --- test_automl/optuna_wandb.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test_automl/optuna_wandb.py b/test_automl/optuna_wandb.py index e94a18d53..65cdb0864 100644 --- a/test_automl/optuna_wandb.py +++ b/test_automl/optuna_wandb.py @@ -106,11 +106,7 @@ def normalize_total(trial: optuna.Trial): } -parameter_config = None - - def objective(trial): - global parameter_config parameter_config = {} for f_str in fun_list: fun_i = eval(f_str) From 6ef23a8f7b9b594796445e96f253d4a037d77f73 Mon Sep 17 00:00:00 2001 From: xzy Date: Thu, 18 Jan 2024 09:57:02 +0800 Subject: [PATCH 022/168] change import --- test_automl/optuna_wandb.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/test_automl/optuna_wandb.py b/test_automl/optuna_wandb.py index 65cdb0864..7968294d6 100644 --- a/test_automl/optuna_wandb.py +++ b/test_automl/optuna_wandb.py @@ -1,9 +1,6 @@ -import json -import os import sys import optuna -import scanpy as sc fun_list = ["log1p", "filter_gene_by_count"] From c48803035f5962622bb900526bbf5220de56410b Mon Sep 17 00:00:00 2001 From: xzy Date: Thu, 18 Jan 2024 09:59:07 +0800 Subject: [PATCH 023/168] change import --- test_automl/test_automl_fun_job.py | 4 +--- test_automl/wandb_step2.py | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/test_automl/test_automl_fun_job.py b/test_automl/test_automl_fun_job.py index d1bfcd1e3..29784d161 100644 --- a/test_automl/test_automl_fun_job.py +++ b/test_automl/test_automl_fun_job.py @@ -1,13 +1,11 @@ -import os -import random import sys import numpy as np import scanpy as sc import torch -import wandb from optuna_wandb import fun_list +import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA diff --git a/test_automl/wandb_step2.py b/test_automl/wandb_step2.py index 97bda32e6..07ddc502d 100644 --- a/test_automl/wandb_step2.py +++ b/test_automl/wandb_step2.py @@ -1,9 +1,8 @@ -from functools import partial from itertools import combinations import scanpy as sc -import wandb +import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform From f0abdfd3082b884dac412051704922741e8f5907 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Jan 2024 01:59:37 +0000 Subject: [PATCH 024/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/test_automl_fun_job.py | 2 +- test_automl/wandb_step2.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test_automl/test_automl_fun_job.py b/test_automl/test_automl_fun_job.py index 29784d161..bab2e4479 100644 --- a/test_automl/test_automl_fun_job.py +++ b/test_automl/test_automl_fun_job.py @@ -3,9 +3,9 @@ import numpy as np import scanpy as sc import torch +import wandb from optuna_wandb import fun_list -import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA diff --git a/test_automl/wandb_step2.py b/test_automl/wandb_step2.py index 07ddc502d..29a879c89 100644 --- a/test_automl/wandb_step2.py +++ b/test_automl/wandb_step2.py @@ -1,8 +1,8 @@ from itertools import combinations import scanpy as sc - import wandb + from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform From 96a3cd9163d357c4658c872064da8e4de933ab4d Mon Sep 17 00:00:00 2001 From: xzy Date: Thu, 18 Jan 2024 19:52:43 +0800 Subject: [PATCH 025/168] delete about singularity --- MANIFEST.in | 1 - test_automl/optuna_wandb.py | 111 -------------------- test_automl/sweep-config.yaml | 21 ---- test_automl/test_automl_fun_2.py | 17 --- test_automl/test_automl_fun_job.py | 163 ----------------------------- 5 files changed, 313 deletions(-) delete mode 100644 MANIFEST.in delete mode 100644 test_automl/optuna_wandb.py delete mode 100644 test_automl/sweep-config.yaml delete mode 100644 test_automl/test_automl_fun_2.py delete mode 100644 test_automl/test_automl_fun_job.py diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 1d3aa0463..000000000 --- a/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ -dance/metadata/* diff --git a/test_automl/optuna_wandb.py b/test_automl/optuna_wandb.py deleted file mode 100644 index 7968294d6..000000000 --- a/test_automl/optuna_wandb.py +++ /dev/null @@ -1,111 +0,0 @@ -import sys - -import optuna - -fun_list = ["log1p", "filter_gene_by_count"] - - -def cell_pca(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" - return {method_name + "n_components": trial.suggest_int(method_name + "n_components", 200, 5000)} - - -def cell_weighted_pca(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" - return {method_name + "n_components": trial.suggest_int(method_name + "n_components", 200, 5000)} - - -def cell_svd(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" - return {method_name + "n_components": trial.suggest_int(method_name + "n_components", 200, 5000)} - - -def Filter_gene_by_regress_score(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" - - return { - method_name + "method": trial.suggest_categorical(method_name + "method", ["enclasc", "seurat3", "scmap"]), - method_name + "num_genes": trial.suggest_int(method_name + "num_genes", 5000, 6000) - } - - -def highly_variable_genes(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" - - return { - method_name + "min_mean": trial.suggest_float(method_name + "min_mean", 0.0025, 0.03), - method_name + "max_mean": trial.suggest_float(method_name + "min_mean", 1.5, 4.5), - method_name + "min_disp": trial.suggest_float(method_name + "min_disp", 0.25, 0.75), - method_name + "span": trial.suggest_float(method_name + "span", 0.2, 1.0), - method_name + "n_bins": trial.suggest_int(method_name + "n_bins", 10, 30), - method_name + "flavor": trial.suggest_categorical(method_name + "flavor", ['seurat', 'cell_ranger']) - } - - -def filter_gene_by_percentile(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" - - return { - method_name + "min_val": trial.suggest_int(method_name + "min_val", 1, 10), - method_name + "max_val": trial.suggest_int(method_name + "max_val", 90, 99), - method_name + "mode": trial.suggest_categorical(method_name + "mode", ["sum", "var", "cv", "rv"]) - } - - -def filter_gene_by_count(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" - method = trial.suggest_categorical(method_name + "method", ['min_counts', 'min_cells', 'max_counts', 'max_cells']) - if method == "min_counts": - num = trial.suggest_int(method_name + "num", 2, 10) - if method == "min_cells": - num = trial.suggest_int(method_name + "num", 2, 10) - if method == "max_counts": - num = trial.suggest_int(method_name + "num", 500, 1000) - if method == "max_cells": - num = trial.suggest_int(method_name + "num", 500, 1000) - return {method_name + "method": method, method_name + "num": num} - - -def log1p(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" - return {method_name + "base": trial.suggest_int(method_name + "base", 2, 10)} - - -def scTransform(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" - return {method_name + "min_cells": trial.suggest_int(method_name + "min_cells", 1, 10)} - - -def scaleFeature(trial: optuna.Trial): #eps未优化 - method_name = str(sys._getframe().f_code.co_name) + "_" - return { - method_name + "mode": trial.suggest_categorical(method_name + "mode", - ["normalize", "standardize", "minmax", "l2"]) - } - - -def normalize_total(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" - exclude_highly_expressed = trial.suggest_categorical(method_name + "exclude_highly_expressed", [False, True]) - - if exclude_highly_expressed: - max_fraction = trial.suggest_float(method_name + "max_fraction", 0.04, 0.1) - return { - method_name + "exclude_highly_expressed": - trial.suggest_categorical(method_name + "exclude_highly_expressed", [False, True]), - method_name + "max_fraction": - max_fraction - } - else: - return { - method_name + "exclude_highly_expressed": - trial.suggest_categorical(method_name + "exclude_highly_expressed", [False, True]) - } - - -def objective(trial): - parameter_config = {} - for f_str in fun_list: - fun_i = eval(f_str) - parameter_config.update(fun_i(trial)) - return -1 diff --git a/test_automl/sweep-config.yaml b/test_automl/sweep-config.yaml deleted file mode 100644 index c19c632da..000000000 --- a/test_automl/sweep-config.yaml +++ /dev/null @@ -1,21 +0,0 @@ -job: xzy11632/pytorch-cell_type_annotation_ACTINN_function_new/job-source-pytorch-cell_type_annotation_ACTINN_function_new-test_automl_test_automl_fun_job.py:latest -metric: - goal: maximize - name: scores -run_cap: 20 -scheduler: - job: xzy11632/pytorch-cell_type_annotation_ACTINN_function_new/job-OptunaScheduler:latest - num_workers: 2 - docker_image: rdance_fcf2b32f.sif - resource_args: - local-container: - env-file: "/home/zyxing/dance/web-variables.env" - settings: - optuna_source: xzy11632/pytorch-cell_type_annotation_ACTINN_function_new/optuna-config:latest - optuna_source_filename: test_automl/optuna_wandb.py - pruner: - args: - n_min_trials: 1 - n_startup_trials: 2 - percentile: 0.25 - type: PercentilePruner diff --git a/test_automl/test_automl_fun_2.py b/test_automl/test_automl_fun_2.py deleted file mode 100644 index 9945cd7f5..000000000 --- a/test_automl/test_automl_fun_2.py +++ /dev/null @@ -1,17 +0,0 @@ -import wandb -import yaml - -ARTIFACT_FILENAME = "/home/zyxing/dance/" -ARTIFACT_NAME = "optuna-config" - -PROJECT = "pytorch-cell_type_annotation_ACTINN_function_new" -ENTITY = "xzy11632" -QUEUE = "actinn" ## Put in a Launch queue you've created and started - -if __name__ == "__main__": - # """create and log artifact to wandb""" - run = wandb.init(project=PROJECT, entity=ENTITY) - artifact = wandb.Artifact(name=ARTIFACT_NAME, type='optuna') - artifact.add_dir(ARTIFACT_FILENAME) - run.log_artifact(artifact) - run.finish() diff --git a/test_automl/test_automl_fun_job.py b/test_automl/test_automl_fun_job.py deleted file mode 100644 index 29784d161..000000000 --- a/test_automl/test_automl_fun_job.py +++ /dev/null @@ -1,163 +0,0 @@ -import sys - -import numpy as np -import scanpy as sc -import torch -from optuna_wandb import fun_list - -import wandb -from dance.datasets.singlemodality import CellTypeAnnotationDataset -from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN -from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA -from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression -from dance.transforms.interface import AnnDataTransform -from dance.transforms.misc import Compose, SetConfig -from dance.transforms.normalize import ScaleFeature, ScTransformR -from dance.utils import set_seed -from test_automl.wandb_step2 import fun2code_dict - -device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu") - - -def cell_pca(parameter_config): - method_name = str(sys._getframe().f_code.co_name) + "_" - return CellPCA(n_components=parameter_config.get(method_name + "n_components")) - - -def cell_weighted_pca(parameter_config): - method_name = str(sys._getframe().f_code.co_name) + "_" - return WeightedFeaturePCA(n_components=parameter_config.get(method_name + "n_components")) - - -def cell_svd(parameter_config): - method_name = str(sys._getframe().f_code.co_name) + "_" - return CellSVD(n_components=parameter_config.get(method_name + "n_components")) - - -def Filter_gene_by_regress_score(parameter_config): - method_name = str(sys._getframe().f_code.co_name) + "_" - return FilterGenesRegression(method=parameter_config.get(method_name + "method"), - num_genes=parameter_config.get(method_name + "num_genes")) - - -def highly_variable_genes(parameter_config): - method_name = str(sys._getframe().f_code.co_name) + "_" - return AnnDataTransform(sc.pp.highly_variable_genes, min_mean=parameter_config.get(method_name + "min_mean"), - max_mean=parameter_config.get(method_name + "min_mean"), - min_disp=parameter_config.get(method_name + "min_disp"), - span=parameter_config.get(method_name + "span"), - n_bins=parameter_config.get(method_name + "n_bins"), - flavor=parameter_config.get(method_name + "flavor")) - - -def filter_gene_by_percentile(parameter_config): - method_name = str(sys._getframe().f_code.co_name) + "_" - return FilterGenesPercentile(min_val=parameter_config.get(method_name + "min_val"), - max_val=parameter_config.get(method_name + "max_val"), - mode=parameter_config.get(method_name + "mode")) - - -def filter_gene_by_count(parameter_config): - method_name = str(sys._getframe().f_code.co_name) + "_" - method = parameter_config.get(method_name + "method") - num = parameter_config.get(method_name + "num") - return AnnDataTransform(sc.pp.filter_genes, **{method: num}) - - -def log1p(parameter_config): - method_name = str(sys._getframe().f_code.co_name) + "_" - base = parameter_config.get(method_name + "base") - return AnnDataTransform(sc.pp.log1p, base=base) - - -def scTransform(parameter_config): - method_name = str(sys._getframe().f_code.co_name) + "_" - return ScTransformR(min_cells=parameter_config.get(method_name + "min_cells")) - - -def scaleFeature(parameter_config): #eps未优化 - method_name = str(sys._getframe().f_code.co_name) + "_" - return ScaleFeature(mode=parameter_config.get(method_name + "mode", ["normalize", "standardize", "minmax", "l2"])) - - -def normalize_total(parameter_config): - method_name = str(sys._getframe().f_code.co_name) + "_" - exclude_highly_expressed = parameter_config.get(method_name + "exclude_highly_expressed", [False, True]) - if exclude_highly_expressed: - max_fraction = parameter_config.get(method_name + "max_fraction") - return AnnDataTransform(sc.pp.normalize_total, target_sum=parameter_config.get(method_name + "target_sum"), - exclude_highly_expressed=exclude_highly_expressed, max_fraction=max_fraction) - else: - return AnnDataTransform(sc.pp.normalize_total, target_sum=parameter_config.get(method_name + "target_sum"), - exclude_highly_expressed=exclude_highly_expressed) - - -def run_training_run(): - settings = wandb.Settings(job_source="artifact") - run = wandb.init( - project="pytorch-cell_type_annotation_ACTINN_function_new", - settings=settings, - entity="xzy11632", - ) - - print("parameter_config") - parameter_config = dict(run.config) - print(parameter_config) - print("fun_list" + str(fun_list)) - - if len(parameter_config.keys()) != 0: - - parameters_dict = { - 'batch_size': 128, - "hidden_dims": [2000], - 'lambd': 0.005, - 'num_epochs': 50, - 'seed': 0, - 'num_runs': 1, - 'learning_rate': 0.0001 - } - parameter_config.update(parameters_dict) - transforms = [] - for f_str in fun_list: - fun_i = eval(f_str) - transforms.append(fun_i(parameter_config)) - print(transforms) - data_config = {"label_channel": "cell_type"} - feature_name = {"cell_svd", "cell_weighted_pca", "cell_pca"} & set(fun_list) - if feature_name: - data_config.update({"feature_channel": fun2code_dict[feature_name].name}) - - transforms.append(SetConfig(data_config)) - preprocessing_pipeline = Compose(*transforms, log_level="INFO") - - train_dataset = [753, 3285] - test_dataset = [2695] - tissue = "Brain" - species = "mouse" - dataloader = CellTypeAnnotationDataset(train_dataset=train_dataset, test_dataset=test_dataset, tissue=tissue, - species=species) - data = dataloader.load_data(transform=preprocessing_pipeline, cache=True) - - # Obtain training and testing data - x_train, y_train = data.get_train_data(return_type="torch") - x_test, y_test = data.get_test_data(return_type="torch") - x_train, y_train, x_test, y_test = x_train.float(), y_train.float(), x_test.float(), y_test.float() - # Train and evaluate models for several rounds - scores = [] - model = ACTINN(hidden_dims=parameter_config.get('hidden_dims'), lambd=parameter_config.get('lambd'), - device=device) - for seed in range(parameter_config.get('seed'), - parameter_config.get('seed') + parameter_config.get('num_runs')): - set_seed(seed) - - model.fit(x_train, y_train, seed=seed, lr=parameter_config.get('learning_rate'), - num_epochs=parameter_config.get('num_epochs'), batch_size=parameter_config.get('batch_size'), - print_cost=False) - scores.append(score := model.score(x_test, y_test)) - - wandb.log({"scores": np.mean(scores)}) - run.log_code() - run.finish() - - -run_training_run() From 1b332ef9518ca37c9f94f6d3e8c4385453749896 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Jan 2024 11:58:19 +0000 Subject: [PATCH 026/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/wandb_step2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/wandb_step2.py b/test_automl/wandb_step2.py index 07ddc502d..29a879c89 100644 --- a/test_automl/wandb_step2.py +++ b/test_automl/wandb_step2.py @@ -1,8 +1,8 @@ from itertools import combinations import scanpy as sc - import wandb + from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform From a5f300473852002b723fe74080f6e21c66a48e14 Mon Sep 17 00:00:00 2001 From: xzy Date: Thu, 18 Jan 2024 20:00:58 +0800 Subject: [PATCH 027/168] delete scheduler --- optuna_scheduler.py | 805 -------------------------------------------- 1 file changed, 805 deletions(-) delete mode 100644 optuna_scheduler.py diff --git a/optuna_scheduler.py b/optuna_scheduler.py deleted file mode 100644 index a84cf1d09..000000000 --- a/optuna_scheduler.py +++ /dev/null @@ -1,805 +0,0 @@ -import argparse -import base64 -import logging -import os -import signal -import traceback -from collections import defaultdict -from dataclasses import dataclass -from enum import Enum -from importlib.machinery import SourceFileLoader -from types import ModuleType -from typing import Any, Dict, List, Optional, Tuple - -import click -import optuna -import wandb -from wandb.apis.internal import Api -from wandb.apis.public import Api as PublicApi -from wandb.apis.public import QueuedRun, Run -from wandb.sdk.artifacts.artifact import Artifact -from wandb.sdk.launch.sweeps import SchedulerError -from wandb.sdk.launch.sweeps.scheduler import RunState, Scheduler, SweepRun - -logger = logging.getLogger(__name__) -optuna.logging.set_verbosity(optuna.logging.WARNING) - -LOG_PREFIX = f"{click.style('optuna sched:', fg='bright_blue')} " - - -class OptunaComponents(Enum): - main_file = "optuna_wandb.py" - storage = "optuna.db" - study = "optuna-study" - pruner = "optuna-pruner" - sampler = "optuna-sampler" - - -@dataclass -class OptunaRun: - num_metrics: int - trial: optuna.Trial - sweep_run: SweepRun - - -@dataclass -class Metric: - name: str - direction: optuna.study.StudyDirection - - -def setup_scheduler(scheduler: Scheduler, **kwargs): - """Setup a run to log a scheduler job. - - If this job is triggered using a sweep config, it will become a sweep scheduler, - automatically managing a launch sweep Otherwise, we just log the code, creating a - job that can be inserted into a sweep config. - - """ - - parser = argparse.ArgumentParser() - parser.add_argument("--project", type=str, default=kwargs.get("project")) - parser.add_argument("--entity", type=str, default=kwargs.get("entity")) - parser.add_argument("--num_workers", type=int, default=1) - parser.add_argument("--name", type=str, default=f"job-{scheduler.__name__}") - cli_args = parser.parse_args() - - settings = {"job_name": cli_args.name, "job_source": "artifact"} - run = wandb.init( - settings=settings, - project=cli_args.project, - entity=cli_args.entity, - ) - config = run.config - args = config.get("sweep_args", {}) - - if not args or not args.get("sweep_id"): - # when the config has no sweep args, this is being run directly from CLI - # and not in a sweep. Just log the code and return - if not os.getenv("WANDB_DOCKER"): - # if not docker, log the code to a git or code artifact - run.log_code(root=os.path.dirname(__file__)) - run.finish() - return - - if cli_args.num_workers: # override - kwargs.update({"num_workers": cli_args.num_workers}) - - _scheduler = scheduler(Api(), run=run, **args, **kwargs) - _scheduler.start() - - -class OptunaScheduler(Scheduler): - OPT_TIMEOUT = 2 - MAX_MISCONFIGURED_RUNS = 3 - - def __init__( - self, - api: Api, - *args: Optional[Any], - **kwargs: Optional[Any], - ): - super().__init__(api, *args, **kwargs) - # Optuna - self._study: Optional[optuna.study.Study] = None - self._storage_path: Optional[str] = None - self._trial_func = self._make_trial - self._optuna_runs: Dict[str, OptunaRun] = {} - - # Load optuna args from kwargs then check wandb run config - self._optuna_config = kwargs.get("settings") - if not self._optuna_config: - self._optuna_config = self._wandb_run.config.get("settings", {}) - - self._metric_defs = self._get_metric_names_and_directions() - - # if metric is misconfigured, increment, stop sweep if 3 consecutive fails - self._num_misconfigured_runs = 0 - - @property - def study(self) -> optuna.study.Study: - if not self._study: - raise SchedulerError("Optuna study=None before scheduler.start") - return self._study - - @property - def study_name(self) -> str: - if not self._study: - return f"optuna-study-{self._sweep_id}" - optuna_study_name: str = self.study.study_name - return optuna_study_name - - @property - def is_multi_objective(self) -> bool: - return len(self._metric_defs) > 1 - - @property - def study_string(self) -> str: - msg = f"{LOG_PREFIX}{'Loading' if self._wandb_run.resumed else 'Creating'}" - msg += f" optuna study: {self.study_name} " - msg += f"[storage:{self.study._storage.__class__.__name__}" - if not self.is_multi_objective: - msg += f", direction: {self._metric_defs[0].direction.name.capitalize()}" - else: - msg += ", directions: " - for metric in self._metric_defs: - msg += f"{metric.name}:{metric.direction.name.capitalize()}, " - msg = msg[:-2] - msg += f", pruner:{self.study.pruner.__class__.__name__}" - msg += f", sampler:{self.study.sampler.__class__.__name__}]" - return msg - - @property - def formatted_trials(self) -> str: - """Print out the last 10 trials from the current optuna study. - - Shows the run_id/run_state/total_metrics/last_metric. Returns a string with - whitespace. - - """ - if not self._study or len(self.study.trials) == 0: - return "" - - trial_strs = [] - for trial in self.study.trials: - if not trial.values: - continue - - run_id = trial.user_attrs["run_id"] - best: str = "" - if not self.is_multi_objective: - vals = list(trial.intermediate_values.values()) - if len(vals) > 0: - if self.study.direction == optuna.study.StudyDirection.MINIMIZE: - best = f"{round(min(vals), 5)}" - elif self.study.direction == optuna.study.StudyDirection.MAXIMIZE: - best = f"{round(max(vals), 5)}" - trial_strs += [ - f"\t[trial-{trial.number + 1}] run: {run_id}, state: " - f"{trial.state.name}, num-metrics: {len(vals)}, best: {best}" - ] - else: # multi-objective optimization, only 1 metric logged in study - if len(trial.values) != len(self._metric_defs): - wandb.termwarn(f"{LOG_PREFIX}Number of logged metrics ({trial.values})" - " does not match number of metrics defined " - f"({self._metric_defs}). Specify metrics for optimization" - " in the scheduler.settings.metrics portion of the sweep config") - continue - - for val, metric in zip(trial.values, self._metric_defs): - direction = metric.direction.name.capitalize() - best += f"{metric.name} ({direction}):" - best += f"{round(val, 5)}, " - - # trim trailing comma and space - best = best[:-2] - trial_strs += [ - f"\t[trial-{trial.number + 1}] run: {run_id}, state: " - f"{trial.state.name}, best: {best}" - ] - - return "\n".join(trial_strs[-10:]) # only print out last 10 - - def _get_metric_names_and_directions(self) -> List[Metric]: - """Helper to configure dict of at least one metric. - - Dict contains the metric names as keys, with the optimization direction (or - goal) as the value (type: optuna.study.StudyDirection) - - """ - # if single-objective, just top level metric is set - if self._sweep_config.get("metric"): - direction = (optuna.study.StudyDirection.MINIMIZE if self._sweep_config["metric"]["goal"] == "minimize" else - optuna.study.StudyDirection.MAXIMIZE) - metric = Metric(name=self._sweep_config["metric"]["name"], direction=direction) - return [metric] - - # multi-objective optimization - metric_defs = [] - for metric in self._optuna_config.get("metrics", []): - if not metric.get("name"): - raise SchedulerError("Optuna metric missing name") - if not metric.get("goal"): - raise SchedulerError("Optuna metric missing goal") - - direction = (optuna.study.StudyDirection.MINIMIZE - if metric["goal"] == "minimize" else optuna.study.StudyDirection.MAXIMIZE) - metric_defs += [Metric(name=metric["name"], direction=direction)] - - if len(metric_defs) == 0: - raise SchedulerError("Zero metrics found in the top level 'metric' section " - "and multi-objective metric section scheduler.settings.metrics") - - return metric_defs - - def _validate_optuna_study(self, study: optuna.Study) -> Optional[str]: - """Accepts an optuna study, runs validation. - - Returns an error string if validation fails - - """ - if len(study.trials) > 0: - wandb.termlog(f"{LOG_PREFIX}User provided study has prior trials") - - if study.user_attrs: - wandb.termwarn(f"{LOG_PREFIX}user_attrs are ignored from provided study:" - f" ({study.user_attrs})") - - if study._storage is not None: - wandb.termlog(f"{LOG_PREFIX}User provided study has storage:{study._storage}") - - return None - - def _load_optuna_classes( - self, - filepath: str, - ) -> Tuple[ - Optional[optuna.Study], - Optional[optuna.pruners.BasePruner], - Optional[optuna.samplers.BaseSampler], - ]: - """Loads custom optuna classes from user-supplied artifact. - - Returns: - study: a custom optuna study object created by the user - pruner: a custom optuna pruner supplied by user - sampler: a custom optuna sampler supplied by user - - """ - mod, err = _get_module("optuna", filepath) - if not mod: - raise SchedulerError(f"Failed to load optuna from path {filepath} with error: {err}") - - # Set custom optuna trial creation method - try: - self._objective_func = mod.objective - self._trial_func = self._make_trial_from_objective - except AttributeError: - pass - - try: - study = mod.study() - val_error: Optional[str] = self._validate_optuna_study(study) - wandb.termlog(f"{LOG_PREFIX}User provided study, ignoring pruner and sampler") - if val_error: - raise SchedulerError(err) - return study, None, None - except AttributeError: - pass - - pruner, sampler = None, None - try: - pruner = mod.pruner() - except AttributeError: - pass - - try: - sampler = mod.sampler() - except AttributeError: - pass - - return None, pruner, sampler - - def _get_and_download_artifact(self, component: OptunaComponents) -> Optional[str]: - """Finds and downloads an artifact, returns name of downloaded artifact.""" - try: - artifact_name = f"{self._entity}/{self._project}/{component.name}:latest" - component_artifact: Artifact = self._wandb_run.use_artifact(artifact_name) - path = component_artifact.download() - - storage_files = os.listdir(path) - if component.value in storage_files: - if path.startswith("./"): # TODO(gst): robust way of handling this - path = path[2:] - wandb.termlog(f"{LOG_PREFIX}Loaded storage from artifact: {artifact_name}") - return f"{path}/{component.value}" - except wandb.errors.CommError as e: - raise SchedulerError(str(e)) - except Exception as e: - raise SchedulerError(str(e)) - - return None - - def _load_file_from_artifact(self, artifact_name: str) -> str: - wandb.termlog(f"{LOG_PREFIX}User set optuna.artifact, attempting download.") - - # load user-set optuna class definition file - artifact = self._wandb_run.use_artifact(artifact_name, type="optuna") - if not artifact: - raise SchedulerError(f"Failed to load artifact: {artifact_name}") - - path = artifact.download() - optuna_filepath = self._optuna_config.get("optuna_source_filename", OptunaComponents.main_file.value) - return f"{path}/{optuna_filepath}" - - def _try_make_existing_objects( - self, optuna_source: Optional[str] - ) -> Tuple[ - Optional[optuna.Study], - Optional[optuna.pruners.BasePruner], - Optional[optuna.samplers.BaseSampler], - ]: - if not optuna_source: - return None, None, None - - optuna_file = None - if ":" in optuna_source: - optuna_file = self._load_file_from_artifact(optuna_source) - elif ".py" in optuna_source: # raw filepath - optuna_file = optuna_source - else: - raise SchedulerError(f"Provided optuna_source='{optuna_source}' not python file or artifact") - - return self._load_optuna_classes(optuna_file) - - def _load_optuna(self) -> None: - """If our run was resumed, attempt to restore optuna artifacts from run state. - - Create an optuna study with a sqlite backened for loose state management - - """ - study, pruner, sampler = self._try_make_existing_objects(self._optuna_config.get("optuna_source")) - - existing_storage = None - if self._wandb_run.resumed or self._kwargs.get("resumed"): - existing_storage = self._get_and_download_artifact(OptunaComponents.storage) - - if study: # user provided a valid study in downloaded artifact - if existing_storage: - wandb.termwarn(f"{LOG_PREFIX}Resuming state unsupported with user-provided study") - self._study = study - wandb.termlog(self.study_string) - return - # making a new study - - if pruner: - wandb.termlog(f"{LOG_PREFIX}Loaded pruner ({pruner.__class__.__name__})") - else: - pruner_args = self._optuna_config.get("pruner", {}) - if pruner_args: - pruner = load_optuna_pruner(pruner_args["type"], pruner_args.get("args")) - wandb.termlog(f"{LOG_PREFIX}Loaded pruner ({pruner.__class__.__name__})") - else: - wandb.termlog(f"{LOG_PREFIX}No pruner args, defaulting to MedianPruner") - - if sampler: - wandb.termlog(f"{LOG_PREFIX}Loaded sampler ({sampler.__class__.__name__})") - else: - sampler_args = self._optuna_config.get("sampler", {}) - if sampler_args: - sampler = load_optuna_sampler(sampler_args["type"], sampler_args.get("args")) - wandb.termlog(f"{LOG_PREFIX}Loaded sampler ({sampler.__class__.__name__})") - else: - wandb.termlog(f"{LOG_PREFIX}No sampler args, defaulting to TPESampler") - - self._storage_path = existing_storage or OptunaComponents.storage.value - directions = [metric.direction for metric in self._metric_defs] - if len(directions) == 1: - self._study = optuna.create_study( - study_name=self.study_name, - storage=f"sqlite:///{self._storage_path}", - pruner=pruner, - sampler=sampler, - load_if_exists=True, - direction=directions[0], - ) - else: # multi-objective optimization - self._study = optuna.create_study( - study_name=self.study_name, - storage=f"sqlite:///{self._storage_path}", - pruner=pruner, - sampler=sampler, - load_if_exists=True, - directions=directions, - ) - wandb.termlog(self.study_string) - - if existing_storage: - wandb.termlog(f"{LOG_PREFIX}Loaded prior runs ({len(self.study.trials)}) from " - f"storage ({existing_storage})\n {self.formatted_trials}") - - return - - def _load_state(self) -> None: - """Called when Scheduler class invokes start(). - - Load optuna study sqlite data from an artifact in controller run. - - """ - self._load_optuna() - - def _save_state(self) -> None: - """Called when Scheduler class invokes exit(). - - Save optuna study, or sqlite data to an artifact in the scheduler run - - """ - if not self._study or self._storage_path: # nothing to save - return None - - artifact_name = f"{OptunaComponents.storage.name}-{self._sweep_id}" - artifact = wandb.Artifact(artifact_name, type="optuna") - artifact.add_file(self._storage_path) - self._wandb_run.log_artifact(artifact) - - if self._study: - wandb.termlog(f"{LOG_PREFIX}Saved study with trials:\n{self.formatted_trials}") - return - - def _get_next_sweep_run(self, worker_id: int) -> Optional[SweepRun]: - """Called repeatedly in the polling loop, whenever a worker is available.""" - config, trial = self._trial_func() - run: dict = self._api.upsert_run( - project=self._project, - entity=self._entity, - sweep_name=self._sweep_id, - config=config, - )[0] - srun = SweepRun( - id=_encode(run["id"]), - args=config, - worker_id=worker_id, - ) - self._optuna_runs[srun.id] = OptunaRun( - num_metrics=0, - trial=trial, - sweep_run=srun, - ) - self._optuna_runs[srun.id].trial.set_user_attr("run_id", srun.id) - - wandb.termlog(f"{LOG_PREFIX}Starting new run ({srun.id}) with params: {trial.params}") - if self.formatted_trials: - wandb.termlog(f"{LOG_PREFIX}Study state:\n{self.formatted_trials}") - - return srun - - def _get_run_history(self, run_id: str) -> List[int]: - """Gets logged metric history for a given run_id.""" - if run_id not in self._runs: - logger.debug(f"Cant get history for run {run_id} not in self.runs") - return [] - - queued_run: Optional[QueuedRun] = self._runs[run_id].queued_run - if not queued_run or queued_run.state == "pending": - return [] - - try: - api_run: Run = self._public_api.run(f"{queued_run.entity}/{queued_run.project}/{run_id}") - except Exception as e: - logger.debug(f"Failed to poll run from public api: {str(e)}") - return [] - - names = [metric.name for metric in self._metric_defs] - history = api_run.scan_history(keys=names + ["_step"]) - metrics = [] - for log in history: - if self.is_multi_objective: - metrics += [tuple(log.get(key) for key in names)] - else: - metrics += [log.get(names[0])] - - if len(metrics) == 0 and api_run.lastHistoryStep > -1: - logger.debug("No metrics, but lastHistoryStep exists") - wandb.termwarn(f"{LOG_PREFIX}Detected logged metrics, but none matching " + - f"provided metric name(s): '{names}'") - - return metrics - - def _poll_run(self, orun: OptunaRun) -> bool: - """Polls metrics for a run, returns true if finished.""" - metrics = self._get_run_history(orun.sweep_run.id) - if not self.is_multi_objective: # can't report to trial when multi - for i, metric_val in enumerate(metrics[orun.num_metrics:]): - logger.debug(f"{orun.sweep_run.id} (step:{i+orun.num_metrics}) {metrics}") - prev = orun.trial._cached_frozen_trial.intermediate_values - if orun.num_metrics + i not in prev: - orun.trial.report(metric_val, orun.num_metrics + i) - - if orun.trial.should_prune(): - wandb.termlog(f"{LOG_PREFIX}Optuna pruning run: {orun.sweep_run.id}") - self.study.tell(orun.trial, state=optuna.trial.TrialState.PRUNED) - self._stop_run(orun.sweep_run.id) - return True - - orun.num_metrics = len(metrics) - - # run still running - if self._runs[orun.sweep_run.id].state.is_alive: - return False - - # run is complete - prev_metrics = orun.trial._cached_frozen_trial.intermediate_values - if (self._runs[orun.sweep_run.id].state == RunState.FINISHED and len(prev_metrics) == 0 - and not self.is_multi_objective): - # run finished correctly, but never logged a metric - wandb.termwarn(f"{LOG_PREFIX}Run ({orun.sweep_run.id}) never logged metric: " + - f"'{self._metric_defs[0].name}'. Check your sweep " + "config and training script.") - self._num_misconfigured_runs += 1 - self.study.tell(orun.trial, state=optuna.trial.TrialState.FAIL) - - if self._num_misconfigured_runs >= self.MAX_MISCONFIGURED_RUNS: - raise SchedulerError(f"Too many misconfigured runs ({self._num_misconfigured_runs})," - " stopping sweep early") - - # Delete run in Scheduler memory, freeing up worker - del self._runs[orun.sweep_run.id] - - return True - - if self.is_multi_objective: - last_value = tuple(metrics[-1]) - else: - last_value = prev_metrics[orun.num_metrics - 1] - - self._num_misconfigured_runs = 0 # only count consecutive - self.study.tell( - trial=orun.trial, - state=optuna.trial.TrialState.COMPLETE, - values=last_value, - ) - wandb.termlog(f"{LOG_PREFIX}Completing trial for run ({orun.sweep_run.id}) " - f"[last metric{'s' if self.is_multi_objective else ''}: {last_value}" - f", total: {orun.num_metrics}]") - - # Delete run in Scheduler memory, freeing up worker - del self._runs[orun.sweep_run.id] - - return True - - def _poll_running_runs(self) -> None: - """Iterates through runs, getting metrics, reporting to optuna. - - Returns list of runs optuna marked as PRUNED, to be deleted - - """ - to_kill = [] - for run_id, orun in self._optuna_runs.items(): - run_finished = self._poll_run(orun) - if run_finished: - wandb.termlog(f"{LOG_PREFIX}Run: {run_id} finished.") - logger.debug(f"Finished run, study state: {self.study.trials}") - to_kill += [run_id] - - for r in to_kill: - del self._optuna_runs[r] - - def _make_trial(self) -> Tuple[Dict[str, Any], optuna.Trial]: - """Use a wandb.config to create an optuna trial.""" - trial = self.study.ask() - config: Dict[str, Dict[str, Any]] = defaultdict(dict) - for param, extras in self._sweep_config["parameters"].items(): - if extras.get("values"): - config[param]["value"] = trial.suggest_categorical(param, extras["values"]) - elif extras.get("value"): - config[param]["value"] = trial.suggest_categorical(param, [extras["value"]]) - elif isinstance(extras.get("min"), float): - if not extras.get("max"): - raise SchedulerError("Error converting config. 'min' requires 'max'") - log = extras.get("log", False) - step = extras.get("step") - config[param]["value"] = trial.suggest_float(param, extras["min"], extras["max"], log=log, step=step) - elif isinstance(extras.get("min"), int): - if not extras.get("max"): - raise SchedulerError("Error converting config. 'min' requires 'max'") - log = extras.get("log", False) - step = extras.get("step") - if step: - config[param]["value"] = trial.suggest_int(param, extras["min"], extras["max"], log=log, step=step) - else: - config[param]["value"] = trial.suggest_int(param, extras["min"], extras["max"], log=log) - else: - logger.debug(f"Unknown parameter type: param={param}, val={extras}") - raise SchedulerError(f"Error converting config. Unknown parameter type: param={param}, val={extras}") - return config, trial - - def _make_trial_from_objective(self) -> Tuple[Dict[str, Any], optuna.Trial]: - """Turn a user-provided MOCK objective func into wandb params. - - This enables pythonic search spaces. - MOCK: does not actually train, only configures params. - - First creates a copy of our real study, quarantined from fake metrics - - Then calls optuna optimize on the copy study, passing in the - loaded-from-user objective function with an aggresive timeout: - ensures the model does not actually train. - - Retrieves created mock-trial from study copy and formats params for wandb - - Finally, ask our real study for a trial with fixed distributions - - Returns wandb formatted config and optuna trial from real study - - """ - wandb.termlog(f"{LOG_PREFIX}Making trial params from objective func," - " ignoring sweep config parameters") - study_copy = optuna.create_study() - study_copy.add_trials(self.study.trials) - - # Signal handler to raise error if objective func takes too long - def handler(signum: Any, frame: Any) -> None: - raise TimeoutError("Passed optuna objective function only creates parameter config." - f" Do not train; must execute in {self.OPT_TIMEOUT} seconds. See docs.") - - signal.signal(signal.SIGALRM, handler) - signal.alarm(self.OPT_TIMEOUT) - # run mock objective func to parse pythonic search space - study_copy.optimize(self._objective_func, n_trials=1) - signal.alarm(0) # disable alarm - - # now ask the study to create a new active trial from the distributions provided - new_trial = self.study.ask(fixed_distributions=study_copy.trials[-1].distributions) - # convert from optuna-type param config to wandb-type param config - config: Dict[str, Dict[str, Any]] = defaultdict(dict) - for param, value in new_trial.params.items(): - config[param]["value"] = value - - return config, new_trial - - def _poll(self) -> None: - self._poll_running_runs() - - def _exit(self) -> None: - pass - - def _cleanup_runs(self, runs_to_remove: List[str]) -> None: - logger.debug(f"[_cleanup_runs] not removing: {runs_to_remove}") - - -# External validation functions -def validate_optuna(public_api: PublicApi, settings_config: Dict[str, Any]) -> bool: - """Accepts a user provided optuna configuration. - - optuna library must be installed in scope, otherwise returns False. validates - sampler and pruner configuration args. validates artifact existence. - - """ - try: - import optuna # noqa: F401 - except ImportError: - wandb.termerror("Optuna must be installed to validate user-provided configuration." - f" Error: {traceback.format_exc()}") - return False - - if settings_config.get("pruner"): - if not validate_optuna_pruner(settings_config["pruner"]): - return False - - if settings_config.get("sampler"): - if not validate_optuna_sampler(settings_config["sampler"]): - return False - - if settings_config.get("artifact"): - try: - _ = public_api.artifact(settings_config["artifact"]) - except Exception as e: - if ":" not in settings_config["artifact"]: - wandb.termerror("No alias (ex. :latest) found in artifact name") - wandb.termerror(f"{e}") - return False - return True - - -def validate_optuna_pruner(args: Dict[str, Any]) -> bool: - if not args.get("type"): - wandb.termerror("key: 'type' is required") - return False - - try: - _ = load_optuna_pruner(args["type"], args.get("args")) - except Exception as e: - wandb.termerror(f"Error loading optuna pruner: {e}") - return False - return True - - -def validate_optuna_sampler(args: Dict[str, Any]) -> bool: - if not args.get("type"): - wandb.termerror("key: 'type' is required") - return False - - try: - _ = load_optuna_sampler(args["type"], args.get("args")) - except Exception as e: - wandb.termerror(f"Error loading optuna sampler: {e}") - return False - return True - - -def load_optuna_pruner( - type_: str, - args: Optional[Dict[str, Any]], -) -> optuna.pruners.BasePruner: - args = args or {} - if type_ == "NopPruner": - return optuna.pruners.NopPruner(**args) - elif type_ == "MedianPruner": - return optuna.pruners.MedianPruner(**args) - elif type_ == "HyperbandPruner": - return optuna.pruners.HyperbandPruner(**args) - elif type_ == "PatientPruner": - wandb.termerror("PatientPruner requires passing in a wrapped_pruner, which is not " - "supported through this simple config path. Please use the adv. " - "artifact upload path for this pruner, specified in the docs.") - return optuna.pruners.PatientPruner(**args) - elif type_ == "PercentilePruner": - return optuna.pruners.PercentilePruner(**args) - elif type_ == "SuccessiveHalvingPruner": - return optuna.pruners.SuccessiveHalvingPruner(**args) - elif type_ == "ThresholdPruner": - return optuna.pruners.ThresholdPruner(**args) - - raise Exception(f"Optuna pruner type: {type_} not supported") - - -def load_optuna_sampler( - type_: str, - args: Optional[Dict[str, Any]], -) -> optuna.samplers.BaseSampler: - args = args or {} - if type_ == "BruteForceSampler": - return optuna.samplers.BruteForceSampler(**args) - elif type_ == "CmaEsSampler": - return optuna.samplers.CmaEsSampler(**args) - elif type_ == "GridSampler": - return optuna.samplers.GridSampler(**args) - elif type_ == "IntersectionSearchSpace": - return optuna.samplers.IntersectionSearchSpace(**args) - elif type_ == "MOTPESampler": - return optuna.samplers.MOTPESampler(**args) - elif type_ == "NSGAIISampler": - return optuna.samplers.NSGAIISampler(**args) - elif type_ == "PartialFixedSampler": - wandb.termerror("PartialFixedSampler requires passing in a base_sampler, which is not " - "supported through this simple config path. Please use the adv. " - "artifact upload path for this sampler, specified in the docs.") - return optuna.samplers.PartialFixedSampler(**args) - elif type_ == "RandomSampler": - return optuna.samplers.RandomSampler(**args) - elif type_ == "TPESampler": - return optuna.samplers.TPESampler(**args) - elif type_ == "QMCSampler": - return optuna.samplers.QMCSampler(**args) - - raise Exception(f"Optuna sampler type: {type_} not supported") - - -def _encode(run_id: str) -> str: - """Helper to hash the run id for backend format.""" - return base64.b64decode(bytes(run_id.encode("utf-8"))).decode("utf-8").split(":")[2] - - -def _get_module(module_name: str, filepath: str) -> Tuple[Optional[ModuleType], Optional[str]]: - """Helper function that loads a python module from provided filepath.""" - try: - loader = SourceFileLoader(module_name, filepath) - mod = ModuleType(loader.name) - loader.exec_module(mod) - except Exception as e: - return None, str(e) - - return mod, None - - -# if __name__ == "__main__": -setup_scheduler(OptunaScheduler) From a33662ef30739aaf1f41fbb822f7adaf35843d5c Mon Sep 17 00:00:00 2001 From: xzy Date: Thu, 18 Jan 2024 20:02:34 +0800 Subject: [PATCH 028/168] recover file --- MANIFEST.in | 1 + 1 file changed, 1 insertion(+) create mode 100644 MANIFEST.in diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 000000000..1d3aa0463 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +dance/metadata/* From 6d830950a96e34c49e290043feb21a1f99d3c79d Mon Sep 17 00:00:00 2001 From: xzy Date: Thu, 18 Jan 2024 20:03:51 +0800 Subject: [PATCH 029/168] delete sh --- automl_fun.sh | 6 ------ 1 file changed, 6 deletions(-) delete mode 100755 automl_fun.sh diff --git a/automl_fun.sh b/automl_fun.sh deleted file mode 100755 index 756ce530a..000000000 --- a/automl_fun.sh +++ /dev/null @@ -1,6 +0,0 @@ -cd ~/dance -python test_automl/test_automl_fun_job.py -python test_automl/test_automl_fun_2.py -cd ~ -python dance/optuna_scheduler.py --entity xzy11632 --project pytorch-cell_type_annotation_ACTINN_function_new -wandb launch-sweep dance/test_automl/sweep-config.yaml -e xzy11632 -p pytorch-cell_type_annotation_ACTINN_function_new -q tutorial-run-queue From 2345c3a0d0997cdea56e7994aa5c347167c714ce Mon Sep 17 00:00:00 2001 From: xzy Date: Thu, 18 Jan 2024 20:33:36 +0800 Subject: [PATCH 030/168] update test --- tests/transforms/test_SC3Feature.py | 2 +- tests/transforms/test_celltypeNums.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/transforms/test_SC3Feature.py b/tests/transforms/test_SC3Feature.py index c64bf209f..5e0be6ca8 100644 --- a/tests/transforms/test_SC3Feature.py +++ b/tests/transforms/test_SC3Feature.py @@ -10,7 +10,7 @@ @pytest.fixture def toy_data(): - x = np.random.default_rng(SEED).random((5, 3)) + x = np.random.default_rng(SEED).random((50, 30)) adata = AnnData(X=x, dtype=np.float32) data = Data(adata.copy()) return adata, data diff --git a/tests/transforms/test_celltypeNums.py b/tests/transforms/test_celltypeNums.py index 18c7c5817..94c51c899 100644 --- a/tests/transforms/test_celltypeNums.py +++ b/tests/transforms/test_celltypeNums.py @@ -18,4 +18,4 @@ def test_cell_type_nums(): data = Data(adata.copy()) data = CellTypeNums()(data) cell_type_nums = data.get_feature(return_type="numpy", channel="CellTypeNums", channel_type="uns") - return cell_type_nums.shape[0] == len(np.unique(cell_types)) + assert cell_type_nums.shape[0] == len(np.unique(cell_types)) From 8606b4ada0d684c6e74d5707170e50ae94b450cf Mon Sep 17 00:00:00 2001 From: xingzhongyu <57212168+xingzhongyu@users.noreply.github.com> Date: Thu, 18 Jan 2024 22:19:19 +0800 Subject: [PATCH 031/168] Delete web-variables.env --- web-variables.env | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 web-variables.env diff --git a/web-variables.env b/web-variables.env deleted file mode 100644 index 61b1e0682..000000000 --- a/web-variables.env +++ /dev/null @@ -1,2 +0,0 @@ -http_proxy=http://121.250.209.147:7890 -https_proxy=http://121.250.209.147:7890 From 2c703cea86d31efd1a3677c9ff13f576cd02a396 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 09:09:04 +0800 Subject: [PATCH 032/168] global pipline2fun_dict --- test_automl/wandb_step2.py | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/test_automl/wandb_step2.py b/test_automl/wandb_step2.py index 29a879c89..eea5742a1 100644 --- a/test_automl/wandb_step2.py +++ b/test_automl/wandb_step2.py @@ -1,8 +1,8 @@ from itertools import combinations import scanpy as sc -import wandb +import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform @@ -22,23 +22,22 @@ "cell_weighted_pca": WeightedFeaturePCA(split_name="train"), "cell_pca": CellPCA() } +pipline2fun_dict = { + "normalize": { + "values": ["normalize_total", "log1p", "scaleFeature", "scTransform"] + }, + "gene_filter": { + "values": + ["filter_gene_by_count", "filter_gene_by_percentile", "highly_variable_genes", "Filter_gene_by_regress_score"] + }, + "gene_dim_reduction": { + "values": ["cell_svd", "cell_weighted_pca", "cell_pca"] + } +} def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): - pipline2fun_dict = { - "normalize": { - "values": ["normalize_total", "log1p", "scaleFeature", "scTransform"] - }, - "gene_filter": { - "values": [ - "filter_gene_by_count", "filter_gene_by_percentile", "highly_variable_genes", - "Filter_gene_by_regress_score" - ] - }, - "gene_dim_reduction": { - "values": ["cell_svd", "cell_weighted_pca", "cell_pca"] - } - } + global pipline2fun_dict pipline2fun_dict = {key: pipline2fun_dict[key] for key in selected_keys} count = 1 for pipline_key, pipline_values in pipline2fun_dict.items(): From 9e1c515b0301e9871d1c663a380ad62b6b088118 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 01:09:33 +0000 Subject: [PATCH 033/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/wandb_step2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/wandb_step2.py b/test_automl/wandb_step2.py index eea5742a1..98ffdc04a 100644 --- a/test_automl/wandb_step2.py +++ b/test_automl/wandb_step2.py @@ -1,8 +1,8 @@ from itertools import combinations import scanpy as sc - import wandb + from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform From be1077956093158ffffd22fd7512a87a45612da4 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 09:11:35 +0800 Subject: [PATCH 034/168] add config.py --- test_automl/config.py | 33 +++++++++++++++++++ test_automl/optuna_wandb_nocontainer_step3.py | 4 +-- test_automl/wandb_step2.py | 33 ------------------- 3 files changed, 35 insertions(+), 35 deletions(-) create mode 100644 test_automl/config.py diff --git a/test_automl/config.py b/test_automl/config.py new file mode 100644 index 000000000..3eaf97854 --- /dev/null +++ b/test_automl/config.py @@ -0,0 +1,33 @@ +import scanpy as sc + +from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA +from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression +from dance.transforms.interface import AnnDataTransform +from dance.transforms.normalize import ScaleFeature, ScTransformR + +fun2code_dict = { + "normalize_total": AnnDataTransform(sc.pp.normalize_total, target_sum=1e4), + "log1p": AnnDataTransform(sc.pp.log1p, base=2), + "scaleFeature": ScaleFeature(split_names="ALL", mode="standardize"), + "scTransform": ScTransformR(mirror_index=1), + "filter_gene_by_count": AnnDataTransform(sc.pp.filter_genes, min_cells=1), + "filter_gene_by_percentile": FilterGenesPercentile(min_val=1, max_val=99, mode="sum"), + "highly_variable_genes": AnnDataTransform(sc.pp.highly_variable_genes), + "regress_out": AnnDataTransform(sc.pp.regress_out), + "Filter_gene_by_regress_score": FilterGenesRegression("enclasc"), + "cell_svd": CellSVD(), + "cell_weighted_pca": WeightedFeaturePCA(split_name="train"), + "cell_pca": CellPCA() +} +pipline2fun_dict = { + "normalize": { + "values": ["normalize_total", "log1p", "scaleFeature", "scTransform"] + }, + "gene_filter": { + "values": + ["filter_gene_by_count", "filter_gene_by_percentile", "highly_variable_genes", "Filter_gene_by_regress_score"] + }, + "gene_dim_reduction": { + "values": ["cell_svd", "cell_weighted_pca", "cell_pca"] + } +} diff --git a/test_automl/optuna_wandb_nocontainer_step3.py b/test_automl/optuna_wandb_nocontainer_step3.py index a827e7b98..aff61fa5c 100644 --- a/test_automl/optuna_wandb_nocontainer_step3.py +++ b/test_automl/optuna_wandb_nocontainer_step3.py @@ -4,9 +4,9 @@ import optuna import scanpy as sc import torch -import wandb from optuna.integration.wandb import WeightsAndBiasesCallback +import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA @@ -15,7 +15,7 @@ from dance.transforms.misc import Compose, SetConfig from dance.transforms.normalize import ScaleFeature, ScTransformR from dance.utils import set_seed -from test_automl.wandb_step2 import fun2code_dict +from test_automl.config import fun2code_dict fun_list = ["log1p", "filter_gene_by_count"] wandb_kwargs = {"project": "my-project"} diff --git a/test_automl/wandb_step2.py b/test_automl/wandb_step2.py index 98ffdc04a..9f0fcae5a 100644 --- a/test_automl/wandb_step2.py +++ b/test_automl/wandb_step2.py @@ -1,40 +1,7 @@ from itertools import combinations -import scanpy as sc import wandb -from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA -from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression -from dance.transforms.interface import AnnDataTransform -from dance.transforms.normalize import ScaleFeature, ScTransformR - -fun2code_dict = { - "normalize_total": AnnDataTransform(sc.pp.normalize_total, target_sum=1e4), - "log1p": AnnDataTransform(sc.pp.log1p, base=2), - "scaleFeature": ScaleFeature(split_names="ALL", mode="standardize"), - "scTransform": ScTransformR(mirror_index=1), - "filter_gene_by_count": AnnDataTransform(sc.pp.filter_genes, min_cells=1), - "filter_gene_by_percentile": FilterGenesPercentile(min_val=1, max_val=99, mode="sum"), - "highly_variable_genes": AnnDataTransform(sc.pp.highly_variable_genes), - "regress_out": AnnDataTransform(sc.pp.regress_out), - "Filter_gene_by_regress_score": FilterGenesRegression("enclasc"), - "cell_svd": CellSVD(), - "cell_weighted_pca": WeightedFeaturePCA(split_name="train"), - "cell_pca": CellPCA() -} -pipline2fun_dict = { - "normalize": { - "values": ["normalize_total", "log1p", "scaleFeature", "scTransform"] - }, - "gene_filter": { - "values": - ["filter_gene_by_count", "filter_gene_by_percentile", "highly_variable_genes", "Filter_gene_by_regress_score"] - }, - "gene_dim_reduction": { - "values": ["cell_svd", "cell_weighted_pca", "cell_pca"] - } -} - def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): global pipline2fun_dict From f312d0113aae89bfcdadc2429f1d2cce8590bb6a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 01:12:00 +0000 Subject: [PATCH 035/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/optuna_wandb_nocontainer_step3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/optuna_wandb_nocontainer_step3.py b/test_automl/optuna_wandb_nocontainer_step3.py index aff61fa5c..61ce8f8e2 100644 --- a/test_automl/optuna_wandb_nocontainer_step3.py +++ b/test_automl/optuna_wandb_nocontainer_step3.py @@ -4,9 +4,9 @@ import optuna import scanpy as sc import torch +import wandb from optuna.integration.wandb import WeightsAndBiasesCallback -import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA From 0ea8574a4b23b0afe3bcb46ca9aacee1768b993b Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 09:15:48 +0800 Subject: [PATCH 036/168] add step3_fun.py --- test_automl/optuna_wandb_nocontainer_step3.py | 95 +------------------ test_automl/step3_fun.py | 94 ++++++++++++++++++ 2 files changed, 95 insertions(+), 94 deletions(-) create mode 100644 test_automl/step3_fun.py diff --git a/test_automl/optuna_wandb_nocontainer_step3.py b/test_automl/optuna_wandb_nocontainer_step3.py index 61ce8f8e2..b804ec225 100644 --- a/test_automl/optuna_wandb_nocontainer_step3.py +++ b/test_automl/optuna_wandb_nocontainer_step3.py @@ -1,19 +1,12 @@ -import sys - import numpy as np import optuna -import scanpy as sc import torch -import wandb from optuna.integration.wandb import WeightsAndBiasesCallback +import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN -from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA -from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression -from dance.transforms.interface import AnnDataTransform from dance.transforms.misc import Compose, SetConfig -from dance.transforms.normalize import ScaleFeature, ScTransformR from dance.utils import set_seed from test_automl.config import fun2code_dict @@ -21,92 +14,6 @@ wandb_kwargs = {"project": "my-project"} wandbc = WeightsAndBiasesCallback(wandb_kwargs=wandb_kwargs, as_multirun=True) - -def cell_pca(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" - return CellPCA(n_components=trial.suggest_int(method_name + "n_components", 200, 5000)) - - -def cell_weighted_pca(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" - return WeightedFeaturePCA(n_components=trial.suggest_int(method_name + "n_components", 200, 5000)) - - -def cell_svd(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" - return CellSVD(n_components=trial.suggest_int(method_name + "n_components", 200, 5000)) - - -def Filter_gene_by_regress_score(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" - return FilterGenesRegression( - method=trial.suggest_categorical(method_name + "method", ["enclasc", "seurat3", "scmap"]), - num_genes=trial.suggest_int(method_name + "num_genes", 5000, 6000)) - - -def highly_variable_genes(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" - return AnnDataTransform(sc.pp.highly_variable_genes, min_mean=trial.suggest_float( - method_name + "min_mean", 0.0025, - 0.03), max_mean=trial.suggest_float(method_name + "min_mean", 1.5, - 4.5), min_disp=trial.suggest_float(method_name + "min_disp", 0.25, 0.75), - span=trial.suggest_float(method_name + "span", 0.2, - 1.0), n_bins=trial.suggest_int(method_name + "n_bins", 10, 30), - flavor=trial.suggest_categorical(method_name + "flavor", ['seurat', 'cell_ranger'])) - - -def filter_gene_by_percentile(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" - return FilterGenesPercentile(min_val=trial.suggest_int(method_name + "min_val", 1, 10), - max_val=trial.suggest_int(method_name + "max_val", 90, 99), - mode=trial.suggest_categorical(method_name + "mode", ["sum", "var", "cv", "rv"])) - - -def filter_gene_by_count(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" - method = trial.suggest_categorical(method_name + "method", ['min_counts', 'min_cells', 'max_counts', 'max_cells']) - if method == "min_counts": - num = trial.suggest_int(method_name + "num", 2, 10) - if method == "min_cells": - num = trial.suggest_int(method_name + "num", 2, 10) - if method == "max_counts": - num = trial.suggest_int(method_name + "num", 500, 1000) - if method == "max_cells": - num = trial.suggest_int(method_name + "num", 500, 1000) - return AnnDataTransform(sc.pp.filter_genes, **{method: num}) - - -def log1p(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" - return AnnDataTransform(sc.pp.log1p, base=trial.suggest_int(method_name + "base", 2, 10)) - - -def scTransform(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" - return ScTransformR(min_cells=trial.suggest_int(method_name + "min_cells", 1, 10)) - - -def scaleFeature(trial: optuna.Trial): #eps未优化 - method_name = str(sys._getframe().f_code.co_name) + "_" - return ScaleFeature(mode=trial.suggest_categorical(method_name + - "mode", ["normalize", "standardize", "minmax", "l2"])) - - -def normalize_total(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" - exclude_highly_expressed = trial.suggest_categorical(method_name + "exclude_highly_expressed", [False, True]) - - if exclude_highly_expressed: - max_fraction = trial.suggest_float(method_name + "max_fraction", 0.04, 0.1) - return AnnDataTransform(sc.pp.normalize_total, - target_sum=trial.suggest_categorical(method_name + "target_sum", [1e4, 1e5, 1e6]), - exclude_highly_expressed=exclude_highly_expressed, max_fraction=max_fraction) - else: - return AnnDataTransform(sc.pp.normalize_total, - target_sum=trial.suggest_categorical(method_name + "target_sum", [1e4, 1e5, 1e6]), - exclude_highly_expressed=exclude_highly_expressed, max_fraction=max_fraction) - - device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu") diff --git a/test_automl/step3_fun.py b/test_automl/step3_fun.py new file mode 100644 index 000000000..a8cc0e2f7 --- /dev/null +++ b/test_automl/step3_fun.py @@ -0,0 +1,94 @@ +import sys + +import optuna +import scanpy as sc + +from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA +from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression +from dance.transforms.interface import AnnDataTransform +from dance.transforms.normalize import ScaleFeature, ScTransformR + + +def cell_pca(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + return CellPCA(n_components=trial.suggest_int(method_name + "n_components", 200, 5000)) + + +def cell_weighted_pca(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + return WeightedFeaturePCA(n_components=trial.suggest_int(method_name + "n_components", 200, 5000)) + + +def cell_svd(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + return CellSVD(n_components=trial.suggest_int(method_name + "n_components", 200, 5000)) + + +def Filter_gene_by_regress_score(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + return FilterGenesRegression( + method=trial.suggest_categorical(method_name + "method", ["enclasc", "seurat3", "scmap"]), + num_genes=trial.suggest_int(method_name + "num_genes", 5000, 6000)) + + +def highly_variable_genes(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + return AnnDataTransform(sc.pp.highly_variable_genes, min_mean=trial.suggest_float( + method_name + "min_mean", 0.0025, + 0.03), max_mean=trial.suggest_float(method_name + "min_mean", 1.5, + 4.5), min_disp=trial.suggest_float(method_name + "min_disp", 0.25, 0.75), + span=trial.suggest_float(method_name + "span", 0.2, + 1.0), n_bins=trial.suggest_int(method_name + "n_bins", 10, 30), + flavor=trial.suggest_categorical(method_name + "flavor", ['seurat', 'cell_ranger'])) + + +def filter_gene_by_percentile(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + return FilterGenesPercentile(min_val=trial.suggest_int(method_name + "min_val", 1, 10), + max_val=trial.suggest_int(method_name + "max_val", 90, 99), + mode=trial.suggest_categorical(method_name + "mode", ["sum", "var", "cv", "rv"])) + + +def filter_gene_by_count(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + method = trial.suggest_categorical(method_name + "method", ['min_counts', 'min_cells', 'max_counts', 'max_cells']) + if method == "min_counts": + num = trial.suggest_int(method_name + "num", 2, 10) + if method == "min_cells": + num = trial.suggest_int(method_name + "num", 2, 10) + if method == "max_counts": + num = trial.suggest_int(method_name + "num", 500, 1000) + if method == "max_cells": + num = trial.suggest_int(method_name + "num", 500, 1000) + return AnnDataTransform(sc.pp.filter_genes, **{method: num}) + + +def log1p(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + return AnnDataTransform(sc.pp.log1p, base=trial.suggest_int(method_name + "base", 2, 10)) + + +def scTransform(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + return ScTransformR(min_cells=trial.suggest_int(method_name + "min_cells", 1, 10)) + + +def scaleFeature(trial: optuna.Trial): #eps未优化 + method_name = str(sys._getframe().f_code.co_name) + "_" + return ScaleFeature(mode=trial.suggest_categorical(method_name + + "mode", ["normalize", "standardize", "minmax", "l2"])) + + +def normalize_total(trial: optuna.Trial): + method_name = str(sys._getframe().f_code.co_name) + "_" + exclude_highly_expressed = trial.suggest_categorical(method_name + "exclude_highly_expressed", [False, True]) + + if exclude_highly_expressed: + max_fraction = trial.suggest_float(method_name + "max_fraction", 0.04, 0.1) + return AnnDataTransform(sc.pp.normalize_total, + target_sum=trial.suggest_categorical(method_name + "target_sum", [1e4, 1e5, 1e6]), + exclude_highly_expressed=exclude_highly_expressed, max_fraction=max_fraction) + else: + return AnnDataTransform(sc.pp.normalize_total, + target_sum=trial.suggest_categorical(method_name + "target_sum", [1e4, 1e5, 1e6]), + exclude_highly_expressed=exclude_highly_expressed, max_fraction=max_fraction) From f324e6387c3865f1be82bfac98a19a88a7a8535a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 01:16:17 +0000 Subject: [PATCH 037/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/optuna_wandb_nocontainer_step3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/optuna_wandb_nocontainer_step3.py b/test_automl/optuna_wandb_nocontainer_step3.py index b804ec225..572350c75 100644 --- a/test_automl/optuna_wandb_nocontainer_step3.py +++ b/test_automl/optuna_wandb_nocontainer_step3.py @@ -1,9 +1,9 @@ import numpy as np import optuna import torch +import wandb from optuna.integration.wandb import WeightsAndBiasesCallback -import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.misc import Compose, SetConfig From 1d91bcb7ab05ac6a30f88def54a9150d3ac357a5 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 09:17:36 +0800 Subject: [PATCH 038/168] update wandb _step2 --- test_automl/wandb_step2.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test_automl/wandb_step2.py b/test_automl/wandb_step2.py index 9f0fcae5a..51d2404d4 100644 --- a/test_automl/wandb_step2.py +++ b/test_automl/wandb_step2.py @@ -1,10 +1,11 @@ from itertools import combinations +from config import fun2code_dict, pipline2fun_dict + import wandb def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): - global pipline2fun_dict pipline2fun_dict = {key: pipline2fun_dict[key] for key in selected_keys} count = 1 for pipline_key, pipline_values in pipline2fun_dict.items(): From 00c1da0cae046d1b3502ce6683a94340c0458214 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 01:18:05 +0000 Subject: [PATCH 039/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/wandb_step2.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test_automl/wandb_step2.py b/test_automl/wandb_step2.py index 51d2404d4..afc4acb5e 100644 --- a/test_automl/wandb_step2.py +++ b/test_automl/wandb_step2.py @@ -1,8 +1,7 @@ from itertools import combinations -from config import fun2code_dict, pipline2fun_dict - import wandb +from config import fun2code_dict, pipline2fun_dict def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): From 583838d4de829e772f5c8b0a5f7adae4e24c7dda Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 09:18:55 +0800 Subject: [PATCH 040/168] update wandb_step2.py --- test_automl/wandb_step2.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test_automl/wandb_step2.py b/test_automl/wandb_step2.py index afc4acb5e..51d2404d4 100644 --- a/test_automl/wandb_step2.py +++ b/test_automl/wandb_step2.py @@ -1,8 +1,9 @@ from itertools import combinations -import wandb from config import fun2code_dict, pipline2fun_dict +import wandb + def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): pipline2fun_dict = {key: pipline2fun_dict[key] for key in selected_keys} From 87bbe1dd6ee865cc488b4d8012b0f1d8ad5c4714 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 01:19:18 +0000 Subject: [PATCH 041/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/wandb_step2.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test_automl/wandb_step2.py b/test_automl/wandb_step2.py index 51d2404d4..afc4acb5e 100644 --- a/test_automl/wandb_step2.py +++ b/test_automl/wandb_step2.py @@ -1,8 +1,7 @@ from itertools import combinations -from config import fun2code_dict, pipline2fun_dict - import wandb +from config import fun2code_dict, pipline2fun_dict def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): From 57e6cde37b8f7b8e70df2e855a1ed941cecf107a Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 11:01:09 +0800 Subject: [PATCH 042/168] add decorator --- .gitignore | 1 + test_automl/optuna_wandb_nocontainer_step3.py | 15 +++-- test_automl/step3_fun.py | 67 +++++++++++++------ test_automl/test.py | 17 +++++ 4 files changed, 72 insertions(+), 28 deletions(-) create mode 100644 test_automl/test.py diff --git a/.gitignore b/.gitignore index 0ee87557d..74c546779 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ wandb test_automl/data +test_automl/test.ipynb diff --git a/test_automl/optuna_wandb_nocontainer_step3.py b/test_automl/optuna_wandb_nocontainer_step3.py index 572350c75..b8e5dc612 100644 --- a/test_automl/optuna_wandb_nocontainer_step3.py +++ b/test_automl/optuna_wandb_nocontainer_step3.py @@ -1,17 +1,19 @@ import numpy as np import optuna +import step3_fun import torch -import wandb +from config import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback +import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.misc import Compose, SetConfig from dance.utils import set_seed -from test_automl.config import fun2code_dict fun_list = ["log1p", "filter_gene_by_count"] -wandb_kwargs = {"project": "my-project"} + +wandb_kwargs = {"project": "step3-project"} wandbc = WeightsAndBiasesCallback(wandb_kwargs=wandb_kwargs, as_multirun=True) device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu") @@ -22,13 +24,13 @@ def objective(trial): transforms = [] for f_str in fun_list: - fun_i = eval(f_str) + fun_i = getattr(step3_fun, f_str) transforms.append(fun_i(trial)) parameters_dict = { 'batch_size': 128, "hidden_dims": [2000], 'lambd': 0.005, - 'num_epochs': 50, + 'num_epochs': 2, 'seed': 0, 'num_runs': 1, 'learning_rate': 0.0001 @@ -67,5 +69,6 @@ def objective(trial): return np.mean(scores) +print(dir(step3_fun)) study = optuna.create_study() -study.optimize(objective, n_trials=10, callbacks=[wandbc]) +study.optimize(objective, n_trials=2, callbacks=[wandbc]) diff --git a/test_automl/step3_fun.py b/test_automl/step3_fun.py index a8cc0e2f7..c1c2fbdf6 100644 --- a/test_automl/step3_fun.py +++ b/test_automl/step3_fun.py @@ -1,3 +1,4 @@ +import inspect import sys import optuna @@ -9,29 +10,40 @@ from dance.transforms.normalize import ScaleFeature, ScTransformR -def cell_pca(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" +def set_method_name(func): + + def wrapper(*args, **kwargs): + method_name = func.__name__ + "_" + result = func(method_name, *args, **kwargs) + return result + + return wrapper + + +@set_method_name +def cell_pca(method_name: str, trial: optuna.Trial): return CellPCA(n_components=trial.suggest_int(method_name + "n_components", 200, 5000)) -def cell_weighted_pca(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" +@set_method_name +def cell_weighted_pca(method_name: str, trial: optuna.Trial): return WeightedFeaturePCA(n_components=trial.suggest_int(method_name + "n_components", 200, 5000)) -def cell_svd(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" +@set_method_name +def cell_svd(method_name: str, trial: optuna.Trial): return CellSVD(n_components=trial.suggest_int(method_name + "n_components", 200, 5000)) -def Filter_gene_by_regress_score(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" +@set_method_name +def Filter_gene_by_regress_score(method_name: str, trial: optuna.Trial): return FilterGenesRegression( method=trial.suggest_categorical(method_name + "method", ["enclasc", "seurat3", "scmap"]), num_genes=trial.suggest_int(method_name + "num_genes", 5000, 6000)) -def highly_variable_genes(trial: optuna.Trial): +@set_method_name +def highly_variable_genes(method_name: str, trial: optuna.Trial): method_name = str(sys._getframe().f_code.co_name) + "_" return AnnDataTransform(sc.pp.highly_variable_genes, min_mean=trial.suggest_float( method_name + "min_mean", 0.0025, @@ -42,15 +54,15 @@ def highly_variable_genes(trial: optuna.Trial): flavor=trial.suggest_categorical(method_name + "flavor", ['seurat', 'cell_ranger'])) -def filter_gene_by_percentile(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" +@set_method_name +def filter_gene_by_percentile(method_name: str, trial: optuna.Trial): return FilterGenesPercentile(min_val=trial.suggest_int(method_name + "min_val", 1, 10), max_val=trial.suggest_int(method_name + "max_val", 90, 99), mode=trial.suggest_categorical(method_name + "mode", ["sum", "var", "cv", "rv"])) -def filter_gene_by_count(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" +@set_method_name +def filter_gene_by_count(method_name: str, trial: optuna.Trial): method = trial.suggest_categorical(method_name + "method", ['min_counts', 'min_cells', 'max_counts', 'max_cells']) if method == "min_counts": num = trial.suggest_int(method_name + "num", 2, 10) @@ -63,26 +75,25 @@ def filter_gene_by_count(trial: optuna.Trial): return AnnDataTransform(sc.pp.filter_genes, **{method: num}) -def log1p(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" +@set_method_name +def log1p(method_name: str, trial: optuna.Trial): return AnnDataTransform(sc.pp.log1p, base=trial.suggest_int(method_name + "base", 2, 10)) -def scTransform(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" +@set_method_name +def scTransform(method_name: str, trial: optuna.Trial): return ScTransformR(min_cells=trial.suggest_int(method_name + "min_cells", 1, 10)) -def scaleFeature(trial: optuna.Trial): #eps未优化 - method_name = str(sys._getframe().f_code.co_name) + "_" +@set_method_name +def scaleFeature(method_name: str, trial: optuna.Trial): #eps未优化 return ScaleFeature(mode=trial.suggest_categorical(method_name + "mode", ["normalize", "standardize", "minmax", "l2"])) -def normalize_total(trial: optuna.Trial): - method_name = str(sys._getframe().f_code.co_name) + "_" +@set_method_name +def normalize_total(method_name: str, trial: optuna.Trial): exclude_highly_expressed = trial.suggest_categorical(method_name + "exclude_highly_expressed", [False, True]) - if exclude_highly_expressed: max_fraction = trial.suggest_float(method_name + "max_fraction", 0.04, 0.1) return AnnDataTransform(sc.pp.normalize_total, @@ -92,3 +103,15 @@ def normalize_total(trial: optuna.Trial): return AnnDataTransform(sc.pp.normalize_total, target_sum=trial.suggest_categorical(method_name + "target_sum", [1e4, 1e5, 1e6]), exclude_highly_expressed=exclude_highly_expressed, max_fraction=max_fraction) + + +# # 获取当前文件中的所有函数 +# functions = [(name,obj) for name, obj in inspect.getmembers( +# sys.modules[__name__]) if inspect.isfunction(obj)] + +# print(functions) +# # 遍历并装饰每个函数 +# for name, function in functions: +# if name != "set_method_name": # 排除装饰器函数本身 +# print(function) +# setattr(__name__, name, set_method_name(function)) diff --git a/test_automl/test.py b/test_automl/test.py new file mode 100644 index 000000000..4a483bcde --- /dev/null +++ b/test_automl/test.py @@ -0,0 +1,17 @@ +import inspect +import sys + + +def function_one(): + pass + + +def function_two(): + pass + + +# 获取当前文件中的所有函数 +current_functions = [(name, obj) for name, obj in inspect.getmembers(sys.modules[__name__]) if inspect.isfunction(obj)] + +# 打印所有函数名 +print("当前文件中的所有函数:", current_functions) From 060e02216695966d27ef51f1de469dd2dcdad20c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 03:01:38 +0000 Subject: [PATCH 043/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/optuna_wandb_nocontainer_step3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/optuna_wandb_nocontainer_step3.py b/test_automl/optuna_wandb_nocontainer_step3.py index b8e5dc612..2ccee46f2 100644 --- a/test_automl/optuna_wandb_nocontainer_step3.py +++ b/test_automl/optuna_wandb_nocontainer_step3.py @@ -2,10 +2,10 @@ import optuna import step3_fun import torch +import wandb from config import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback -import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.misc import Compose, SetConfig From 87b9acd0b8cab4c18714383a6a91efa08ea15a98 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 11:03:31 +0800 Subject: [PATCH 044/168] ignore test.py --- .gitignore | 2 +- test_automl/test.py | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 74c546779..3471a1ae3 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,4 @@ wandb test_automl/data -test_automl/test.ipynb +test_automl/test.py diff --git a/test_automl/test.py b/test_automl/test.py index 4a483bcde..91ebd027b 100644 --- a/test_automl/test.py +++ b/test_automl/test.py @@ -15,3 +15,25 @@ def function_two(): # 打印所有函数名 print("当前文件中的所有函数:", current_functions) + +import sys + + +def set_method_name(func): + + def wrapper(*args, **kwargs): + method_name = func.__name__ + "_" + print(method_name) + result = func(*args, **kwargs) + return result + + return wrapper + + +@set_method_name +def function1(): + method_name = str(sys._getframe().f_code.co_name) + "_" + print("函数 1 被调用") + + +function1() From d3a5e1546761acb7735ace149417886cffa092cd Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 11:06:28 +0800 Subject: [PATCH 045/168] rename file --- test_automl/optuna_wandb_nocontainer_step3.py | 3 +-- test_automl/{config.py => pipline_config.py} | 0 test_automl/{step3_fun.py => register_function.py} | 0 3 files changed, 1 insertion(+), 2 deletions(-) rename test_automl/{config.py => pipline_config.py} (100%) rename test_automl/{step3_fun.py => register_function.py} (100%) diff --git a/test_automl/optuna_wandb_nocontainer_step3.py b/test_automl/optuna_wandb_nocontainer_step3.py index 2ccee46f2..2e0ef9f1c 100644 --- a/test_automl/optuna_wandb_nocontainer_step3.py +++ b/test_automl/optuna_wandb_nocontainer_step3.py @@ -2,10 +2,10 @@ import optuna import step3_fun import torch -import wandb from config import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback +import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.misc import Compose, SetConfig @@ -69,6 +69,5 @@ def objective(trial): return np.mean(scores) -print(dir(step3_fun)) study = optuna.create_study() study.optimize(objective, n_trials=2, callbacks=[wandbc]) diff --git a/test_automl/config.py b/test_automl/pipline_config.py similarity index 100% rename from test_automl/config.py rename to test_automl/pipline_config.py diff --git a/test_automl/step3_fun.py b/test_automl/register_function.py similarity index 100% rename from test_automl/step3_fun.py rename to test_automl/register_function.py From 4ea38e3f99db5e59e9714d33f11835d0e0a71344 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 03:06:54 +0000 Subject: [PATCH 046/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/optuna_wandb_nocontainer_step3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/optuna_wandb_nocontainer_step3.py b/test_automl/optuna_wandb_nocontainer_step3.py index 2e0ef9f1c..a30c35114 100644 --- a/test_automl/optuna_wandb_nocontainer_step3.py +++ b/test_automl/optuna_wandb_nocontainer_step3.py @@ -2,10 +2,10 @@ import optuna import step3_fun import torch +import wandb from config import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback -import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.misc import Compose, SetConfig From 9254078f9c1b8c6c6e10ce82825fce84b24a4300 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 11:08:15 +0800 Subject: [PATCH 047/168] update import --- test_automl/optuna_wandb_nocontainer_step3.py | 8 ++++---- test_automl/wandb_step2.py | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/test_automl/optuna_wandb_nocontainer_step3.py b/test_automl/optuna_wandb_nocontainer_step3.py index a30c35114..b95fc7bba 100644 --- a/test_automl/optuna_wandb_nocontainer_step3.py +++ b/test_automl/optuna_wandb_nocontainer_step3.py @@ -1,15 +1,15 @@ import numpy as np import optuna -import step3_fun import torch -import wandb -from config import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback +import test_automl.register_function as register_function +import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.misc import Compose, SetConfig from dance.utils import set_seed +from test_automl.pipline_config import fun2code_dict fun_list = ["log1p", "filter_gene_by_count"] @@ -24,7 +24,7 @@ def objective(trial): transforms = [] for f_str in fun_list: - fun_i = getattr(step3_fun, f_str) + fun_i = getattr(register_function, f_str) transforms.append(fun_i(trial)) parameters_dict = { 'batch_size': 128, diff --git a/test_automl/wandb_step2.py b/test_automl/wandb_step2.py index afc4acb5e..45c6196f5 100644 --- a/test_automl/wandb_step2.py +++ b/test_automl/wandb_step2.py @@ -1,10 +1,11 @@ from itertools import combinations import wandb -from config import fun2code_dict, pipline2fun_dict +from test_automl.pipline_config import fun2code_dict, pipline2fun_dict def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): + global pipline2fun_dict pipline2fun_dict = {key: pipline2fun_dict[key] for key in selected_keys} count = 1 for pipline_key, pipline_values in pipline2fun_dict.items(): From 7c31cacee08498ac7143d70daf122fb2d6494a34 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 03:08:39 +0000 Subject: [PATCH 048/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/optuna_wandb_nocontainer_step3.py | 2 +- test_automl/wandb_step2.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/test_automl/optuna_wandb_nocontainer_step3.py b/test_automl/optuna_wandb_nocontainer_step3.py index b95fc7bba..87f5e71ad 100644 --- a/test_automl/optuna_wandb_nocontainer_step3.py +++ b/test_automl/optuna_wandb_nocontainer_step3.py @@ -1,10 +1,10 @@ import numpy as np import optuna import torch +import wandb from optuna.integration.wandb import WeightsAndBiasesCallback import test_automl.register_function as register_function -import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.misc import Compose, SetConfig diff --git a/test_automl/wandb_step2.py b/test_automl/wandb_step2.py index 45c6196f5..e16b3d4d4 100644 --- a/test_automl/wandb_step2.py +++ b/test_automl/wandb_step2.py @@ -1,6 +1,7 @@ from itertools import combinations import wandb + from test_automl.pipline_config import fun2code_dict, pipline2fun_dict From 4005cc7140b865ac3e4af21285cccbeb7b48d273 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 11:16:15 +0800 Subject: [PATCH 049/168] rename file --- test_automl/{wandb_step2.py => step2.py} | 1 - test_automl/{pipline_config.py => step2_config.py} | 0 test_automl/{optuna_wandb_nocontainer_step3.py => step3.py} | 2 +- test_automl/{register_function.py => step3_config.py} | 0 4 files changed, 1 insertion(+), 2 deletions(-) rename test_automl/{wandb_step2.py => step2.py} (99%) rename test_automl/{pipline_config.py => step2_config.py} (100%) rename test_automl/{optuna_wandb_nocontainer_step3.py => step3.py} (100%) rename test_automl/{register_function.py => step3_config.py} (100%) diff --git a/test_automl/wandb_step2.py b/test_automl/step2.py similarity index 99% rename from test_automl/wandb_step2.py rename to test_automl/step2.py index e16b3d4d4..45c6196f5 100644 --- a/test_automl/wandb_step2.py +++ b/test_automl/step2.py @@ -1,7 +1,6 @@ from itertools import combinations import wandb - from test_automl.pipline_config import fun2code_dict, pipline2fun_dict diff --git a/test_automl/pipline_config.py b/test_automl/step2_config.py similarity index 100% rename from test_automl/pipline_config.py rename to test_automl/step2_config.py diff --git a/test_automl/optuna_wandb_nocontainer_step3.py b/test_automl/step3.py similarity index 100% rename from test_automl/optuna_wandb_nocontainer_step3.py rename to test_automl/step3.py index 87f5e71ad..b95fc7bba 100644 --- a/test_automl/optuna_wandb_nocontainer_step3.py +++ b/test_automl/step3.py @@ -1,10 +1,10 @@ import numpy as np import optuna import torch -import wandb from optuna.integration.wandb import WeightsAndBiasesCallback import test_automl.register_function as register_function +import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.misc import Compose, SetConfig diff --git a/test_automl/register_function.py b/test_automl/step3_config.py similarity index 100% rename from test_automl/register_function.py rename to test_automl/step3_config.py From 9b5d1b00bd2152b7d7c5585112884f2aa6a17ac4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 03:16:38 +0000 Subject: [PATCH 050/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2.py | 1 + test_automl/step3.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index 45c6196f5..e16b3d4d4 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -1,6 +1,7 @@ from itertools import combinations import wandb + from test_automl.pipline_config import fun2code_dict, pipline2fun_dict diff --git a/test_automl/step3.py b/test_automl/step3.py index b95fc7bba..87f5e71ad 100644 --- a/test_automl/step3.py +++ b/test_automl/step3.py @@ -1,10 +1,10 @@ import numpy as np import optuna import torch +import wandb from optuna.integration.wandb import WeightsAndBiasesCallback import test_automl.register_function as register_function -import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.misc import Compose, SetConfig From f69fbc0efb142fdf21ab307bbc3fbcd380a9efbf Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 11:17:55 +0800 Subject: [PATCH 051/168] rename import --- test_automl/step3.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test_automl/step3.py b/test_automl/step3.py index 87f5e71ad..915245b1f 100644 --- a/test_automl/step3.py +++ b/test_automl/step3.py @@ -1,15 +1,15 @@ import numpy as np import optuna +import step3_config as register_function import torch -import wandb from optuna.integration.wandb import WeightsAndBiasesCallback +from step2_config import fun2code_dict -import test_automl.register_function as register_function +import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.misc import Compose, SetConfig from dance.utils import set_seed -from test_automl.pipline_config import fun2code_dict fun_list = ["log1p", "filter_gene_by_count"] From 68c009916cb129ba849f7f9047fd4145f424d3b1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 03:18:18 +0000 Subject: [PATCH 052/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/step3.py b/test_automl/step3.py index 915245b1f..436d85ba1 100644 --- a/test_automl/step3.py +++ b/test_automl/step3.py @@ -2,10 +2,10 @@ import optuna import step3_config as register_function import torch +import wandb from optuna.integration.wandb import WeightsAndBiasesCallback from step2_config import fun2code_dict -import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.misc import Compose, SetConfig From ed3ccc507b80870718922d2d3b050c8aea707be5 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 11:18:34 +0800 Subject: [PATCH 053/168] rename import --- test_automl/step2.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index e16b3d4d4..635bcdba3 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -1,8 +1,8 @@ from itertools import combinations -import wandb +from step2_config import fun2code_dict, pipline2fun_dict -from test_automl.pipline_config import fun2code_dict, pipline2fun_dict +import wandb def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): From 80d2cab7e4723439d3f520db3294e520428f03d5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 03:19:34 +0000 Subject: [PATCH 054/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index 635bcdba3..fec4dea15 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -1,8 +1,7 @@ from itertools import combinations -from step2_config import fun2code_dict, pipline2fun_dict - import wandb +from step2_config import fun2code_dict, pipline2fun_dict def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): From ef0cc50d93c1fc3c64abb533211ed5c740ebef32 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 11:23:41 +0800 Subject: [PATCH 055/168] rename import --- test_automl/step2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index 635bcdba3..f50599348 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -9,7 +9,7 @@ def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]) global pipline2fun_dict pipline2fun_dict = {key: pipline2fun_dict[key] for key in selected_keys} count = 1 - for pipline_key, pipline_values in pipline2fun_dict.items(): + for _, pipline_values in pipline2fun_dict.items(): count *= len(pipline_values['values']) parameters_dict = pipline2fun_dict parameters_dict.update({ From 29a332cdea5bae09a1f566ae63f9bb4b642423fb Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 11:29:13 +0800 Subject: [PATCH 056/168] rename file --- test_automl/fun2code.py | 21 +++++++++++++++++++++ test_automl/step2.py | 4 +++- test_automl/step2_config.py | 21 --------------------- test_automl/step3.py | 4 ++-- 4 files changed, 26 insertions(+), 24 deletions(-) create mode 100644 test_automl/fun2code.py diff --git a/test_automl/fun2code.py b/test_automl/fun2code.py new file mode 100644 index 000000000..6f6e07987 --- /dev/null +++ b/test_automl/fun2code.py @@ -0,0 +1,21 @@ +import scanpy as sc + +from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA +from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression +from dance.transforms.interface import AnnDataTransform +from dance.transforms.normalize import ScaleFeature, ScTransformR + +fun2code_dict = { + "normalize_total": AnnDataTransform(sc.pp.normalize_total, target_sum=1e4), + "log1p": AnnDataTransform(sc.pp.log1p, base=2), + "scaleFeature": ScaleFeature(split_names="ALL", mode="standardize"), + "scTransform": ScTransformR(mirror_index=1), + "filter_gene_by_count": AnnDataTransform(sc.pp.filter_genes, min_cells=1), + "filter_gene_by_percentile": FilterGenesPercentile(min_val=1, max_val=99, mode="sum"), + "highly_variable_genes": AnnDataTransform(sc.pp.highly_variable_genes), + "regress_out": AnnDataTransform(sc.pp.regress_out), + "Filter_gene_by_regress_score": FilterGenesRegression("enclasc"), + "cell_svd": CellSVD(), + "cell_weighted_pca": WeightedFeaturePCA(split_name="train"), + "cell_pca": CellPCA() +} diff --git a/test_automl/step2.py b/test_automl/step2.py index 8f938afaf..d68e80a32 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -1,7 +1,9 @@ from itertools import combinations +from fun2code import fun2code_dict +from step2_config import pipline2fun_dict + import wandb -from step2_config import fun2code_dict, pipline2fun_dict def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index 3eaf97854..f773f5177 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,24 +1,3 @@ -import scanpy as sc - -from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA -from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression -from dance.transforms.interface import AnnDataTransform -from dance.transforms.normalize import ScaleFeature, ScTransformR - -fun2code_dict = { - "normalize_total": AnnDataTransform(sc.pp.normalize_total, target_sum=1e4), - "log1p": AnnDataTransform(sc.pp.log1p, base=2), - "scaleFeature": ScaleFeature(split_names="ALL", mode="standardize"), - "scTransform": ScTransformR(mirror_index=1), - "filter_gene_by_count": AnnDataTransform(sc.pp.filter_genes, min_cells=1), - "filter_gene_by_percentile": FilterGenesPercentile(min_val=1, max_val=99, mode="sum"), - "highly_variable_genes": AnnDataTransform(sc.pp.highly_variable_genes), - "regress_out": AnnDataTransform(sc.pp.regress_out), - "Filter_gene_by_regress_score": FilterGenesRegression("enclasc"), - "cell_svd": CellSVD(), - "cell_weighted_pca": WeightedFeaturePCA(split_name="train"), - "cell_pca": CellPCA() -} pipline2fun_dict = { "normalize": { "values": ["normalize_total", "log1p", "scaleFeature", "scTransform"] diff --git a/test_automl/step3.py b/test_automl/step3.py index 436d85ba1..3d0576786 100644 --- a/test_automl/step3.py +++ b/test_automl/step3.py @@ -2,10 +2,10 @@ import optuna import step3_config as register_function import torch -import wandb +from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback -from step2_config import fun2code_dict +import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.misc import Compose, SetConfig From 2cb837f9501fd5c5831711ff60aa1a147e0cfc15 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 03:29:35 +0000 Subject: [PATCH 057/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2.py | 3 +-- test_automl/step3.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index d68e80a32..74c13b4f9 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -1,10 +1,9 @@ from itertools import combinations +import wandb from fun2code import fun2code_dict from step2_config import pipline2fun_dict -import wandb - def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): global pipline2fun_dict diff --git a/test_automl/step3.py b/test_automl/step3.py index 3d0576786..35c39bf8b 100644 --- a/test_automl/step3.py +++ b/test_automl/step3.py @@ -2,10 +2,10 @@ import optuna import step3_config as register_function import torch +import wandb from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback -import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.misc import Compose, SetConfig From 72a6f8e3cf59b8ee030a58cf7b940d6b756308a4 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 11:38:31 +0800 Subject: [PATCH 058/168] delete test.py --- test_automl/test.py | 39 --------------------------------------- 1 file changed, 39 deletions(-) delete mode 100644 test_automl/test.py diff --git a/test_automl/test.py b/test_automl/test.py deleted file mode 100644 index 91ebd027b..000000000 --- a/test_automl/test.py +++ /dev/null @@ -1,39 +0,0 @@ -import inspect -import sys - - -def function_one(): - pass - - -def function_two(): - pass - - -# 获取当前文件中的所有函数 -current_functions = [(name, obj) for name, obj in inspect.getmembers(sys.modules[__name__]) if inspect.isfunction(obj)] - -# 打印所有函数名 -print("当前文件中的所有函数:", current_functions) - -import sys - - -def set_method_name(func): - - def wrapper(*args, **kwargs): - method_name = func.__name__ + "_" - print(method_name) - result = func(*args, **kwargs) - return result - - return wrapper - - -@set_method_name -def function1(): - method_name = str(sys._getframe().f_code.co_name) + "_" - print("函数 1 被调用") - - -function1() From 84fb98a563c8a3398b89854c337692852971306f Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 11:41:55 +0800 Subject: [PATCH 059/168] add readme.txt --- test_automl/readme.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 test_automl/readme.txt diff --git a/test_automl/readme.txt b/test_automl/readme.txt new file mode 100644 index 000000000..41dcf31cb --- /dev/null +++ b/test_automl/readme.txt @@ -0,0 +1,3 @@ +If you need to register a new function, first pass the new function in the fun2 code file. +If you use step2, you can declare the step2 process. + If you use step3, you can register a new optimization function. From 2ab442ebe5a56dec204a6fa0542a1d6dd9d5a339 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 11:43:29 +0800 Subject: [PATCH 060/168] update readme.txt --- test_automl/readme.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_automl/readme.txt b/test_automl/readme.txt index 41dcf31cb..4d6fb2d21 100644 --- a/test_automl/readme.txt +++ b/test_automl/readme.txt @@ -1,3 +1,3 @@ If you need to register a new function, first pass the new function in the fun2 code file. -If you use step2, you can declare the step2 process. - If you use step3, you can register a new optimization function. +If you use step2, you can declare the step2 pipline in step2_config. +If you use step3, you can register a new optimization function in step3_config. From 0be408055f7047bb13d6c4db1a64a2b32502dbc9 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 11:54:13 +0800 Subject: [PATCH 061/168] update step2.py --- test_automl/step2.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index 74c13b4f9..5116df283 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -1,16 +1,22 @@ from itertools import combinations -import wandb from fun2code import fun2code_dict from step2_config import pipline2fun_dict +import wandb + -def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): +def getFunConfig(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): global pipline2fun_dict pipline2fun_dict = {key: pipline2fun_dict[key] for key in selected_keys} count = 1 for _, pipline_values in pipline2fun_dict.items(): count *= len(pipline_values['values']) + return pipline2fun_dict, count + + +def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): + pipline2fun_dict, count = getFunConfig(selected_keys) parameters_dict = pipline2fun_dict parameters_dict.update({ 'batch_size': { From 68403457178fd2281fc8e95d318cc2e2a56746bc Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 03:59:09 +0000 Subject: [PATCH 062/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index 5116df283..48fc40a71 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -1,10 +1,9 @@ from itertools import combinations +import wandb from fun2code import fun2code_dict from step2_config import pipline2fun_dict -import wandb - def getFunConfig(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): global pipline2fun_dict From 26a7388fd1e15ca04ad71a8c6d07573975c90488 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 15:22:45 +0800 Subject: [PATCH 063/168] update step2_config.py --- test_automl/step2.py | 12 ++---------- test_automl/step2_config.py | 9 +++++++++ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index 48fc40a71..e76a8ee2b 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -1,17 +1,9 @@ from itertools import combinations -import wandb from fun2code import fun2code_dict -from step2_config import pipline2fun_dict - +from step2_config import getFunConfig -def getFunConfig(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): - global pipline2fun_dict - pipline2fun_dict = {key: pipline2fun_dict[key] for key in selected_keys} - count = 1 - for _, pipline_values in pipline2fun_dict.items(): - count *= len(pipline_values['values']) - return pipline2fun_dict, count +import wandb def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index f773f5177..2794705ad 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -10,3 +10,12 @@ "values": ["cell_svd", "cell_weighted_pca", "cell_pca"] } } + + +def getFunConfig(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): + global pipline2fun_dict + pipline2fun_dict = {key: pipline2fun_dict[key] for key in selected_keys} + count = 1 + for _, pipline_values in pipline2fun_dict.items(): + count *= len(pipline_values['values']) + return pipline2fun_dict, count From 5e15e77efb86118551e484cbb9eaee2c48dee06b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 07:23:35 +0000 Subject: [PATCH 064/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index e76a8ee2b..4d19d720c 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -1,10 +1,9 @@ from itertools import combinations +import wandb from fun2code import fun2code_dict from step2_config import getFunConfig -import wandb - def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): pipline2fun_dict, count = getFunConfig(selected_keys) From 9a751836231746f40e366ab6bd4b8f50ffb143d2 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 16:03:26 +0800 Subject: [PATCH 065/168] update step2_config.py --- test_automl/step2.py | 17 +++-------------- test_automl/step2_config.py | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index e76a8ee2b..08d6abd67 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -1,6 +1,5 @@ from itertools import combinations -from fun2code import fun2code_dict from step2_config import getFunConfig import wandb @@ -46,7 +45,6 @@ def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]) from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN -from dance.transforms.misc import Compose, SetConfig from dance.utils import set_seed device = torch.device("cuda" if torch.cuda.is_available() else "cpu") @@ -55,20 +53,11 @@ def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]) def train(config=None): with wandb.init(config=config): config = wandb.config - if ("normalize" not in config.keys() or config.normalize - != "log1p") and ("gene_filter" in config.keys() and config.gene_filter == "highly_variable_genes"): + model = ACTINN(hidden_dims=config.hidden_dims, lambd=config.lambd, device=device) + preprocessing_pipeline = get_preprocessing_pipeline(config=config) + if preprocessing_pipeline is None: wandb.log({"scores": 0}) return - model = ACTINN(hidden_dims=config.hidden_dims, lambd=config.lambd, device=device) - transforms = [] - transforms.append(fun2code_dict[config.normalize]) if "normalize" in config.keys() else None - transforms.append(fun2code_dict[config.gene_filter]) if "gene_filter" in config.keys() else None - transforms.append(fun2code_dict[config.gene_dim_reduction]) if "gene_dim_reduction" in config.keys() else None - data_config = {"label_channel": "cell_type"} - if "gene_dim_reduction" in config.keys(): - data_config.update({"feature_channel": fun2code_dict[config.gene_dim_reduction].name}) - transforms.append(SetConfig(data_config)) - preprocessing_pipeline = Compose(*transforms, log_level="INFO") train_dataset = [753, 3285] test_dataset = [2695] tissue = "Brain" diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index 2794705ad..1008630fa 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,3 +1,5 @@ +from fun2code import fun2code_dict + pipline2fun_dict = { "normalize": { "values": ["normalize_total", "log1p", "scaleFeature", "scTransform"] @@ -19,3 +21,20 @@ def getFunConfig(selected_keys=["normalize", "gene_filter", "gene_dim_reduction" for _, pipline_values in pipline2fun_dict.items(): count *= len(pipline_values['values']) return pipline2fun_dict, count + + +def get_preprocessing_pipeline(config=None): + if ("normalize" not in config.keys() or config.normalize + != "log1p") and ("gene_filter" in config.keys() and config.gene_filter == "highly_variable_genes"): + + return None + transforms = [] + transforms.append(fun2code_dict[config.normalize]) if "normalize" in config.keys() else None + transforms.append(fun2code_dict[config.gene_filter]) if "gene_filter" in config.keys() else None + transforms.append(fun2code_dict[config.gene_dim_reduction]) if "gene_dim_reduction" in config.keys() else None + data_config = {"label_channel": "cell_type"} + if "gene_dim_reduction" in config.keys(): + data_config.update({"feature_channel": fun2code_dict[config.gene_dim_reduction].name}) + transforms.append(SetConfig(data_config)) + preprocessing_pipeline = Compose(*transforms, log_level="INFO") + return preprocessing_pipeline From 0f069085a22d79c787e2b0908009c82bd28f6a5d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 08:06:09 +0000 Subject: [PATCH 066/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index 08d6abd67..2b9e3b0fc 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -1,8 +1,7 @@ from itertools import combinations -from step2_config import getFunConfig - import wandb +from step2_config import getFunConfig def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): From d663f04908f522ea9e95a744a30c8c630822020c Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 16:07:27 +0800 Subject: [PATCH 067/168] update step2_config.py --- test_automl/step2.py | 3 ++- test_automl/step2_config.py | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index 2b9e3b0fc..a6d64494f 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -1,7 +1,8 @@ from itertools import combinations +from step2_config import get_preprocessing_pipeline, getFunConfig + import wandb -from step2_config import getFunConfig def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index 1008630fa..482fe238f 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,5 +1,7 @@ from fun2code import fun2code_dict +from dance.transforms.misc import Compose, SetConfig + pipline2fun_dict = { "normalize": { "values": ["normalize_total", "log1p", "scaleFeature", "scTransform"] From 387f6defcf85a3d6f83136f376517cb510388008 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 08:07:50 +0000 Subject: [PATCH 068/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index a6d64494f..2d37337d3 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -1,8 +1,7 @@ from itertools import combinations -from step2_config import get_preprocessing_pipeline, getFunConfig - import wandb +from step2_config import get_preprocessing_pipeline, getFunConfig def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): From 99f35aad2a7e5bf1248dc4b9c9ca09bd6e6078a8 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 16:20:41 +0800 Subject: [PATCH 069/168] update step3_config.py --- test_automl/step3.py | 18 ++++-------------- test_automl/step3_config.py | 17 ++++++++++++++++- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/test_automl/step3.py b/test_automl/step3.py index 35c39bf8b..b2254f8ef 100644 --- a/test_automl/step3.py +++ b/test_automl/step3.py @@ -1,14 +1,12 @@ import numpy as np import optuna -import step3_config as register_function import torch -import wandb -from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback +from step3_config import get_preprocessing_pipeline +import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN -from dance.transforms.misc import Compose, SetConfig from dance.utils import set_seed fun_list = ["log1p", "filter_gene_by_count"] @@ -22,10 +20,6 @@ @wandbc.track_in_wandb() def objective(trial): - transforms = [] - for f_str in fun_list: - fun_i = getattr(register_function, f_str) - transforms.append(fun_i(trial)) parameters_dict = { 'batch_size': 128, "hidden_dims": [2000], @@ -35,18 +29,14 @@ def objective(trial): 'num_runs': 1, 'learning_rate': 0.0001 } - data_config = {"label_channel": "cell_type"} - feature_name = {"cell_svd", "cell_weighted_pca", "cell_pca"} & set(fun_list) - if feature_name: - data_config.update({"feature_channel": fun2code_dict[feature_name].name}) - transforms.append(SetConfig(data_config)) - preprocessing_pipeline = Compose(*transforms, log_level="INFO") + train_dataset = [753, 3285] test_dataset = [2695] tissue = "Brain" species = "mouse" dataloader = CellTypeAnnotationDataset(train_dataset=train_dataset, test_dataset=test_dataset, tissue=tissue, species=species, data_dir="./test_automl/data") + preprocessing_pipeline = get_preprocessing_pipeline(trial=trial, fun_list=fun_list) data = dataloader.load_data(transform=preprocessing_pipeline, cache=True) # Obtain training and testing data diff --git a/test_automl/step3_config.py b/test_automl/step3_config.py index c1c2fbdf6..ba47ff351 100644 --- a/test_automl/step3_config.py +++ b/test_automl/step3_config.py @@ -1,12 +1,13 @@ -import inspect import sys import optuna import scanpy as sc +from fun2code import fun2code_dict from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform +from dance.transforms.misc import Compose, SetConfig from dance.transforms.normalize import ScaleFeature, ScTransformR @@ -115,3 +116,17 @@ def normalize_total(method_name: str, trial: optuna.Trial): # if name != "set_method_name": # 排除装饰器函数本身 # print(function) # setattr(__name__, name, set_method_name(function)) + + +def get_preprocessing_pipeline(trial, fun_list): + transforms = [] + for f_str in fun_list: + fun_i = eval(f_str) + transforms.append(fun_i(trial)) + data_config = {"label_channel": "cell_type"} + feature_name = {"cell_svd", "cell_weighted_pca", "cell_pca"} & set(fun_list) + if feature_name: + data_config.update({"feature_channel": fun2code_dict[feature_name].name}) + transforms.append(SetConfig(data_config)) + preprocessing_pipeline = Compose(*transforms, log_level="INFO") + return preprocessing_pipeline From 0e43aeae9e94764f99c6a22e5f6393619de87cae Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 08:23:46 +0000 Subject: [PATCH 070/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/step3.py b/test_automl/step3.py index b2254f8ef..2eac66a5f 100644 --- a/test_automl/step3.py +++ b/test_automl/step3.py @@ -1,10 +1,10 @@ import numpy as np import optuna import torch +import wandb from optuna.integration.wandb import WeightsAndBiasesCallback from step3_config import get_preprocessing_pipeline -import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.utils import set_seed From 397a5eadefff3ac3aa63abaf7deae0369ffc958c Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 16:42:34 +0800 Subject: [PATCH 071/168] update step2.py --- test_automl/step2.py | 83 +++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 44 deletions(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index 2d37337d3..b935d968f 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -1,47 +1,10 @@ from itertools import combinations -import wandb -from step2_config import get_preprocessing_pipeline, getFunConfig - - -def getSweepId(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): - pipline2fun_dict, count = getFunConfig(selected_keys) - parameters_dict = pipline2fun_dict - parameters_dict.update({ - 'batch_size': { - 'value': 128 - }, - "hidden_dims": { - 'value': [2000] - }, - 'lambd': { - 'value': 0.005 - }, - 'num_epochs': { - 'value': 50 - }, - 'seed': { - 'value': 0 - }, - 'num_runs': { - 'value': 1 - }, - 'learning_rate': { - 'value': 0.0001 - } - }) - sweep_config = {'method': 'grid'} - sweep_config['parameters'] = parameters_dict - metric = {'name': 'scores', 'goal': 'maximize'} - - sweep_config['metric'] = metric - sweep_id = wandb.sweep(sweep_config, project="pytorch-cell_type_annotation_ACTINN") - return sweep_id, count - - import numpy as np import torch +from step2_config import get_preprocessing_pipeline, getFunConfig +import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.utils import set_seed @@ -80,12 +43,44 @@ def train(config=None): wandb.log({"scores": np.mean(scores)}) -if __name__ == "__main__": - original_list = ["normalize", "gene_filter", "gene_dim_reduction"] +def startSweep(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): + pipline2fun_dict, count = getFunConfig(selected_keys) + parameters_dict = pipline2fun_dict + parameters_dict.update({ + 'batch_size': { + 'value': 128 + }, + "hidden_dims": { + 'value': [2000] + }, + 'lambd': { + 'value': 0.005 + }, + 'num_epochs': { + 'value': 50 + }, + 'seed': { + 'value': 0 + }, + 'num_runs': { + 'value': 1 + }, + 'learning_rate': { + 'value': 0.0001 + } + }) + sweep_config = {'method': 'grid'} + sweep_config['parameters'] = parameters_dict + metric = {'name': 'scores', 'goal': 'maximize'} + + sweep_config['metric'] = metric + sweep_id = wandb.sweep(sweep_config, project="pytorch-cell_type_annotation_ACTINN") + wandb.agent(sweep_id, train, count=count) + + +def setStep2(original_list=["normalize", "gene_filter", "gene_dim_reduction"]): all_combinations = [combo for i in range(1, len(original_list) + 1) for combo in combinations(original_list, i)] all_combinations.append([]) for s_key in all_combinations: s_list = list(s_key) - sweep_id, count = getSweepId(s_list) - print(s_list, count) - wandb.agent(sweep_id, train, count=count) + startSweep(s_list) From db6b984f4d57adc58d7ebaf6d65dad2e2b2ef8db Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 08:42:59 +0000 Subject: [PATCH 072/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index b935d968f..591a5d4d2 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -2,9 +2,9 @@ import numpy as np import torch +import wandb from step2_config import get_preprocessing_pipeline, getFunConfig -import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.utils import set_seed From d06cb02ffec07ad237f8a07d828207ef7ee73b99 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 17:19:24 +0800 Subject: [PATCH 073/168] add track in wandb --- test_automl/step2.py | 79 +++++++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 30 deletions(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index 591a5d4d2..cacbf3785 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -2,9 +2,9 @@ import numpy as np import torch -import wandb from step2_config import get_preprocessing_pipeline, getFunConfig +import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.utils import set_seed @@ -12,35 +12,50 @@ device = torch.device("cuda" if torch.cuda.is_available() else "cpu") -def train(config=None): - with wandb.init(config=config): - config = wandb.config - model = ACTINN(hidden_dims=config.hidden_dims, lambd=config.lambd, device=device) - preprocessing_pipeline = get_preprocessing_pipeline(config=config) - if preprocessing_pipeline is None: - wandb.log({"scores": 0}) - return - train_dataset = [753, 3285] - test_dataset = [2695] - tissue = "Brain" - species = "mouse" - dataloader = CellTypeAnnotationDataset(train_dataset=train_dataset, test_dataset=test_dataset, tissue=tissue, - species=species) - data = dataloader.load_data(transform=preprocessing_pipeline, cache=False) - - # Obtain training and testing data - x_train, y_train = data.get_train_data(return_type="torch") - x_test, y_test = data.get_test_data(return_type="torch") - x_train, y_train, x_test, y_test = x_train.float(), y_train.float(), x_test.float(), y_test.float() - # Train and evaluate models for several rounds - scores = [] - for seed in range(config.seed, config.seed + config.num_runs): - set_seed(seed) - - model.fit(x_train, y_train, seed=seed, lr=config.learning_rate, num_epochs=config.num_epochs, - batch_size=config.batch_size, print_cost=False) - scores.append(score := model.score(x_test, y_test)) - wandb.log({"scores": np.mean(scores)}) +def track_in_wandb(config): + + def decorator(func): + + def wrapper(*args, **kwargs): + with wandb.init(config=config): + config = wandb.config + print(config) + result = func(config, *args, **kwargs) + return result + + return wrapper + + return decorator + + +@track_in_wandb(config=None) +def train(config): + model = ACTINN(hidden_dims=config.hidden_dims, lambd=config.lambd, device=device) + preprocessing_pipeline = get_preprocessing_pipeline(config=config) + if preprocessing_pipeline is None: + wandb.log({"scores": 0}) + return + train_dataset = [753, 3285] + test_dataset = [2695] + tissue = "Brain" + species = "mouse" + dataloader = CellTypeAnnotationDataset(train_dataset=train_dataset, test_dataset=test_dataset, tissue=tissue, + species=species, data_dir="./test_automl/data") + data = dataloader.load_data(transform=preprocessing_pipeline, cache=False) + + # Obtain training and testing data + x_train, y_train = data.get_train_data(return_type="torch") + x_test, y_test = data.get_test_data(return_type="torch") + x_train, y_train, x_test, y_test = x_train.float(), y_train.float(), x_test.float(), y_test.float() + # Train and evaluate models for several rounds + scores = [] + for seed in range(config.seed, config.seed + config.num_runs): + set_seed(seed) + + model.fit(x_train, y_train, seed=seed, lr=config.learning_rate, num_epochs=config.num_epochs, + batch_size=config.batch_size, print_cost=False) + scores.append(score := model.score(x_test, y_test)) + wandb.log({"scores": np.mean(scores)}) def startSweep(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): @@ -84,3 +99,7 @@ def setStep2(original_list=["normalize", "gene_filter", "gene_dim_reduction"]): for s_key in all_combinations: s_list = list(s_key) startSweep(s_list) + + +if __name__ == "__main__": + setStep2() From d39546900604bfd42caa4114c45a4a994185cd3a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 09:19:51 +0000 Subject: [PATCH 074/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index cacbf3785..39316faf8 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -2,9 +2,9 @@ import numpy as np import torch +import wandb from step2_config import get_preprocessing_pipeline, getFunConfig -import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.utils import set_seed From efba6dfeb99da67df7aac57a7f64c5c6c40ac54d Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 17:24:16 +0800 Subject: [PATCH 075/168] update track in wandb --- test_automl/step2.py | 20 ++------------------ test_automl/step2_config.py | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index 39316faf8..4049dedfa 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -2,9 +2,9 @@ import numpy as np import torch -import wandb -from step2_config import get_preprocessing_pipeline, getFunConfig +from step2_config import get_preprocessing_pipeline, getFunConfig, track_in_wandb +import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.utils import set_seed @@ -12,22 +12,6 @@ device = torch.device("cuda" if torch.cuda.is_available() else "cpu") -def track_in_wandb(config): - - def decorator(func): - - def wrapper(*args, **kwargs): - with wandb.init(config=config): - config = wandb.config - print(config) - result = func(config, *args, **kwargs) - return result - - return wrapper - - return decorator - - @track_in_wandb(config=None) def train(config): model = ACTINN(hidden_dims=config.hidden_dims, lambd=config.lambd, device=device) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index 482fe238f..70a4f30b2 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,5 +1,6 @@ from fun2code import fun2code_dict +import wandb from dance.transforms.misc import Compose, SetConfig pipline2fun_dict = { @@ -40,3 +41,19 @@ def get_preprocessing_pipeline(config=None): transforms.append(SetConfig(data_config)) preprocessing_pipeline = Compose(*transforms, log_level="INFO") return preprocessing_pipeline + + +def track_in_wandb(config): + + def decorator(func): + + def wrapper(*args, **kwargs): + with wandb.init(config=config): + config = wandb.config + print(config) + result = func(config, *args, **kwargs) + return result + + return wrapper + + return decorator From 64f773846c06c03a01837df2e495a99cbb255054 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 09:24:42 +0000 Subject: [PATCH 076/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2.py | 2 +- test_automl/step2_config.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index 4049dedfa..a0b40f42c 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -2,9 +2,9 @@ import numpy as np import torch +import wandb from step2_config import get_preprocessing_pipeline, getFunConfig, track_in_wandb -import wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.utils import set_seed diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index 70a4f30b2..e280dded0 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,6 +1,6 @@ +import wandb from fun2code import fun2code_dict -import wandb from dance.transforms.misc import Compose, SetConfig pipline2fun_dict = { From df455b2956ca51974755a4021098efeee5b389df Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 17:27:27 +0800 Subject: [PATCH 077/168] update step2.py --- test_automl/step2.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index 4049dedfa..192430b98 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -78,8 +78,8 @@ def startSweep(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]) def setStep2(original_list=["normalize", "gene_filter", "gene_dim_reduction"]): - all_combinations = [combo for i in range(1, len(original_list) + 1) for combo in combinations(original_list, i)] - all_combinations.append([]) + all_combinations = [combo for i in range(1, + len(original_list) + 1) for combo in combinations(original_list, i)] + [[]] for s_key in all_combinations: s_list = list(s_key) startSweep(s_list) From 14b5d4bdaf5195882e63e1984f598a15d960414c Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 20:32:48 +0800 Subject: [PATCH 078/168] update step2 --- test_automl/step2.py | 28 ++++++----------- test_automl/step2_config.py | 60 ++++++++++++++++++++++++++++++++----- 2 files changed, 62 insertions(+), 26 deletions(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index 4a36af4b5..94ef6ae09 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -2,8 +2,7 @@ import numpy as np import torch -import wandb -from step2_config import get_preprocessing_pipeline, getFunConfig, track_in_wandb +from step2_config import get_preprocessing_pipeline, setStep2, track_in_wandb from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN @@ -14,11 +13,11 @@ @track_in_wandb(config=None) def train(config): + model = ACTINN(hidden_dims=config.hidden_dims, lambd=config.lambd, device=device) preprocessing_pipeline = get_preprocessing_pipeline(config=config) if preprocessing_pipeline is None: - wandb.log({"scores": 0}) - return + return {"scores": 0} train_dataset = [753, 3285] test_dataset = [2695] tissue = "Brain" @@ -39,12 +38,10 @@ def train(config): model.fit(x_train, y_train, seed=seed, lr=config.learning_rate, num_epochs=config.num_epochs, batch_size=config.batch_size, print_cost=False) scores.append(score := model.score(x_test, y_test)) - wandb.log({"scores": np.mean(scores)}) + return {"scores": np.mean(scores)} -def startSweep(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): - pipline2fun_dict, count = getFunConfig(selected_keys) - parameters_dict = pipline2fun_dict +def startSweep(parameters_dict): parameters_dict.update({ 'batch_size': { 'value': 128 @@ -73,17 +70,10 @@ def startSweep(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]) metric = {'name': 'scores', 'goal': 'maximize'} sweep_config['metric'] = metric - sweep_id = wandb.sweep(sweep_config, project="pytorch-cell_type_annotation_ACTINN") - wandb.agent(sweep_id, train, count=count) - - -def setStep2(original_list=["normalize", "gene_filter", "gene_dim_reduction"]): - all_combinations = [combo for i in range(1, - len(original_list) + 1) for combo in combinations(original_list, i)] + [[]] - for s_key in all_combinations: - s_list = list(s_key) - startSweep(s_list) + return sweep_config, train if __name__ == "__main__": - setStep2() + function_list = setStep2(startSweep) + for func in function_list: + func() diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index e280dded0..4329dfc76 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,6 +1,9 @@ -import wandb +import functools +from itertools import combinations + from fun2code import fun2code_dict +import wandb from dance.transforms.misc import Compose, SetConfig pipline2fun_dict = { @@ -14,10 +17,11 @@ "gene_dim_reduction": { "values": ["cell_svd", "cell_weighted_pca", "cell_pca"] } -} +} #Functions registered in the preprocessing process def getFunConfig(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): + """Get the config that needs to be optimized and the number of rounds.""" global pipline2fun_dict pipline2fun_dict = {key: pipline2fun_dict[key] for key in selected_keys} count = 1 @@ -27,6 +31,8 @@ def getFunConfig(selected_keys=["normalize", "gene_filter", "gene_dim_reduction" def get_preprocessing_pipeline(config=None): + """Obtain the Compose of the preprocessing function according to the preprocessing + process.""" if ("normalize" not in config.keys() or config.normalize != "log1p") and ("gene_filter" in config.keys() and config.gene_filter == "highly_variable_genes"): @@ -43,16 +49,56 @@ def get_preprocessing_pipeline(config=None): return preprocessing_pipeline +def sweepDecorator(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"], + project="pytorch-cell_type_annotation_ACTINN"): + """Decorator for preprocessing configuration functions.""" + + def decorator(func): + + @functools.wraps(func) + def wrapper(*args, **kwargs): + pipline2fun_dict, count = getFunConfig(selected_keys) + parameters_dict = pipline2fun_dict + try: + sweep_config, train = func(parameters_dict) + sweep_id = wandb.sweep(sweep_config, project=project) + wandb.agent(sweep_id, train, count=count) + except Exception as e: + print(f"{func.__name__}{args}\n==> {e}") + raise e + + return wrapper + + return decorator + + +def setStep2(func=None, original_list=["normalize", "gene_filter", "gene_dim_reduction"]): + """Generate corresponding decorators for different preprocessing.""" + all_combinations = [combo for i in range(1, + len(original_list) + 1) for combo in combinations(original_list, i)] + [[]] + generated_functions = [] + for s_key in all_combinations: + s_list = list(s_key) + decorator = sweepDecorator(selected_keys=s_list) + generated_functions.append(decorator(func)) + return generated_functions + + def track_in_wandb(config): + """Decorator wrapped using wandb.""" def decorator(func): + @functools.wraps(func) def wrapper(*args, **kwargs): - with wandb.init(config=config): - config = wandb.config - print(config) - result = func(config, *args, **kwargs) - return result + try: + with wandb.init(config=config): + config_s = wandb.config + result = func(config_s, *args, **kwargs) + wandb.log(result) + except Exception as e: + print(f"{func.__name__}{args}\n==> {e}") + raise e return wrapper From 04d578209c219bf4f4686b8b9f0a50c93d890878 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 12:33:23 +0000 Subject: [PATCH 079/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index 4329dfc76..f0e84ed90 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,9 @@ import functools from itertools import combinations +import wandb from fun2code import fun2code_dict -import wandb from dance.transforms.misc import Compose, SetConfig pipline2fun_dict = { From b713abdeb71a354c517b02897b309c0bd83a9686 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 20:40:46 +0800 Subject: [PATCH 080/168] update step2 --- test_automl/step2.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index 94ef6ae09..c701e0c46 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -1,4 +1,4 @@ -from itertools import combinations +from typing import Any, Callable, Dict, Tuple import numpy as np import torch @@ -41,7 +41,7 @@ def train(config): return {"scores": np.mean(scores)} -def startSweep(parameters_dict): +def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: parameters_dict.update({ 'batch_size': { 'value': 128 @@ -70,7 +70,7 @@ def startSweep(parameters_dict): metric = {'name': 'scores', 'goal': 'maximize'} sweep_config['metric'] = metric - return sweep_config, train + return sweep_config, train #Return function configuration and training function if __name__ == "__main__": From 44e3acf22569068f115415f4aba92c63a9e0da4f Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 21:29:48 +0800 Subject: [PATCH 081/168] update step2 --- test_automl/step2.py | 2 +- test_automl/step2_config.py | 15 +++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index c701e0c46..3f1eaa20d 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -74,6 +74,6 @@ def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: if __name__ == "__main__": - function_list = setStep2(startSweep) + function_list = setStep2(startSweep, original_list=["gene_filter", "gene_dim_reduction"]) for func in function_list: func() diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index f0e84ed90..a276089e2 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,9 @@ import functools from itertools import combinations -import wandb from fun2code import fun2code_dict +import wandb from dance.transforms.misc import Compose, SetConfig pipline2fun_dict = { @@ -20,14 +20,14 @@ } #Functions registered in the preprocessing process -def getFunConfig(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"]): +def getFunConfig(selected_keys=None): """Get the config that needs to be optimized and the number of rounds.""" global pipline2fun_dict - pipline2fun_dict = {key: pipline2fun_dict[key] for key in selected_keys} + pipline2fun_dict_subset = {key: pipline2fun_dict[key] for key in selected_keys} count = 1 - for _, pipline_values in pipline2fun_dict.items(): + for _, pipline_values in pipline2fun_dict_subset.items(): count *= len(pipline_values['values']) - return pipline2fun_dict, count + return pipline2fun_dict_subset, count def get_preprocessing_pipeline(config=None): @@ -49,8 +49,7 @@ def get_preprocessing_pipeline(config=None): return preprocessing_pipeline -def sweepDecorator(selected_keys=["normalize", "gene_filter", "gene_dim_reduction"], - project="pytorch-cell_type_annotation_ACTINN"): +def sweepDecorator(selected_keys=None, project="pytorch-cell_type_annotation_ACTINN"): """Decorator for preprocessing configuration functions.""" def decorator(func): @@ -72,7 +71,7 @@ def wrapper(*args, **kwargs): return decorator -def setStep2(func=None, original_list=["normalize", "gene_filter", "gene_dim_reduction"]): +def setStep2(func=None, original_list=None): """Generate corresponding decorators for different preprocessing.""" all_combinations = [combo for i in range(1, len(original_list) + 1) for combo in combinations(original_list, i)] + [[]] From 1ef119091e5ffd6a2b4e300ceca24e0a5b50d197 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 13:32:15 +0000 Subject: [PATCH 082/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index a276089e2..d54a20ecc 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,9 @@ import functools from itertools import combinations +import wandb from fun2code import fun2code_dict -import wandb from dance.transforms.misc import Compose, SetConfig pipline2fun_dict = { From a94cf4cecafe70ba25b30e32d4b0bb1d42e83461 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 21:35:31 +0800 Subject: [PATCH 083/168] update step2 --- test_automl/step2.py | 4 ++-- test_automl/step2_config.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test_automl/step2.py b/test_automl/step2.py index 3f1eaa20d..6586affc4 100644 --- a/test_automl/step2.py +++ b/test_automl/step2.py @@ -2,7 +2,7 @@ import numpy as np import torch -from step2_config import get_preprocessing_pipeline, setStep2, track_in_wandb +from step2_config import get_preprocessing_pipeline, log_in_wandb, setStep2 from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN @@ -11,7 +11,7 @@ device = torch.device("cuda" if torch.cuda.is_available() else "cpu") -@track_in_wandb(config=None) +@log_in_wandb(config=None) def train(config): model = ACTINN(hidden_dims=config.hidden_dims, lambd=config.lambd, device=device) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index d54a20ecc..5ffccbb02 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,9 @@ import functools from itertools import combinations -import wandb from fun2code import fun2code_dict +import wandb from dance.transforms.misc import Compose, SetConfig pipline2fun_dict = { @@ -83,7 +83,7 @@ def setStep2(func=None, original_list=None): return generated_functions -def track_in_wandb(config): +def log_in_wandb(config): """Decorator wrapped using wandb.""" def decorator(func): From e579344f7a385ef27b6adc255e79c329d4b7a534 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 13:37:30 +0000 Subject: [PATCH 084/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index 5ffccbb02..08a862c6d 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,9 @@ import functools from itertools import combinations +import wandb from fun2code import fun2code_dict -import wandb from dance.transforms.misc import Compose, SetConfig pipline2fun_dict = { From 07301a83ac14150829664769e0ff7e8935e2c511 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 22:30:57 +0800 Subject: [PATCH 085/168] update step3 --- test_automl/step3.py | 23 ++++++++------------- test_automl/step3_config.py | 40 +++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/test_automl/step3.py b/test_automl/step3.py index 2eac66a5f..22a977691 100644 --- a/test_automl/step3.py +++ b/test_automl/step3.py @@ -1,9 +1,7 @@ import numpy as np import optuna import torch -import wandb -from optuna.integration.wandb import WeightsAndBiasesCallback -from step3_config import get_preprocessing_pipeline +from step3_config import get_optimizer, get_preprocessing_pipeline from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN @@ -11,20 +9,16 @@ fun_list = ["log1p", "filter_gene_by_count"] -wandb_kwargs = {"project": "step3-project"} -wandbc = WeightsAndBiasesCallback(wandb_kwargs=wandb_kwargs, as_multirun=True) - device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu") -@wandbc.track_in_wandb() def objective(trial): - + """Optimization function.""" parameters_dict = { 'batch_size': 128, "hidden_dims": [2000], 'lambd': 0.005, - 'num_epochs': 2, + 'num_epochs': 10, 'seed': 0, 'num_runs': 1, 'learning_rate': 0.0001 @@ -50,14 +44,13 @@ def objective(trial): model = ACTINN(hidden_dims=parameter_config.get('hidden_dims'), lambd=parameter_config.get('lambd'), device=device) for seed in range(parameter_config.get('seed'), parameter_config.get('seed') + parameter_config.get('num_runs')): set_seed(seed) - model.fit(x_train, y_train, seed=seed, lr=parameter_config.get('learning_rate'), num_epochs=parameter_config.get('num_epochs'), batch_size=parameter_config.get('batch_size'), print_cost=False) - scores.append(score := model.score(x_test, y_test)) - wandb.log({"scores": np.mean(scores)}) - return np.mean(scores) + scores.append(model.score(x_test, y_test)) + return {"scores": np.mean(scores)} -study = optuna.create_study() -study.optimize(objective, n_trials=2, callbacks=[wandbc]) +if __name__ == "__main__": + start_optimizer = get_optimizer(project="step3-project", objective=objective) + start_optimizer() diff --git a/test_automl/step3_config.py b/test_automl/step3_config.py index ba47ff351..2054bd95a 100644 --- a/test_automl/step3_config.py +++ b/test_automl/step3_config.py @@ -3,7 +3,9 @@ import optuna import scanpy as sc from fun2code import fun2code_dict +from optuna.integration.wandb import WeightsAndBiasesCallback +import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform @@ -12,6 +14,7 @@ def set_method_name(func): + """get_method_name.""" def wrapper(*args, **kwargs): method_name = func.__name__ + "_" @@ -119,6 +122,8 @@ def normalize_total(method_name: str, trial: optuna.Trial): def get_preprocessing_pipeline(trial, fun_list): + """Obtain the Compose of the preprocessing function according to the preprocessing + function.""" transforms = [] for f_str in fun_list: fun_i = eval(f_str) @@ -130,3 +135,38 @@ def get_preprocessing_pipeline(trial, fun_list): transforms.append(SetConfig(data_config)) preprocessing_pipeline = Compose(*transforms, log_level="INFO") return preprocessing_pipeline + + +def log_in_wandb(wandbc=None): + """Decorate optimization functions.""" + + def decorator(func): + + def wrapper(*args, **kwargs): + wandb_decorator = wandbc.track_in_wandb() + decorator_function = wandb_decorator(func) + result = decorator_function(*args, **kwargs) + wandb.log(result) + values = list(result.values()) + if len(values) == 1: + return values[0] + else: + return tuple(values) + + return wrapper + + return decorator + + +def get_optimizer(project, objective, n_trials=2): + """Get optimizer.""" + wandb_kwargs = {"project": project} + wandbc = WeightsAndBiasesCallback(wandb_kwargs=wandb_kwargs, as_multirun=True) + decorator = log_in_wandb(wandbc) + decorator_function = decorator(objective) + study = optuna.create_study() + + def wrapper(): + study.optimize(decorator_function, n_trials=n_trials, callbacks=[wandbc]) + + return wrapper From 061a659aaf719897adc4b29cc23b146271d557d4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 14:33:55 +0000 Subject: [PATCH 086/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step3_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/step3_config.py b/test_automl/step3_config.py index 2054bd95a..2a95b5767 100644 --- a/test_automl/step3_config.py +++ b/test_automl/step3_config.py @@ -2,10 +2,10 @@ import optuna import scanpy as sc +import wandb from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback -import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform From 6b5c635dcd360d804b7b95454bc4e49978e17bd2 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 22:40:17 +0800 Subject: [PATCH 087/168] rename example.py --- test_automl/{step2.py => step2_example.py} | 0 test_automl/{step3.py => step3_example.py} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename test_automl/{step2.py => step2_example.py} (100%) rename test_automl/{step3.py => step3_example.py} (100%) diff --git a/test_automl/step2.py b/test_automl/step2_example.py similarity index 100% rename from test_automl/step2.py rename to test_automl/step2_example.py diff --git a/test_automl/step3.py b/test_automl/step3_example.py similarity index 100% rename from test_automl/step3.py rename to test_automl/step3_example.py From 98d96fe57ae534ca6d430630433410524208c0ae Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 22:43:22 +0800 Subject: [PATCH 088/168] add todo --- test_automl/fun2code.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test_automl/fun2code.py b/test_automl/fun2code.py index 6f6e07987..75f0e82b2 100644 --- a/test_automl/fun2code.py +++ b/test_automl/fun2code.py @@ -5,6 +5,7 @@ from dance.transforms.interface import AnnDataTransform from dance.transforms.normalize import ScaleFeature, ScTransformR +#TODO register more functions fun2code_dict = { "normalize_total": AnnDataTransform(sc.pp.normalize_total, target_sum=1e4), "log1p": AnnDataTransform(sc.pp.log1p, base=2), @@ -18,4 +19,4 @@ "cell_svd": CellSVD(), "cell_weighted_pca": WeightedFeaturePCA(split_name="train"), "cell_pca": CellPCA() -} +} #funcion 2 code From 5909a9ddfe2d7f8a7842cb6dea8716a1c4ba7f73 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 23:02:37 +0800 Subject: [PATCH 089/168] add comments --- test_automl/step2_config.py | 3 ++- test_automl/step2_example.py | 3 ++- test_automl/step3_config.py | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index 08a862c6d..95bdb8f1d 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,11 +1,12 @@ import functools from itertools import combinations -import wandb from fun2code import fun2code_dict +import wandb from dance.transforms.misc import Compose, SetConfig +#TODO register more functions pipline2fun_dict = { "normalize": { "values": ["normalize_total", "log1p", "scaleFeature", "scTransform"] diff --git a/test_automl/step2_example.py b/test_automl/step2_example.py index 6586affc4..101743bb5 100644 --- a/test_automl/step2_example.py +++ b/test_automl/step2_example.py @@ -74,6 +74,7 @@ def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: if __name__ == "__main__": - function_list = setStep2(startSweep, original_list=["gene_filter", "gene_dim_reduction"]) + """get_function_combinations.""" + function_list = setStep2(startSweep, original_list=["normalize_total", "gene_filter", "gene_dim_reduction"]) for func in function_list: func() diff --git a/test_automl/step3_config.py b/test_automl/step3_config.py index 2a95b5767..a38b055c6 100644 --- a/test_automl/step3_config.py +++ b/test_automl/step3_config.py @@ -2,10 +2,10 @@ import optuna import scanpy as sc -import wandb from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback +import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform @@ -14,7 +14,7 @@ def set_method_name(func): - """get_method_name.""" + """Get method name to name the optimization option.""" def wrapper(*args, **kwargs): method_name = func.__name__ + "_" From a4459b2a309bd9448eea92535fe7bf1b124e5f93 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 15:03:33 +0000 Subject: [PATCH 090/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2_config.py | 2 +- test_automl/step3_config.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index 95bdb8f1d..0e344ade5 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,9 @@ import functools from itertools import combinations +import wandb from fun2code import fun2code_dict -import wandb from dance.transforms.misc import Compose, SetConfig #TODO register more functions diff --git a/test_automl/step3_config.py b/test_automl/step3_config.py index a38b055c6..8bd97e64e 100644 --- a/test_automl/step3_config.py +++ b/test_automl/step3_config.py @@ -2,10 +2,10 @@ import optuna import scanpy as sc +import wandb from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback -import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform From f35022fbc11b3fe1ae3dc26450517eb214f72874 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 23:07:33 +0800 Subject: [PATCH 091/168] update func --- test_automl/step2_config.py | 2 +- test_automl/step3_config.py | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index 0e344ade5..95bdb8f1d 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,9 @@ import functools from itertools import combinations -import wandb from fun2code import fun2code_dict +import wandb from dance.transforms.misc import Compose, SetConfig #TODO register more functions diff --git a/test_automl/step3_config.py b/test_automl/step3_config.py index 8bd97e64e..a2897755a 100644 --- a/test_automl/step3_config.py +++ b/test_automl/step3_config.py @@ -1,11 +1,12 @@ +import functools import sys import optuna import scanpy as sc -import wandb from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback +import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform @@ -16,10 +17,15 @@ def set_method_name(func): """Get method name to name the optimization option.""" + @functools.wraps(func) def wrapper(*args, **kwargs): - method_name = func.__name__ + "_" - result = func(method_name, *args, **kwargs) - return result + try: + method_name = func.__name__ + "_" + result = func(method_name, *args, **kwargs) + return result + except Exception as e: + print(f"{func.__name__}{args}\n==> {e}") + raise e return wrapper From 6a9e62103bfc4a6e8e27c92336d7c7117fbf4efb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 15:07:59 +0000 Subject: [PATCH 092/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2_config.py | 2 +- test_automl/step3_config.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index 95bdb8f1d..0e344ade5 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,9 @@ import functools from itertools import combinations +import wandb from fun2code import fun2code_dict -import wandb from dance.transforms.misc import Compose, SetConfig #TODO register more functions diff --git a/test_automl/step3_config.py b/test_automl/step3_config.py index a2897755a..d60a329a8 100644 --- a/test_automl/step3_config.py +++ b/test_automl/step3_config.py @@ -3,10 +3,10 @@ import optuna import scanpy as sc +import wandb from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback -import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform From 1f349a7c59136b444d72eefc6482bd16b05bb681 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 23:12:49 +0800 Subject: [PATCH 093/168] add comment --- test_automl/step2_config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index 0e344ade5..48099317c 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,9 @@ import functools from itertools import combinations -import wandb from fun2code import fun2code_dict +import wandb from dance.transforms.misc import Compose, SetConfig #TODO register more functions @@ -63,7 +63,7 @@ def wrapper(*args, **kwargs): sweep_config, train = func(parameters_dict) sweep_id = wandb.sweep(sweep_config, project=project) wandb.agent(sweep_id, train, count=count) - except Exception as e: + except Exception as e: #Except, etc. are not necessarily needed in the code. print(f"{func.__name__}{args}\n==> {e}") raise e From ddb460a62123a118bf457685b42fe6c903feb262 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 15:13:20 +0000 Subject: [PATCH 094/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index 48099317c..768847491 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,9 @@ import functools from itertools import combinations +import wandb from fun2code import fun2code_dict -import wandb from dance.transforms.misc import Compose, SetConfig #TODO register more functions From 88f1e654bd176e2bec05ecc72f88f841515001c1 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 19 Jan 2024 23:15:44 +0800 Subject: [PATCH 095/168] add comment --- test_automl/readme.txt | 2 +- test_automl/step2_config.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test_automl/readme.txt b/test_automl/readme.txt index 4d6fb2d21..6c8af9b9c 100644 --- a/test_automl/readme.txt +++ b/test_automl/readme.txt @@ -1,3 +1,3 @@ -If you need to register a new function, first pass the new function in the fun2 code file. +If you need to register a new function, first pass the new function in the fun2code file. If you use step2, you can declare the step2 pipline in step2_config. If you use step3, you can register a new optimization function in step3_config. diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index 768847491..f5b7b62b9 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,12 +1,12 @@ import functools from itertools import combinations -import wandb from fun2code import fun2code_dict +import wandb from dance.transforms.misc import Compose, SetConfig -#TODO register more functions +#TODO register more functions and add more examples pipline2fun_dict = { "normalize": { "values": ["normalize_total", "log1p", "scaleFeature", "scTransform"] From d926a8fd96357c35ee4eed8de869f96e5b4abb86 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 15:16:09 +0000 Subject: [PATCH 096/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index f5b7b62b9..77e1c99c3 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,9 @@ import functools from itertools import combinations +import wandb from fun2code import fun2code_dict -import wandb from dance.transforms.misc import Compose, SetConfig #TODO register more functions and add more examples From 057fea8bf4afcf9b356ae3b1ed27aebb26b368a3 Mon Sep 17 00:00:00 2001 From: xzy Date: Sat, 20 Jan 2024 10:11:41 +0800 Subject: [PATCH 097/168] rename file --- test_automl/fun2code.py | 3 ++- ...example.py => step2_cell_type_annotation_actinn_example.py} | 0 ...example.py => step3_cell_type_annotation_actinn_example.py} | 0 3 files changed, 2 insertions(+), 1 deletion(-) rename test_automl/{step2_example.py => step2_cell_type_annotation_actinn_example.py} (100%) rename test_automl/{step3_example.py => step3_cell_type_annotation_actinn_example.py} (100%) diff --git a/test_automl/fun2code.py b/test_automl/fun2code.py index 75f0e82b2..b6fdcb7cd 100644 --- a/test_automl/fun2code.py +++ b/test_automl/fun2code.py @@ -18,5 +18,6 @@ "Filter_gene_by_regress_score": FilterGenesRegression("enclasc"), "cell_svd": CellSVD(), "cell_weighted_pca": WeightedFeaturePCA(split_name="train"), - "cell_pca": CellPCA() + "cell_pca": CellPCA(), + # "filter_cell_by_count":AnnDataTransform(sc.pp.filter_cells,min_genes=1) } #funcion 2 code diff --git a/test_automl/step2_example.py b/test_automl/step2_cell_type_annotation_actinn_example.py similarity index 100% rename from test_automl/step2_example.py rename to test_automl/step2_cell_type_annotation_actinn_example.py diff --git a/test_automl/step3_example.py b/test_automl/step3_cell_type_annotation_actinn_example.py similarity index 100% rename from test_automl/step3_example.py rename to test_automl/step3_cell_type_annotation_actinn_example.py From 96fe34a0acd5a7065eeaff436eaea44889cf5c48 Mon Sep 17 00:00:00 2001 From: xzy Date: Sat, 20 Jan 2024 17:11:40 +0800 Subject: [PATCH 098/168] step2 cluster --- test_automl/fun2code.py | 4 +- ...ep2_cell_type_annotation_actinn_example.py | 12 +- test_automl/step2_clustering_scdcc.py | 153 ++++++++++++++++++ test_automl/step2_config.py | 26 +-- test_automl/step2_test.py | 2 + ...ep3_cell_type_annotation_actinn_example.py | 10 +- test_automl/step3_clustering_scdcc.py | 0 test_automl/step3_config.py | 34 ++-- test_automl/step3_test.py | 2 + 9 files changed, 218 insertions(+), 25 deletions(-) create mode 100644 test_automl/step2_clustering_scdcc.py create mode 100644 test_automl/step2_test.py create mode 100644 test_automl/step3_clustering_scdcc.py create mode 100644 test_automl/step3_test.py diff --git a/test_automl/fun2code.py b/test_automl/fun2code.py index b6fdcb7cd..7108dec4a 100644 --- a/test_automl/fun2code.py +++ b/test_automl/fun2code.py @@ -3,6 +3,7 @@ from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform +from dance.transforms.misc import SaveRaw from dance.transforms.normalize import ScaleFeature, ScTransformR #TODO register more functions @@ -19,5 +20,6 @@ "cell_svd": CellSVD(), "cell_weighted_pca": WeightedFeaturePCA(split_name="train"), "cell_pca": CellPCA(), - # "filter_cell_by_count":AnnDataTransform(sc.pp.filter_cells,min_genes=1) + "filter_cell_by_count": AnnDataTransform(sc.pp.filter_cells, min_genes=1), + "save_raw": SaveRaw() } #funcion 2 code diff --git a/test_automl/step2_cell_type_annotation_actinn_example.py b/test_automl/step2_cell_type_annotation_actinn_example.py index 101743bb5..7d5b87dcc 100644 --- a/test_automl/step2_cell_type_annotation_actinn_example.py +++ b/test_automl/step2_cell_type_annotation_actinn_example.py @@ -2,10 +2,12 @@ import numpy as np import torch -from step2_config import get_preprocessing_pipeline, log_in_wandb, setStep2 +from step2_config import get_transforms, log_in_wandb, setStep2 +from dance import logger from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN +from dance.transforms.misc import Compose from dance.utils import set_seed device = torch.device("cuda" if torch.cuda.is_available() else "cpu") @@ -15,9 +17,11 @@ def train(config): model = ACTINN(hidden_dims=config.hidden_dims, lambd=config.lambd, device=device) - preprocessing_pipeline = get_preprocessing_pipeline(config=config) - if preprocessing_pipeline is None: + transforms = get_transforms(config=config) + if transforms is None: + logger.warning("skip transforms") return {"scores": 0} + preprocessing_pipeline = Compose(*transforms, log_level="INFO") train_dataset = [753, 3285] test_dataset = [2695] tissue = "Brain" @@ -75,6 +79,6 @@ def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: if __name__ == "__main__": """get_function_combinations.""" - function_list = setStep2(startSweep, original_list=["normalize_total", "gene_filter", "gene_dim_reduction"]) + function_list = setStep2(startSweep, original_list=["normalize", "gene_filter", "gene_dim_reduction"]) for func in function_list: func() diff --git a/test_automl/step2_clustering_scdcc.py b/test_automl/step2_clustering_scdcc.py new file mode 100644 index 000000000..d83e482b0 --- /dev/null +++ b/test_automl/step2_clustering_scdcc.py @@ -0,0 +1,153 @@ +#normalize_per_cell是一定要选的,因为需要n_counts +import os +from typing import Any, Callable, Dict, Tuple + +import numpy as np +import torch +from step2_config import get_transforms, log_in_wandb, setStep2 + +from dance import logger +from dance.datasets.singlemodality import CellTypeAnnotationDataset, ClusteringDataset +from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN +from dance.modules.single_modality.clustering.scdcc import ScDCC +from dance.transforms.misc import Compose, SetConfig +from dance.transforms.preprocess import generate_random_pair +from dance.utils import set_seed + +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + + +@log_in_wandb(config=None) +def train(config): + aris = [] + for seed in range(config.seed, config.seed + config.num_runs): + set_seed(seed) + + # Load data and perform necessary preprocessing + dataloader = ClusteringDataset("./test_automl/data", "10X_PBMC") + + transforms = get_transforms(config=config, set_data_config=False, save_raw=True) + if ("normalize" not in config.keys() or config.normalize != "normalize_total") or transforms is None: + logger.warning("skip transforms") + return {"scores": 0} + transforms.append( + SetConfig({ + "feature_channel": [None, None, "n_counts"], + "feature_channel_type": ["X", "raw_X", "obs"], + "label_channel": "Group" + })) + preprocessing_pipeline = Compose(*transforms, log_level="INFO") + data = dataloader.load_data(transform=preprocessing_pipeline, cache=config.cache) + + # inputs: x, x_raw, n_counts + inputs, y = data.get_train_data() + n_clusters = len(np.unique(y)) + in_dim = inputs[0].shape[1] + + # Generate random pairs + if not os.path.exists(config.label_cells_files): + indx = np.arange(len(y)) + np.random.shuffle(indx) + label_cell_indx = indx[0:int(np.ceil(config.label_cells * len(y)))] + else: + label_cell_indx = np.loadtxt(config.label_cells_files, dtype=np.int) + + if config.n_pairwise > 0: + ml_ind1, ml_ind2, cl_ind1, cl_ind2, error_num = generate_random_pair(y, label_cell_indx, config.n_pairwise, + config.n_pairwise_error) + print("Must link paris: %d" % ml_ind1.shape[0]) + print("Cannot link paris: %d" % cl_ind1.shape[0]) + print("Number of error pairs: %d" % error_num) + else: + ml_ind1, ml_ind2, cl_ind1, cl_ind2 = np.array([]), np.array([]), np.array([]), np.array([]) + + # Build and train moodel + model = ScDCC(input_dim=in_dim, z_dim=config.z_dim, n_clusters=n_clusters, encodeLayer=config.encodeLayer, + decodeLayer=config.encodeLayer[::-1], sigma=config.sigma, gamma=config.gamma, + ml_weight=config.ml_weight, cl_weight=config.ml_weight, device=config.device, + pretrain_path=f"scdcc_{config.dataset}_pre.pkl") + model.fit(inputs, y, lr=config.lr, batch_size=config.batch_size, epochs=config.epochs, ml_ind1=ml_ind1, + ml_ind2=ml_ind2, cl_ind1=cl_ind1, cl_ind2=cl_ind2, update_interval=config.update_interval, + tol=config.tol, pt_batch_size=config.batch_size, pt_lr=config.pretrain_lr, + pt_epochs=config.pretrain_epochs) + + # Evaluate model predictions + score = model.score(None, y) + print(f"{score=:.4f}") + aris.append(score) + + print('scdcc') + print(config.dataset) + print(f'aris: {aris}') + print(f'aris: {np.mean(aris)} +/- {np.std(aris)}') + return ({"scores": np.mean(aris)}) + + +def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: + parameters_dict.update({ + 'seed': { + 'value': 0 + }, + 'num_runs': { + 'value': 1 + }, + 'cache': { + 'value': True + }, + 'label_cells_files': { + 'value': 'label_10X_PBMC.txt' + }, + 'label_cells': { + 'value': 0.1 + }, + 'n_pairwise': { + 'value': 0 + }, + 'n_pairwise_error': { + 'value': 0 + }, + 'z_dim': { + 'value': 32 + }, + 'encodeLayer': { + 'value': [256, 64] + }, + 'sigma': { + 'value': 2.5 + }, + 'gamma': { + 'value': 1.0 + }, + 'ml_weight': { + 'value': 1.0 + }, + 'cl_weight': { + 'value': 1.0 + }, + 'update_interval': { + 'value': 1.0 + }, + 'tol': { + 'value': 0.00001 + }, + 'ae_weights': { + 'value': None + }, + 'ae_weight_file': { + 'value': "AE_weights.pth.tar" + } + }) + + sweep_config = {'method': 'grid'} + sweep_config['parameters'] = parameters_dict + metric = {'name': 'scores', 'goal': 'maximize'} + + sweep_config['metric'] = metric + return sweep_config, train #Return function configuration and training function + + +if __name__ == "__main__": + """get_function_combinations.""" + function_list = setStep2(startSweep, original_list=["gene_filter", "cell_filter", "normalize"]) + for func in function_list: + func() diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index 77e1c99c3..aa0407bac 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,9 @@ import functools from itertools import combinations -import wandb from fun2code import fun2code_dict +import wandb from dance.transforms.misc import Compose, SetConfig #TODO register more functions and add more examples @@ -17,6 +17,9 @@ }, "gene_dim_reduction": { "values": ["cell_svd", "cell_weighted_pca", "cell_pca"] + }, + "cell_filter": { + "values": ["filter_cell_by_count"] } } #Functions registered in the preprocessing process @@ -25,13 +28,14 @@ def getFunConfig(selected_keys=None): """Get the config that needs to be optimized and the number of rounds.""" global pipline2fun_dict pipline2fun_dict_subset = {key: pipline2fun_dict[key] for key in selected_keys} + print(pipline2fun_dict) count = 1 for _, pipline_values in pipline2fun_dict_subset.items(): count *= len(pipline_values['values']) return pipline2fun_dict_subset, count -def get_preprocessing_pipeline(config=None): +def get_transforms(config=None, set_data_config=True, save_raw=False): """Obtain the Compose of the preprocessing function according to the preprocessing process.""" if ("normalize" not in config.keys() or config.normalize @@ -39,15 +43,19 @@ def get_preprocessing_pipeline(config=None): return None transforms = [] - transforms.append(fun2code_dict[config.normalize]) if "normalize" in config.keys() else None transforms.append(fun2code_dict[config.gene_filter]) if "gene_filter" in config.keys() else None + transforms.append(fun2code_dict[config.cell_filter]) if "cell_filter" in config.keys() else None + if save_raw: + transforms.append(fun2code_dict["save_raw"]) + transforms.append(fun2code_dict[config.normalize]) if "normalize" in config.keys() else None transforms.append(fun2code_dict[config.gene_dim_reduction]) if "gene_dim_reduction" in config.keys() else None - data_config = {"label_channel": "cell_type"} - if "gene_dim_reduction" in config.keys(): - data_config.update({"feature_channel": fun2code_dict[config.gene_dim_reduction].name}) - transforms.append(SetConfig(data_config)) - preprocessing_pipeline = Compose(*transforms, log_level="INFO") - return preprocessing_pipeline + + if set_data_config: + data_config = {"label_channel": "cell_type"} + if "gene_dim_reduction" in config.keys(): + data_config.update({"feature_channel": fun2code_dict[config.gene_dim_reduction].name}) + transforms.append(SetConfig(data_config)) + return transforms def sweepDecorator(selected_keys=None, project="pytorch-cell_type_annotation_ACTINN"): diff --git a/test_automl/step2_test.py b/test_automl/step2_test.py new file mode 100644 index 000000000..6cac0ed0c --- /dev/null +++ b/test_automl/step2_test.py @@ -0,0 +1,2 @@ +def test_get_preprocessing_pipeline(): + pass #不一定需要,因为主要都是装饰器函数 diff --git a/test_automl/step3_cell_type_annotation_actinn_example.py b/test_automl/step3_cell_type_annotation_actinn_example.py index 22a977691..e913e10d6 100644 --- a/test_automl/step3_cell_type_annotation_actinn_example.py +++ b/test_automl/step3_cell_type_annotation_actinn_example.py @@ -1,10 +1,12 @@ import numpy as np import optuna import torch -from step3_config import get_optimizer, get_preprocessing_pipeline +from step3_config import get_optimizer, get_transforms +from dance import logger from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN +from dance.transforms.misc import Compose from dance.utils import set_seed fun_list = ["log1p", "filter_gene_by_count"] @@ -30,7 +32,11 @@ def objective(trial): species = "mouse" dataloader = CellTypeAnnotationDataset(train_dataset=train_dataset, test_dataset=test_dataset, tissue=tissue, species=species, data_dir="./test_automl/data") - preprocessing_pipeline = get_preprocessing_pipeline(trial=trial, fun_list=fun_list) + transforms = get_transforms(trial=trial, fun_list=fun_list) + if transforms is None: + logger.warning("skip transforms") + return {"scores": 0} + preprocessing_pipeline = Compose(*transforms, log_level="INFO") data = dataloader.load_data(transform=preprocessing_pipeline, cache=True) # Obtain training and testing data diff --git a/test_automl/step3_clustering_scdcc.py b/test_automl/step3_clustering_scdcc.py new file mode 100644 index 000000000..e69de29bb diff --git a/test_automl/step3_config.py b/test_automl/step3_config.py index d60a329a8..6b575319a 100644 --- a/test_automl/step3_config.py +++ b/test_automl/step3_config.py @@ -3,10 +3,10 @@ import optuna import scanpy as sc -import wandb from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback +import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform @@ -115,6 +115,20 @@ def normalize_total(method_name: str, trial: optuna.Trial): exclude_highly_expressed=exclude_highly_expressed, max_fraction=max_fraction) +@set_method_name +def filter_cell_by_count(method_name: str, trial: optuna.Trial): + method = trial.suggest_categorical(method_name + "method", ['min_counts', 'min_genes', 'max_counts', 'max_genes']) + if method == "min_counts": + num = trial.suggest_int(method_name + "num", 2, 10) + if method == "min_genes": + num = trial.suggest_int(method_name + "num", 2, 10) + if method == "max_counts": + num = trial.suggest_int(method_name + "num", 500, 1000) + if method == "max_genes": + num = trial.suggest_int(method_name + "num", 500, 1000) + return AnnDataTransform(sc.pp.filter_cells, **{method: num}) + + # # 获取当前文件中的所有函数 # functions = [(name,obj) for name, obj in inspect.getmembers( # sys.modules[__name__]) if inspect.isfunction(obj)] @@ -127,20 +141,22 @@ def normalize_total(method_name: str, trial: optuna.Trial): # setattr(__name__, name, set_method_name(function)) -def get_preprocessing_pipeline(trial, fun_list): +def get_transforms(trial, fun_list, set_data_config=True): """Obtain the Compose of the preprocessing function according to the preprocessing function.""" transforms = [] for f_str in fun_list: fun_i = eval(f_str) transforms.append(fun_i(trial)) - data_config = {"label_channel": "cell_type"} - feature_name = {"cell_svd", "cell_weighted_pca", "cell_pca"} & set(fun_list) - if feature_name: - data_config.update({"feature_channel": fun2code_dict[feature_name].name}) - transforms.append(SetConfig(data_config)) - preprocessing_pipeline = Compose(*transforms, log_level="INFO") - return preprocessing_pipeline + if "highly_variable_genes" in fun_list and "log1p" not in fun_list[:fun_list.index('"highly_variable_genes"')]: + return None + if set_data_config: + data_config = {"label_channel": "cell_type"} + feature_name = {"cell_svd", "cell_weighted_pca", "cell_pca"} & set(fun_list) + if feature_name: + data_config.update({"feature_channel": fun2code_dict[feature_name].name}) + transforms.append(SetConfig(data_config)) + return transforms def log_in_wandb(wandbc=None): diff --git a/test_automl/step3_test.py b/test_automl/step3_test.py new file mode 100644 index 000000000..6cac0ed0c --- /dev/null +++ b/test_automl/step3_test.py @@ -0,0 +1,2 @@ +def test_get_preprocessing_pipeline(): + pass #不一定需要,因为主要都是装饰器函数 From ba32644b861643e19dc5bed6cd76e97b0b297004 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 20 Jan 2024 09:12:09 +0000 Subject: [PATCH 099/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2_config.py | 2 +- test_automl/step3_config.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index aa0407bac..b6dd3d189 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,9 @@ import functools from itertools import combinations +import wandb from fun2code import fun2code_dict -import wandb from dance.transforms.misc import Compose, SetConfig #TODO register more functions and add more examples diff --git a/test_automl/step3_config.py b/test_automl/step3_config.py index 6b575319a..055bbb9f7 100644 --- a/test_automl/step3_config.py +++ b/test_automl/step3_config.py @@ -3,10 +3,10 @@ import optuna import scanpy as sc +import wandb from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback -import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform From 56e12917e0c41f27600ec0a6521e0b1b3847a92a Mon Sep 17 00:00:00 2001 From: xzy Date: Sun, 21 Jan 2024 00:02:07 +0800 Subject: [PATCH 100/168] update step2 cluster --- .gitignore | 1 + test_automl/fun2code.py | 2 +- test_automl/step2_clustering_scdcc.py | 27 ++++++++++++++++++++------- test_automl/step2_config.py | 2 +- test_automl/step3_config.py | 8 +++++--- 5 files changed, 28 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 3471a1ae3..db77ec215 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ wandb test_automl/data test_automl/test.py +*.pkl diff --git a/test_automl/fun2code.py b/test_automl/fun2code.py index 7108dec4a..01e4c6579 100644 --- a/test_automl/fun2code.py +++ b/test_automl/fun2code.py @@ -8,7 +8,7 @@ #TODO register more functions fun2code_dict = { - "normalize_total": AnnDataTransform(sc.pp.normalize_total, target_sum=1e4), + "normalize_total": AnnDataTransform(sc.pp.normalize_total, target_sum=1e4, key_added="n_counts"), "log1p": AnnDataTransform(sc.pp.log1p, base=2), "scaleFeature": ScaleFeature(split_names="ALL", mode="standardize"), "scTransform": ScTransformR(mirror_index=1), diff --git a/test_automl/step2_clustering_scdcc.py b/test_automl/step2_clustering_scdcc.py index d83e482b0..325ac0fca 100644 --- a/test_automl/step2_clustering_scdcc.py +++ b/test_automl/step2_clustering_scdcc.py @@ -7,8 +7,7 @@ from step2_config import get_transforms, log_in_wandb, setStep2 from dance import logger -from dance.datasets.singlemodality import CellTypeAnnotationDataset, ClusteringDataset -from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN +from dance.datasets.singlemodality import ClusteringDataset from dance.modules.single_modality.clustering.scdcc import ScDCC from dance.transforms.misc import Compose, SetConfig from dance.transforms.preprocess import generate_random_pair @@ -22,9 +21,9 @@ def train(config): aris = [] for seed in range(config.seed, config.seed + config.num_runs): set_seed(seed) - + dataset = "10X_PBMC" # Load data and perform necessary preprocessing - dataloader = ClusteringDataset("./test_automl/data", "10X_PBMC") + dataloader = ClusteringDataset("./test_automl/data", dataset=dataset) transforms = get_transforms(config=config, set_data_config=False, save_raw=True) if ("normalize" not in config.keys() or config.normalize != "normalize_total") or transforms is None: @@ -64,8 +63,8 @@ def train(config): # Build and train moodel model = ScDCC(input_dim=in_dim, z_dim=config.z_dim, n_clusters=n_clusters, encodeLayer=config.encodeLayer, decodeLayer=config.encodeLayer[::-1], sigma=config.sigma, gamma=config.gamma, - ml_weight=config.ml_weight, cl_weight=config.ml_weight, device=config.device, - pretrain_path=f"scdcc_{config.dataset}_pre.pkl") + ml_weight=config.ml_weight, cl_weight=config.ml_weight, device=device, + pretrain_path=f"scdcc_{dataset}_pre.pkl") model.fit(inputs, y, lr=config.lr, batch_size=config.batch_size, epochs=config.epochs, ml_ind1=ml_ind1, ml_ind2=ml_ind2, cl_ind1=cl_ind1, cl_ind2=cl_ind2, update_interval=config.update_interval, tol=config.tol, pt_batch_size=config.batch_size, pt_lr=config.pretrain_lr, @@ -77,7 +76,6 @@ def train(config): aris.append(score) print('scdcc') - print(config.dataset) print(f'aris: {aris}') print(f'aris: {np.mean(aris)} +/- {np.std(aris)}') return ({"scores": np.mean(aris)}) @@ -118,6 +116,12 @@ def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: 'gamma': { 'value': 1.0 }, + 'lr': { + 'value': 0.01 + }, + 'pretrain_lr': { + 'value': 0.001 + }, 'ml_weight': { 'value': 1.0 }, @@ -135,6 +139,15 @@ def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: }, 'ae_weight_file': { 'value': "AE_weights.pth.tar" + }, + 'pretrain_epochs': { + 'value': 50 + }, + 'epochs': { + 'value': 500 + }, + 'batch_size': { + 'value': 256 } }) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index b6dd3d189..aa0407bac 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,9 @@ import functools from itertools import combinations -import wandb from fun2code import fun2code_dict +import wandb from dance.transforms.misc import Compose, SetConfig #TODO register more functions and add more examples diff --git a/test_automl/step3_config.py b/test_automl/step3_config.py index 055bbb9f7..edd361e64 100644 --- a/test_automl/step3_config.py +++ b/test_automl/step3_config.py @@ -3,10 +3,10 @@ import optuna import scanpy as sc -import wandb from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback +import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform @@ -108,11 +108,13 @@ def normalize_total(method_name: str, trial: optuna.Trial): max_fraction = trial.suggest_float(method_name + "max_fraction", 0.04, 0.1) return AnnDataTransform(sc.pp.normalize_total, target_sum=trial.suggest_categorical(method_name + "target_sum", [1e4, 1e5, 1e6]), - exclude_highly_expressed=exclude_highly_expressed, max_fraction=max_fraction) + exclude_highly_expressed=exclude_highly_expressed, max_fraction=max_fraction, + key_added="n_counts") else: return AnnDataTransform(sc.pp.normalize_total, target_sum=trial.suggest_categorical(method_name + "target_sum", [1e4, 1e5, 1e6]), - exclude_highly_expressed=exclude_highly_expressed, max_fraction=max_fraction) + exclude_highly_expressed=exclude_highly_expressed, max_fraction=max_fraction, + key_added="n_counts") @set_method_name From 93ad2f0245c1e8d7369b63297a9bd803448fa0ab Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 20 Jan 2024 16:02:50 +0000 Subject: [PATCH 101/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2_config.py | 2 +- test_automl/step3_config.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index aa0407bac..b6dd3d189 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,9 @@ import functools from itertools import combinations +import wandb from fun2code import fun2code_dict -import wandb from dance.transforms.misc import Compose, SetConfig #TODO register more functions and add more examples diff --git a/test_automl/step3_config.py b/test_automl/step3_config.py index edd361e64..a2a13f2a7 100644 --- a/test_automl/step3_config.py +++ b/test_automl/step3_config.py @@ -3,10 +3,10 @@ import optuna import scanpy as sc +import wandb from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback -import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform From 404763e1bbb06ba817c50b5803befb2ca00766b8 Mon Sep 17 00:00:00 2001 From: xzy Date: Sun, 21 Jan 2024 09:11:48 +0800 Subject: [PATCH 102/168] change location --- test_automl/{ => tests}/step2_test.py | 0 test_automl/{ => tests}/step3_test.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename test_automl/{ => tests}/step2_test.py (100%) rename test_automl/{ => tests}/step3_test.py (100%) diff --git a/test_automl/step2_test.py b/test_automl/tests/step2_test.py similarity index 100% rename from test_automl/step2_test.py rename to test_automl/tests/step2_test.py diff --git a/test_automl/step3_test.py b/test_automl/tests/step3_test.py similarity index 100% rename from test_automl/step3_test.py rename to test_automl/tests/step3_test.py From 11367957ac188cdd673fa99461d0106e5beed311 Mon Sep 17 00:00:00 2001 From: xzy Date: Sun, 21 Jan 2024 09:13:24 +0800 Subject: [PATCH 103/168] update comment --- test_automl/step2_clustering_scdcc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/step2_clustering_scdcc.py b/test_automl/step2_clustering_scdcc.py index 325ac0fca..e35f86fb4 100644 --- a/test_automl/step2_clustering_scdcc.py +++ b/test_automl/step2_clustering_scdcc.py @@ -1,4 +1,4 @@ -#normalize_per_cell是一定要选的,因为需要n_counts +#normalize_total是一定要选的,因为需要n_counts import os from typing import Any, Callable, Dict, Tuple From 9e8fe52382872cb1429e7ff2cc2ad727c0835eba Mon Sep 17 00:00:00 2001 From: xzy Date: Sun, 21 Jan 2024 10:52:53 +0800 Subject: [PATCH 104/168] add step3 cluster --- .../single_modality/clustering/scdcc.py | 2 +- test_automl/step3_clustering_scdcc.py | 113 ++++++++++++++++++ test_automl/step3_config.py | 10 +- 3 files changed, 120 insertions(+), 5 deletions(-) diff --git a/dance/modules/single_modality/clustering/scdcc.py b/dance/modules/single_modality/clustering/scdcc.py index 8fbe0f6ff..02c4ab78e 100644 --- a/dance/modules/single_modality/clustering/scdcc.py +++ b/dance/modules/single_modality/clustering/scdcc.py @@ -521,7 +521,7 @@ def fit( float(ml_loss.cpu()) + float(cl_loss.cpu()), ml_loss.cpu(), cl_loss.cpu()) index = update_interval * np.argmax(aris) - self.q = Q[f"epoch{index}"] + self.q = Q[f"epoch{int(index)}"] def predict_proba(self, x: Optional[Any] = None) -> np.ndarray: """Get the predicted propabilities for each cell. diff --git a/test_automl/step3_clustering_scdcc.py b/test_automl/step3_clustering_scdcc.py index e69de29bb..99a6f2f88 100644 --- a/test_automl/step3_clustering_scdcc.py +++ b/test_automl/step3_clustering_scdcc.py @@ -0,0 +1,113 @@ +import os + +import numpy as np +import torch +from step3_config import get_optimizer, get_transforms + +from dance import logger +from dance.datasets.singlemodality import ClusteringDataset +from dance.modules.single_modality.clustering.scdcc import ScDCC +from dance.registry import DotDict # 可以用可以不用 +from dance.transforms.misc import Compose, SetConfig +from dance.transforms.preprocess import generate_random_pair +from dance.utils import set_seed + +fun_list = ["filter_cell_by_count", "filter_gene_by_count", "normalize_total"] + +device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu") + + +def objective(trial): + """Optimization function.""" + parameters_dict = { + 'seed': 0, + 'num_runs': 1, + 'cache': True, + 'label_cells_files': 'label_10X_PBMC.txt', + 'label_cells': 0.1, + 'n_pairwise': 0, + 'n_pairwise_error': 0, + 'z_dim': 32, + 'encodeLayer': [256, 64], + 'sigma': 2.5, + 'gamma': 1.0, + 'lr': 0.01, + 'pretrain_lr': 0.001, + 'ml_weight': 1.0, + 'cl_weight': 1.0, + 'update_interval': 1.0, + 'tol': 0.00001, + 'ae_weights': None, + 'ae_weight_file': "AE_weights.pth.tar", + 'pretrain_epochs': 50, + 'epochs': 500, + 'batch_size': 256 + } + transforms = get_transforms(trial=trial, fun_list=fun_list, set_data_config=False, save_raw=True) + transforms.append( + SetConfig({ + "feature_channel": [None, None, "n_counts"], + "feature_channel_type": ["X", "raw_X", "obs"], + "label_channel": "Group" + })) + preprocessing_pipeline = Compose(*transforms, log_level="INFO") + parameters_config = {} + parameters_config.update(parameters_dict) + parameters_config = DotDict(parameters_config) + aris = [] + for seed in range(parameters_config.seed, parameters_config.seed + parameters_config.num_runs): + set_seed(seed) + dataset = "10X_PBMC" + # Load data and perform necessary preprocessing + dataloader = ClusteringDataset("./test_automl/data", dataset=dataset) + data = dataloader.load_data(transform=preprocessing_pipeline, cache=parameters_config.cache) + + # inputs: x, x_raw, n_counts + inputs, y = data.get_train_data() + n_clusters = len(np.unique(y)) + in_dim = inputs[0].shape[1] + + # Generate random pairs + if not os.path.exists(parameters_config.label_cells_files): + indx = np.arange(len(y)) + np.random.shuffle(indx) + label_cell_indx = indx[0:int(np.ceil(parameters_config.label_cells * len(y)))] + else: + label_cell_indx = np.loadtxt(parameters_config.label_cells_files, dtype=np.int) + + if parameters_config.n_pairwise > 0: + ml_ind1, ml_ind2, cl_ind1, cl_ind2, error_num = generate_random_pair(y, label_cell_indx, + parameters_config.n_pairwise, + parameters_config.n_pairwise_error) + print("Must link paris: %d" % ml_ind1.shape[0]) + print("Cannot link paris: %d" % cl_ind1.shape[0]) + print("Number of error pairs: %d" % error_num) + else: + ml_ind1, ml_ind2, cl_ind1, cl_ind2 = np.array([]), np.array([]), np.array([]), np.array([]) + + # Build and train moodel + model = ScDCC(input_dim=in_dim, z_dim=parameters_config.z_dim, n_clusters=n_clusters, + encodeLayer=parameters_config.encodeLayer, decodeLayer=parameters_config.encodeLayer[::-1], + sigma=parameters_config.sigma, gamma=parameters_config.gamma, + ml_weight=parameters_config.ml_weight, cl_weight=parameters_config.ml_weight, device=device, + pretrain_path=f"scdcc_{dataset}_pre.pkl") + model.fit(inputs, y, lr=parameters_config.lr, batch_size=parameters_config.batch_size, + epochs=parameters_config.epochs, ml_ind1=ml_ind1, ml_ind2=ml_ind2, cl_ind1=cl_ind1, cl_ind2=cl_ind2, + update_interval=parameters_config.update_interval, tol=parameters_config.tol, + pt_batch_size=parameters_config.batch_size, pt_lr=parameters_config.pretrain_lr, + pt_epochs=parameters_config.pretrain_epochs) + + # Evaluate model predictions + score = model.score(None, y) + print(f"{score=:.4f}") + aris.append(score) + + print('scdcc') + print(f'aris: {aris}') + print(f'aris: {np.mean(aris)} +/- {np.std(aris)}') + return ({"scores": np.mean(aris)}) + + +if __name__ == "__main__": + start_optimizer = get_optimizer(project="step3-cluster-scdcc-project", objective=objective) + start_optimizer() diff --git a/test_automl/step3_config.py b/test_automl/step3_config.py index a2a13f2a7..741e2ea43 100644 --- a/test_automl/step3_config.py +++ b/test_automl/step3_config.py @@ -3,10 +3,11 @@ import optuna import scanpy as sc -import wandb from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback +from step2_config import pipline2fun_dict +import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform @@ -113,8 +114,7 @@ def normalize_total(method_name: str, trial: optuna.Trial): else: return AnnDataTransform(sc.pp.normalize_total, target_sum=trial.suggest_categorical(method_name + "target_sum", [1e4, 1e5, 1e6]), - exclude_highly_expressed=exclude_highly_expressed, max_fraction=max_fraction, - key_added="n_counts") + exclude_highly_expressed=exclude_highly_expressed, key_added="n_counts") @set_method_name @@ -143,11 +143,13 @@ def filter_cell_by_count(method_name: str, trial: optuna.Trial): # setattr(__name__, name, set_method_name(function)) -def get_transforms(trial, fun_list, set_data_config=True): +def get_transforms(trial, fun_list, set_data_config=True, save_raw=False): """Obtain the Compose of the preprocessing function according to the preprocessing function.""" transforms = [] for f_str in fun_list: + if f_str in pipline2fun_dict['normalize']['values'] and save_raw: + transforms.append(fun2code_dict["save_raw"]) fun_i = eval(f_str) transforms.append(fun_i(trial)) if "highly_variable_genes" in fun_list and "log1p" not in fun_list[:fun_list.index('"highly_variable_genes"')]: From 557a9a3bf75e29c725259b10aa3abec133e8b10e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 21 Jan 2024 02:53:19 +0000 Subject: [PATCH 105/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step3_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/step3_config.py b/test_automl/step3_config.py index 741e2ea43..a621acc74 100644 --- a/test_automl/step3_config.py +++ b/test_automl/step3_config.py @@ -3,11 +3,11 @@ import optuna import scanpy as sc +import wandb from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback from step2_config import pipline2fun_dict -import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform From 1c62d3c1efeefe59ea0b77487c134f6012de3777 Mon Sep 17 00:00:00 2001 From: xzy Date: Sun, 21 Jan 2024 15:04:03 +0800 Subject: [PATCH 106/168] update step3 cluster --- test_automl/step3_clustering_scdcc.py | 21 ++++++++++++++------- test_automl/step3_config.py | 8 ++++---- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/test_automl/step3_clustering_scdcc.py b/test_automl/step3_clustering_scdcc.py index 99a6f2f88..f93b1963c 100644 --- a/test_automl/step3_clustering_scdcc.py +++ b/test_automl/step3_clustering_scdcc.py @@ -91,12 +91,19 @@ def objective(trial): sigma=parameters_config.sigma, gamma=parameters_config.gamma, ml_weight=parameters_config.ml_weight, cl_weight=parameters_config.ml_weight, device=device, pretrain_path=f"scdcc_{dataset}_pre.pkl") - model.fit(inputs, y, lr=parameters_config.lr, batch_size=parameters_config.batch_size, - epochs=parameters_config.epochs, ml_ind1=ml_ind1, ml_ind2=ml_ind2, cl_ind1=cl_ind1, cl_ind2=cl_ind2, - update_interval=parameters_config.update_interval, tol=parameters_config.tol, - pt_batch_size=parameters_config.batch_size, pt_lr=parameters_config.pretrain_lr, - pt_epochs=parameters_config.pretrain_epochs) - + try: + model.fit(inputs, y, lr=parameters_config.lr, batch_size=parameters_config.batch_size, + epochs=parameters_config.epochs, ml_ind1=ml_ind1, ml_ind2=ml_ind2, cl_ind1=cl_ind1, + cl_ind2=cl_ind2, update_interval=parameters_config.update_interval, tol=parameters_config.tol, + pt_batch_size=parameters_config.batch_size, pt_lr=parameters_config.pretrain_lr, + pt_epochs=parameters_config.pretrain_epochs) + except Exception as e: + """If don't skip the error, then all hyperparameter combinations will + inevitably have problems when facing all datasets and models, and need to + ensure the effectiveness of automatic machine learning and ignore some + hyperparameters.""" + print(e) + return ({"scores": 0}) # Evaluate model predictions score = model.score(None, y) print(f"{score=:.4f}") @@ -109,5 +116,5 @@ def objective(trial): if __name__ == "__main__": - start_optimizer = get_optimizer(project="step3-cluster-scdcc-project", objective=objective) + start_optimizer = get_optimizer(project="step3-cluster-scdcc-project", objective=objective, n_trials=10) start_optimizer() diff --git a/test_automl/step3_config.py b/test_automl/step3_config.py index a621acc74..566b19e27 100644 --- a/test_automl/step3_config.py +++ b/test_automl/step3_config.py @@ -3,11 +3,11 @@ import optuna import scanpy as sc -import wandb from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback from step2_config import pipline2fun_dict +import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform @@ -106,7 +106,7 @@ def scaleFeature(method_name: str, trial: optuna.Trial): #eps未优化 def normalize_total(method_name: str, trial: optuna.Trial): exclude_highly_expressed = trial.suggest_categorical(method_name + "exclude_highly_expressed", [False, True]) if exclude_highly_expressed: - max_fraction = trial.suggest_float(method_name + "max_fraction", 0.04, 0.1) + max_fraction = trial.suggest_float(method_name + "max_fraction", 0.08, 0.1) return AnnDataTransform(sc.pp.normalize_total, target_sum=trial.suggest_categorical(method_name + "target_sum", [1e4, 1e5, 1e6]), exclude_highly_expressed=exclude_highly_expressed, max_fraction=max_fraction, @@ -121,9 +121,9 @@ def normalize_total(method_name: str, trial: optuna.Trial): def filter_cell_by_count(method_name: str, trial: optuna.Trial): method = trial.suggest_categorical(method_name + "method", ['min_counts', 'min_genes', 'max_counts', 'max_genes']) if method == "min_counts": - num = trial.suggest_int(method_name + "num", 2, 10) + num = trial.suggest_int(method_name + "num", 1, 10) if method == "min_genes": - num = trial.suggest_int(method_name + "num", 2, 10) + num = trial.suggest_int(method_name + "num", 1, 10) if method == "max_counts": num = trial.suggest_int(method_name + "num", 500, 1000) if method == "max_genes": From 64ef717cca4a982e53e3d07662aebdc294b401ee Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 21 Jan 2024 07:04:36 +0000 Subject: [PATCH 107/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step3_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/step3_config.py b/test_automl/step3_config.py index 566b19e27..67a466c1d 100644 --- a/test_automl/step3_config.py +++ b/test_automl/step3_config.py @@ -3,11 +3,11 @@ import optuna import scanpy as sc +import wandb from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback from step2_config import pipline2fun_dict -import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform From 0bf93bd507a28ea2f140c28ab60cb303f30e82ed Mon Sep 17 00:00:00 2001 From: xzy Date: Sun, 21 Jan 2024 16:15:36 +0800 Subject: [PATCH 108/168] register imputation --- test_automl/fun2code.py | 5 ++++- test_automl/step2_config.py | 5 ++++- test_automl/step2_imputation_deepimpute.py | 0 test_automl/step3_config.py | 15 ++++++++++++++- 4 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 test_automl/step2_imputation_deepimpute.py diff --git a/test_automl/fun2code.py b/test_automl/fun2code.py index 01e4c6579..7656c88f7 100644 --- a/test_automl/fun2code.py +++ b/test_automl/fun2code.py @@ -3,6 +3,7 @@ from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform +from dance.transforms.mask import CellwiseMaskData, MaskData from dance.transforms.misc import SaveRaw from dance.transforms.normalize import ScaleFeature, ScTransformR @@ -21,5 +22,7 @@ "cell_weighted_pca": WeightedFeaturePCA(split_name="train"), "cell_pca": CellPCA(), "filter_cell_by_count": AnnDataTransform(sc.pp.filter_cells, min_genes=1), - "save_raw": SaveRaw() + "save_raw": SaveRaw(), + "cell_wise_mask_data": CellwiseMaskData(), + "mask_data": MaskData() } #funcion 2 code diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index b6dd3d189..c1406161b 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,9 @@ import functools from itertools import combinations -import wandb from fun2code import fun2code_dict +import wandb from dance.transforms.misc import Compose, SetConfig #TODO register more functions and add more examples @@ -20,6 +20,9 @@ }, "cell_filter": { "values": ["filter_cell_by_count"] + }, + "mask": { + "values": ["cell_wise_mask_data", "mask_data"] } } #Functions registered in the preprocessing process diff --git a/test_automl/step2_imputation_deepimpute.py b/test_automl/step2_imputation_deepimpute.py new file mode 100644 index 000000000..e69de29bb diff --git a/test_automl/step3_config.py b/test_automl/step3_config.py index 67a466c1d..2a0810a9e 100644 --- a/test_automl/step3_config.py +++ b/test_automl/step3_config.py @@ -3,14 +3,15 @@ import optuna import scanpy as sc -import wandb from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback from step2_config import pipline2fun_dict +import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform +from dance.transforms.mask import CellwiseMaskData, MaskData from dance.transforms.misc import Compose, SetConfig from dance.transforms.normalize import ScaleFeature, ScTransformR @@ -131,6 +132,18 @@ def filter_cell_by_count(method_name: str, trial: optuna.Trial): return AnnDataTransform(sc.pp.filter_cells, **{method: num}) +@set_method_name +def cell_wise_mask_data(method_name: str, trial: optuna.Trial): + return CellwiseMaskData(distr=trial.suggest_categorical(method_name + "distr", ['exp', 'uniform']), + mask_rate=trial.suggest_float(method_name + "mask_rate", 0.01, 0.5), + min_gene_counts=trial.suggest_int(method_name + "min_gene_counts", 1, 10)) + + +@set_method_name +def mask_data(method_name: str, trial: optuna.Trial): + return MaskData(mask_rate=trial.suggest_float(method_name + "mask_rate", 0.01, 0.5)) + + # # 获取当前文件中的所有函数 # functions = [(name,obj) for name, obj in inspect.getmembers( # sys.modules[__name__]) if inspect.isfunction(obj)] From af396af60ca901f5a2671e56829ae60431904b36 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 21 Jan 2024 08:16:04 +0000 Subject: [PATCH 109/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2_config.py | 2 +- test_automl/step3_config.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index c1406161b..a0af7ad38 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,9 @@ import functools from itertools import combinations +import wandb from fun2code import fun2code_dict -import wandb from dance.transforms.misc import Compose, SetConfig #TODO register more functions and add more examples diff --git a/test_automl/step3_config.py b/test_automl/step3_config.py index 2a0810a9e..9850b0997 100644 --- a/test_automl/step3_config.py +++ b/test_automl/step3_config.py @@ -3,11 +3,11 @@ import optuna import scanpy as sc +import wandb from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback from step2_config import pipline2fun_dict -import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.interface import AnnDataTransform From 2f6ed9ef6862d210c06fc3860e0545b03b190c66 Mon Sep 17 00:00:00 2001 From: xzy Date: Sun, 21 Jan 2024 22:00:46 +0800 Subject: [PATCH 110/168] try step2 imputation --- test_automl/fun2code.py | 4 ++- test_automl/step2_config.py | 38 ++++++++++++++++++++-- test_automl/step2_imputation_deepimpute.py | 33 +++++++++++++++++++ 3 files changed, 71 insertions(+), 4 deletions(-) diff --git a/test_automl/fun2code.py b/test_automl/fun2code.py index 7656c88f7..3d18b1766 100644 --- a/test_automl/fun2code.py +++ b/test_automl/fun2code.py @@ -2,6 +2,7 @@ from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression +from dance.transforms.gene_holdout import GeneHoldout from dance.transforms.interface import AnnDataTransform from dance.transforms.mask import CellwiseMaskData, MaskData from dance.transforms.misc import SaveRaw @@ -24,5 +25,6 @@ "filter_cell_by_count": AnnDataTransform(sc.pp.filter_cells, min_genes=1), "save_raw": SaveRaw(), "cell_wise_mask_data": CellwiseMaskData(), - "mask_data": MaskData() + "mask_data": MaskData(), + "gene_hold_out": GeneHoldout() } #funcion 2 code diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index c1406161b..9dbcf0fdd 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -23,10 +23,40 @@ }, "mask": { "values": ["cell_wise_mask_data", "mask_data"] + }, + "gene_hold_out_name": { + "values": ["gene_hold_out"] } } #Functions registered in the preprocessing process +def generate_combinations_with_required_elements(elements, r, required_elements=[]): + """生成元素的所有组合,其中多个元素为必选. + + 参数: + - elements: 元素的集合 + - r: 每个组合的元素个数 + - required_elements: 必选的元素集合 + + 返回: + 一个包含所有组合的列表 + + """ + + def combinations_helper(current_combo, remaining_elements, r, required_elements): + if r == 0 and all(elem in current_combo for elem in required_elements): + all_combinations.append(tuple(current_combo)) + return + + for i, element in enumerate(remaining_elements): + print(remaining_elements) + combinations_helper(current_combo + [element], remaining_elements[i + 1:], r - 1, required_elements) + + all_combinations = [] + combinations_helper([], elements, r, required_elements) + return all_combinations + + def getFunConfig(selected_keys=None): """Get the config that needs to be optimized and the number of rounds.""" global pipline2fun_dict @@ -83,10 +113,12 @@ def wrapper(*args, **kwargs): return decorator -def setStep2(func=None, original_list=None): +def setStep2(func=None, original_list=None, required_elements=[]): """Generate corresponding decorators for different preprocessing.""" - all_combinations = [combo for i in range(1, - len(original_list) + 1) for combo in combinations(original_list, i)] + [[]] + all_combinations = [ + combo for i in range(len(original_list) + 1) + for combo in generate_combinations_with_required_elements(original_list, i, required_elements=required_elements) + ] generated_functions = [] for s_key in all_combinations: s_list = list(s_key) diff --git a/test_automl/step2_imputation_deepimpute.py b/test_automl/step2_imputation_deepimpute.py index e69de29bb..7ddc465a4 100644 --- a/test_automl/step2_imputation_deepimpute.py +++ b/test_automl/step2_imputation_deepimpute.py @@ -0,0 +1,33 @@ +#normalize_total是一定要选的,因为需要n_counts +import os +from typing import Any, Callable, Dict, Tuple + +import numpy as np +import torch +from step2_config import get_transforms, log_in_wandb, setStep2 + +from dance import logger +from dance.datasets.singlemodality import ClusteringDataset +from dance.modules.single_modality.clustering.scdcc import ScDCC +from dance.transforms.misc import Compose, SetConfig +from dance.transforms.preprocess import generate_random_pair +from dance.utils import set_seed + +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + + +@log_in_wandb(config=None) +def train(config): + pass + + +def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: + pass + + +if __name__ == "__main__": + """get_function_combinations.""" + function_list = setStep2(startSweep, + original_list=["gene_filter", "cell_filter", "normalize", "gene_hold_out_name", "mask"]) + for func in function_list: + func() From 7ceccedccd3b8fc1c4e52848131c190093f7f0d7 Mon Sep 17 00:00:00 2001 From: xzy Date: Sun, 21 Jan 2024 22:05:09 +0800 Subject: [PATCH 111/168] add required_elements --- test_automl/step2_imputation_deepimpute.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test_automl/step2_imputation_deepimpute.py b/test_automl/step2_imputation_deepimpute.py index 7ddc465a4..5ddbde926 100644 --- a/test_automl/step2_imputation_deepimpute.py +++ b/test_automl/step2_imputation_deepimpute.py @@ -28,6 +28,7 @@ def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: if __name__ == "__main__": """get_function_combinations.""" function_list = setStep2(startSweep, - original_list=["gene_filter", "cell_filter", "normalize", "gene_hold_out_name", "mask"]) + original_list=["gene_filter", "cell_filter", "normalize", "gene_hold_out_name", + "mask"], required_elements=["gene_hold_out_name"]) for func in function_list: func() From 0bf230169b308b47e22e601dfc267e400bfbae27 Mon Sep 17 00:00:00 2001 From: xzy Date: Sun, 21 Jan 2024 22:36:03 +0800 Subject: [PATCH 112/168] add step2 imputation config --- test_automl/step2_imputation_deepimpute.py | 54 +++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/test_automl/step2_imputation_deepimpute.py b/test_automl/step2_imputation_deepimpute.py index 5ddbde926..70036334d 100644 --- a/test_automl/step2_imputation_deepimpute.py +++ b/test_automl/step2_imputation_deepimpute.py @@ -22,7 +22,59 @@ def train(config): def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: - pass + parameters_dict.update({ + 'dropout': { + 'value': 0.1 + }, + 'lr': { + 'value': 1e-5 + }, + 'n_epochs': { + 'value': 500 + }, + 'batch_size': { + 'value': 64 + }, + 'sub_outputdim': { + 'value': 512 + }, + 'hidden_dim': { + 'value': 256 + }, + 'patience': { + 'value': 20 + }, + 'min_cells': { + 'value': 0.05 + }, + "n_top": { + 'value': 5 + }, + "train_size": { + "value": 0.9 + }, + "mask_rate": { + "value": 0.1 + }, + "cache": { + "value": False + }, + "mask": { + "value": True + }, + "seed": { + "value": 0 + }, + "num_runs": { + "value": 1 + } + }) + sweep_config = {'method': 'grid'} + sweep_config['parameters'] = parameters_dict + metric = {'name': 'scores', 'goal': 'maximize'} + + sweep_config['metric'] = metric + return sweep_config, train #Return function configuration and training function if __name__ == "__main__": From c5e2003a61be540b6c0895ebe99c9a6670bc4e6a Mon Sep 17 00:00:00 2001 From: xzy Date: Mon, 22 Jan 2024 12:49:59 +0800 Subject: [PATCH 113/168] update step2 imputation --- test_automl/step2_config.py | 79 ++++++++++++++-------- test_automl/step2_imputation_deepimpute.py | 62 ++++++++++++++--- 2 files changed, 101 insertions(+), 40 deletions(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index 5616a7449..100843e66 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,10 @@ import functools +import itertools from itertools import combinations -import wandb from fun2code import fun2code_dict +import wandb from dance.transforms.misc import Compose, SetConfig #TODO register more functions and add more examples @@ -21,7 +22,7 @@ "cell_filter": { "values": ["filter_cell_by_count"] }, - "mask": { + "mask_name": { "values": ["cell_wise_mask_data", "mask_data"] }, "gene_hold_out_name": { @@ -29,31 +30,47 @@ } } #Functions registered in the preprocessing process +# def generate_combinations_with_required_elements(elements, r, required_elements=[]): +# """生成元素的所有组合,其中多个元素为必选. + +# 参数: +# - elements: 元素的集合 +# - r: 每个组合的元素个数 +# - required_elements: 必选的元素集合 + +# 返回: +# 一个包含所有组合的列表 -def generate_combinations_with_required_elements(elements, r, required_elements=[]): - """生成元素的所有组合,其中多个元素为必选. +# """ - 参数: - - elements: 元素的集合 - - r: 每个组合的元素个数 - - required_elements: 必选的元素集合 +# def combinations_helper(current_combo, remaining_elements, r, required_elements): +# if r == 0 and all(elem in current_combo for elem in required_elements): +# all_combinations.append(tuple(current_combo)) +# return - 返回: - 一个包含所有组合的列表 +# for i, element in enumerate(remaining_elements): +# print(remaining_elements) +# combinations_helper(current_combo + [element], remaining_elements[i + 1:], r - 1, required_elements) - """ - def combinations_helper(current_combo, remaining_elements, r, required_elements): - if r == 0 and all(elem in current_combo for elem in required_elements): - all_combinations.append(tuple(current_combo)) - return +# all_combinations = [] +# combinations_helper([], elements, r, required_elements) +# return all_combinations +def generate_combinations_with_required_elements(elements, required_elements=[]): + optional_elements = [x for x in elements if x not in required_elements] - for i, element in enumerate(remaining_elements): - print(remaining_elements) - combinations_helper(current_combo + [element], remaining_elements[i + 1:], r - 1, required_elements) + # Sort optional elements in the same order as in the `elements` list + optional_elements.sort(key=lambda x: elements.index(x)) + # Generate all possible combinations of optional elements + optional_combinations = [] + for i in range(len(optional_elements) + 1): + optional_combinations += list(itertools.combinations(optional_elements, i)) + + # Combine required elements with optional combinations to get all possible combinations all_combinations = [] - combinations_helper([], elements, r, required_elements) + for optional_combination in optional_combinations: + all_combinations.append([x for x in elements if x in required_elements or x in optional_combination]) return all_combinations @@ -75,14 +92,15 @@ def get_transforms(config=None, set_data_config=True, save_raw=False): != "log1p") and ("gene_filter" in config.keys() and config.gene_filter == "highly_variable_genes"): return None + transforms = [] - transforms.append(fun2code_dict[config.gene_filter]) if "gene_filter" in config.keys() else None - transforms.append(fun2code_dict[config.cell_filter]) if "cell_filter" in config.keys() else None - if save_raw: + for key in config.keys(): + if save_raw and key == "normalize": + transforms.append(fun2code_dict["save_raw"]) + print(key, config[key]) + transforms.append(fun2code_dict[config[key]]) if key in pipline2fun_dict.keys() else None + if save_raw and "normalize" not in config.keys(): transforms.append(fun2code_dict["save_raw"]) - transforms.append(fun2code_dict[config.normalize]) if "normalize" in config.keys() else None - transforms.append(fun2code_dict[config.gene_dim_reduction]) if "gene_dim_reduction" in config.keys() else None - if set_data_config: data_config = {"label_channel": "cell_type"} if "gene_dim_reduction" in config.keys(): @@ -115,13 +133,16 @@ def wrapper(*args, **kwargs): def setStep2(func=None, original_list=None, required_elements=[]): """Generate corresponding decorators for different preprocessing.""" - all_combinations = [ - combo for i in range(len(original_list) + 1) - for combo in generate_combinations_with_required_elements(original_list, i, required_elements=required_elements) - ] + # all_combinations = [ + # combo for i in range(len(original_list) + 1) + # for combo in generate_combinations_with_required_elements(original_list, i, required_elements=required_elements) + # ] + all_combinations = generate_combinations_with_required_elements(elements=original_list, + required_elements=required_elements) generated_functions = [] for s_key in all_combinations: s_list = list(s_key) + print(s_list) decorator = sweepDecorator(selected_keys=s_list) generated_functions.append(decorator(func)) return generated_functions diff --git a/test_automl/step2_imputation_deepimpute.py b/test_automl/step2_imputation_deepimpute.py index 70036334d..8cbc6cada 100644 --- a/test_automl/step2_imputation_deepimpute.py +++ b/test_automl/step2_imputation_deepimpute.py @@ -1,5 +1,3 @@ -#normalize_total是一定要选的,因为需要n_counts -import os from typing import Any, Callable, Dict, Tuple import numpy as np @@ -7,18 +5,60 @@ from step2_config import get_transforms, log_in_wandb, setStep2 from dance import logger -from dance.datasets.singlemodality import ClusteringDataset -from dance.modules.single_modality.clustering.scdcc import ScDCC +from dance.datasets.singlemodality import ImputationDataset +from dance.modules.single_modality.imputation.deepimpute import DeepImpute from dance.transforms.misc import Compose, SetConfig -from dance.transforms.preprocess import generate_random_pair from dance.utils import set_seed -device = torch.device("cuda" if torch.cuda.is_available() else "cpu") +device = torch.device("cuda:2" if torch.cuda.is_available() else "cpu") @log_in_wandb(config=None) def train(config): - pass + rmses = [] + for seed in range(config.seed, config.seed + config.num_runs): + set_seed(seed) + dataset = "mouse_brain_data" + data_dir = "./test_automl/data" + dataloader = ImputationDataset(data_dir=data_dir, dataset=dataset, train_size=config.train_size) + # preprocessing_pipeline = DeepImpute.preprocessing_pipeline(min_cells=config.min_cells, n_top=config.n_top, + # sub_outputdim=config.sub_outputdim, mask=config.mask, + # seed=seed, mask_rate=config.mask_rate) + transforms = get_transforms(config=config, set_data_config=False, save_raw=True) + if transforms is None: + logger.warning("skip transforms") + return {"scores": 0} + transforms.append( + SetConfig({ + "feature_channel": [None, None, "targets", "predictors", "train_mask"], + "feature_channel_type": ["X", "raw_X", "uns", "uns", "layers"], + "label_channel": [None, None], + "label_channel_type": ["X", "raw_X"], + })) + preprocessing_pipeline = Compose(*transforms, log_level="INFO") + data = dataloader.load_data(transform=preprocessing_pipeline, cache=config.cache) + + if config.mask: + X, X_raw, targets, predictors, mask = data.get_x(return_type="default") + else: + mask = None + X, X_raw, targets, predictors = data.get_x(return_type="default") + X = torch.tensor(X.toarray()).float() + X_raw = torch.tensor(X_raw.toarray()).float() + X_train = X * mask + model = DeepImpute(predictors, targets, dataset, config.sub_outputdim, config.hidden_dim, config.dropout, seed, + config.gpu) + + model.fit(X_train, X_train, mask, config.batch_size, config.lr, config.n_epochs, config.patience) + imputed_data = model.predict(X_train, mask) + score = model.score(X, imputed_data, mask, metric='RMSE') + print("RMSE: %.4f" % score) + rmses.append(score) + + print('deepimpute') + print(f'rmses: {rmses}') + print(f'rmses: {np.mean(rmses)} +/- {np.std(rmses)}') + return ({"scores": np.mean(rmses)}) def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: @@ -59,7 +99,7 @@ def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: "cache": { "value": False }, - "mask": { + "mask": { #避免出现与超参数流程重复的情况,一般没有 "value": True }, "seed": { @@ -79,8 +119,8 @@ def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: if __name__ == "__main__": """get_function_combinations.""" - function_list = setStep2(startSweep, - original_list=["gene_filter", "cell_filter", "normalize", "gene_hold_out_name", - "mask"], required_elements=["gene_hold_out_name"]) + function_list = setStep2( + startSweep, original_list=["gene_filter", "cell_filter", "normalize", "gene_hold_out_name", "mask_name"], + required_elements=["gene_hold_out_name", "mask_name"]) for func in function_list: func() From fe8bc3adb4801c90369cad7040c0a41972132f44 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 04:50:25 +0000 Subject: [PATCH 114/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index 100843e66..d74399b01 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -2,9 +2,9 @@ import itertools from itertools import combinations +import wandb from fun2code import fun2code_dict -import wandb from dance.transforms.misc import Compose, SetConfig #TODO register more functions and add more examples From cc500a98cd61aab770af690439e042800737d691 Mon Sep 17 00:00:00 2001 From: xzy Date: Mon, 22 Jan 2024 15:36:08 +0800 Subject: [PATCH 115/168] update step2 imputation --- .gitignore | 2 ++ test_automl/step2_imputation_deepimpute.py | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index db77ec215..c89316820 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ wandb test_automl/data test_automl/test.py *.pkl +*.pt +openfe-singlecell diff --git a/test_automl/step2_imputation_deepimpute.py b/test_automl/step2_imputation_deepimpute.py index 8cbc6cada..9d7f83878 100644 --- a/test_automl/step2_imputation_deepimpute.py +++ b/test_automl/step2_imputation_deepimpute.py @@ -47,7 +47,7 @@ def train(config): X_raw = torch.tensor(X_raw.toarray()).float() X_train = X * mask model = DeepImpute(predictors, targets, dataset, config.sub_outputdim, config.hidden_dim, config.dropout, seed, - config.gpu) + 2) model.fit(X_train, X_train, mask, config.batch_size, config.lr, config.n_epochs, config.patience) imputed_data = model.predict(X_train, mask) @@ -70,7 +70,7 @@ def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: 'value': 1e-5 }, 'n_epochs': { - 'value': 500 + 'value': 5 }, 'batch_size': { 'value': 64 From 6d4141552bfda6c633ad8c0fb806c9c99255b4ce Mon Sep 17 00:00:00 2001 From: xzy Date: Mon, 22 Jan 2024 15:42:18 +0800 Subject: [PATCH 116/168] update step2 imputation --- test_automl/step2_imputation_deepimpute.py | 4 ++-- test_automl/step3_imputation_deepimpute.py | 0 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 test_automl/step3_imputation_deepimpute.py diff --git a/test_automl/step2_imputation_deepimpute.py b/test_automl/step2_imputation_deepimpute.py index 9d7f83878..38779fb09 100644 --- a/test_automl/step2_imputation_deepimpute.py +++ b/test_automl/step2_imputation_deepimpute.py @@ -58,7 +58,7 @@ def train(config): print('deepimpute') print(f'rmses: {rmses}') print(f'rmses: {np.mean(rmses)} +/- {np.std(rmses)}') - return ({"scores": np.mean(rmses)}) + return ({"rmses": np.mean(rmses)}) def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: @@ -111,7 +111,7 @@ def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: }) sweep_config = {'method': 'grid'} sweep_config['parameters'] = parameters_dict - metric = {'name': 'scores', 'goal': 'maximize'} + metric = {'name': 'rmses', 'goal': 'minimize'} sweep_config['metric'] = metric return sweep_config, train #Return function configuration and training function diff --git a/test_automl/step3_imputation_deepimpute.py b/test_automl/step3_imputation_deepimpute.py new file mode 100644 index 000000000..e69de29bb From c86cfbba44dc1daef05666487bc5b9b609914e15 Mon Sep 17 00:00:00 2001 From: xzy Date: Mon, 22 Jan 2024 16:38:48 +0800 Subject: [PATCH 117/168] update step3 imputation --- test_automl/step2_imputation_deepimpute.py | 4 +- test_automl/step3_config.py | 13 +++- test_automl/step3_imputation_deepimpute.py | 87 ++++++++++++++++++++++ 3 files changed, 99 insertions(+), 5 deletions(-) diff --git a/test_automl/step2_imputation_deepimpute.py b/test_automl/step2_imputation_deepimpute.py index 38779fb09..5038bcac2 100644 --- a/test_automl/step2_imputation_deepimpute.py +++ b/test_automl/step2_imputation_deepimpute.py @@ -58,7 +58,7 @@ def train(config): print('deepimpute') print(f'rmses: {rmses}') print(f'rmses: {np.mean(rmses)} +/- {np.std(rmses)}') - return ({"rmses": np.mean(rmses)}) + return ({"scores": np.mean(rmses)}) def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: @@ -111,7 +111,7 @@ def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: }) sweep_config = {'method': 'grid'} sweep_config['parameters'] = parameters_dict - metric = {'name': 'rmses', 'goal': 'minimize'} + metric = {'name': 'scores', 'goal': 'minimize'} sweep_config['metric'] = metric return sweep_config, train #Return function configuration and training function diff --git a/test_automl/step3_config.py b/test_automl/step3_config.py index 9850b0997..6d162479f 100644 --- a/test_automl/step3_config.py +++ b/test_automl/step3_config.py @@ -3,13 +3,14 @@ import optuna import scanpy as sc -import wandb from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback from step2_config import pipline2fun_dict +import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression +from dance.transforms.gene_holdout import GeneHoldout from dance.transforms.interface import AnnDataTransform from dance.transforms.mask import CellwiseMaskData, MaskData from dance.transforms.misc import Compose, SetConfig @@ -144,6 +145,12 @@ def mask_data(method_name: str, trial: optuna.Trial): return MaskData(mask_rate=trial.suggest_float(method_name + "mask_rate", 0.01, 0.5)) +@set_method_name +def gene_hold_out(method_name: str, trial: optuna.Trial): + return GeneHoldout(n_top=trial.suggest_int(method_name + "n_top", 1, 10), + batch_size=trial.suggest_categorical(method_name + "batch_size", [256, 512, 1024])) + + # # 获取当前文件中的所有函数 # functions = [(name,obj) for name, obj in inspect.getmembers( # sys.modules[__name__]) if inspect.isfunction(obj)] @@ -197,13 +204,13 @@ def wrapper(*args, **kwargs): return decorator -def get_optimizer(project, objective, n_trials=2): +def get_optimizer(project, objective, n_trials=2, direction="maximize"): """Get optimizer.""" wandb_kwargs = {"project": project} wandbc = WeightsAndBiasesCallback(wandb_kwargs=wandb_kwargs, as_multirun=True) decorator = log_in_wandb(wandbc) decorator_function = decorator(objective) - study = optuna.create_study() + study = optuna.create_study(direction=direction) def wrapper(): study.optimize(decorator_function, n_trials=n_trials, callbacks=[wandbc]) diff --git a/test_automl/step3_imputation_deepimpute.py b/test_automl/step3_imputation_deepimpute.py index e69de29bb..616950851 100644 --- a/test_automl/step3_imputation_deepimpute.py +++ b/test_automl/step3_imputation_deepimpute.py @@ -0,0 +1,87 @@ +import torch +from step3_config import get_optimizer, get_transforms + +from dance import logger +from dance.datasets.singlemodality import ImputationDataset +from dance.modules.single_modality.imputation.deepimpute import DeepImpute +from dance.registry import DotDict +from dance.transforms.misc import Compose, SetConfig +from dance.utils import set_seed + +fun_list = ["filter_gene_by_count", "filter_cell_by_count", "log1p", "gene_hold_out", "cell_wise_mask_data"] +device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu") +import numpy as np + + +def objective(trial): + parameters_dict = { + 'dropout': 0.1, + 'lr': 1e-5, + 'n_epochs': 5, + 'batch_size': 64, + 'sub_outputdim': 512, + 'hidden_dim': 256, + 'patience': 20, + 'min_cells': 0.05, + "n_top": 5, + "train_size": 0.9, + "mask_rate": 0.1, + "cache": False, + "mask": True, #避免出现与超参数流程重复的情况,一般没有 + "seed": 0, + "num_runs": 1 + } + parameters_config = {} + parameters_config.update(parameters_dict) + parameters_config = DotDict(parameters_config) + rmses = [] + for seed in range(parameters_config.seed, parameters_config.seed + parameters_config.num_runs): + set_seed(seed) + dataset = "mouse_brain_data" + data_dir = "./test_automl/data" + dataloader = ImputationDataset(data_dir=data_dir, dataset=dataset, train_size=parameters_config.train_size) + # preprocessing_pipeline = DeepImpute.preprocessing_pipeline(min_cells=parameters_config.min_cells, n_top=parameters_config.n_top, + # sub_outputdim=parameters_config.sub_outputdim, mask=parameters_config.mask, + # seed=seed, mask_rate=parameters_config.mask_rate) + transforms = get_transforms(trial=trial, fun_list=fun_list, set_data_config=False, save_raw=True) + if transforms is None: + logger.warning("skip transforms") + return {"scores": 0} + transforms.append( + SetConfig({ + "feature_channel": [None, None, "targets", "predictors", "train_mask"], + "feature_channel_type": ["X", "raw_X", "uns", "uns", "layers"], + "label_channel": [None, None], + "label_channel_type": ["X", "raw_X"], + })) + preprocessing_pipeline = Compose(*transforms, log_level="INFO") + data = dataloader.load_data(transform=preprocessing_pipeline, cache=parameters_config.cache) + + if parameters_config.mask: + X, X_raw, targets, predictors, mask = data.get_x(return_type="default") + else: + mask = None + X, X_raw, targets, predictors = data.get_x(return_type="default") + X = torch.tensor(X.toarray()).float() + X_raw = torch.tensor(X_raw.toarray()).float() + X_train = X * mask + model = DeepImpute(predictors, targets, dataset, parameters_config.sub_outputdim, parameters_config.hidden_dim, + parameters_config.dropout, seed, 1) + + model.fit(X_train, X_train, mask, parameters_config.batch_size, parameters_config.lr, + parameters_config.n_epochs, parameters_config.patience) + imputed_data = model.predict(X_train, mask) + score = model.score(X, imputed_data, mask, metric='RMSE') + print("RMSE: %.4f" % score) + rmses.append(score) + + print('deepimpute') + print(f'rmses: {rmses}') + print(f'rmses: {np.mean(rmses)} +/- {np.std(rmses)}') + return ({"scores": np.mean(rmses)}) + + +if __name__ == "__main__": + start_optimizer = get_optimizer(project="step3-imputation-deepimpute-project", objective=objective, n_trials=10, + direction="minimize") + start_optimizer() From b961e1747cb8671ed1ecc255a8fb7f6cca70780a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 08:39:49 +0000 Subject: [PATCH 118/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step3_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/step3_config.py b/test_automl/step3_config.py index 6d162479f..6bd47cbc2 100644 --- a/test_automl/step3_config.py +++ b/test_automl/step3_config.py @@ -3,11 +3,11 @@ import optuna import scanpy as sc +import wandb from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback from step2_config import pipline2fun_dict -import wandb from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.gene_holdout import GeneHoldout From 1574d5bdfc96966b69451e29df2812860698579f Mon Sep 17 00:00:00 2001 From: xzy Date: Mon, 22 Jan 2024 20:15:17 +0800 Subject: [PATCH 119/168] update step3 imputation --- test_automl/step3_imputation_deepimpute.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test_automl/step3_imputation_deepimpute.py b/test_automl/step3_imputation_deepimpute.py index 616950851..fc8f62e3b 100644 --- a/test_automl/step3_imputation_deepimpute.py +++ b/test_automl/step3_imputation_deepimpute.py @@ -29,7 +29,8 @@ def objective(trial): "cache": False, "mask": True, #避免出现与超参数流程重复的情况,一般没有 "seed": 0, - "num_runs": 1 + "num_runs": 1, + "gpu": 3 } parameters_config = {} parameters_config.update(parameters_dict) @@ -66,7 +67,7 @@ def objective(trial): X_raw = torch.tensor(X_raw.toarray()).float() X_train = X * mask model = DeepImpute(predictors, targets, dataset, parameters_config.sub_outputdim, parameters_config.hidden_dim, - parameters_config.dropout, seed, 1) + parameters_config.dropout, seed, parameters_config.gpu) model.fit(X_train, X_train, mask, parameters_config.batch_size, parameters_config.lr, parameters_config.n_epochs, parameters_config.patience) From 95057fb280bb40282dbbc52c5e18f0ce9864c631 Mon Sep 17 00:00:00 2001 From: xzy Date: Tue, 23 Jan 2024 09:00:06 +0800 Subject: [PATCH 120/168] normalize code --- test_automl/step2_config.py | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index d74399b01..309a7de23 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -2,9 +2,9 @@ import itertools from itertools import combinations -import wandb from fun2code import fun2code_dict +import wandb from dance.transforms.misc import Compose, SetConfig #TODO register more functions and add more examples @@ -30,32 +30,7 @@ } } #Functions registered in the preprocessing process -# def generate_combinations_with_required_elements(elements, r, required_elements=[]): -# """生成元素的所有组合,其中多个元素为必选. - -# 参数: -# - elements: 元素的集合 -# - r: 每个组合的元素个数 -# - required_elements: 必选的元素集合 - -# 返回: -# 一个包含所有组合的列表 - -# """ - -# def combinations_helper(current_combo, remaining_elements, r, required_elements): -# if r == 0 and all(elem in current_combo for elem in required_elements): -# all_combinations.append(tuple(current_combo)) -# return - -# for i, element in enumerate(remaining_elements): -# print(remaining_elements) -# combinations_helper(current_combo + [element], remaining_elements[i + 1:], r - 1, required_elements) - -# all_combinations = [] -# combinations_helper([], elements, r, required_elements) -# return all_combinations def generate_combinations_with_required_elements(elements, required_elements=[]): optional_elements = [x for x in elements if x not in required_elements] From e2b53a3a30e6b2108554d33074dcbf302b8fa8ba Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 01:00:29 +0000 Subject: [PATCH 121/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index 309a7de23..fed413511 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -2,9 +2,9 @@ import itertools from itertools import combinations +import wandb from fun2code import fun2code_dict -import wandb from dance.transforms.misc import Compose, SetConfig #TODO register more functions and add more examples From bf585f762ceb1fefabe51e400b6ccd9d7311d501 Mon Sep 17 00:00:00 2001 From: xzy Date: Tue, 23 Jan 2024 09:02:30 +0800 Subject: [PATCH 122/168] normalize code --- test_automl/step2_config.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index fed413511..dd03290fd 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,11 +1,10 @@ import functools import itertools -from itertools import combinations -import wandb from fun2code import fun2code_dict -from dance.transforms.misc import Compose, SetConfig +import wandb +from dance.transforms.misc import SetConfig #TODO register more functions and add more examples pipline2fun_dict = { From 3b558785b0dc79cbec303e99ec2fe8793e282c60 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 01:02:54 +0000 Subject: [PATCH 123/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index dd03290fd..fe5790acd 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,9 @@ import functools import itertools +import wandb from fun2code import fun2code_dict -import wandb from dance.transforms.misc import SetConfig #TODO register more functions and add more examples From e6dd690ba311425e4726087b77ef2bdcfcdc41a1 Mon Sep 17 00:00:00 2001 From: xzy Date: Tue, 23 Jan 2024 09:03:38 +0800 Subject: [PATCH 124/168] normalize code --- test_automl/step2_imputation_deepimpute.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test_automl/step2_imputation_deepimpute.py b/test_automl/step2_imputation_deepimpute.py index 5038bcac2..3991499d0 100644 --- a/test_automl/step2_imputation_deepimpute.py +++ b/test_automl/step2_imputation_deepimpute.py @@ -15,15 +15,13 @@ @log_in_wandb(config=None) def train(config): + """imputation.""" rmses = [] for seed in range(config.seed, config.seed + config.num_runs): set_seed(seed) dataset = "mouse_brain_data" data_dir = "./test_automl/data" dataloader = ImputationDataset(data_dir=data_dir, dataset=dataset, train_size=config.train_size) - # preprocessing_pipeline = DeepImpute.preprocessing_pipeline(min_cells=config.min_cells, n_top=config.n_top, - # sub_outputdim=config.sub_outputdim, mask=config.mask, - # seed=seed, mask_rate=config.mask_rate) transforms = get_transforms(config=config, set_data_config=False, save_raw=True) if transforms is None: logger.warning("skip transforms") From 24424c776e9c561bd78774e9786a831cbcfcc7e8 Mon Sep 17 00:00:00 2001 From: xzy Date: Tue, 23 Jan 2024 09:04:59 +0800 Subject: [PATCH 125/168] normalize code --- test_automl/step2_clustering_scdcc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test_automl/step2_clustering_scdcc.py b/test_automl/step2_clustering_scdcc.py index e35f86fb4..bb692a38d 100644 --- a/test_automl/step2_clustering_scdcc.py +++ b/test_automl/step2_clustering_scdcc.py @@ -18,6 +18,7 @@ @log_in_wandb(config=None) def train(config): + """clustering.""" aris = [] for seed in range(config.seed, config.seed + config.num_runs): set_seed(seed) From 455f7ae612a86716c96a4fbbf4665d324f927790 Mon Sep 17 00:00:00 2001 From: xzy Date: Tue, 23 Jan 2024 20:44:37 +0800 Subject: [PATCH 126/168] add comment --- test_automl/fun2code.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/fun2code.py b/test_automl/fun2code.py index 3d18b1766..25f76b659 100644 --- a/test_automl/fun2code.py +++ b/test_automl/fun2code.py @@ -27,4 +27,4 @@ "cell_wise_mask_data": CellwiseMaskData(), "mask_data": MaskData(), "gene_hold_out": GeneHoldout() -} #funcion 2 code +} #funcion 2 code,map functions as variables From de9ac93cd3e2fbed85bb0da5bdae8e00017c5eb0 Mon Sep 17 00:00:00 2001 From: xzy Date: Tue, 23 Jan 2024 21:07:20 +0800 Subject: [PATCH 127/168] add comment --- test_automl/step2_config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index fe5790acd..a32bdc2cb 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,9 @@ import functools import itertools -import wandb from fun2code import fun2code_dict +import wandb from dance.transforms.misc import SetConfig #TODO register more functions and add more examples @@ -123,7 +123,7 @@ def setStep2(func=None, original_list=None, required_elements=[]): def log_in_wandb(config): - """Decorator wrapped using wandb.""" + """Decorator wrapped using wandb.It is used in train function.""" def decorator(func): From a853a21db10c1cebb49597a6e6febc170dad573c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 13:07:50 +0000 Subject: [PATCH 128/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_automl/step2_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/step2_config.py b/test_automl/step2_config.py index a32bdc2cb..7b62a4e63 100644 --- a/test_automl/step2_config.py +++ b/test_automl/step2_config.py @@ -1,9 +1,9 @@ import functools import itertools +import wandb from fun2code import fun2code_dict -import wandb from dance.transforms.misc import SetConfig #TODO register more functions and add more examples From 451b13561ddb09643ee13ccc0764a910b833c721 Mon Sep 17 00:00:00 2001 From: xzy Date: Tue, 23 Jan 2024 21:31:24 +0800 Subject: [PATCH 129/168] add comment --- test_automl/step2_clustering_scdcc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_automl/step2_clustering_scdcc.py b/test_automl/step2_clustering_scdcc.py index bb692a38d..535b328c7 100644 --- a/test_automl/step2_clustering_scdcc.py +++ b/test_automl/step2_clustering_scdcc.py @@ -1,4 +1,4 @@ -#normalize_total是一定要选的,因为需要n_counts +"""normalize_total is a must at SCDCC because it requires n_counts.""" import os from typing import Any, Callable, Dict, Tuple From c8124cb7f3d8c4ede2b0636a596f5658ddfe6b99 Mon Sep 17 00:00:00 2001 From: xzy Date: Tue, 23 Jan 2024 21:33:02 +0800 Subject: [PATCH 130/168] add comment --- test_automl/step3_cell_type_annotation_actinn_example.py | 1 - test_automl/step3_clustering_scdcc.py | 3 +-- test_automl/step3_imputation_deepimpute.py | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/test_automl/step3_cell_type_annotation_actinn_example.py b/test_automl/step3_cell_type_annotation_actinn_example.py index e913e10d6..4ab19e97d 100644 --- a/test_automl/step3_cell_type_annotation_actinn_example.py +++ b/test_automl/step3_cell_type_annotation_actinn_example.py @@ -1,5 +1,4 @@ import numpy as np -import optuna import torch from step3_config import get_optimizer, get_transforms diff --git a/test_automl/step3_clustering_scdcc.py b/test_automl/step3_clustering_scdcc.py index f93b1963c..eb3fa94f8 100644 --- a/test_automl/step3_clustering_scdcc.py +++ b/test_automl/step3_clustering_scdcc.py @@ -4,10 +4,9 @@ import torch from step3_config import get_optimizer, get_transforms -from dance import logger from dance.datasets.singlemodality import ClusteringDataset from dance.modules.single_modality.clustering.scdcc import ScDCC -from dance.registry import DotDict # 可以用可以不用 +from dance.registry import DotDict # Optional from dance.transforms.misc import Compose, SetConfig from dance.transforms.preprocess import generate_random_pair from dance.utils import set_seed diff --git a/test_automl/step3_imputation_deepimpute.py b/test_automl/step3_imputation_deepimpute.py index fc8f62e3b..29726a862 100644 --- a/test_automl/step3_imputation_deepimpute.py +++ b/test_automl/step3_imputation_deepimpute.py @@ -27,7 +27,7 @@ def objective(trial): "train_size": 0.9, "mask_rate": 0.1, "cache": False, - "mask": True, #避免出现与超参数流程重复的情况,一般没有 + "mask": True, #Avoid duplication with hyperparameter processes "seed": 0, "num_runs": 1, "gpu": 3 From 7b4ea0c356d548c8178e4a7dde146feba194e7e3 Mon Sep 17 00:00:00 2001 From: xzy Date: Tue, 23 Jan 2024 21:34:19 +0800 Subject: [PATCH 131/168] add comment --- tests/transforms/test_celltypeNums.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/transforms/test_celltypeNums.py b/tests/transforms/test_celltypeNums.py index 94c51c899..901c1d776 100644 --- a/tests/transforms/test_celltypeNums.py +++ b/tests/transforms/test_celltypeNums.py @@ -9,7 +9,7 @@ def test_cell_type_nums(): - np.random.seed() + np.random.seed(SEED) num_cells = 100 num_genes = 500 gene_expression = np.random.default_rng(seed=SEED).random((num_cells, num_genes)) From 5a75e61dd09a04102c61e818dd143a6034b36286 Mon Sep 17 00:00:00 2001 From: xzy Date: Tue, 23 Jan 2024 21:45:29 +0800 Subject: [PATCH 132/168] add comment --- tests/transforms/test_RESPETGraph.py | 1 - tests/transforms/test_celltypeNums.py | 1 - 2 files changed, 2 deletions(-) diff --git a/tests/transforms/test_RESPETGraph.py b/tests/transforms/test_RESPETGraph.py index 4b478ec45..86d9442d2 100644 --- a/tests/transforms/test_RESPETGraph.py +++ b/tests/transforms/test_RESPETGraph.py @@ -1,6 +1,5 @@ import numpy as np import pandas as pd -import pytest from anndata import AnnData from dance.data import Data diff --git a/tests/transforms/test_celltypeNums.py b/tests/transforms/test_celltypeNums.py index 901c1d776..ec2b557d7 100644 --- a/tests/transforms/test_celltypeNums.py +++ b/tests/transforms/test_celltypeNums.py @@ -1,5 +1,4 @@ import numpy as np -import pytest from anndata import AnnData from dance.data import Data From 716576b735bd41e7544586253d2bce1afd4fb54a Mon Sep 17 00:00:00 2001 From: xzy Date: Tue, 23 Jan 2024 23:31:09 +0800 Subject: [PATCH 133/168] move automl file --- ...ep2_cell_type_annotation_actinn_example.py | 84 +++++++++ .../step2_examples/step2_clustering_scdcc.py | 167 ++++++++++++++++++ .../step2_imputation_deepimpute.py | 124 +++++++++++++ 3 files changed, 375 insertions(+) create mode 100644 test_automl/step2_examples/step2_cell_type_annotation_actinn_example.py create mode 100644 test_automl/step2_examples/step2_clustering_scdcc.py create mode 100644 test_automl/step2_examples/step2_imputation_deepimpute.py diff --git a/test_automl/step2_examples/step2_cell_type_annotation_actinn_example.py b/test_automl/step2_examples/step2_cell_type_annotation_actinn_example.py new file mode 100644 index 000000000..07a887b97 --- /dev/null +++ b/test_automl/step2_examples/step2_cell_type_annotation_actinn_example.py @@ -0,0 +1,84 @@ +from typing import Any, Callable, Dict, Tuple + +import numpy as np +import torch + +from dance import logger +from dance.automl_config.step2_config import get_transforms, log_in_wandb, setStep2 +from dance.datasets.singlemodality import CellTypeAnnotationDataset +from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN +from dance.transforms.misc import Compose +from dance.utils import set_seed + +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + + +@log_in_wandb(config=None) +def train(config): + + model = ACTINN(hidden_dims=config.hidden_dims, lambd=config.lambd, device=device) + transforms = get_transforms(config=config) + if transforms is None: + logger.warning("skip transforms") + return {"scores": 0} + preprocessing_pipeline = Compose(*transforms, log_level="INFO") + train_dataset = [753, 3285] + test_dataset = [2695] + tissue = "Brain" + species = "mouse" + dataloader = CellTypeAnnotationDataset(train_dataset=train_dataset, test_dataset=test_dataset, tissue=tissue, + species=species, data_dir="./test_automl/data") + data = dataloader.load_data(transform=preprocessing_pipeline, cache=False) + + # Obtain training and testing data + x_train, y_train = data.get_train_data(return_type="torch") + x_test, y_test = data.get_test_data(return_type="torch") + x_train, y_train, x_test, y_test = x_train.float(), y_train.float(), x_test.float(), y_test.float() + # Train and evaluate models for several rounds + scores = [] + for seed in range(config.seed, config.seed + config.num_runs): + set_seed(seed) + + model.fit(x_train, y_train, seed=seed, lr=config.learning_rate, num_epochs=config.num_epochs, + batch_size=config.batch_size, print_cost=False) + scores.append(score := model.score(x_test, y_test)) + return {"scores": np.mean(scores)} + + +def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: + parameters_dict.update({ + 'batch_size': { + 'value': 128 + }, + "hidden_dims": { + 'value': [2000] + }, + 'lambd': { + 'value': 0.005 + }, + 'num_epochs': { + 'value': 50 + }, + 'seed': { + 'value': 0 + }, + 'num_runs': { + 'value': 1 + }, + 'learning_rate': { + 'value': 0.0001 + } + }) + sweep_config = {'method': 'grid'} + sweep_config['parameters'] = parameters_dict + metric = {'name': 'scores', 'goal': 'maximize'} + + sweep_config['metric'] = metric + return sweep_config, train #Return function configuration and training function + + +if __name__ == "__main__": + """get_function_combinations.""" + function_list = setStep2(startSweep, original_list=["normalize", "gene_filter", "gene_dim_reduction"]) + for func in function_list: + func() diff --git a/test_automl/step2_examples/step2_clustering_scdcc.py b/test_automl/step2_examples/step2_clustering_scdcc.py new file mode 100644 index 000000000..f92759a3a --- /dev/null +++ b/test_automl/step2_examples/step2_clustering_scdcc.py @@ -0,0 +1,167 @@ +"""normalize_total is a must at SCDCC because it requires n_counts.""" +import os +from typing import Any, Callable, Dict, Tuple + +import numpy as np +import torch + +from dance import logger +from dance.automl_config.step2_config import get_transforms, log_in_wandb, setStep2 +from dance.datasets.singlemodality import ClusteringDataset +from dance.modules.single_modality.clustering.scdcc import ScDCC +from dance.transforms.misc import Compose, SetConfig +from dance.transforms.preprocess import generate_random_pair +from dance.utils import set_seed + +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + + +@log_in_wandb(config=None) +def train(config): + """clustering.""" + aris = [] + for seed in range(config.seed, config.seed + config.num_runs): + set_seed(seed) + dataset = "10X_PBMC" + # Load data and perform necessary preprocessing + dataloader = ClusteringDataset("./test_automl/data", dataset=dataset) + + transforms = get_transforms(config=config, set_data_config=False, save_raw=True) + if ("normalize" not in config.keys() or config.normalize != "normalize_total") or transforms is None: + logger.warning("skip transforms") + return {"scores": 0} + transforms.append( + SetConfig({ + "feature_channel": [None, None, "n_counts"], + "feature_channel_type": ["X", "raw_X", "obs"], + "label_channel": "Group" + })) + preprocessing_pipeline = Compose(*transforms, log_level="INFO") + data = dataloader.load_data(transform=preprocessing_pipeline, cache=config.cache) + + # inputs: x, x_raw, n_counts + inputs, y = data.get_train_data() + n_clusters = len(np.unique(y)) + in_dim = inputs[0].shape[1] + + # Generate random pairs + if not os.path.exists(config.label_cells_files): + indx = np.arange(len(y)) + np.random.shuffle(indx) + label_cell_indx = indx[0:int(np.ceil(config.label_cells * len(y)))] + else: + label_cell_indx = np.loadtxt(config.label_cells_files, dtype=np.int) + + if config.n_pairwise > 0: + ml_ind1, ml_ind2, cl_ind1, cl_ind2, error_num = generate_random_pair(y, label_cell_indx, config.n_pairwise, + config.n_pairwise_error) + print("Must link paris: %d" % ml_ind1.shape[0]) + print("Cannot link paris: %d" % cl_ind1.shape[0]) + print("Number of error pairs: %d" % error_num) + else: + ml_ind1, ml_ind2, cl_ind1, cl_ind2 = np.array([]), np.array([]), np.array([]), np.array([]) + + # Build and train moodel + model = ScDCC(input_dim=in_dim, z_dim=config.z_dim, n_clusters=n_clusters, encodeLayer=config.encodeLayer, + decodeLayer=config.encodeLayer[::-1], sigma=config.sigma, gamma=config.gamma, + ml_weight=config.ml_weight, cl_weight=config.ml_weight, device=device, + pretrain_path=f"scdcc_{dataset}_pre.pkl") + model.fit(inputs, y, lr=config.lr, batch_size=config.batch_size, epochs=config.epochs, ml_ind1=ml_ind1, + ml_ind2=ml_ind2, cl_ind1=cl_ind1, cl_ind2=cl_ind2, update_interval=config.update_interval, + tol=config.tol, pt_batch_size=config.batch_size, pt_lr=config.pretrain_lr, + pt_epochs=config.pretrain_epochs) + + # Evaluate model predictions + score = model.score(None, y) + print(f"{score=:.4f}") + aris.append(score) + + print('scdcc') + print(f'aris: {aris}') + print(f'aris: {np.mean(aris)} +/- {np.std(aris)}') + return ({"scores": np.mean(aris)}) + + +def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: + parameters_dict.update({ + 'seed': { + 'value': 0 + }, + 'num_runs': { + 'value': 1 + }, + 'cache': { + 'value': True + }, + 'label_cells_files': { + 'value': 'label_10X_PBMC.txt' + }, + 'label_cells': { + 'value': 0.1 + }, + 'n_pairwise': { + 'value': 0 + }, + 'n_pairwise_error': { + 'value': 0 + }, + 'z_dim': { + 'value': 32 + }, + 'encodeLayer': { + 'value': [256, 64] + }, + 'sigma': { + 'value': 2.5 + }, + 'gamma': { + 'value': 1.0 + }, + 'lr': { + 'value': 0.01 + }, + 'pretrain_lr': { + 'value': 0.001 + }, + 'ml_weight': { + 'value': 1.0 + }, + 'cl_weight': { + 'value': 1.0 + }, + 'update_interval': { + 'value': 1.0 + }, + 'tol': { + 'value': 0.00001 + }, + 'ae_weights': { + 'value': None + }, + 'ae_weight_file': { + 'value': "AE_weights.pth.tar" + }, + 'pretrain_epochs': { + 'value': 50 + }, + 'epochs': { + 'value': 500 + }, + 'batch_size': { + 'value': 256 + } + }) + + sweep_config = {'method': 'grid'} + sweep_config['parameters'] = parameters_dict + metric = {'name': 'scores', 'goal': 'maximize'} + + sweep_config['metric'] = metric + return sweep_config, train #Return function configuration and training function + + +if __name__ == "__main__": + """get_function_combinations.""" + function_list = setStep2(startSweep, original_list=["gene_filter", "cell_filter", "normalize"]) + for func in function_list: + func() diff --git a/test_automl/step2_examples/step2_imputation_deepimpute.py b/test_automl/step2_examples/step2_imputation_deepimpute.py new file mode 100644 index 000000000..5643a667e --- /dev/null +++ b/test_automl/step2_examples/step2_imputation_deepimpute.py @@ -0,0 +1,124 @@ +from typing import Any, Callable, Dict, Tuple + +import numpy as np +import torch + +from dance import logger +from dance.automl_config.step2_config import get_transforms, log_in_wandb, setStep2 +from dance.datasets.singlemodality import ImputationDataset +from dance.modules.single_modality.imputation.deepimpute import DeepImpute +from dance.transforms.misc import Compose, SetConfig +from dance.utils import set_seed + +device = torch.device("cuda:2" if torch.cuda.is_available() else "cpu") + + +@log_in_wandb(config=None) +def train(config): + """imputation.""" + rmses = [] + for seed in range(config.seed, config.seed + config.num_runs): + set_seed(seed) + dataset = "mouse_brain_data" + data_dir = "./test_automl/data" + dataloader = ImputationDataset(data_dir=data_dir, dataset=dataset, train_size=config.train_size) + transforms = get_transforms(config=config, set_data_config=False, save_raw=True) + if transforms is None: + logger.warning("skip transforms") + return {"scores": 0} + transforms.append( + SetConfig({ + "feature_channel": [None, None, "targets", "predictors", "train_mask"], + "feature_channel_type": ["X", "raw_X", "uns", "uns", "layers"], + "label_channel": [None, None], + "label_channel_type": ["X", "raw_X"], + })) + preprocessing_pipeline = Compose(*transforms, log_level="INFO") + data = dataloader.load_data(transform=preprocessing_pipeline, cache=config.cache) + + if config.mask: + X, X_raw, targets, predictors, mask = data.get_x(return_type="default") + else: + mask = None + X, X_raw, targets, predictors = data.get_x(return_type="default") + X = torch.tensor(X.toarray()).float() + X_raw = torch.tensor(X_raw.toarray()).float() + X_train = X * mask + model = DeepImpute(predictors, targets, dataset, config.sub_outputdim, config.hidden_dim, config.dropout, seed, + 2) + + model.fit(X_train, X_train, mask, config.batch_size, config.lr, config.n_epochs, config.patience) + imputed_data = model.predict(X_train, mask) + score = model.score(X, imputed_data, mask, metric='RMSE') + print("RMSE: %.4f" % score) + rmses.append(score) + + print('deepimpute') + print(f'rmses: {rmses}') + print(f'rmses: {np.mean(rmses)} +/- {np.std(rmses)}') + return ({"scores": np.mean(rmses)}) + + +def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: + parameters_dict.update({ + 'dropout': { + 'value': 0.1 + }, + 'lr': { + 'value': 1e-5 + }, + 'n_epochs': { + 'value': 5 + }, + 'batch_size': { + 'value': 64 + }, + 'sub_outputdim': { + 'value': 512 + }, + 'hidden_dim': { + 'value': 256 + }, + 'patience': { + 'value': 20 + }, + 'min_cells': { + 'value': 0.05 + }, + "n_top": { + 'value': 5 + }, + "train_size": { + "value": 0.9 + }, + "mask_rate": { + "value": 0.1 + }, + "cache": { + "value": False + }, + "mask": { #避免出现与超参数流程重复的情况,一般没有 + "value": True + }, + "seed": { + "value": 0 + }, + "num_runs": { + "value": 1 + } + }) + sweep_config = {'method': 'grid'} + sweep_config['parameters'] = parameters_dict + metric = {'name': 'scores', 'goal': 'minimize'} + + sweep_config['metric'] = metric + return sweep_config, train #Return function configuration and training function + + +if __name__ == "__main__": + """get_function_combinations.""" + function_list = setStep2( + startSweep, original_list=["gene_filter", "cell_filter", "normalize", "gene_hold_out_name", "mask_name"], + required_elements=["gene_hold_out_name", "mask_name"]) + for func in function_list: + func() From 9aa8fa2af85158abc5eed0731eb893f41d242dc9 Mon Sep 17 00:00:00 2001 From: xzy Date: Tue, 23 Jan 2024 23:40:14 +0800 Subject: [PATCH 134/168] update import --- dance/automl_config/__init__.py | 0 .../automl_config}/fun2code.py | 0 .../automl_config}/readme.txt | 0 .../automl_config}/step2_config.py | 3 +- .../automl_config}/step3_config.py | 6 +- ...ep2_cell_type_annotation_actinn_example.py | 84 --------- test_automl/step2_clustering_scdcc.py | 167 ------------------ test_automl/step2_imputation_deepimpute.py | 124 ------------- ...ep3_cell_type_annotation_actinn_example.py | 2 +- .../step3_clustering_scdcc.py | 2 +- .../step3_imputation_deepimpute.py | 2 +- 11 files changed, 7 insertions(+), 383 deletions(-) create mode 100644 dance/automl_config/__init__.py rename {test_automl => dance/automl_config}/fun2code.py (100%) rename {test_automl => dance/automl_config}/readme.txt (100%) rename {test_automl => dance/automl_config}/step2_config.py (98%) rename {test_automl => dance/automl_config}/step3_config.py (98%) delete mode 100644 test_automl/step2_cell_type_annotation_actinn_example.py delete mode 100644 test_automl/step2_clustering_scdcc.py delete mode 100644 test_automl/step2_imputation_deepimpute.py rename test_automl/{ => step3_examples}/step3_cell_type_annotation_actinn_example.py (96%) rename test_automl/{ => step3_examples}/step3_clustering_scdcc.py (98%) rename test_automl/{ => step3_examples}/step3_imputation_deepimpute.py (98%) diff --git a/dance/automl_config/__init__.py b/dance/automl_config/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test_automl/fun2code.py b/dance/automl_config/fun2code.py similarity index 100% rename from test_automl/fun2code.py rename to dance/automl_config/fun2code.py diff --git a/test_automl/readme.txt b/dance/automl_config/readme.txt similarity index 100% rename from test_automl/readme.txt rename to dance/automl_config/readme.txt diff --git a/test_automl/step2_config.py b/dance/automl_config/step2_config.py similarity index 98% rename from test_automl/step2_config.py rename to dance/automl_config/step2_config.py index 7b62a4e63..c89f999ca 100644 --- a/test_automl/step2_config.py +++ b/dance/automl_config/step2_config.py @@ -2,8 +2,7 @@ import itertools import wandb -from fun2code import fun2code_dict - +from dance.automl_config.fun2code import fun2code_dict from dance.transforms.misc import SetConfig #TODO register more functions and add more examples diff --git a/test_automl/step3_config.py b/dance/automl_config/step3_config.py similarity index 98% rename from test_automl/step3_config.py rename to dance/automl_config/step3_config.py index 6bd47cbc2..1560da958 100644 --- a/test_automl/step3_config.py +++ b/dance/automl_config/step3_config.py @@ -3,11 +3,11 @@ import optuna import scanpy as sc -import wandb -from fun2code import fun2code_dict from optuna.integration.wandb import WeightsAndBiasesCallback -from step2_config import pipline2fun_dict +import wandb +from dance.automl_config.fun2code import fun2code_dict +from dance.automl_config.step2_config import pipline2fun_dict from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA from dance.transforms.filter import FilterGenesPercentile, FilterGenesRegression from dance.transforms.gene_holdout import GeneHoldout diff --git a/test_automl/step2_cell_type_annotation_actinn_example.py b/test_automl/step2_cell_type_annotation_actinn_example.py deleted file mode 100644 index 7d5b87dcc..000000000 --- a/test_automl/step2_cell_type_annotation_actinn_example.py +++ /dev/null @@ -1,84 +0,0 @@ -from typing import Any, Callable, Dict, Tuple - -import numpy as np -import torch -from step2_config import get_transforms, log_in_wandb, setStep2 - -from dance import logger -from dance.datasets.singlemodality import CellTypeAnnotationDataset -from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN -from dance.transforms.misc import Compose -from dance.utils import set_seed - -device = torch.device("cuda" if torch.cuda.is_available() else "cpu") - - -@log_in_wandb(config=None) -def train(config): - - model = ACTINN(hidden_dims=config.hidden_dims, lambd=config.lambd, device=device) - transforms = get_transforms(config=config) - if transforms is None: - logger.warning("skip transforms") - return {"scores": 0} - preprocessing_pipeline = Compose(*transforms, log_level="INFO") - train_dataset = [753, 3285] - test_dataset = [2695] - tissue = "Brain" - species = "mouse" - dataloader = CellTypeAnnotationDataset(train_dataset=train_dataset, test_dataset=test_dataset, tissue=tissue, - species=species, data_dir="./test_automl/data") - data = dataloader.load_data(transform=preprocessing_pipeline, cache=False) - - # Obtain training and testing data - x_train, y_train = data.get_train_data(return_type="torch") - x_test, y_test = data.get_test_data(return_type="torch") - x_train, y_train, x_test, y_test = x_train.float(), y_train.float(), x_test.float(), y_test.float() - # Train and evaluate models for several rounds - scores = [] - for seed in range(config.seed, config.seed + config.num_runs): - set_seed(seed) - - model.fit(x_train, y_train, seed=seed, lr=config.learning_rate, num_epochs=config.num_epochs, - batch_size=config.batch_size, print_cost=False) - scores.append(score := model.score(x_test, y_test)) - return {"scores": np.mean(scores)} - - -def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: - parameters_dict.update({ - 'batch_size': { - 'value': 128 - }, - "hidden_dims": { - 'value': [2000] - }, - 'lambd': { - 'value': 0.005 - }, - 'num_epochs': { - 'value': 50 - }, - 'seed': { - 'value': 0 - }, - 'num_runs': { - 'value': 1 - }, - 'learning_rate': { - 'value': 0.0001 - } - }) - sweep_config = {'method': 'grid'} - sweep_config['parameters'] = parameters_dict - metric = {'name': 'scores', 'goal': 'maximize'} - - sweep_config['metric'] = metric - return sweep_config, train #Return function configuration and training function - - -if __name__ == "__main__": - """get_function_combinations.""" - function_list = setStep2(startSweep, original_list=["normalize", "gene_filter", "gene_dim_reduction"]) - for func in function_list: - func() diff --git a/test_automl/step2_clustering_scdcc.py b/test_automl/step2_clustering_scdcc.py deleted file mode 100644 index 535b328c7..000000000 --- a/test_automl/step2_clustering_scdcc.py +++ /dev/null @@ -1,167 +0,0 @@ -"""normalize_total is a must at SCDCC because it requires n_counts.""" -import os -from typing import Any, Callable, Dict, Tuple - -import numpy as np -import torch -from step2_config import get_transforms, log_in_wandb, setStep2 - -from dance import logger -from dance.datasets.singlemodality import ClusteringDataset -from dance.modules.single_modality.clustering.scdcc import ScDCC -from dance.transforms.misc import Compose, SetConfig -from dance.transforms.preprocess import generate_random_pair -from dance.utils import set_seed - -device = torch.device("cuda" if torch.cuda.is_available() else "cpu") - - -@log_in_wandb(config=None) -def train(config): - """clustering.""" - aris = [] - for seed in range(config.seed, config.seed + config.num_runs): - set_seed(seed) - dataset = "10X_PBMC" - # Load data and perform necessary preprocessing - dataloader = ClusteringDataset("./test_automl/data", dataset=dataset) - - transforms = get_transforms(config=config, set_data_config=False, save_raw=True) - if ("normalize" not in config.keys() or config.normalize != "normalize_total") or transforms is None: - logger.warning("skip transforms") - return {"scores": 0} - transforms.append( - SetConfig({ - "feature_channel": [None, None, "n_counts"], - "feature_channel_type": ["X", "raw_X", "obs"], - "label_channel": "Group" - })) - preprocessing_pipeline = Compose(*transforms, log_level="INFO") - data = dataloader.load_data(transform=preprocessing_pipeline, cache=config.cache) - - # inputs: x, x_raw, n_counts - inputs, y = data.get_train_data() - n_clusters = len(np.unique(y)) - in_dim = inputs[0].shape[1] - - # Generate random pairs - if not os.path.exists(config.label_cells_files): - indx = np.arange(len(y)) - np.random.shuffle(indx) - label_cell_indx = indx[0:int(np.ceil(config.label_cells * len(y)))] - else: - label_cell_indx = np.loadtxt(config.label_cells_files, dtype=np.int) - - if config.n_pairwise > 0: - ml_ind1, ml_ind2, cl_ind1, cl_ind2, error_num = generate_random_pair(y, label_cell_indx, config.n_pairwise, - config.n_pairwise_error) - print("Must link paris: %d" % ml_ind1.shape[0]) - print("Cannot link paris: %d" % cl_ind1.shape[0]) - print("Number of error pairs: %d" % error_num) - else: - ml_ind1, ml_ind2, cl_ind1, cl_ind2 = np.array([]), np.array([]), np.array([]), np.array([]) - - # Build and train moodel - model = ScDCC(input_dim=in_dim, z_dim=config.z_dim, n_clusters=n_clusters, encodeLayer=config.encodeLayer, - decodeLayer=config.encodeLayer[::-1], sigma=config.sigma, gamma=config.gamma, - ml_weight=config.ml_weight, cl_weight=config.ml_weight, device=device, - pretrain_path=f"scdcc_{dataset}_pre.pkl") - model.fit(inputs, y, lr=config.lr, batch_size=config.batch_size, epochs=config.epochs, ml_ind1=ml_ind1, - ml_ind2=ml_ind2, cl_ind1=cl_ind1, cl_ind2=cl_ind2, update_interval=config.update_interval, - tol=config.tol, pt_batch_size=config.batch_size, pt_lr=config.pretrain_lr, - pt_epochs=config.pretrain_epochs) - - # Evaluate model predictions - score = model.score(None, y) - print(f"{score=:.4f}") - aris.append(score) - - print('scdcc') - print(f'aris: {aris}') - print(f'aris: {np.mean(aris)} +/- {np.std(aris)}') - return ({"scores": np.mean(aris)}) - - -def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: - parameters_dict.update({ - 'seed': { - 'value': 0 - }, - 'num_runs': { - 'value': 1 - }, - 'cache': { - 'value': True - }, - 'label_cells_files': { - 'value': 'label_10X_PBMC.txt' - }, - 'label_cells': { - 'value': 0.1 - }, - 'n_pairwise': { - 'value': 0 - }, - 'n_pairwise_error': { - 'value': 0 - }, - 'z_dim': { - 'value': 32 - }, - 'encodeLayer': { - 'value': [256, 64] - }, - 'sigma': { - 'value': 2.5 - }, - 'gamma': { - 'value': 1.0 - }, - 'lr': { - 'value': 0.01 - }, - 'pretrain_lr': { - 'value': 0.001 - }, - 'ml_weight': { - 'value': 1.0 - }, - 'cl_weight': { - 'value': 1.0 - }, - 'update_interval': { - 'value': 1.0 - }, - 'tol': { - 'value': 0.00001 - }, - 'ae_weights': { - 'value': None - }, - 'ae_weight_file': { - 'value': "AE_weights.pth.tar" - }, - 'pretrain_epochs': { - 'value': 50 - }, - 'epochs': { - 'value': 500 - }, - 'batch_size': { - 'value': 256 - } - }) - - sweep_config = {'method': 'grid'} - sweep_config['parameters'] = parameters_dict - metric = {'name': 'scores', 'goal': 'maximize'} - - sweep_config['metric'] = metric - return sweep_config, train #Return function configuration and training function - - -if __name__ == "__main__": - """get_function_combinations.""" - function_list = setStep2(startSweep, original_list=["gene_filter", "cell_filter", "normalize"]) - for func in function_list: - func() diff --git a/test_automl/step2_imputation_deepimpute.py b/test_automl/step2_imputation_deepimpute.py deleted file mode 100644 index 3991499d0..000000000 --- a/test_automl/step2_imputation_deepimpute.py +++ /dev/null @@ -1,124 +0,0 @@ -from typing import Any, Callable, Dict, Tuple - -import numpy as np -import torch -from step2_config import get_transforms, log_in_wandb, setStep2 - -from dance import logger -from dance.datasets.singlemodality import ImputationDataset -from dance.modules.single_modality.imputation.deepimpute import DeepImpute -from dance.transforms.misc import Compose, SetConfig -from dance.utils import set_seed - -device = torch.device("cuda:2" if torch.cuda.is_available() else "cpu") - - -@log_in_wandb(config=None) -def train(config): - """imputation.""" - rmses = [] - for seed in range(config.seed, config.seed + config.num_runs): - set_seed(seed) - dataset = "mouse_brain_data" - data_dir = "./test_automl/data" - dataloader = ImputationDataset(data_dir=data_dir, dataset=dataset, train_size=config.train_size) - transforms = get_transforms(config=config, set_data_config=False, save_raw=True) - if transforms is None: - logger.warning("skip transforms") - return {"scores": 0} - transforms.append( - SetConfig({ - "feature_channel": [None, None, "targets", "predictors", "train_mask"], - "feature_channel_type": ["X", "raw_X", "uns", "uns", "layers"], - "label_channel": [None, None], - "label_channel_type": ["X", "raw_X"], - })) - preprocessing_pipeline = Compose(*transforms, log_level="INFO") - data = dataloader.load_data(transform=preprocessing_pipeline, cache=config.cache) - - if config.mask: - X, X_raw, targets, predictors, mask = data.get_x(return_type="default") - else: - mask = None - X, X_raw, targets, predictors = data.get_x(return_type="default") - X = torch.tensor(X.toarray()).float() - X_raw = torch.tensor(X_raw.toarray()).float() - X_train = X * mask - model = DeepImpute(predictors, targets, dataset, config.sub_outputdim, config.hidden_dim, config.dropout, seed, - 2) - - model.fit(X_train, X_train, mask, config.batch_size, config.lr, config.n_epochs, config.patience) - imputed_data = model.predict(X_train, mask) - score = model.score(X, imputed_data, mask, metric='RMSE') - print("RMSE: %.4f" % score) - rmses.append(score) - - print('deepimpute') - print(f'rmses: {rmses}') - print(f'rmses: {np.mean(rmses)} +/- {np.std(rmses)}') - return ({"scores": np.mean(rmses)}) - - -def startSweep(parameters_dict) -> Tuple[Dict[str, Any], Callable[..., Any]]: - parameters_dict.update({ - 'dropout': { - 'value': 0.1 - }, - 'lr': { - 'value': 1e-5 - }, - 'n_epochs': { - 'value': 5 - }, - 'batch_size': { - 'value': 64 - }, - 'sub_outputdim': { - 'value': 512 - }, - 'hidden_dim': { - 'value': 256 - }, - 'patience': { - 'value': 20 - }, - 'min_cells': { - 'value': 0.05 - }, - "n_top": { - 'value': 5 - }, - "train_size": { - "value": 0.9 - }, - "mask_rate": { - "value": 0.1 - }, - "cache": { - "value": False - }, - "mask": { #避免出现与超参数流程重复的情况,一般没有 - "value": True - }, - "seed": { - "value": 0 - }, - "num_runs": { - "value": 1 - } - }) - sweep_config = {'method': 'grid'} - sweep_config['parameters'] = parameters_dict - metric = {'name': 'scores', 'goal': 'minimize'} - - sweep_config['metric'] = metric - return sweep_config, train #Return function configuration and training function - - -if __name__ == "__main__": - """get_function_combinations.""" - function_list = setStep2( - startSweep, original_list=["gene_filter", "cell_filter", "normalize", "gene_hold_out_name", "mask_name"], - required_elements=["gene_hold_out_name", "mask_name"]) - for func in function_list: - func() diff --git a/test_automl/step3_cell_type_annotation_actinn_example.py b/test_automl/step3_examples/step3_cell_type_annotation_actinn_example.py similarity index 96% rename from test_automl/step3_cell_type_annotation_actinn_example.py rename to test_automl/step3_examples/step3_cell_type_annotation_actinn_example.py index 4ab19e97d..578ec91e6 100644 --- a/test_automl/step3_cell_type_annotation_actinn_example.py +++ b/test_automl/step3_examples/step3_cell_type_annotation_actinn_example.py @@ -1,8 +1,8 @@ import numpy as np import torch -from step3_config import get_optimizer, get_transforms from dance import logger +from dance.automl_config.step3_config import get_optimizer, get_transforms from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.misc import Compose diff --git a/test_automl/step3_clustering_scdcc.py b/test_automl/step3_examples/step3_clustering_scdcc.py similarity index 98% rename from test_automl/step3_clustering_scdcc.py rename to test_automl/step3_examples/step3_clustering_scdcc.py index eb3fa94f8..9280eb62b 100644 --- a/test_automl/step3_clustering_scdcc.py +++ b/test_automl/step3_examples/step3_clustering_scdcc.py @@ -2,8 +2,8 @@ import numpy as np import torch -from step3_config import get_optimizer, get_transforms +from dance.automl_config.step3_config import get_optimizer, get_transforms from dance.datasets.singlemodality import ClusteringDataset from dance.modules.single_modality.clustering.scdcc import ScDCC from dance.registry import DotDict # Optional diff --git a/test_automl/step3_imputation_deepimpute.py b/test_automl/step3_examples/step3_imputation_deepimpute.py similarity index 98% rename from test_automl/step3_imputation_deepimpute.py rename to test_automl/step3_examples/step3_imputation_deepimpute.py index 29726a862..2041906c5 100644 --- a/test_automl/step3_imputation_deepimpute.py +++ b/test_automl/step3_examples/step3_imputation_deepimpute.py @@ -1,7 +1,7 @@ import torch -from step3_config import get_optimizer, get_transforms from dance import logger +from dance.automl_config.step3_config import get_optimizer, get_transforms from dance.datasets.singlemodality import ImputationDataset from dance.modules.single_modality.imputation.deepimpute import DeepImpute from dance.registry import DotDict From 0b663f4c1f01a487ba8c68d1477e64e263cb7233 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 15:41:07 +0000 Subject: [PATCH 135/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dance/automl_config/step2_config.py | 1 + dance/automl_config/step3_config.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/dance/automl_config/step2_config.py b/dance/automl_config/step2_config.py index c89f999ca..ba874cdc3 100644 --- a/dance/automl_config/step2_config.py +++ b/dance/automl_config/step2_config.py @@ -2,6 +2,7 @@ import itertools import wandb + from dance.automl_config.fun2code import fun2code_dict from dance.transforms.misc import SetConfig diff --git a/dance/automl_config/step3_config.py b/dance/automl_config/step3_config.py index 1560da958..e42934cf9 100644 --- a/dance/automl_config/step3_config.py +++ b/dance/automl_config/step3_config.py @@ -3,9 +3,9 @@ import optuna import scanpy as sc +import wandb from optuna.integration.wandb import WeightsAndBiasesCallback -import wandb from dance.automl_config.fun2code import fun2code_dict from dance.automl_config.step2_config import pipline2fun_dict from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA From ea9275e1196656f3ad23a972f55a020b8b87d93b Mon Sep 17 00:00:00 2001 From: xzy Date: Tue, 23 Jan 2024 23:54:07 +0800 Subject: [PATCH 136/168] add warning message --- dance/automl_config/step2_config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dance/automl_config/step2_config.py b/dance/automl_config/step2_config.py index ba874cdc3..24ad670fe 100644 --- a/dance/automl_config/step2_config.py +++ b/dance/automl_config/step2_config.py @@ -2,7 +2,7 @@ import itertools import wandb - +from dance import logger from dance.automl_config.fun2code import fun2code_dict from dance.transforms.misc import SetConfig @@ -64,7 +64,7 @@ def get_transforms(config=None, set_data_config=True, save_raw=False): process.""" if ("normalize" not in config.keys() or config.normalize != "log1p") and ("gene_filter" in config.keys() and config.gene_filter == "highly_variable_genes"): - + logger.warning("Expects logarithmized data, except when flavor='seurat_v3', in which count data is expected.") return None transforms = [] From 8f741513c122f9d92c7d9642c6dbc727e056c796 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 15:55:11 +0000 Subject: [PATCH 137/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dance/automl_config/step2_config.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dance/automl_config/step2_config.py b/dance/automl_config/step2_config.py index 24ad670fe..deb18aa19 100644 --- a/dance/automl_config/step2_config.py +++ b/dance/automl_config/step2_config.py @@ -2,6 +2,7 @@ import itertools import wandb + from dance import logger from dance.automl_config.fun2code import fun2code_dict from dance.transforms.misc import SetConfig From c3cd1911ea6206a423229fbbcdd336a453eff8fa Mon Sep 17 00:00:00 2001 From: xzy Date: Tue, 23 Jan 2024 23:59:00 +0800 Subject: [PATCH 138/168] add warning message --- dance/automl_config/step2_config.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dance/automl_config/step2_config.py b/dance/automl_config/step2_config.py index deb18aa19..7dbb04b24 100644 --- a/dance/automl_config/step2_config.py +++ b/dance/automl_config/step2_config.py @@ -2,7 +2,6 @@ import itertools import wandb - from dance import logger from dance.automl_config.fun2code import fun2code_dict from dance.transforms.misc import SetConfig @@ -65,7 +64,9 @@ def get_transforms(config=None, set_data_config=True, save_raw=False): process.""" if ("normalize" not in config.keys() or config.normalize != "log1p") and ("gene_filter" in config.keys() and config.gene_filter == "highly_variable_genes"): - logger.warning("Expects logarithmized data, except when flavor='seurat_v3', in which count data is expected.") + logger.warning( + "highly_variable_genes expects logarithmized data, except when flavor='seurat_v3', in which count data is expected." + ) return None transforms = [] From 435366baea6f5344f71680eae749a79890396d2e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 15:59:36 +0000 Subject: [PATCH 139/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dance/automl_config/step2_config.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dance/automl_config/step2_config.py b/dance/automl_config/step2_config.py index 7dbb04b24..15f4cf498 100644 --- a/dance/automl_config/step2_config.py +++ b/dance/automl_config/step2_config.py @@ -2,6 +2,7 @@ import itertools import wandb + from dance import logger from dance.automl_config.fun2code import fun2code_dict from dance.transforms.misc import SetConfig From 05c808b910f5e3245875284d2afd031983f70e0a Mon Sep 17 00:00:00 2001 From: xzy Date: Wed, 24 Jan 2024 00:27:52 +0800 Subject: [PATCH 140/168] add warning message --- dance/automl_config/step3_config.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/dance/automl_config/step3_config.py b/dance/automl_config/step3_config.py index e42934cf9..f0cf4d4e4 100644 --- a/dance/automl_config/step3_config.py +++ b/dance/automl_config/step3_config.py @@ -3,9 +3,10 @@ import optuna import scanpy as sc -import wandb from optuna.integration.wandb import WeightsAndBiasesCallback +import wandb +from dance import logger from dance.automl_config.fun2code import fun2code_dict from dance.automl_config.step2_config import pipline2fun_dict from dance.transforms.cell_feature import CellPCA, CellSVD, WeightedFeaturePCA @@ -173,6 +174,12 @@ def get_transforms(trial, fun_list, set_data_config=True, save_raw=False): fun_i = eval(f_str) transforms.append(fun_i(trial)) if "highly_variable_genes" in fun_list and "log1p" not in fun_list[:fun_list.index('"highly_variable_genes"')]: + logger.warning( + "highly_variable_genes expects logarithmized data, except when flavor='seurat_v3', in which count data is expected." + ) + + #The relationship between highly_variable_genes and log1p needs to be further discussed based on the flavor parameter + #A little change is needed return None if set_data_config: data_config = {"label_channel": "cell_type"} From 20136dd2ae5c9e814f0ba4f340672ee65daaf111 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 16:29:19 +0000 Subject: [PATCH 141/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dance/automl_config/step3_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dance/automl_config/step3_config.py b/dance/automl_config/step3_config.py index f0cf4d4e4..5d4613b50 100644 --- a/dance/automl_config/step3_config.py +++ b/dance/automl_config/step3_config.py @@ -3,9 +3,9 @@ import optuna import scanpy as sc +import wandb from optuna.integration.wandb import WeightsAndBiasesCallback -import wandb from dance import logger from dance.automl_config.fun2code import fun2code_dict from dance.automl_config.step2_config import pipline2fun_dict From 93d3a81c443aa41931db0dd3cc11db21108bb0d9 Mon Sep 17 00:00:00 2001 From: xzy Date: Thu, 25 Jan 2024 10:27:20 +0800 Subject: [PATCH 142/168] normalize code --- dance/automl_config/step3_config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dance/automl_config/step3_config.py b/dance/automl_config/step3_config.py index 5d4613b50..53f944e71 100644 --- a/dance/automl_config/step3_config.py +++ b/dance/automl_config/step3_config.py @@ -3,9 +3,9 @@ import optuna import scanpy as sc -import wandb from optuna.integration.wandb import WeightsAndBiasesCallback +import wandb from dance import logger from dance.automl_config.fun2code import fun2code_dict from dance.automl_config.step2_config import pipline2fun_dict @@ -14,7 +14,7 @@ from dance.transforms.gene_holdout import GeneHoldout from dance.transforms.interface import AnnDataTransform from dance.transforms.mask import CellwiseMaskData, MaskData -from dance.transforms.misc import Compose, SetConfig +from dance.transforms.misc import SetConfig from dance.transforms.normalize import ScaleFeature, ScTransformR From 6ec53fc2710b5565ff4b9492614e12ac54fc0dbb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 02:27:48 +0000 Subject: [PATCH 143/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dance/automl_config/step3_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dance/automl_config/step3_config.py b/dance/automl_config/step3_config.py index 53f944e71..989206fbc 100644 --- a/dance/automl_config/step3_config.py +++ b/dance/automl_config/step3_config.py @@ -3,9 +3,9 @@ import optuna import scanpy as sc +import wandb from optuna.integration.wandb import WeightsAndBiasesCallback -import wandb from dance import logger from dance.automl_config.fun2code import fun2code_dict from dance.automl_config.step2_config import pipline2fun_dict From 8af1e27e98e57c00c711da791275c75e04237f20 Mon Sep 17 00:00:00 2001 From: xzy Date: Thu, 25 Jan 2024 11:03:30 +0800 Subject: [PATCH 144/168] normalize code --- dance/automl_config/step2_config.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/dance/automl_config/step2_config.py b/dance/automl_config/step2_config.py index 15f4cf498..690f61a07 100644 --- a/dance/automl_config/step2_config.py +++ b/dance/automl_config/step2_config.py @@ -2,7 +2,6 @@ import itertools import wandb - from dance import logger from dance.automl_config.fun2code import fun2code_dict from dance.transforms.misc import SetConfig @@ -32,6 +31,14 @@ def generate_combinations_with_required_elements(elements, required_elements=[]): + """ + Parameters + ---------- + elements + Optional process in Step 2 + required_elements + The required process in Step 2 + """ optional_elements = [x for x in elements if x not in required_elements] # Sort optional elements in the same order as in the `elements` list From d6343d9c115ad24152830daeb41c0ab6fe702935 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 03:03:58 +0000 Subject: [PATCH 145/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dance/automl_config/step2_config.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dance/automl_config/step2_config.py b/dance/automl_config/step2_config.py index 690f61a07..6eed364cb 100644 --- a/dance/automl_config/step2_config.py +++ b/dance/automl_config/step2_config.py @@ -2,6 +2,7 @@ import itertools import wandb + from dance import logger from dance.automl_config.fun2code import fun2code_dict from dance.transforms.misc import SetConfig From 904261eddb8df357ef9840189e9512d1c43ad4f2 Mon Sep 17 00:00:00 2001 From: xzy Date: Thu, 25 Jan 2024 16:17:04 +0800 Subject: [PATCH 146/168] don't delete --- .gitignore | 6 ++++-- dance/{ => legacy}/automl_config/__init__.py | 0 dance/{ => legacy}/automl_config/fun2code.py | 0 dance/{ => legacy}/automl_config/readme.txt | 0 dance/{ => legacy}/automl_config/step2_config.py | 0 dance/{ => legacy}/automl_config/step3_config.py | 2 +- .../step2_cell_type_annotation_actinn_example.py | 0 .../test_automl}/step2_examples/step2_clustering_scdcc.py | 2 +- .../step2_examples/step2_imputation_deepimpute.py | 2 +- .../step3_cell_type_annotation_actinn_example.py | 2 +- .../test_automl}/step3_examples/step3_clustering_scdcc.py | 2 +- .../step3_examples/step3_imputation_deepimpute.py | 2 +- {test_automl => legacy/test_automl}/tests/step2_test.py | 0 {test_automl => legacy/test_automl}/tests/step3_test.py | 0 14 files changed, 10 insertions(+), 8 deletions(-) rename dance/{ => legacy}/automl_config/__init__.py (100%) rename dance/{ => legacy}/automl_config/fun2code.py (100%) rename dance/{ => legacy}/automl_config/readme.txt (100%) rename dance/{ => legacy}/automl_config/step2_config.py (100%) rename dance/{ => legacy}/automl_config/step3_config.py (100%) rename {test_automl => legacy/test_automl}/step2_examples/step2_cell_type_annotation_actinn_example.py (100%) rename {test_automl => legacy/test_automl}/step2_examples/step2_clustering_scdcc.py (98%) rename {test_automl => legacy/test_automl}/step2_examples/step2_imputation_deepimpute.py (97%) rename {test_automl => legacy/test_automl}/step3_examples/step3_cell_type_annotation_actinn_example.py (96%) rename {test_automl => legacy/test_automl}/step3_examples/step3_clustering_scdcc.py (98%) rename {test_automl => legacy/test_automl}/step3_examples/step3_imputation_deepimpute.py (97%) rename {test_automl => legacy/test_automl}/tests/step2_test.py (100%) rename {test_automl => legacy/test_automl}/tests/step3_test.py (100%) diff --git a/.gitignore b/.gitignore index c89316820..539fb3bb0 100644 --- a/.gitignore +++ b/.gitignore @@ -11,8 +11,10 @@ __pycache__ wandb -test_automl/data -test_automl/test.py +legacy/test_automl/data +legacy/test_automl/test.py *.pkl *.pt openfe-singlecell +examples/tuning/cta_svm/test +examples/tuning/cta_svm/train diff --git a/dance/automl_config/__init__.py b/dance/legacy/automl_config/__init__.py similarity index 100% rename from dance/automl_config/__init__.py rename to dance/legacy/automl_config/__init__.py diff --git a/dance/automl_config/fun2code.py b/dance/legacy/automl_config/fun2code.py similarity index 100% rename from dance/automl_config/fun2code.py rename to dance/legacy/automl_config/fun2code.py diff --git a/dance/automl_config/readme.txt b/dance/legacy/automl_config/readme.txt similarity index 100% rename from dance/automl_config/readme.txt rename to dance/legacy/automl_config/readme.txt diff --git a/dance/automl_config/step2_config.py b/dance/legacy/automl_config/step2_config.py similarity index 100% rename from dance/automl_config/step2_config.py rename to dance/legacy/automl_config/step2_config.py diff --git a/dance/automl_config/step3_config.py b/dance/legacy/automl_config/step3_config.py similarity index 100% rename from dance/automl_config/step3_config.py rename to dance/legacy/automl_config/step3_config.py index 989206fbc..53f944e71 100644 --- a/dance/automl_config/step3_config.py +++ b/dance/legacy/automl_config/step3_config.py @@ -3,9 +3,9 @@ import optuna import scanpy as sc -import wandb from optuna.integration.wandb import WeightsAndBiasesCallback +import wandb from dance import logger from dance.automl_config.fun2code import fun2code_dict from dance.automl_config.step2_config import pipline2fun_dict diff --git a/test_automl/step2_examples/step2_cell_type_annotation_actinn_example.py b/legacy/test_automl/step2_examples/step2_cell_type_annotation_actinn_example.py similarity index 100% rename from test_automl/step2_examples/step2_cell_type_annotation_actinn_example.py rename to legacy/test_automl/step2_examples/step2_cell_type_annotation_actinn_example.py diff --git a/test_automl/step2_examples/step2_clustering_scdcc.py b/legacy/test_automl/step2_examples/step2_clustering_scdcc.py similarity index 98% rename from test_automl/step2_examples/step2_clustering_scdcc.py rename to legacy/test_automl/step2_examples/step2_clustering_scdcc.py index f92759a3a..e8e6383bf 100644 --- a/test_automl/step2_examples/step2_clustering_scdcc.py +++ b/legacy/test_automl/step2_examples/step2_clustering_scdcc.py @@ -6,8 +6,8 @@ import torch from dance import logger -from dance.automl_config.step2_config import get_transforms, log_in_wandb, setStep2 from dance.datasets.singlemodality import ClusteringDataset +from dance.legacy.automl_config.step2_config import get_transforms, log_in_wandb, setStep2 from dance.modules.single_modality.clustering.scdcc import ScDCC from dance.transforms.misc import Compose, SetConfig from dance.transforms.preprocess import generate_random_pair diff --git a/test_automl/step2_examples/step2_imputation_deepimpute.py b/legacy/test_automl/step2_examples/step2_imputation_deepimpute.py similarity index 97% rename from test_automl/step2_examples/step2_imputation_deepimpute.py rename to legacy/test_automl/step2_examples/step2_imputation_deepimpute.py index 5643a667e..df4b0ed3d 100644 --- a/test_automl/step2_examples/step2_imputation_deepimpute.py +++ b/legacy/test_automl/step2_examples/step2_imputation_deepimpute.py @@ -4,8 +4,8 @@ import torch from dance import logger -from dance.automl_config.step2_config import get_transforms, log_in_wandb, setStep2 from dance.datasets.singlemodality import ImputationDataset +from dance.legacy.automl_config.step2_config import get_transforms, log_in_wandb, setStep2 from dance.modules.single_modality.imputation.deepimpute import DeepImpute from dance.transforms.misc import Compose, SetConfig from dance.utils import set_seed diff --git a/test_automl/step3_examples/step3_cell_type_annotation_actinn_example.py b/legacy/test_automl/step3_examples/step3_cell_type_annotation_actinn_example.py similarity index 96% rename from test_automl/step3_examples/step3_cell_type_annotation_actinn_example.py rename to legacy/test_automl/step3_examples/step3_cell_type_annotation_actinn_example.py index 578ec91e6..7914d0f23 100644 --- a/test_automl/step3_examples/step3_cell_type_annotation_actinn_example.py +++ b/legacy/test_automl/step3_examples/step3_cell_type_annotation_actinn_example.py @@ -2,8 +2,8 @@ import torch from dance import logger -from dance.automl_config.step3_config import get_optimizer, get_transforms from dance.datasets.singlemodality import CellTypeAnnotationDataset +from dance.legacy.automl_config.step3_config import get_optimizer, get_transforms from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.misc import Compose from dance.utils import set_seed diff --git a/test_automl/step3_examples/step3_clustering_scdcc.py b/legacy/test_automl/step3_examples/step3_clustering_scdcc.py similarity index 98% rename from test_automl/step3_examples/step3_clustering_scdcc.py rename to legacy/test_automl/step3_examples/step3_clustering_scdcc.py index 9280eb62b..29266bfaf 100644 --- a/test_automl/step3_examples/step3_clustering_scdcc.py +++ b/legacy/test_automl/step3_examples/step3_clustering_scdcc.py @@ -3,8 +3,8 @@ import numpy as np import torch -from dance.automl_config.step3_config import get_optimizer, get_transforms from dance.datasets.singlemodality import ClusteringDataset +from dance.legacy.automl_config.step3_config import get_optimizer, get_transforms from dance.modules.single_modality.clustering.scdcc import ScDCC from dance.registry import DotDict # Optional from dance.transforms.misc import Compose, SetConfig diff --git a/test_automl/step3_examples/step3_imputation_deepimpute.py b/legacy/test_automl/step3_examples/step3_imputation_deepimpute.py similarity index 97% rename from test_automl/step3_examples/step3_imputation_deepimpute.py rename to legacy/test_automl/step3_examples/step3_imputation_deepimpute.py index 2041906c5..77fdfbb92 100644 --- a/test_automl/step3_examples/step3_imputation_deepimpute.py +++ b/legacy/test_automl/step3_examples/step3_imputation_deepimpute.py @@ -1,8 +1,8 @@ import torch from dance import logger -from dance.automl_config.step3_config import get_optimizer, get_transforms from dance.datasets.singlemodality import ImputationDataset +from dance.legacy.automl_config.step3_config import get_optimizer, get_transforms from dance.modules.single_modality.imputation.deepimpute import DeepImpute from dance.registry import DotDict from dance.transforms.misc import Compose, SetConfig diff --git a/test_automl/tests/step2_test.py b/legacy/test_automl/tests/step2_test.py similarity index 100% rename from test_automl/tests/step2_test.py rename to legacy/test_automl/tests/step2_test.py diff --git a/test_automl/tests/step3_test.py b/legacy/test_automl/tests/step3_test.py similarity index 100% rename from test_automl/tests/step3_test.py rename to legacy/test_automl/tests/step3_test.py From ee61d25a1e75ff4694b6bd98b573f336f70ce3c0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 08:18:49 +0000 Subject: [PATCH 147/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dance/legacy/automl_config/step3_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dance/legacy/automl_config/step3_config.py b/dance/legacy/automl_config/step3_config.py index 53f944e71..989206fbc 100644 --- a/dance/legacy/automl_config/step3_config.py +++ b/dance/legacy/automl_config/step3_config.py @@ -3,9 +3,9 @@ import optuna import scanpy as sc +import wandb from optuna.integration.wandb import WeightsAndBiasesCallback -import wandb from dance import logger from dance.automl_config.fun2code import fun2code_dict from dance.automl_config.step2_config import pipline2fun_dict From 82aa0f9ffa4d1dc04687afa9b68ca701b4bbd340 Mon Sep 17 00:00:00 2001 From: xzy Date: Thu, 25 Jan 2024 16:56:53 +0800 Subject: [PATCH 148/168] add gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 539fb3bb0..24b551b10 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ legacy/test_automl/test.py openfe-singlecell examples/tuning/cta_svm/test examples/tuning/cta_svm/train +examples/tuning/cta_svm/map From 432d7526cd6aa47099ae4dd4b5f072697dda45c1 Mon Sep 17 00:00:00 2001 From: xzy Date: Thu, 25 Jan 2024 17:16:09 +0800 Subject: [PATCH 149/168] add comment --- .gitignore | 3 +++ examples/tuning/cta_svm/main.py | 3 +-- examples/tuning/cta_svm/tuning_config.yaml | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 24b551b10..c5cfd1e16 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,6 @@ openfe-singlecell examples/tuning/cta_svm/test examples/tuning/cta_svm/train examples/tuning/cta_svm/map +test +train +map diff --git a/examples/tuning/cta_svm/main.py b/examples/tuning/cta_svm/main.py index df9fb2bdb..7d606b737 100644 --- a/examples/tuning/cta_svm/main.py +++ b/examples/tuning/cta_svm/main.py @@ -3,7 +3,6 @@ from typing import get_args import wandb - from dance import logger from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.svm import SVM @@ -28,7 +27,7 @@ logger.setLevel(args.log_level) logger.info(f"\n{pprint.pformat(vars(args))}") - pipeline_planer = PipelinePlaner.from_config_file("tuning_config.yaml") + pipeline_planer = PipelinePlaner.from_config_file("examples/tuning/cta_svm/tuning_config.yaml") def evaluate_pipeline(): wandb.init() diff --git a/examples/tuning/cta_svm/tuning_config.yaml b/examples/tuning/cta_svm/tuning_config.yaml index b73c86dbb..095e4d96c 100644 --- a/examples/tuning/cta_svm/tuning_config.yaml +++ b/examples/tuning/cta_svm/tuning_config.yaml @@ -7,7 +7,7 @@ pipeline: - CellPCA - CellSVD params: - n_components: 400 + n_components: 400 #set same params? out: feature.cell default_params: WeightedFeaturePCA: From 4f93d768ea491c4d963d54a1d48b85a8741d26e2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 09:16:51 +0000 Subject: [PATCH 150/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- examples/tuning/cta_svm/main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/tuning/cta_svm/main.py b/examples/tuning/cta_svm/main.py index 7d606b737..892476e60 100644 --- a/examples/tuning/cta_svm/main.py +++ b/examples/tuning/cta_svm/main.py @@ -3,6 +3,7 @@ from typing import get_args import wandb + from dance import logger from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.svm import SVM From 32380e62419b29dc03b071d77efa1bc5e520717f Mon Sep 17 00:00:00 2001 From: xzy Date: Thu, 25 Jan 2024 20:41:21 +0800 Subject: [PATCH 151/168] add comment --- examples/tuning/cta_svm/tuning_config.yaml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/examples/tuning/cta_svm/tuning_config.yaml b/examples/tuning/cta_svm/tuning_config.yaml index 095e4d96c..03ac9b98c 100644 --- a/examples/tuning/cta_svm/tuning_config.yaml +++ b/examples/tuning/cta_svm/tuning_config.yaml @@ -7,11 +7,21 @@ pipeline: - CellPCA - CellSVD params: - n_components: 400 #set same params? + #It is suggested to change to common_params out: feature.cell default_params: + CellSVD: + n_components: 400 + CellPCA: + n_components: 400 WeightedFeaturePCA: + n_components: 400 split_name: train + # -type: filter.gene + # include: + # - FilterGenesTopK + # - FilterGenesPercentile + # params - type: misc target: SetConfig params: From 5b589432edec4f527cdea795a5c0bf8929436fa6 Mon Sep 17 00:00:00 2001 From: xzy Date: Thu, 25 Jan 2024 21:50:10 +0800 Subject: [PATCH 152/168] add comment --- examples/tuning/cta_svm/tuning_config.yaml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/examples/tuning/cta_svm/tuning_config.yaml b/examples/tuning/cta_svm/tuning_config.yaml index 03ac9b98c..7a43bf6a0 100644 --- a/examples/tuning/cta_svm/tuning_config.yaml +++ b/examples/tuning/cta_svm/tuning_config.yaml @@ -1,6 +1,13 @@ type: preprocessor tune_mode: pipeline pipeline: + - type: filter.gene + include: + - FilterGenesTopK + - FilterGenesPercentile + default_params: + FilterGenesTopK: + num_genes: 2000 - type: feature.cell include: - WeightedFeaturePCA @@ -17,11 +24,6 @@ pipeline: WeightedFeaturePCA: n_components: 400 split_name: train - # -type: filter.gene - # include: - # - FilterGenesTopK - # - FilterGenesPercentile - # params - type: misc target: SetConfig params: @@ -31,7 +33,7 @@ pipeline: wandb: entity: danceteam project: dance-dev - method: bayes + method: bayes #maybe grid metric: name: acc # val/acc goal: maximize From fa31616374ab96fa3e8cb29083097cb6e8579083 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 26 Jan 2024 09:47:43 +0800 Subject: [PATCH 153/168] add step3 example --- examples/tuning/cta_svm/main.py | 3 +- .../tuning/cta_svm/tuning_config_step3.yaml | 31 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 examples/tuning/cta_svm/tuning_config_step3.yaml diff --git a/examples/tuning/cta_svm/main.py b/examples/tuning/cta_svm/main.py index 892476e60..2ea245fa4 100644 --- a/examples/tuning/cta_svm/main.py +++ b/examples/tuning/cta_svm/main.py @@ -3,7 +3,6 @@ from typing import get_args import wandb - from dance import logger from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.svm import SVM @@ -28,7 +27,7 @@ logger.setLevel(args.log_level) logger.info(f"\n{pprint.pformat(vars(args))}") - pipeline_planer = PipelinePlaner.from_config_file("examples/tuning/cta_svm/tuning_config.yaml") + pipeline_planer = PipelinePlaner.from_config_file("examples/tuning/cta_svm/tuning_config_step3.yaml") def evaluate_pipeline(): wandb.init() diff --git a/examples/tuning/cta_svm/tuning_config_step3.yaml b/examples/tuning/cta_svm/tuning_config_step3.yaml new file mode 100644 index 000000000..db1f93431 --- /dev/null +++ b/examples/tuning/cta_svm/tuning_config_step3.yaml @@ -0,0 +1,31 @@ +type: preprocessor +tune_mode: params +pipeline: + - type: filter.gene + target: FilterGenesTopK + params: + num_genes: + min: 2000 + max: 4000 + - type: feature.cell + target: WeightedFeaturePCA + params: + n_components: + min: 200 + max: 400 + default_params: + out: feature.cell + split_name: train + - type: misc + target: SetConfig + default_params: + config_dict: + feature_channel: feature.cell + label_channel: cell_type +wandb: + entity: danceteam + project: dance-dev + method: bayes #maybe grid + metric: + name: acc # val/acc + goal: maximize From 761a2e31aaf270fda270c605123cb74707d2988e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 26 Jan 2024 01:49:47 +0000 Subject: [PATCH 154/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- examples/tuning/cta_svm/main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/tuning/cta_svm/main.py b/examples/tuning/cta_svm/main.py index 2ea245fa4..15e91111d 100644 --- a/examples/tuning/cta_svm/main.py +++ b/examples/tuning/cta_svm/main.py @@ -3,6 +3,7 @@ from typing import get_args import wandb + from dance import logger from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.svm import SVM From dcf41bff1caaf091d5ac3c4821da2aaae8cfd0ba Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 26 Jan 2024 19:03:40 +0800 Subject: [PATCH 155/168] step3 example --- dance/pipeline.py | 2 +- examples/tuning/cta_svm/main.py | 13 ++++++++++++- tests/test_pipeline.py | 3 ++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/dance/pipeline.py b/dance/pipeline.py index 63c52649a..cad4cc938 100644 --- a/dance/pipeline.py +++ b/dance/pipeline.py @@ -728,7 +728,7 @@ def _params_search_space(self) -> Dict[str, Dict[str, Optional[Union[str, float] for i, param_dict in enumerate(self.candidate_params): if param_dict is not None: for key, val in param_dict.items(): - search_space[f"{self.PARAMS_KEY}.{i}.{key}"] = val + search_space[f"{self.PARAMS_KEY}.{i}.{key}"] = OmegaConf.to_yaml(val, resolve=True) return search_space def wandb_sweep_config(self) -> Dict[str, Any]: diff --git a/examples/tuning/cta_svm/main.py b/examples/tuning/cta_svm/main.py index 2ea245fa4..74c9855fd 100644 --- a/examples/tuning/cta_svm/main.py +++ b/examples/tuning/cta_svm/main.py @@ -40,7 +40,18 @@ def evaluate_pipeline(): species=args.species, tissue=args.tissue).load_data() # Prepare preprocessing pipeline and apply it to data - preprocessing_pipeline = pipeline_planer.generate(pipeline=dict(wandb.config)) + preprocessing_pipeline = pipeline_planer.generate( + pipeline=dict(wandb.config), params=[{ + "n_components": { + "min": 200, + "max": 400 + } + }, { + "num_genes:": { + "min": 2000, + "max": 4000 + } + }, None]) print(f"Pipeline config:\n{preprocessing_pipeline.to_yaml()}") preprocessing_pipeline(data) diff --git a/tests/test_pipeline.py b/tests/test_pipeline.py index 612823cbd..22ff7ab3e 100644 --- a/tests/test_pipeline.py +++ b/tests/test_pipeline.py @@ -564,7 +564,8 @@ def test_pipeline_planer_generation(subtests, planer_toy_registry): "target": "func_b1", "params": { "x": { - "values": ["x1", "x2", "x3"] + "min": 2000, + "max": 4000, }, "y": { "values": ["y1", "y2", "y3"] From aeac46273a417ed55f7bf0d3e9523d98fe5df1d1 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 26 Jan 2024 19:08:52 +0800 Subject: [PATCH 156/168] step3 example --- dance/pipeline.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dance/pipeline.py b/dance/pipeline.py index cad4cc938..ead760984 100644 --- a/dance/pipeline.py +++ b/dance/pipeline.py @@ -728,7 +728,8 @@ def _params_search_space(self) -> Dict[str, Dict[str, Optional[Union[str, float] for i, param_dict in enumerate(self.candidate_params): if param_dict is not None: for key, val in param_dict.items(): - search_space[f"{self.PARAMS_KEY}.{i}.{key}"] = OmegaConf.to_yaml(val, resolve=True) + # search_space[f"{self.PARAMS_KEY}.{i}.{key}"] = OmegaConf.to_yaml(val, resolve=True) type of DotConfig + search_space[f"{self.PARAMS_KEY}.{i}.{key}"] = val return search_space def wandb_sweep_config(self) -> Dict[str, Any]: From bec59c14968ef44d4185ca7e5b0c301fea917398 Mon Sep 17 00:00:00 2001 From: xzy Date: Fri, 26 Jan 2024 22:12:04 +0800 Subject: [PATCH 157/168] step3 example --- dance/pipeline.py | 10 +++++-- examples/tuning/cta_svm/main.py | 30 +++++++++++-------- .../tuning/cta_svm/tuning_config_step3.yaml | 14 +++++---- tests/test_pipeline.py | 3 +- 4 files changed, 33 insertions(+), 24 deletions(-) diff --git a/dance/pipeline.py b/dance/pipeline.py index ead760984..2d563fd50 100644 --- a/dance/pipeline.py +++ b/dance/pipeline.py @@ -434,7 +434,7 @@ def _sanitize_params( params_dict = params params = [None] * pipeline_length for i, j in params_dict.items(): - idx, key = i.split(f"{Pipeline.PIPELINE_KEY}.", 1)[1].split(".", 1) + idx, key = i.split(f"{Pipeline.PIPELINE_KEY}.", i)[1].split(".", 1) idx = int(idx) logger.debug(f"Setting {key!r} for pipeline element {idx} to {j}") @@ -728,8 +728,12 @@ def _params_search_space(self) -> Dict[str, Dict[str, Optional[Union[str, float] for i, param_dict in enumerate(self.candidate_params): if param_dict is not None: for key, val in param_dict.items(): - # search_space[f"{self.PARAMS_KEY}.{i}.{key}"] = OmegaConf.to_yaml(val, resolve=True) type of DotConfig - search_space[f"{self.PARAMS_KEY}.{i}.{key}"] = val + if type(val) == DictConfig: + search_space[f"{self.PARAMS_KEY}.{i}.{key}"] = OmegaConf.to_container(val, resolve=True) + else: + search_space[f"{self.PARAMS_KEY}.{i}.{key}"] = val + # type of DotConfig + # search_space[f"{self.PARAMS_KEY}.{i}.{key}"] = val return search_space def wandb_sweep_config(self) -> Dict[str, Any]: diff --git a/examples/tuning/cta_svm/main.py b/examples/tuning/cta_svm/main.py index 525afde8d..88e52388e 100644 --- a/examples/tuning/cta_svm/main.py +++ b/examples/tuning/cta_svm/main.py @@ -3,7 +3,6 @@ from typing import get_args import wandb - from dance import logger from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.svm import SVM @@ -39,20 +38,25 @@ def evaluate_pipeline(): # Load raw data data = CellTypeAnnotationDataset(train_dataset=args.train_dataset, test_dataset=args.test_dataset, species=args.species, tissue=args.tissue).load_data() - + print("???") + print(dict(wandb.config)) # Prepare preprocessing pipeline and apply it to data preprocessing_pipeline = pipeline_planer.generate( - pipeline=dict(wandb.config), params=[{ - "n_components": { - "min": 200, - "max": 400 - } - }, { - "num_genes:": { - "min": 2000, - "max": 4000 - } - }, None]) + pipeline=None, + # params=[{ + # "num_genes": 2000, + # }, { + # "n_components":200, + # "out":"feature.cell", + # "split_name":"train", + + # }, + # {"config_dict":{ + # "feature_channel": "feature.cell", + # "label_channel": "cell_type" + # } + # }] + params=list(dict(wandb.config))) print(f"Pipeline config:\n{preprocessing_pipeline.to_yaml()}") preprocessing_pipeline(data) diff --git a/examples/tuning/cta_svm/tuning_config_step3.yaml b/examples/tuning/cta_svm/tuning_config_step3.yaml index db1f93431..670663673 100644 --- a/examples/tuning/cta_svm/tuning_config_step3.yaml +++ b/examples/tuning/cta_svm/tuning_config_step3.yaml @@ -13,15 +13,17 @@ pipeline: n_components: min: 200 max: 400 - default_params: - out: feature.cell - split_name: train + out: + value: feature.cell + split_name: + value: train - type: misc target: SetConfig - default_params: + params: config_dict: - feature_channel: feature.cell - label_channel: cell_type + value: + feature_channel: feature.cell + label_channel: cell_type wandb: entity: danceteam project: dance-dev diff --git a/tests/test_pipeline.py b/tests/test_pipeline.py index 22ff7ab3e..612823cbd 100644 --- a/tests/test_pipeline.py +++ b/tests/test_pipeline.py @@ -564,8 +564,7 @@ def test_pipeline_planer_generation(subtests, planer_toy_registry): "target": "func_b1", "params": { "x": { - "min": 2000, - "max": 4000, + "values": ["x1", "x2", "x3"] }, "y": { "values": ["y1", "y2", "y3"] From 612cecef3633853b1d5c67268251e99a1343f3ad Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 26 Jan 2024 14:13:20 +0000 Subject: [PATCH 158/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- examples/tuning/cta_svm/main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/tuning/cta_svm/main.py b/examples/tuning/cta_svm/main.py index 88e52388e..06c1eb6e3 100644 --- a/examples/tuning/cta_svm/main.py +++ b/examples/tuning/cta_svm/main.py @@ -3,6 +3,7 @@ from typing import get_args import wandb + from dance import logger from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.svm import SVM From d982ece99f916abdf601bdcdf6181ba0a5db2501 Mon Sep 17 00:00:00 2001 From: xzy Date: Sun, 28 Jan 2024 23:48:20 +0800 Subject: [PATCH 159/168] step3 example --- dance/pipeline.py | 2 +- examples/tuning/cta_svm/main.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dance/pipeline.py b/dance/pipeline.py index 2d563fd50..f75f4295e 100644 --- a/dance/pipeline.py +++ b/dance/pipeline.py @@ -434,7 +434,7 @@ def _sanitize_params( params_dict = params params = [None] * pipeline_length for i, j in params_dict.items(): - idx, key = i.split(f"{Pipeline.PIPELINE_KEY}.", i)[1].split(".", 1) + idx, key = i.split(f"{Pipeline.PARAMS_KEY}.", 1)[1].split(".", 1) idx = int(idx) logger.debug(f"Setting {key!r} for pipeline element {idx} to {j}") diff --git a/examples/tuning/cta_svm/main.py b/examples/tuning/cta_svm/main.py index 06c1eb6e3..747c84974 100644 --- a/examples/tuning/cta_svm/main.py +++ b/examples/tuning/cta_svm/main.py @@ -3,7 +3,6 @@ from typing import get_args import wandb - from dance import logger from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.svm import SVM @@ -57,7 +56,8 @@ def evaluate_pipeline(): # "label_channel": "cell_type" # } # }] - params=list(dict(wandb.config))) + params=dict(wandb.config)) + print(f"Pipeline config:\n{preprocessing_pipeline.to_yaml()}") preprocessing_pipeline(data) From 59ac7422bd237c2f1cf4e19bff30a1d960ac78d0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 28 Jan 2024 15:48:54 +0000 Subject: [PATCH 160/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- examples/tuning/cta_svm/main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/tuning/cta_svm/main.py b/examples/tuning/cta_svm/main.py index 747c84974..7d62a0c86 100644 --- a/examples/tuning/cta_svm/main.py +++ b/examples/tuning/cta_svm/main.py @@ -3,6 +3,7 @@ from typing import get_args import wandb + from dance import logger from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.svm import SVM From 715c0c6850693b4b5a7d7f2e73ddbfded71d5fd8 Mon Sep 17 00:00:00 2001 From: Remy Date: Sun, 28 Jan 2024 14:56:18 -0500 Subject: [PATCH 161/168] rename example pipeline tuning config --- examples/tuning/cta_svm/main.py | 2 +- .../cta_svm/{tuning_config.yaml => pipeline_tuning_config.yaml} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename examples/tuning/cta_svm/{tuning_config.yaml => pipeline_tuning_config.yaml} (100%) diff --git a/examples/tuning/cta_svm/main.py b/examples/tuning/cta_svm/main.py index df9fb2bdb..a403e33ab 100644 --- a/examples/tuning/cta_svm/main.py +++ b/examples/tuning/cta_svm/main.py @@ -28,7 +28,7 @@ logger.setLevel(args.log_level) logger.info(f"\n{pprint.pformat(vars(args))}") - pipeline_planer = PipelinePlaner.from_config_file("tuning_config.yaml") + pipeline_planer = PipelinePlaner.from_config_file("pipeline_tuning_config.yaml") def evaluate_pipeline(): wandb.init() diff --git a/examples/tuning/cta_svm/tuning_config.yaml b/examples/tuning/cta_svm/pipeline_tuning_config.yaml similarity index 100% rename from examples/tuning/cta_svm/tuning_config.yaml rename to examples/tuning/cta_svm/pipeline_tuning_config.yaml From bf47d3057b27c0db68e94335717ef7c1a061b663 Mon Sep 17 00:00:00 2001 From: Remy Date: Sun, 28 Jan 2024 16:32:32 -0500 Subject: [PATCH 162/168] move tuning params setting to 'params_to_tune' --- dance/pipeline.py | 18 +++++++++++++++--- tests/test_pipeline.py | 18 ++++++++---------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/dance/pipeline.py b/dance/pipeline.py index 63c52649a..1f355c1fd 100644 --- a/dance/pipeline.py +++ b/dance/pipeline.py @@ -243,6 +243,7 @@ def to_config(self) -> Config: class PipelinePlaner(Pipeline): TUNE_MODE_KEY = "tune_mode" + TUNING_PARAMS_KEY = "params_to_tune" DEFAULT_PARAMS_KEY = "default_params" PELEM_INCLUDE_KEY = "include" PELEM_EXCLUDE_KEY = "exclude" @@ -371,9 +372,17 @@ def config(self, cfg: ConfigLike): elif self.tune_mode == "params": self._candidate_params = [None] * pipeline_length for i in range(pipeline_length): - self._default_params[i] = pipeline_config[i].get(self.DEFAULT_PARAMS_KEY) - if val := self[i].params: - self._candidate_params[i] = val + if self.DEFAULT_PARAMS_KEY in pipeline_config[i]: + logger.warning(f"params tuning mode ignores {self.DEFAULT_PARAMS_KEY!r}, which is " + f"currently specified pipeline element #{i}:\n\t{pipeline_config[i]}") + + # Set default params (auto set key to the current target) + if val := pipeline_config[i].get(self.PARAMS_KEY): + self._default_params[i] = {self[i].target: val} + + # Set tuning params + if val := pipeline_config[i].get(self.TUNING_PARAMS_KEY): + self._candidate_params[i] = OmegaConf.to_container(val) # Make sure targets are set missed_target_idx = [ @@ -684,6 +693,9 @@ def search_space(self) -> Dict[str, Any]: "type": "feature.cell", "target": "WeightedFeaturePCA", "params": { + "out": "feature.cell", + } + "params_to_tune": { "n_components": { "values": [128, 256, 512, 1024], }, diff --git a/tests/test_pipeline.py b/tests/test_pipeline.py index 612823cbd..d45aa238e 100644 --- a/tests/test_pipeline.py +++ b/tests/test_pipeline.py @@ -352,7 +352,7 @@ def test_pipeline_planer_construction(subtests, planer_toy_registry): { "type": "b", "target": "func_b1", - "params": { + "params_to_tune": { "x": { "values": ["x1", "x2", "x3"] }, @@ -402,7 +402,7 @@ def test_pipeline_planer_construction(subtests, planer_toy_registry): { "type": "b", "target": "func_b1", - "params": { + "params_to_tune": { "x": { "values": ["x1", "x2", "x3"] }, @@ -414,7 +414,7 @@ def test_pipeline_planer_construction(subtests, planer_toy_registry): { "type": "c", "target": "func_c1", - "params": { + "params_to_tune": { "z": { "min": 0, "max": 1 @@ -424,7 +424,7 @@ def test_pipeline_planer_construction(subtests, planer_toy_registry): { "type": "c", "target": "func_c1", - "params": { + "params_to_tune": { "z": { "min": -10., "max": 10. @@ -562,7 +562,7 @@ def test_pipeline_planer_generation(subtests, planer_toy_registry): { "type": "b", "target": "func_b1", - "params": { + "params_to_tune": { "x": { "values": ["x1", "x2", "x3"] }, @@ -639,7 +639,7 @@ def test_pipeline_planer_generation(subtests, planer_toy_registry): "pipeline": [{ "type": "b", # "target": "func_b1", # this must be set - "params": { + "params_to_tune": { "x": { "values": ["x1", "x2", "x3"] }, @@ -725,10 +725,8 @@ def test_pipeline_planer_generation(subtests, planer_toy_registry): { "type": "b", "target": "func_b1", - "default_params": { - "func_b1": { - "x": "b1" - }, + "params": { + "x": "b1" }, }, { From 7feb79ad3971004eb136a3cbc9c178db1dc3888f Mon Sep 17 00:00:00 2001 From: Remy Date: Sun, 28 Jan 2024 16:33:36 -0500 Subject: [PATCH 163/168] minor fixes and edits --- dance/pipeline.py | 6 +++--- dance/transforms/cell_feature.py | 3 +++ dance/utils/matrix.py | 2 -- tests/test_pipeline.py | 8 +++++--- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/dance/pipeline.py b/dance/pipeline.py index 1f355c1fd..c30a769d0 100644 --- a/dance/pipeline.py +++ b/dance/pipeline.py @@ -426,7 +426,7 @@ def _sanitize_pipeline( raise ValueError(f"Expecting {pipeline_length} targets specifications, " f"but only got {len(pipeline)}: {pipeline}") - logger.info(f"Pipeline plane:\n{Color('green')(pformat(pipeline))}") + logger.info(f"Pipeline plan:\n{Color('green')(pformat(pipeline))}") return pipeline @@ -443,7 +443,7 @@ def _sanitize_params( params_dict = params params = [None] * pipeline_length for i, j in params_dict.items(): - idx, key = i.split(f"{Pipeline.PIPELINE_KEY}.", 1)[1].split(".", 1) + idx, key = i.split(f"{Pipeline.PARAMS_KEY}.", 1)[1].split(".", 1) idx = int(idx) logger.debug(f"Setting {key!r} for pipeline element {idx} to {j}") @@ -459,7 +459,7 @@ def _sanitize_params( raise ValueError(f"Expecting {pipeline_length} targets specifications, " f"but only got {len(params)}: {params}") - logger.info(f"Params plane:\n{Color('green')(pformat(params))}") + logger.info(f"Params plan:\n{Color('green')(pformat(params))}") return params diff --git a/dance/transforms/cell_feature.py b/dance/transforms/cell_feature.py index 313b03642..af23a9a51 100644 --- a/dance/transforms/cell_feature.py +++ b/dance/transforms/cell_feature.py @@ -21,6 +21,9 @@ class WeightedFeaturePCA(BaseTransform): Number of PCs to use. split_name Which split to use to compute the gene PCA. If not set, use all data. + feat_norm_mode + Feature normalization mode, see :func:`dance.utils.matrix.normalize`. If set to `None`, then do not perform + feature normalization before reduction. """ diff --git a/dance/utils/matrix.py b/dance/utils/matrix.py index 424e651c4..4176b6b17 100644 --- a/dance/utils/matrix.py +++ b/dance/utils/matrix.py @@ -1,5 +1,3 @@ -import sys - import numba import numpy as np import torch diff --git a/tests/test_pipeline.py b/tests/test_pipeline.py index d45aa238e..9f2a80bd4 100644 --- a/tests/test_pipeline.py +++ b/tests/test_pipeline.py @@ -605,9 +605,7 @@ def test_pipeline_planer_generation(subtests, planer_toy_registry): ] } - assert dict(p.generate_config(params=[{ - "x": "x1" - }, None])) == { + ans = { "type": "a", "pipeline": [ { @@ -623,6 +621,10 @@ def test_pipeline_planer_generation(subtests, planer_toy_registry): }, ], } + # Option 1: list of param dict + assert dict(p.generate_config(params=[{"x": "x1"}, None])) == ans + # Option 2: wandb type config + assert dict(p.generate_config(params={"params.0.x": "x1"})) == ans with pytest.raises(ValueError): # Unknown param key 'y' From 4a90367b75a7eca941f846e3e4569c2d0791bc8a Mon Sep 17 00:00:00 2001 From: xzy Date: Mon, 29 Jan 2024 11:08:40 +0800 Subject: [PATCH 164/168] step3 example --- dance/pipeline.py | 7 +------ examples/tuning/cta_svm/main.py | 3 +-- examples/tuning/cta_svm/tuning_config_step3.yaml | 14 +++++++------- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/dance/pipeline.py b/dance/pipeline.py index 1631241be..c30a769d0 100644 --- a/dance/pipeline.py +++ b/dance/pipeline.py @@ -740,12 +740,7 @@ def _params_search_space(self) -> Dict[str, Dict[str, Optional[Union[str, float] for i, param_dict in enumerate(self.candidate_params): if param_dict is not None: for key, val in param_dict.items(): - if type(val) == DictConfig: - search_space[f"{self.PARAMS_KEY}.{i}.{key}"] = OmegaConf.to_container(val, resolve=True) - else: - search_space[f"{self.PARAMS_KEY}.{i}.{key}"] = val - # type of DotConfig - # search_space[f"{self.PARAMS_KEY}.{i}.{key}"] = val + search_space[f"{self.PARAMS_KEY}.{i}.{key}"] = val return search_space def wandb_sweep_config(self) -> Dict[str, Any]: diff --git a/examples/tuning/cta_svm/main.py b/examples/tuning/cta_svm/main.py index 94d3e1039..3e5994fd7 100644 --- a/examples/tuning/cta_svm/main.py +++ b/examples/tuning/cta_svm/main.py @@ -3,7 +3,6 @@ from typing import get_args import wandb - from dance import logger from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.svm import SVM @@ -28,7 +27,7 @@ logger.setLevel(args.log_level) logger.info(f"\n{pprint.pformat(vars(args))}") - pipeline_planer = PipelinePlaner.from_config_file("pipeline_tuning_config.yaml") + pipeline_planer = PipelinePlaner.from_config_file("examples/tuning/cta_svm/tuning_config_step3.yaml") def evaluate_pipeline(): wandb.init() diff --git a/examples/tuning/cta_svm/tuning_config_step3.yaml b/examples/tuning/cta_svm/tuning_config_step3.yaml index 670663673..3b729da37 100644 --- a/examples/tuning/cta_svm/tuning_config_step3.yaml +++ b/examples/tuning/cta_svm/tuning_config_step3.yaml @@ -3,27 +3,27 @@ tune_mode: params pipeline: - type: filter.gene target: FilterGenesTopK - params: + params_to_tune: num_genes: min: 2000 max: 4000 - type: feature.cell target: WeightedFeaturePCA - params: + params_to_tune: n_components: min: 200 max: 400 + params: out: - value: feature.cell + feature.cell split_name: - value: train + train - type: misc target: SetConfig params: config_dict: - value: - feature_channel: feature.cell - label_channel: cell_type + feature_channel: feature.cell + label_channel: cell_type wandb: entity: danceteam project: dance-dev From d2fe0c71a29d684abdc30ab6348fe1e63d8d2728 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 03:09:08 +0000 Subject: [PATCH 165/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- examples/tuning/cta_svm/main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/tuning/cta_svm/main.py b/examples/tuning/cta_svm/main.py index 3e5994fd7..6bf971392 100644 --- a/examples/tuning/cta_svm/main.py +++ b/examples/tuning/cta_svm/main.py @@ -3,6 +3,7 @@ from typing import get_args import wandb + from dance import logger from dance.datasets.singlemodality import CellTypeAnnotationDataset from dance.modules.single_modality.cell_type_annotation.svm import SVM From 87ea8375da901c478cfdec55d05d575fefe242e4 Mon Sep 17 00:00:00 2001 From: xzy Date: Mon, 29 Jan 2024 17:28:30 +0800 Subject: [PATCH 166/168] step3 example --- examples/tuning/cta_svm/main.py | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/examples/tuning/cta_svm/main.py b/examples/tuning/cta_svm/main.py index 3e5994fd7..a09516e37 100644 --- a/examples/tuning/cta_svm/main.py +++ b/examples/tuning/cta_svm/main.py @@ -39,22 +39,7 @@ def evaluate_pipeline(): data = CellTypeAnnotationDataset(train_dataset=args.train_dataset, test_dataset=args.test_dataset, species=args.species, tissue=args.tissue).load_data() # Prepare preprocessing pipeline and apply it to data - preprocessing_pipeline = pipeline_planer.generate( - pipeline=None, - # params=[{ - # "num_genes": 2000, - # }, { - # "n_components":200, - # "out":"feature.cell", - # "split_name":"train", - - # }, - # {"config_dict":{ - # "feature_channel": "feature.cell", - # "label_channel": "cell_type" - # } - # }] - params=dict(wandb.config)) + preprocessing_pipeline = pipeline_planer.generate(pipeline=None, params=dict(wandb.config)) print(f"Pipeline config:\n{preprocessing_pipeline.to_yaml()}") preprocessing_pipeline(data) From 3eb9ed6199cbfe6c13652221a8d2610da585588f Mon Sep 17 00:00:00 2001 From: xzy Date: Tue, 30 Jan 2024 08:48:08 +0800 Subject: [PATCH 167/168] step3 example --- dance/legacy/automl_config/step2_config.py | 3 +- dance/transforms/normalize.py | 16 +++ examples/tuning/all_params_config.yaml | 0 examples/tuning/all_pipline_config.yaml | 18 +++ examples/tuning/variable.yaml | 121 ++++++++++++++++++ examples/variable | 0 ...ep2_cell_type_annotation_actinn_example.py | 2 +- 7 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 examples/tuning/all_params_config.yaml create mode 100644 examples/tuning/all_pipline_config.yaml create mode 100644 examples/tuning/variable.yaml create mode 100644 examples/variable diff --git a/dance/legacy/automl_config/step2_config.py b/dance/legacy/automl_config/step2_config.py index 6eed364cb..3d8327890 100644 --- a/dance/legacy/automl_config/step2_config.py +++ b/dance/legacy/automl_config/step2_config.py @@ -2,9 +2,8 @@ import itertools import wandb - from dance import logger -from dance.automl_config.fun2code import fun2code_dict +from dance.legacy.automl_config import fun2code_dict from dance.transforms.misc import SetConfig #TODO register more functions and add more examples diff --git a/dance/transforms/normalize.py b/dance/transforms/normalize.py index 507da66b4..296fe306c 100644 --- a/dance/transforms/normalize.py +++ b/dance/transforms/normalize.py @@ -4,6 +4,7 @@ import anndata as ad import numpy as np import pandas as pd +import scanpy as sc import scipy.sparse as sp import statsmodels.discrete.discrete_model import statsmodels.nonparametric.kernel_regression @@ -13,6 +14,7 @@ from dance.data.base import Data from dance.registry import register_preprocessor from dance.transforms.base import BaseTransform +from dance.transforms.interface import AnnDataTransform from dance.typing import Dict, List, Literal, NormMode, Optional, Union from dance.utils.matrix import normalize @@ -483,3 +485,17 @@ def info(n, th, mu, y, w): t0 = max(t0, 0) return t0 + + +@register_preprocessor("normalize") +class Log1P(AnnDataTransform): + + def __init__(self, **kwargs): + super().__init__(sc.pp.log1p, **kwargs) + + +@register_preprocessor("normalize") +class NormalizeTotal(AnnDataTransform): + + def __init__(self, **kwargs): + super().__init__(sc.pp.normalize_total, **kwargs) diff --git a/examples/tuning/all_params_config.yaml b/examples/tuning/all_params_config.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/examples/tuning/all_pipline_config.yaml b/examples/tuning/all_pipline_config.yaml new file mode 100644 index 000000000..3e23617c1 --- /dev/null +++ b/examples/tuning/all_pipline_config.yaml @@ -0,0 +1,18 @@ +type: preprocessor +tune_mode: pipeline +pipeline: + - type: normalize + include: + - ScaleFeature + - ScTransform + - Log1P + - NormalizeTotal + - type: filter.gene + include: + - FilterGenesTopK + - FilterGenesPercentile + - FilterGenesMarker + - FilterGenesRegression + - FilterGenesMarkerGini + - FilterGenesCommon + - FilterGenesMatch diff --git a/examples/tuning/variable.yaml b/examples/tuning/variable.yaml new file mode 100644 index 000000000..e53823b1a --- /dev/null +++ b/examples/tuning/variable.yaml @@ -0,0 +1,121 @@ +filter_gene_sequence: + - 0: + - min_counts + - min_cells + - max_counts + - max_cells + - 1: + - min_counts + - min_cells + - max_cells + - max_counts + - 2: + - min_counts + - max_counts + - min_cells + - max_cells + - 3: + - min_counts + - max_counts + - max_cells + - min_cells + - 4: + - min_counts + - max_cells + - min_cells + - max_counts + - 5: + - min_counts + - max_cells + - max_counts + - min_cells + - 6: + - min_cells + - min_counts + - max_counts + - max_cells + - 7: + - min_cells + - min_counts + - max_cells + - max_counts + - 8: + - min_cells + - max_counts + - min_counts + - max_cells + - 9: + - min_cells + - max_counts + - max_cells + - min_counts + - 10: + - min_cells + - max_cells + - min_counts + - max_counts + - 11: + - min_cells + - max_cells + - max_counts + - min_counts + - 12: + - max_counts + - min_counts + - min_cells + - max_cells + - 13: + - max_counts + - min_counts + - max_cells + - min_cells + - 14: + - max_counts + - min_cells + - min_counts + - max_cells + - 15: + - max_counts + - min_cells + - max_cells + - min_counts + - 16: + - max_counts + - max_cells + - min_counts + - min_cells + - 17: + - max_counts + - max_cells + - min_cells + - min_counts + - 18: + - max_cells + - min_counts + - min_cells + - max_counts + - 19: + - max_cells + - min_counts + - max_counts + - min_cells + - 20: + - max_cells + - min_cells + - min_counts + - max_counts + - 21: + - max_cells + - min_cells + - max_counts + - min_counts + - 22: + - max_cells + - max_counts + - min_counts + - min_cells + - 23: + - max_cells + - max_counts + - min_cells + - min_counts diff --git a/examples/variable b/examples/variable new file mode 100644 index 000000000..e69de29bb diff --git a/legacy/test_automl/step2_examples/step2_cell_type_annotation_actinn_example.py b/legacy/test_automl/step2_examples/step2_cell_type_annotation_actinn_example.py index 07a887b97..62e81e17a 100644 --- a/legacy/test_automl/step2_examples/step2_cell_type_annotation_actinn_example.py +++ b/legacy/test_automl/step2_examples/step2_cell_type_annotation_actinn_example.py @@ -4,8 +4,8 @@ import torch from dance import logger -from dance.automl_config.step2_config import get_transforms, log_in_wandb, setStep2 from dance.datasets.singlemodality import CellTypeAnnotationDataset +from dance.legacy.automl_config.step2_config import get_transforms, log_in_wandb, setStep2 from dance.modules.single_modality.cell_type_annotation.actinn import ACTINN from dance.transforms.misc import Compose from dance.utils import set_seed From cd2cba9cb0fd3d43fd43a03611073539d1899622 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 00:48:46 +0000 Subject: [PATCH 168/168] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dance/legacy/automl_config/step2_config.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dance/legacy/automl_config/step2_config.py b/dance/legacy/automl_config/step2_config.py index 3d8327890..b2ead8b08 100644 --- a/dance/legacy/automl_config/step2_config.py +++ b/dance/legacy/automl_config/step2_config.py @@ -2,6 +2,7 @@ import itertools import wandb + from dance import logger from dance.legacy.automl_config import fun2code_dict from dance.transforms.misc import SetConfig