Spaces:
Sleeping
Sleeping
# -*- coding: utf-8 -*- | |
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved | |
import logging | |
import numpy as np | |
from collections import Counter | |
import tqdm | |
from detectron2.checkpoint import DetectionCheckpointer | |
from detectron2.config import get_cfg | |
from detectron2.data import build_detection_test_loader | |
from detectron2.engine import default_argument_parser | |
from detectron2.modeling import build_model | |
from detectron2.utils.analysis import ( | |
activation_count_operators, | |
flop_count_operators, | |
parameter_count_table, | |
) | |
from detectron2.utils.logger import setup_logger | |
logger = logging.getLogger("detectron2") | |
def setup(args): | |
cfg = get_cfg() | |
cfg.merge_from_file(args.config_file) | |
cfg.DATALOADER.NUM_WORKERS = 0 | |
cfg.merge_from_list(args.opts) | |
cfg.freeze() | |
setup_logger() | |
return cfg | |
def do_flop(cfg): | |
data_loader = build_detection_test_loader(cfg, cfg.DATASETS.TEST[0]) | |
model = build_model(cfg) | |
DetectionCheckpointer(model).load(cfg.MODEL.WEIGHTS) | |
model.eval() | |
counts = Counter() | |
total_flops = [] | |
for idx, data in zip(tqdm.trange(args.num_inputs), data_loader): # noqa | |
count = flop_count_operators(model, data) | |
counts += count | |
total_flops.append(sum(count.values())) | |
logger.info( | |
"(G)Flops for Each Type of Operators:\n" + str([(k, v / idx) for k, v in counts.items()]) | |
) | |
logger.info("Total (G)Flops: {}±{}".format(np.mean(total_flops), np.std(total_flops))) | |
def do_activation(cfg): | |
data_loader = build_detection_test_loader(cfg, cfg.DATASETS.TEST[0]) | |
model = build_model(cfg) | |
DetectionCheckpointer(model).load(cfg.MODEL.WEIGHTS) | |
model.eval() | |
counts = Counter() | |
total_activations = [] | |
for idx, data in zip(tqdm.trange(args.num_inputs), data_loader): # noqa | |
count = activation_count_operators(model, data) | |
counts += count | |
total_activations.append(sum(count.values())) | |
logger.info( | |
"(Million) Activations for Each Type of Operators:\n" | |
+ str([(k, v / idx) for k, v in counts.items()]) | |
) | |
logger.info( | |
"Total (Million) Activations: {}±{}".format( | |
np.mean(total_activations), np.std(total_activations) | |
) | |
) | |
def do_parameter(cfg): | |
model = build_model(cfg) | |
logger.info("Parameter Count:\n" + parameter_count_table(model, max_depth=5)) | |
def do_structure(cfg): | |
model = build_model(cfg) | |
logger.info("Model Structure:\n" + str(model)) | |
if __name__ == "__main__": | |
parser = default_argument_parser( | |
epilog=""" | |
Examples: | |
To show parameters of a model: | |
$ ./analyze_model.py --tasks parameter \\ | |
--config-file ../configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml | |
Flops and activations are data-dependent, therefore inputs and model weights | |
are needed to count them: | |
$ ./analyze_model.py --num-inputs 100 --tasks flop \\ | |
--config-file ../configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml \\ | |
MODEL.WEIGHTS /path/to/model.pkl | |
""" | |
) | |
parser.add_argument( | |
"--tasks", | |
choices=["flop", "activation", "parameter", "structure"], | |
required=True, | |
nargs="+", | |
) | |
parser.add_argument( | |
"--num-inputs", | |
default=100, | |
type=int, | |
help="number of inputs used to compute statistics for flops/activations, " | |
"both are data dependent.", | |
) | |
args = parser.parse_args() | |
assert not args.eval_only | |
assert args.num_gpus == 1 | |
cfg = setup(args) | |
for task in args.tasks: | |
{ | |
"flop": do_flop, | |
"activation": do_activation, | |
"parameter": do_parameter, | |
"structure": do_structure, | |
}[task](cfg) | |