2022-09-07 23:28:46 +08:00
|
|
|
import logging
|
|
|
|
import os
|
|
|
|
from urllib.parse import urlparse
|
|
|
|
|
|
|
|
try:
|
|
|
|
import comet_ml
|
|
|
|
except (ModuleNotFoundError, ImportError):
|
|
|
|
comet_ml = None
|
|
|
|
|
|
|
|
import yaml
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
2023-02-18 08:06:24 +08:00
|
|
|
COMET_PREFIX = 'comet://'
|
|
|
|
COMET_MODEL_NAME = os.getenv('COMET_MODEL_NAME', 'yolov5')
|
|
|
|
COMET_DEFAULT_CHECKPOINT_FILENAME = os.getenv('COMET_DEFAULT_CHECKPOINT_FILENAME', 'last.pt')
|
2022-09-07 23:28:46 +08:00
|
|
|
|
|
|
|
|
|
|
|
def download_model_checkpoint(opt, experiment):
|
2023-02-18 08:06:24 +08:00
|
|
|
model_dir = f'{opt.project}/{experiment.name}'
|
2022-09-07 23:28:46 +08:00
|
|
|
os.makedirs(model_dir, exist_ok=True)
|
|
|
|
|
|
|
|
model_name = COMET_MODEL_NAME
|
|
|
|
model_asset_list = experiment.get_model_asset_list(model_name)
|
|
|
|
|
|
|
|
if len(model_asset_list) == 0:
|
2023-02-18 08:06:24 +08:00
|
|
|
logger.error(f'COMET ERROR: No checkpoints found for model name : {model_name}')
|
2022-09-07 23:28:46 +08:00
|
|
|
return
|
|
|
|
|
|
|
|
model_asset_list = sorted(
|
|
|
|
model_asset_list,
|
2023-02-18 08:06:24 +08:00
|
|
|
key=lambda x: x['step'],
|
2022-09-07 23:28:46 +08:00
|
|
|
reverse=True,
|
|
|
|
)
|
2023-02-18 08:06:24 +08:00
|
|
|
logged_checkpoint_map = {asset['fileName']: asset['assetId'] for asset in model_asset_list}
|
2022-09-07 23:28:46 +08:00
|
|
|
|
|
|
|
resource_url = urlparse(opt.weights)
|
|
|
|
checkpoint_filename = resource_url.query
|
|
|
|
|
|
|
|
if checkpoint_filename:
|
|
|
|
asset_id = logged_checkpoint_map.get(checkpoint_filename)
|
|
|
|
else:
|
|
|
|
asset_id = logged_checkpoint_map.get(COMET_DEFAULT_CHECKPOINT_FILENAME)
|
|
|
|
checkpoint_filename = COMET_DEFAULT_CHECKPOINT_FILENAME
|
|
|
|
|
|
|
|
if asset_id is None:
|
2023-02-18 08:06:24 +08:00
|
|
|
logger.error(f'COMET ERROR: Checkpoint {checkpoint_filename} not found in the given Experiment')
|
2022-09-07 23:28:46 +08:00
|
|
|
return
|
|
|
|
|
|
|
|
try:
|
2023-02-18 08:06:24 +08:00
|
|
|
logger.info(f'COMET INFO: Downloading checkpoint {checkpoint_filename}')
|
2022-09-07 23:28:46 +08:00
|
|
|
asset_filename = checkpoint_filename
|
|
|
|
|
2023-02-18 08:06:24 +08:00
|
|
|
model_binary = experiment.get_asset(asset_id, return_type='binary', stream=False)
|
|
|
|
model_download_path = f'{model_dir}/{asset_filename}'
|
|
|
|
with open(model_download_path, 'wb') as f:
|
2022-09-07 23:28:46 +08:00
|
|
|
f.write(model_binary)
|
|
|
|
|
|
|
|
opt.weights = model_download_path
|
|
|
|
|
|
|
|
except Exception as e:
|
2023-02-18 08:06:24 +08:00
|
|
|
logger.warning('COMET WARNING: Unable to download checkpoint from Comet')
|
2022-09-07 23:28:46 +08:00
|
|
|
logger.exception(e)
|
|
|
|
|
|
|
|
|
|
|
|
def set_opt_parameters(opt, experiment):
|
|
|
|
"""Update the opts Namespace with parameters
|
|
|
|
from Comet's ExistingExperiment when resuming a run
|
|
|
|
|
|
|
|
Args:
|
|
|
|
opt (argparse.Namespace): Namespace of command line options
|
|
|
|
experiment (comet_ml.APIExperiment): Comet API Experiment object
|
|
|
|
"""
|
|
|
|
asset_list = experiment.get_asset_list()
|
|
|
|
resume_string = opt.resume
|
|
|
|
|
|
|
|
for asset in asset_list:
|
2023-02-18 08:06:24 +08:00
|
|
|
if asset['fileName'] == 'opt.yaml':
|
|
|
|
asset_id = asset['assetId']
|
|
|
|
asset_binary = experiment.get_asset(asset_id, return_type='binary', stream=False)
|
2022-09-07 23:28:46 +08:00
|
|
|
opt_dict = yaml.safe_load(asset_binary)
|
|
|
|
for key, value in opt_dict.items():
|
|
|
|
setattr(opt, key, value)
|
|
|
|
opt.resume = resume_string
|
|
|
|
|
|
|
|
# Save hyperparameters to YAML file
|
|
|
|
# Necessary to pass checks in training script
|
2023-02-18 08:06:24 +08:00
|
|
|
save_dir = f'{opt.project}/{experiment.name}'
|
2022-09-07 23:28:46 +08:00
|
|
|
os.makedirs(save_dir, exist_ok=True)
|
|
|
|
|
2023-02-18 08:06:24 +08:00
|
|
|
hyp_yaml_path = f'{save_dir}/hyp.yaml'
|
|
|
|
with open(hyp_yaml_path, 'w') as f:
|
2022-09-07 23:28:46 +08:00
|
|
|
yaml.dump(opt.hyp, f)
|
|
|
|
opt.hyp = hyp_yaml_path
|
|
|
|
|
|
|
|
|
|
|
|
def check_comet_weights(opt):
|
|
|
|
"""Downloads model weights from Comet and updates the
|
|
|
|
weights path to point to saved weights location
|
|
|
|
|
|
|
|
Args:
|
|
|
|
opt (argparse.Namespace): Command Line arguments passed
|
|
|
|
to YOLOv5 training script
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
None/bool: Return True if weights are successfully downloaded
|
|
|
|
else return None
|
|
|
|
"""
|
|
|
|
if comet_ml is None:
|
|
|
|
return
|
|
|
|
|
|
|
|
if isinstance(opt.weights, str):
|
|
|
|
if opt.weights.startswith(COMET_PREFIX):
|
|
|
|
api = comet_ml.API()
|
|
|
|
resource = urlparse(opt.weights)
|
2023-02-18 08:06:24 +08:00
|
|
|
experiment_path = f'{resource.netloc}{resource.path}'
|
2022-09-07 23:28:46 +08:00
|
|
|
experiment = api.get(experiment_path)
|
|
|
|
download_model_checkpoint(opt, experiment)
|
|
|
|
return True
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
def check_comet_resume(opt):
|
|
|
|
"""Restores run parameters to its original state based on the model checkpoint
|
|
|
|
and logged Experiment parameters.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
opt (argparse.Namespace): Command Line arguments passed
|
|
|
|
to YOLOv5 training script
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
None/bool: Return True if the run is restored successfully
|
|
|
|
else return None
|
|
|
|
"""
|
|
|
|
if comet_ml is None:
|
|
|
|
return
|
|
|
|
|
|
|
|
if isinstance(opt.resume, str):
|
|
|
|
if opt.resume.startswith(COMET_PREFIX):
|
|
|
|
api = comet_ml.API()
|
|
|
|
resource = urlparse(opt.resume)
|
2023-02-18 08:06:24 +08:00
|
|
|
experiment_path = f'{resource.netloc}{resource.path}'
|
2022-09-07 23:28:46 +08:00
|
|
|
experiment = api.get(experiment_path)
|
|
|
|
set_opt_parameters(opt, experiment)
|
|
|
|
download_model_checkpoint(opt, experiment)
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
return None
|