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

Use logging #129

Merged
merged 6 commits into from
May 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions fnet/cli/init.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
from typing import Optional
from pathlib import Path
import argparse
import json
import logging
import os
import shutil
import sys


logger = logging.getLogger(__name__)


def save_example_scripts(path_save_dir: str) -> None:
"""Save example training and prediction scripts.

Expand All @@ -24,10 +29,10 @@ def save_example_scripts(path_save_dir: str) -> None:
path_src = os.path.join(path_examples_dir, fname)
path_dst = os.path.join(path_save_dir, fname)
if os.path.exists(path_dst):
print('Example script already exists:', path_dst)
logger.info(f'Example script already exists: {path_dst}')
continue
shutil.copy(path_src, path_dst)
print('Saved:', path_dst)
logger.info(f'Saved: {path_dst}')


def save_default_train_options(path_save: str) -> None:
Expand All @@ -39,12 +44,11 @@ def save_default_train_options(path_save: str) -> None:
Save path for default training options json.

"""
if os.path.exists(path_save):
print('Training options file already exists:', path_save)
path_save = Path(path_save)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may want to make this Path(path_save).expanduser().resolve(). It will make it so people can put relative paths and also include their home directory like ~/Desktop/trained_fnet_model/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! I'll look to add this type of functionality when I address #128.

if path_save.exists():
logger.info(f'Training options file already exists: {path_save}')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd probably throw a custom exception here personally.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An exception would imply that something went "wrong" though. The idea is to simply exit if the intended action had already been completed in the past. That way the user does not have to manually check the file system.

return
dirname = os.path.dirname(path_save)
if not os.path.exists(dirname):
os.makedirs(dirname)
path_save.parent.mkdir(parents=True, exist_ok=True)
train_options = {
'batch_size': 28,
'bpds_kwargs': {
Expand All @@ -69,12 +73,12 @@ def save_default_train_options(path_save: str) -> None:
'interval_save': 1000,
'iter_checkpoint': [],
'n_iter': 250000,
'path_save_dir': dirname,
'path_save_dir': str(path_save.parent),
'seed': None,
}
with open(path_save, 'w') as fo:
with path_save.open('w') as fo:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pathlib.Path works with the default open function, but TIL Path objects have an open function too.

json.dump(train_options, fo, indent=4, sort_keys=True)
print('Saved:', path_save)
logger.info(f'Saved: {path_save}')


def add_parser_arguments(parser: argparse.ArgumentParser) -> None:
Expand Down
2 changes: 2 additions & 0 deletions fnet/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
from fnet.cli import init
from fnet.cli import predict
from fnet.cli import train_model
from fnet.utils.general_utils import init_fnet_logging


def main() -> None:
"""Main function for command-line 'fnet' command."""
init_fnet_logging()
parser = argparse.ArgumentParser(prog='fnet')
subparser = parser.add_subparsers(title='command')
parser_init = subparser.add_parser(
Expand Down
18 changes: 11 additions & 7 deletions fnet/cli/predict.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from typing import Any, Callable, Dict, List, Optional, Tuple
import argparse
import json
import logging
import os

import numpy as np
Expand All @@ -19,6 +20,9 @@
from fnet.utils.general_utils import str_to_object


logger = logging.getLogger(__name__)


def get_dataset(args: argparse.Namespace) -> torch.utils.data.Dataset:
"""Returns dataset.

Expand Down Expand Up @@ -126,10 +130,10 @@ def save_tif(fname: str, ar: np.ndarray, path_root: str) -> str:
path_tif_dir = os.path.join(path_root, 'tifs')
if not os.path.exists(path_tif_dir):
os.makedirs(path_tif_dir)
print('Created:', path_tif_dir)
logger.info(f'Created: {path_tif_dir}')
path_save = os.path.join(path_tif_dir, fname)
tifffile.imsave(path_save, ar, compress=2)
print('Saved:', path_save)
logger.info('Saved: {path_save}')
return os.path.relpath(path_save, path_root)


Expand Down Expand Up @@ -182,9 +186,9 @@ def save_predictions_csv(
dirname = os.path.dirname(path_csv)
if not os.path.exists(dirname):
os.makedirs(dirname)
print('Created:', dirname)
logger.info('Created: {dirname}')
retry_if_oserror(df.to_csv)(path_csv)
print('Saved:', path_csv)
logger.info('Saved: {path_csv}')


def save_args_as_json(path_save_dir: str, args: argparse.Namespace) -> None:
Expand Down Expand Up @@ -213,7 +217,7 @@ def save_args_as_json(path_save_dir: str, args: argparse.Namespace) -> None:
)
with open(path_json, 'w') as fo:
json.dump(vars(args), fo, indent=4, sort_keys=True)
print('Saved:', path_json)
logger.info('Saved: {path_json}')


def add_parser_arguments(parser) -> None:
Expand Down Expand Up @@ -244,7 +248,7 @@ def main(args: Optional[argparse.Namespace] = None) -> None:
model = None
indices = get_indices(args, dataset)
for count, idx in enumerate(indices, 1):
print(f'Processing: {idx:3d} ({count}/{len(indices)})')
logger.info(f'Processing: {idx:3d} ({count}/{len(indices)})')
entry = {}
entry['index'] = idx
signal, target = item_from_dataset(dataset, idx)
Expand All @@ -261,7 +265,7 @@ def main(args: Optional[argparse.Namespace] = None) -> None:
model_def = parse_model(path_model_dir)
model = load_model(model_def['path'], no_optim=True)
model.to_gpu(args.gpu_ids)
print('Loaded model:', model_def['name'])
logger.info(f'Loaded model: {model_def["name"]}')
prediction = model.predict_piecewise(
signal,
tta=('no_tta' not in model_def['options']),
Expand Down
58 changes: 23 additions & 35 deletions fnet/cli/train_model.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,40 @@
"""Trains a model."""


from typing import Callable, Optional
from pathlib import Path
from typing import Callable, Dict, Optional
import argparse
import copy
import datetime
import json
import logging
import os
import pprint
import sys
import time

import numpy as np
import torch
import torch.utils.data

from fnet.cli.init import save_default_train_options
from fnet.utils.general_utils import add_logging_file_handler
from fnet.utils.general_utils import str_to_object
import fnet
import fnet.utils.viz_utils as vu


logger = logging.getLogger(__name__)


def log_training_options(options: Dict) -> None:
"""Logs training options."""
for line in (
['*** Training options ***']
+ pprint.pformat(options).split(os.linesep)
):
logger.info(line)


def set_seeds(seed: Optional[int]) -> None:
"""Sets random seeds"""
if seed is None:
Expand All @@ -35,8 +48,11 @@ def init_cuda(gpu: int) -> None:
"""Initialize Pytorch CUDA state."""
if gpu < 0:
return
torch.cuda.set_device(gpu)
torch.cuda.init()
try:
torch.cuda.set_device(gpu)
torch.cuda.init()
except RuntimeError:
logger.exception('Failed to init CUDA')


def get_dataloader_train(
Expand Down Expand Up @@ -74,30 +90,6 @@ def get_dataloader_val(
return dataloader


def init_logger(path_save: str) -> None:
"""Initialize training logger.

Parameters
----------
path_save
Location to save training log.

"""
dirname = os.path.dirname(path_save)
if not os.path.exists(dirname):
os.makedirs(dirname)
logging.basicConfig(
handlers=[
logging.StreamHandler(sys.stdout),
logging.FileHandler(path_save, mode='a'),
]
)
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logger.info('Started training at: %s', datetime.datetime.now())
return logger


def add_parser_arguments(parser) -> None:
"""Add training script arguments to parser."""
parser.add_argument('json', help='json with training options')
Expand All @@ -117,15 +109,11 @@ def main(args: Optional[argparse.Namespace] = None) -> None:
with open(args.json, 'r') as fi:
train_options = json.load(fi)
args.__dict__.update(train_options)
add_logging_file_handler(Path(args.path_save_dir, 'train_model.log'))
logger.info('Started training at: %s', datetime.datetime.now())

logger = init_logger(path_save=os.path.join(args.path_save_dir, 'run.log'))
set_seeds(args.seed)
logger.info(
os.linesep.join(
['*** Training options ***', pprint.pformat(vars(args))]
)
)

log_training_options(vars(args))
path_model = os.path.join(args.path_save_dir, 'model.p')
model = fnet.models.load_or_init_model(path_model, args.json)
init_cuda(args.gpu_ids[0])
Expand Down
12 changes: 9 additions & 3 deletions fnet/data/bufferedpatchdataset.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
from fnet.data.fnetdataset import FnetDataset
import logging

from tqdm import tqdm
import numpy as np
import torch

from fnet.data.fnetdataset import FnetDataset


logger = logging.getLogger(__name__)


class BufferedPatchDataset(FnetDataset):
"""Dataset that provides chunks/patchs from another dataset."""
Expand Down Expand Up @@ -54,7 +60,7 @@ def __getitem__(self, index):
self.counter % self.buffer_switch_frequency == 0
):
if self.verbose:
print("Inserting new item into buffer")
logger.info("Inserting new item into buffer")
self.insert_new_element_into_buffer()
return self.get_random_patch()

Expand All @@ -81,7 +87,7 @@ def insert_new_element_into_buffer(self):
self.buffer.append(self.dataset[new_datum_index])

if self.verbose:
print("Added item {0}".format(new_datum_index))
logger.info(f"Added item {new_datum_index}")

def get_random_patch(self):
buffer_index = np.random.randint(len(self.buffer))
Expand Down
15 changes: 10 additions & 5 deletions fnet/fnet_ensemble.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
from fnet.fnet_model import Model
from fnet.utils.general_utils import str_to_class
from typing import Union, List
import numpy as np
import logging
import os

import numpy as np
import torch

from fnet.fnet_model import Model
from fnet.utils.general_utils import str_to_class


logger = logging.info(__name__)


def _load_model(path_model: str) -> Model:
"""Load saved model from path."""
Expand Down Expand Up @@ -89,7 +95,6 @@ def predict(
for path_model in self.paths_model:
model = _load_model(path_model)
model.to_gpu(self.gpu_ids)
print(model)
y_hat = model.predict(x=x, tta=tta)
if y_hat_mean is None:
y_hat_mean = torch.zeros(*y_hat.size())
Expand All @@ -116,7 +121,7 @@ def save(self, path_save: str):
if not os.path.exists(dirname):
os.makedirs(dirname)
torch.save(state, path_save)
print('Ensemble model saved to:', path_save)
logger.info(f'Ensemble model saved to: {path_save}')

# Override
def load_state(self, state: dict, no_optim: bool = False):
Expand Down
6 changes: 5 additions & 1 deletion fnet/fnet_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


from typing import Union, Iterator, Optional, Tuple
import logging
import math
import os

Expand All @@ -15,6 +16,9 @@
from fnet.utils.model_utils import move_optim


logger = logging.getLogger(__name__)


def _weights_init(m):
classname = m.__class__.__name__
if classname.startswith('Conv'):
Expand Down Expand Up @@ -185,7 +189,7 @@ def save(self, path_save: str):
dirname = os.path.dirname(path_save)
if not os.path.exists(dirname):
os.makedirs(dirname)
print('Created:', dirname)
logger.info('Created: {dirname}')
curr_gpu_ids = self.gpu_ids
self.to_gpu(-1)
retry_if_oserror(torch.save)(self.get_state(), path_save)
Expand Down
31 changes: 0 additions & 31 deletions fnet/fnet_model_3d_from_2d.py

This file was deleted.

Loading