Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/wandb logging #218

Merged
merged 44 commits into from
Apr 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
9b6a11f
refactor: move default kwargs
asawczyn Feb 11, 2022
408182b
feat(logging): add args for logging
asawczyn Feb 15, 2022
5a8a328
feat(logging): update pyproject and tests
asawczyn Feb 15, 2022
7593322
feat(logging): add logging to seq labelling
asawczyn Feb 16, 2022
e054f8c
fix: fixes after rebase
asawczyn Feb 16, 2022
3d0fe42
feat(logging): add naming of run in hps
asawczyn Feb 17, 2022
83360bb
test: repair hps tests
asawczyn Mar 3, 2022
1a790d2
add dataset info to logging
asawczyn Mar 3, 2022
7242929
ci(poetry): lock dependencies
asawczyn Mar 3, 2022
fe24b5a
feat(logging): add evaluation.json as artifact to wandb
asawczyn Mar 4, 2022
e45e358
fix: fix artifacts naming
asawczyn Mar 8, 2022
0686a22
style: fix formatting
asawczyn Mar 9, 2022
49336be
feat: make saving params more unified
asawczyn Mar 16, 2022
4afa30a
feat: add dataset version to hparams
asawczyn Mar 17, 2022
e8fd9ec
feat(logging): organize artifacts
asawczyn Mar 18, 2022
1572c76
feat(scripts): add hps examples
asawczyn Mar 18, 2022
5d673ee
fix(scripts): fix document classification script
asawczyn Mar 18, 2022
d9e8ff2
fix: fix lack of test metrics
asawczyn Mar 24, 2022
d6e009c
feat: add logits to evaluation.json
asawczyn Mar 25, 2022
96a8727
fix: apply softmax to logits
asawczyn Mar 25, 2022
a3234b8
fix: fix test stem in seq labelling
asawczyn Mar 25, 2022
ec8ca54
refactor(tests): refactor result path in tests
asawczyn Mar 26, 2022
6b5616b
feat(sequence-labelling): add names and probabilities to returned dict
asawczyn Mar 26, 2022
006b975
test: disable mkdirs during tests
asawczyn Mar 26, 2022
b2c583b
fix: fix sequence labelling test
asawczyn Mar 30, 2022
1a9f8bc
fix: lock dependencies
asawczyn Mar 30, 2022
403ab1b
fix: froze click
asawczyn Mar 30, 2022
ef60e6a
refactor: refactor due to comments in PR
asawczyn Mar 30, 2022
600803c
feat: add target names to text classification
asawczyn Mar 31, 2022
7c16ccd
style: format code
asawczyn Apr 1, 2022
8e94854
test: fix tests and add missing
asawczyn Apr 1, 2022
699b7b6
refactor: refactor due to pr comments
asawczyn Apr 1, 2022
092a042
feat(logging): add LightningLoggingConfig
asawczyn Apr 4, 2022
5355702
test: fix hps test
asawczyn Apr 4, 2022
251832b
fix: fix literal type import
asawczyn Apr 4, 2022
a40160d
test: fix hps test
asawczyn Apr 4, 2022
5493ad5
fix: fix list type
asawczyn Apr 5, 2022
fd96167
ci: update lock
asawczyn Apr 5, 2022
109fae6
fix: artifacts naming
asawczyn Apr 5, 2022
bde2f93
refactor: edit default exceptions in hps
asawczyn Apr 5, 2022
f239841
refactor: move mkdir
asawczyn Apr 5, 2022
9f9281d
refactor: add logger wrappers
asawczyn Apr 5, 2022
35f6341
refactor: move get_lightning_loggers to loggers config
asawczyn Apr 6, 2022
01f5b41
refactor: refactor due to pr comments
asawczyn Apr 6, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions embeddings/data/datamodule.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
class BaseDataModule(abc.ABC, pl.LightningDataModule, Generic[Data]):
dataset: Data

def __init__(self) -> None:
def __init__(self, **kwargs: Any) -> None:
# ignoring the type to avoid calling to untyped function "__init__" in typed context error
# caused by pl.LightningDataModule __init__ method not being typed
super().__init__() # type: ignore
Expand Down Expand Up @@ -64,9 +64,8 @@ def __init__(
seed: int = 441,
**kwargs: Any,
) -> None:
super().__init__()
self.tokenizer_name_or_path = tokenizer_name_or_path
self.dataset_name_or_path = dataset_name_or_path
self.tokenizer_name_or_path = tokenizer_name_or_path
self.target_field = target_field
self.max_seq_length = max_seq_length
self.train_batch_size = train_batch_size
Expand All @@ -82,6 +81,10 @@ def __init__(
)
self.load_dataset_kwargs = load_dataset_kwargs if load_dataset_kwargs else {}
self.seed = seed
dataset_info = self.load_dataset()["train"].info
ktagowski marked this conversation as resolved.
Show resolved Hide resolved
super().__init__(
dataset_info=dataset_info, dataset_version=dataset_info.version.version_str
)

@abc.abstractmethod
def prepare_labels(self) -> None:
Expand Down
4 changes: 2 additions & 2 deletions embeddings/model/base_model.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Generic, TypeVar
from typing import Any, Generic, TypeVar

from embeddings.embedding.embedding import Embedding
from embeddings.model.model import Model
Expand All @@ -16,6 +16,6 @@ def __init__(
self.embedding = embedding
self.task = task

def execute(self, data: Input) -> Output:
def execute(self, data: Input, **kwargs: Any) -> Output:
embedded = self.embedding.embed(data)
return self.task.fit_predict(embedded)
2 changes: 1 addition & 1 deletion embeddings/model/flair_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def __init__(
self.task = task
self.predict_subset = predict_subset

def execute(self, data: Corpus) -> Dict[str, nptyping.NDArray[Any]]:
def execute(self, data: Corpus, **kwargs: Any) -> Dict[str, nptyping.NDArray[Any]]:
self.task.build_task_model(
embedding=self.embedding, y_dictionary=self.task.make_y_dictionary(data)
)
Expand Down
8 changes: 5 additions & 3 deletions embeddings/model/lightning_model.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict
from typing import Any, Dict, Optional

from numpy import typing as nptyping

Expand All @@ -18,6 +18,8 @@ def __init__(
self.task = task
self.predict_subset = predict_subset

def execute(self, data: HuggingFaceDataModule) -> Dict[str, nptyping.NDArray[Any]]:
def execute(
self, data: HuggingFaceDataModule, run_name: Optional[str] = None, **kwargs: Any
) -> Dict[str, nptyping.NDArray[Any]]:
self.task.build_task_model()
return self.task.fit_predict(data, self.predict_subset)
return self.task.fit_predict(data, self.predict_subset, run_name=run_name)
17 changes: 11 additions & 6 deletions embeddings/model/lightning_module/lightning_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import torch
from numpy import typing as nptyping
from pytorch_lightning.utilities.types import STEP_OUTPUT
from torch.nn.functional import softmax
from torch.optim import AdamW, Optimizer
from torch.utils.data import DataLoader
from torchmetrics import MetricCollection
Expand Down Expand Up @@ -57,21 +58,25 @@ def validation_step(self, *args: Any, **kwargs: Any) -> Optional[STEP_OUTPUT]:
def test_step(self, *args: Any, **kwargs: Any) -> Optional[STEP_OUTPUT]:
pass

def predict_step(self, *args: Any, **kwargs: Any) -> Optional[STEP_OUTPUT]:
def predict_step(self, *args: Any, **kwargs: Any) -> Optional[Tuple[STEP_OUTPUT, STEP_OUTPUT]]:
batch, batch_idx = args
loss, logits, preds = self.shared_step(**batch)
return preds
return logits, preds

def predict(
self, dataloader: DataLoader[HuggingFaceDataset]
) -> Dict[str, nptyping.NDArray[Any]]:
assert self.trainer is not None
predictions = self.trainer.predict(dataloaders=dataloader, return_predictions=True)
logits_predictions = self.trainer.predict(
dataloaders=dataloader, return_predictions=True, ckpt_path="best"
)
logits, predictions = zip(*logits_predictions)
probabilities = softmax(torch.cat(logits), dim=1).numpy()
predictions = torch.cat(predictions).numpy()
assert isinstance(predictions, np.ndarray)
ground_truth = torch.cat([x["labels"] for x in dataloader]).numpy()
assert isinstance(ground_truth, np.ndarray)
return {"y_pred": predictions, "y_true": ground_truth}
result = {"y_pred": predictions, "y_true": ground_truth, "y_probabilities": probabilities}
assert all(isinstance(x, np.ndarray) for x in result.values())
return result

def configure_metrics(self) -> None:
if self.metrics is None:
Expand Down
2 changes: 1 addition & 1 deletion embeddings/model/lightning_module/sequence_labeling.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def test_step(self, *args: Any, **kwargs: Any) -> Optional[STEP_OUTPUT]:
loss, logits, preds = self.shared_step(**batch)
if -1 not in labels:
self.test_metrics(
preds[labels != self.IGNORE_INDEX], labels[labels != self.IGNORE_INDEX]
preds[labels != self.ignore_index], labels[labels != self.ignore_index]
)
self.log("test/Loss", loss, on_epoch=True)
else:
Expand Down
4 changes: 2 additions & 2 deletions embeddings/model/model.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import abc
from typing import Generic, TypeVar
from typing import Any, Generic, TypeVar

Input = TypeVar("Input")
Output = TypeVar("Output")
Expand All @@ -10,5 +10,5 @@ def __init__(self) -> None:
pass

@abc.abstractmethod
def execute(self, data: Input) -> Output:
def execute(self, data: Input, **kwargs: Any) -> Output:
pass
2 changes: 1 addition & 1 deletion embeddings/model/sklearn_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def __init__(
self.task = task
self.predict_subset = predict_subset

def execute(self, data: Dict[str, Any]) -> Dict[str, Any]:
def execute(self, data: Dict[str, Any], **kwargs: Any) -> Dict[str, Any]:
self.embedding.fit(data["train"]["x"])
self.task.build_task_model(self.embedding)
return self.task.fit_predict(data, self.predict_subset)
2 changes: 1 addition & 1 deletion embeddings/pipeline/evaluation_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def __init__(
self.model = model
self.evaluator = evaluator

def run(self) -> EvaluationResult:
def run(self, **kwargs: Any) -> EvaluationResult:
loaded_data = self.data_loader.load(self.dataset)
model_result = self.model.execute(loaded_data)
return self.evaluator.evaluate(model_result)
Expand Down
15 changes: 11 additions & 4 deletions embeddings/pipeline/flair_hps_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
from dataclasses import dataclass, field
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import Dict, Generic, Optional, Tuple
from typing import Any, Dict, Generic, Optional, Tuple

import datasets
from flair.data import Corpus
from numpy import typing as nptyping

from embeddings.data.io import T_path
from embeddings.evaluator.sequence_labeling_evaluator import (
Expand Down Expand Up @@ -109,6 +110,8 @@ class OptimizedFlairClassificationPipeline(
str,
datasets.DatasetDict,
Corpus,
Dict[str, nptyping.NDArray[Any]],
Dict[str, Any],
],
AbstractOptimizedFlairClassificationPipeline,
_OptimizedFlairPipelineBase[FlairTextClassificationConfigSpace],
Expand Down Expand Up @@ -164,7 +167,7 @@ def _get_metadata(self, parameters: SampledParameters) -> FlairClassificationPip
return metadata

def _get_evaluation_metadata(
self, parameters: SampledParameters
self, parameters: SampledParameters, **kwargs: Any
) -> FlairClassificationEvaluationPipelineMetadata:
(
embedding_name,
Expand Down Expand Up @@ -200,6 +203,8 @@ class OptimizedFlairPairClassificationPipeline(
str,
datasets.DatasetDict,
Corpus,
Dict[str, nptyping.NDArray[Any]],
Dict[str, Any],
],
AbstractOptimizedFlairClassificationPipeline,
_OptimizedFlairPairClassificationPipelineBase[FlairTextClassificationConfigSpace],
Expand Down Expand Up @@ -257,7 +262,7 @@ def _get_metadata(
return metadata

def _get_evaluation_metadata(
self, parameters: SampledParameters
self, parameters: SampledParameters, **kwargs: Any
) -> FlairClassificationEvaluationPipelineMetadata:
(
embedding_name,
Expand Down Expand Up @@ -293,6 +298,8 @@ class OptimizedFlairSequenceLabelingPipeline(
str,
datasets.DatasetDict,
Corpus,
Dict[str, nptyping.NDArray[Any]],
Dict[str, Any],
],
AbstractHuggingFaceOptimizedPipeline[FlairSequenceLabelingConfigSpace],
_OptimizedFlairPipelineDefaultsBase,
Expand Down Expand Up @@ -379,7 +386,7 @@ def _get_metadata(self, parameters: SampledParameters) -> FlairSequenceLabelingP
return metadata

def _get_evaluation_metadata(
self, parameters: SampledParameters
self, parameters: SampledParameters, **kwargs: Any
) -> FlairSequenceLabelingEvaluationPipelineMetadata:
(
embedding_name,
Expand Down
53 changes: 37 additions & 16 deletions embeddings/pipeline/hps_pipeline.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import abc
import logging
import os
from abc import ABC
from dataclasses import dataclass, field
from tempfile import TemporaryDirectory
Expand All @@ -18,7 +19,7 @@
from embeddings.pipeline.preprocessing_pipeline import PreprocessingPipeline
from embeddings.pipeline.standard_pipeline import LoaderResult, ModelResult, TransformationResult
from embeddings.utils.hps_persister import HPSResultsPersister
from embeddings.utils.utils import PrimitiveTypes
from embeddings.utils.utils import PrimitiveTypes, standardize_name

EvaluationResult = TypeVar("EvaluationResult", bound=Dict[str, Dict[str, PrimitiveTypes]])

Expand All @@ -28,7 +29,7 @@ def __init__(self) -> None:
pass

@abc.abstractmethod
def run(self) -> Tuple[pd.DataFrame, Metadata]:
def run(self, **kwargs: Any) -> Tuple[pd.DataFrame, Metadata]:
pass

def persisting(
Expand All @@ -46,15 +47,24 @@ def __init__(
best_params_path=best_params_path, log_path=log_path
)

def run(self) -> Tuple[pd.DataFrame, Metadata]:
result = self.base_pipeline.run()
def run(self, **kwargs: Any) -> Tuple[pd.DataFrame, Metadata]:
result = self.base_pipeline.run(**kwargs)
self.persister.persist(result)
return result


class OptunaPipeline(
OptimizedPipeline[Metadata],
Generic[ConfigSpace, Metadata, EvaluationMetadata, Data, LoaderResult, TransformationResult],
Generic[
ConfigSpace,
Metadata,
EvaluationMetadata,
Data,
LoaderResult,
TransformationResult,
ModelResult,
EvaluationResult,
],
):
def __init__(
self,
Expand All @@ -64,7 +74,7 @@ def __init__(
],
evaluation_pipeline: Union[
Type[ModelEvaluationPipeline[Data, LoaderResult, ModelResult, EvaluationResult]],
Type[LightningPipeline[Data, ModelResult, EvaluationResult]],
Type[LightningPipeline[TransformationResult, ModelResult, EvaluationResult]],
],
pruner: optuna.pruners.BasePruner,
sampler: optuna.samplers.BaseSampler,
Expand All @@ -88,7 +98,9 @@ def _get_metadata(self, parameters: SampledParameters) -> Metadata:
pass

@abc.abstractmethod
def _get_evaluation_metadata(self, parameters: SampledParameters) -> EvaluationMetadata:
def _get_evaluation_metadata(
self, parameters: SampledParameters, **kwargs: Any
) -> EvaluationMetadata:
pass

def get_best_paramaters(self, study: Study) -> Metadata:
Expand All @@ -99,18 +111,17 @@ def get_best_paramaters(self, study: Study) -> Metadata:

def run(
self,
run_name: Optional[str] = None,
catch: Tuple[Type[Exception], ...] = (Exception,),
**kwargs: Any,
) -> Tuple[pd.DataFrame, Metadata]:
self._pre_run_hook()
if self.preprocessing_pipeline is not None:
self.preprocessing_pipeline.run()
study: Study = optuna.create_study(
direction="maximize",
sampler=self.sampler,
pruner=self.pruner,
)
study.optimize(
self.objective, n_trials=self.n_trials, show_progress_bar=True, catch=(Exception,)
direction="maximize", sampler=self.sampler, pruner=self.pruner, study_name=run_name
)
study.optimize(self.objective, n_trials=self.n_trials, show_progress_bar=True, catch=catch)
ktagowski marked this conversation as resolved.
Show resolved Hide resolved

if isinstance(self.dataset_path, TemporaryDirectory):
self.dataset_path.cleanup()
Expand All @@ -120,15 +131,25 @@ def run(
return study.trials_dataframe(), metadata

def objective(self, trial: optuna.trial.Trial) -> float:
trial_name = standardize_name(f"study_{trial.study.study_name}_trial_{trial.number}")
parameters = self.config_space.sample_parameters(trial=trial)
parsed_params = self.config_space.parse_parameters(parameters)
args = self._get_evaluation_metadata(parsed_params)
pipeline = self.evaluation_pipeline(**args)
results = pipeline.run()
kwargs = self._get_evaluation_metadata(parsed_params, trial_name=trial_name)
os.makedirs(kwargs["output_path"], exist_ok=True)
pipeline = self._get_evaluation_pipeline(**kwargs)
results = pipeline.run(run_name=trial_name)
metric = results[self.metric_name][self.metric_key]
assert isinstance(metric, float)
return metric

def _get_evaluation_pipeline(
self, **kwargs: Any
) -> Union[
ModelEvaluationPipeline[Data, LoaderResult, ModelResult, EvaluationResult],
LightningPipeline[TransformationResult, ModelResult, EvaluationResult],
]:
return self.evaluation_pipeline(**kwargs)
ktagowski marked this conversation as resolved.
Show resolved Hide resolved

def _pre_run_hook(self) -> None:
logging.getLogger("optuna").setLevel(logging.WARNING)

Expand Down
Loading