diff --git a/examples/automated_deep_compression/ADC.py b/examples/automated_deep_compression/ADC.py index 740e76f5b6fffef885e0a71a2ae2d0747cb57e6e..a93a5156af8be2ec3bad4cf360917b6f5488eee5 100755 --- a/examples/automated_deep_compression/ADC.py +++ b/examples/automated_deep_compression/ADC.py @@ -13,13 +13,23 @@ # See the License for the specific language governing permissions and # limitations under the License. # -import random +"""To execute this code: + +$ time python3 compress_classifier.py --arch=plain20_cifar ../../../data.cifar --adc --resume=checkpoint.plain20_cifar.pth.tar --name="AMC-plain20" --lr=0.1 + +After creating the virtual environment and installing Distiller's Python package dependencies, go ahead and install Coach's +package dependencies using pip. Follow up by running the setup scripts as detailed here: +https://github.com/NervanaSystems/coach#installation. + +If you are running Coach in a development environment, you need to tell the Python runtime where to find the Coach code: +$ export PYTHONPATH=<path-to-coach-code> + +""" import math import copy import logging import numpy as np import torch -import json import csv import gym from gym import spaces @@ -45,95 +55,78 @@ Observation = namedtuple('Observation', ['t', 'n', 'c', 'h', 'w', 'stride', 'k', ALMOST_ONE = 0.9999 USE_COACH = True -PERFORM_THINNING = True +PERFORM_THINNING = False +NUM_TRAINING_EPOCHS = 1 -#reward = -1 * (1-top1/100) * math.log(total_macs/self.dense_model_macs) -# -#reward = -1 * (1-top1/100) + math.log(total_macs/self.dense_model_macs) -#reward = 4*top1/100 - math.log(total_macs) -#reward = reward * total_macs/213201664 -#reward = reward - 5 * total_macs/213201664 -#reward = -1 * vloss * math.sqrt(math.log(total_macs)) -#reward = top1 / math.log(total_macs) -#alpha = 0.9 -#reward = -1 * ( (1-alpha)*(top1/100) + 10*alpha*(total_macs/self.dense_model_macs) ) -#alpha = 0.99 -#reward = -1 * ( (1-alpha)*(top1/100) + alpha*(total_macs/self.dense_model_macs) ) +def count_conv_layer(model): + """Count the number of Convolution layers exist in this model""" + conv_cnt = 0 + for module in model.modules(): + if type(module) == torch.nn.Conv2d: + conv_cnt += 1 + return conv_cnt -#reward = vloss * math.log(total_macs) -#reward = -1 * vloss * (total_macs / self.dense_model_macs) -#reward = top1 * (self.dense_model_macs / total_macs) -#reward = -1 * math.log(total_macs) -#reward = -1 * vloss -NUM_CONVS = 13 -steps_per_episode = NUM_CONVS # TODO: this should not be hard-coded - - -def do_adc(model, dataset, arch, data_loader, validate_fn, save_checkpoint_fn): +def do_adc(model, dataset, arch, optimizer_data, validate_fn, save_checkpoint_fn, train_fn): np.random.seed() if USE_COACH: - return coach_adc(model, dataset, arch, data_loader, validate_fn, save_checkpoint_fn) - return random_adc(model, dataset, arch, data_loader, validate_fn, save_checkpoint_fn) + return coach_adc(model, dataset, arch, optimizer_data, validate_fn, save_checkpoint_fn, train_fn) + return random_adc(model, dataset, arch, optimizer_data, validate_fn, save_checkpoint_fn) -def coach_adc(model, dataset, arch, data_loader, validate_fn, save_checkpoint_fn): +def coach_adc(model, dataset, arch, optimizer_data, validate_fn, save_checkpoint_fn, train_fn): task_parameters = TaskParameters(framework_type="tensorflow", experiment_path="./experiments/test") extra_params = {'save_checkpoint_secs': None, 'render': True} task_parameters.__dict__.update(extra_params) + conv_cnt = count_conv_layer(model) # Create a dictionary of parameters that Coach will handover to CNNEnvironment # Once it creates it. + services = distiller.utils.MutableNamedTuple({ + 'validate_fn': validate_fn, + 'save_checkpoint_fn': save_checkpoint_fn, + 'train_fn': train_fn}) + + app_args = distiller.utils.MutableNamedTuple({ + 'dataset': dataset, + 'arch': arch, + 'optimizer_data': optimizer_data}) if True: - exploration_noise = 0.5 - #exploration_noise = 0.25 - exploitation_decay = 0.996 - # These parameters are passed to the Distiller environment - graph_manager.env_params.additional_simulator_parameters = { - 'model': model, - 'dataset': dataset, - 'arch': arch, - 'data_loader': data_loader, - 'validate_fn': validate_fn, - 'save_checkpoint_fn': save_checkpoint_fn, - #'action_range': (0.10, 0.95), - 'action_range': (0.20, 0.85), - 'onehot_encoding': False, - 'normalize_obs': True, - 'desired_reduction': None, - #'reward_fn': lambda top1, top5, vloss, total_macs: -1 * (1-top5/100) * math.log(total_macs) - 'reward_fn': lambda top1, top5, vloss, total_macs: -1 * (1-top1/100) * math.log(total_macs) - #'reward_fn': lambda top1, total_macs: -1 * max(1-top1/100, 0.25) * math.log(total_macs) - #'reward_fn': lambda top1, total_macs: -1 * (1-top1/100) * math.log(total_macs/100000) - #'reward_fn': lambda top1, total_macs: top1/100 * total_macs/self.dense_model_macs - } + amc_cfg = distiller.utils.MutableNamedTuple({ + #'action_range': (0.20, 0.95), + 'action_range': (0.20, 0.70), + 'onehot_encoding': False, + 'normalize_obs': True, + 'desired_reduction': None, + 'reward_fn': lambda top1, top5, vloss, total_macs: -1 * (1-top1/100) * math.log(total_macs), + 'conv_cnt': conv_cnt, + 'max_reward': -1000}) else: - exploration_noise = 0.5 - #exploration_noise = 0.25 - exploitation_decay = 0.996 - graph_manager.env_params.additional_simulator_parameters = { - 'model': model, - 'dataset': dataset, - 'arch': arch, - 'data_loader': data_loader, - 'validate_fn': validate_fn, - 'save_checkpoint_fn': save_checkpoint_fn, - 'action_range': (0.10, 0.95), - 'onehot_encoding': False, - 'normalize_obs': True, - 'desired_reduction': 1.5e8, - 'reward_fn': lambda top1, total_macs: top1/100 - #'reward_fn': lambda top1, total_macs: min(top1/100, 0.75) - } - - agent_params.exploration.noise_percentage_schedule = PieceWiseSchedule([(ConstantSchedule(exploration_noise), - EnvironmentSteps(100*steps_per_episode)), - (ExponentialSchedule(exploration_noise, 0, exploitation_decay), - EnvironmentSteps(300*steps_per_episode))]) + amc_cfg = distiller.utils.MutableNamedTuple({ + 'action_range': (0.10, 0.95), + 'onehot_encoding': False, + 'normalize_obs': True, + 'desired_reduction': 1.5e8, + 'reward_fn': lambda top1, top5, vloss, total_macs: top1/100, + #'reward_fn': lambda top1, total_macs: min(top1/100, 0.75), + 'conv_cnt': conv_cnt, + 'max_reward': -1000}) + + # These parameters are passed to the Distiller environment + graph_manager.env_params.additional_simulator_parameters = {'model': model, + 'app_args': app_args, + 'amc_cfg': amc_cfg, + 'services': services} + exploration_noise = 0.5 + exploitation_decay = 0.996 + steps_per_episode = conv_cnt + agent_params.exploration.noise_percentage_schedule = PieceWiseSchedule([ + (ConstantSchedule(exploration_noise), EnvironmentSteps(100*steps_per_episode)), + (ExponentialSchedule(exploration_noise, 0, exploitation_decay), EnvironmentSteps(300*steps_per_episode))]) graph_manager.create_graph(task_parameters) graph_manager.improve() @@ -141,43 +134,32 @@ def coach_adc(model, dataset, arch, data_loader, validate_fn, save_checkpoint_fn class CNNEnvironment(gym.Env): metadata = {'render.modes': ['human']} - def __init__(self, model, dataset, arch, data_loader, validate_fn, save_checkpoint_fn, - action_range, onehot_encoding, normalize_obs, desired_reduction, - reward_fn): + def __init__(self, model, app_args, amc_cfg, services): self.pylogger = distiller.data_loggers.PythonLogger(msglogger) self.tflogger = distiller.data_loggers.TensorBoardLogger(msglogger.logdir) - - self.dataset = dataset - self.arch = arch - self.data_loader = data_loader - self.validate_fn = validate_fn - self.save_checkpoint_fn = save_checkpoint_fn self.orig_model = model - self.onehot_encoding = onehot_encoding - self.normalize_obs = normalize_obs - self.max_reward = -1000 - self.reward_fn = reward_fn + self.app_args = app_args + self.amc_cfg = amc_cfg + self.services = services + self.conv_layers, self.dense_model_macs, self.dense_model_size = collect_conv_details(model, self.app_args.dataset) - self.conv_layers, self.dense_model_macs, self.dense_model_size = collect_conv_details(model, dataset) self.reset(init_only=True) - msglogger.info("Model %s has %d Convolution layers", arch, len(self.conv_layers)) + msglogger.info("Model %s has %d Convolution layers", self.app_args.arch, len(self.conv_layers)) msglogger.info("\tTotal MACs: %s" % distiller.pretty_int(self.dense_model_macs)) - msglogger.info("Configuration:\n\tonehot_encoding={}\n\tnormalize_obs={}".format(self.onehot_encoding, - self.normalize_obs)) + msglogger.info("Configuration:\n\tonehot_encoding={}\n\tnormalize_obs={}".format(self.amc_cfg.onehot_encoding, + self.amc_cfg.normalize_obs)) self.debug_stats = {'episode': 0} - self.action_low = action_range[0] - self.action_high = action_range[1] - # Gym - # spaces documentation: https://gym.openai.com/docs/ + self.action_low = amc_cfg.action_range[0] + self.action_high = amc_cfg.action_range[1] + # Gym spaces documentation: https://gym.openai.com/docs/ self.action_space = spaces.Box(self.action_low, self.action_high, shape=(1,)) self.action_space.default_action = self.action_low - self.desired_reduction = desired_reduction self.STATE_EMBEDDING_LEN = len(Observation._fields) - if self.onehot_encoding: - self.STATE_EMBEDDING_LEN += (steps_per_episode - 1) + if self.amc_cfg.onehot_encoding: + self.STATE_EMBEDDING_LEN += (self.amc_cfg.conv_cnt - 1) self.observation_space = spaces.Box(0, float("inf"), shape=(self.STATE_EMBEDDING_LEN,)) - fields = ['top1', 'reward', 'total_macs', 'total_nnz'] + fields = ['top1', 'reward', 'total_macs', 'normalize_macs', 'total_nnz'] with open(r'amc.csv', 'w') as f: writer = csv.writer(f) writer.writerow(fields) @@ -195,8 +177,10 @@ class CNNEnvironment(gym.Env): self._removed_macs = 0 if init_only: return - obs, _, _, _, = self.step(0) - return obs + + layer_macs = self.get_layer_macs(self.current_layer()) + initial_observation = self._get_obs(layer_macs) + return initial_observation def num_layers(self): return len(self.conv_layers) @@ -217,23 +201,14 @@ class CNNEnvironment(gym.Env): """Return the amount of MACs remaining in the model's unprocessed Convolution layers. This is normalized to the range 0..1 """ - #return 1 - self.sum_list_macs(self.unprocessed_layers) / self.dense_model_macs return self._remaining_macs / self.dense_model_macs def removed_macs(self): """Return the amount of MACs removed so far. This is normalized to the range 0..1 """ - #return self.sum_list_macs(self.processed_layers) / self.dense_model_macs return self._removed_macs / self.dense_model_macs - # def sum_list_macs(self, conv_list): - # """Sum the MACs in the provided list of Convolution layers""" - # total_macs = 0 - # for conv in conv_list: - # total_macs += conv.macs - # return total_macs - def render(self, mode, close): """Provide some feedback to the user about what's going on. This is invoked by the Agent. @@ -251,14 +226,14 @@ class CNNEnvironment(gym.Env): rest = self._remaining_macs #duty = self.desired_reduction - (1.2*reduced + rest) - duty = self.desired_reduction - (reduced + rest) - flops = self.get_macs(self.current_layer()) + duty = self.amc_cfg.desired_reduction - (reduced + rest) + flops = self.get_layer_macs(self.current_layer()) msglogger.info("action ********** a={} duty={} desired_reduction={} reduced={} rest={} flops={}". - format(a, duty, self.desired_reduction, reduced, rest, flops)) + format(a, duty, self.amc_cfg.desired_reduction, reduced, rest, flops)) if duty > 0: #duty = 0.9*desired_reduction - (reduced + rest) - duty = self.desired_reduction - (reduced + rest) + duty = self.amc_cfg.desired_reduction - (reduced + rest) msglogger.info("action ********** duty/flops={}".format(duty / flops)) msglogger.info("action ********** 1 - duty/flops={}".format(1 - duty / flops)) #a = max(1-self.action_low, min(a, 1 - duty/flops)) @@ -271,18 +246,21 @@ class CNNEnvironment(gym.Env): a = max(0.05, min(a, 1 - duty/flops)) return a - - def save_record(self, top1, reward, total_macs, total_nnz): - fields = [top1, reward, total_macs, total_nnz] + def save_record(self, top1, reward, total_macs, normalized_macs, total_nnz): + fields = [top1, reward, total_macs, normalized_macs, total_nnz] with open(r'amc.csv', 'a') as f: writer = csv.writer(f) writer.writerow(fields) - def save_checkpoint(self, is_best=False): - # Save the learned-model checkpoint + def create_scheduler(self): scheduler = distiller.CompressionScheduler(self.model) masks = {param_name: masker.mask for param_name, masker in self.zeros_mask_dict.items()} scheduler.load_state_dict(state={'masks_dict': masks}) + return scheduler + + def save_checkpoint(self, is_best=False): + # Save the learned-model checkpoint + scheduler = self.create_scheduler() episode = self.debug_stats['episode'] episode = str(episode).zfill(3) if is_best: @@ -290,7 +268,8 @@ class CNNEnvironment(gym.Env): else: name = "adc_episode_{}".format(episode) - self.save_checkpoint_fn(epoch=self.debug_stats['episode'], model=self.model, scheduler=scheduler, name=name) + self.services.save_checkpoint_fn(epoch=self.debug_stats['episode'], model=self.model, + scheduler=scheduler, name=name) def step(self, action): """Take a step, given an action. @@ -300,21 +279,21 @@ class CNNEnvironment(gym.Env): """ msglogger.info("env.step - current_layer_id={} action={}".format(self.current_layer_id, action)) assert action == 0 or (action >= self.action_low-0.001 and action <= self.action_high+0.001) - if self.desired_reduction is not None: + if self.amc_cfg.desired_reduction is not None: action = self.get_action(action) msglogger.info("action ********** (leave) {}".format(action)) action = 1 - action - layer_macs = self.get_macs(self.current_layer()) - if action > 0 and self.current_layer_id > 0: # skip first convolution - actual_action = self.__remove_channels(self.current_layer_id, action, prune_what="filters") + layer_macs = self.get_layer_macs(self.current_layer()) + if action > 0 and self.current_layer_id >= 0: # skip first convolution + actual_action = self.__remove_structures(self.current_layer_id, action, prune_what="filters") else: actual_action = 0 - layer_macs_after_action = self.get_macs(self.current_layer()) + layer_macs_after_action = self.get_layer_macs(self.current_layer()) # Update the various counters after taking the step self.current_layer_id += 1 - #next_layer_macs = self.get_macs(self.current_layer()) + #next_layer_macs = self.get_layer_macs(self.current_layer()) self._removed_macs += (layer_macs - layer_macs_after_action) self._remaining_macs -= layer_macs # next_layer_macs #self.prev_action = 1 - actual_action @@ -323,22 +302,23 @@ class CNNEnvironment(gym.Env): OrderedDict([('requested_action', action), ('actual_action', 1-actual_action)])) distiller.log_training_progress(stats, None, self.debug_stats['episode'], steps_completed=self.current_layer_id, - total_steps=steps_per_episode, + total_steps=self.amc_cfg.conv_cnt, log_freq=1, loggers=[self.tflogger]) if self.episode_is_done(): observation = self.get_final_obs() reward, top1, total_macs, total_nnz = self.compute_reward() self.debug_stats['episode'] += 1 - self.save_record(top1, reward, total_macs, total_nnz) - if reward > self.max_reward: - self.max_reward = reward + normalized_macs = total_macs/self.dense_model_macs * 100 + self.save_record(top1, reward, total_macs, normalized_macs, total_nnz) + if reward > self.amc_cfg.max_reward: + self.amc_cfg.max_reward = reward self.save_checkpoint(is_best=True) msglogger.info("Best reward={} episode={} top1={}".format(reward, self.debug_stats['episode'], top1)) else: self.save_checkpoint(is_best=False) else: - observation = self._get_obs(layer_macs) #next_layer_macs) + observation = self._get_obs(layer_macs) reward = 0 self.prev_action = 1 - action @@ -349,7 +329,7 @@ class CNNEnvironment(gym.Env): def _get_obs4(self, current_layer_macs, current_layer, conv_module): """Produce a state embedding (i.e. an observation)""" - if self.normalize_obs: + if self.amc_cfg.normalize_obs: obs = np.array([current_layer.t, conv_module.out_channels / 512, conv_module.in_channels / 512, @@ -366,8 +346,8 @@ class CNNEnvironment(gym.Env): current_layer_macs/self.dense_model_macs, self.removed_macs(), self.remaining_macs(), self.prev_action]) - if self.onehot_encoding: - id = np.zeros(NUM_CONVS) + if self.amc_cfg.onehot_encoding: + id = np.zeros(self.amc_cfg.conv_cnt) id[current_layer.t] = 1 obs = np.concatenate([id, obs[1:]]) msglogger.info("obs={}".format(obs)) @@ -395,14 +375,14 @@ class CNNEnvironment(gym.Env): 0, 0, 0, 0, 0, self.removed_macs(), 0, 1 - self.prev_action]) - if self.onehot_encoding: - id = np.zeros(NUM_CONVS) + if self.amc_cfg.onehot_encoding: + id = np.zeros(self.amc_cfg.conv_cnt) obs = np.concatenate([id, obs[1:]]) assert len(obs) == self.STATE_EMBEDDING_LEN return obs - def get_macs(self, layer): + def get_layer_macs(self, layer): """Return the number of MACs required to compute <layer>'s Convolution""" if layer is None: return 0 @@ -416,9 +396,10 @@ class CNNEnvironment(gym.Env): # If we didn't physically remove structures, we need to use the structural sparsity to compute MACs conv_pname = layer.name + ".weight" conv_p = distiller.model_find_param(self.model, conv_pname) - return dense_macs * distiller.density_ch(conv_p) + # return dense_macs * distiller.density_ch(conv_p) # Channel pruning + return dense_macs * distiller.density_3D(conv_p) # Filter pruning - def __remove_channels(self, idx, fraction_to_prune, prune_what="channels"): + def __remove_structures(self, idx, fraction_to_prune, prune_what="channels"): """Physically remove channels and corresponding filters from the model""" if idx not in range(self.num_layers()): raise ValueError("idx=%d is not in correct range (0-%d)" % (idx, self.num_layers())) @@ -454,14 +435,14 @@ class CNNEnvironment(gym.Env): if (self.zeros_mask_dict[conv_pname].mask is None or calculate_sparsity(self.zeros_mask_dict[conv_pname].mask) == 0): - msglogger.info("__remove_channels: aborting because there are no channels to prune") + msglogger.info("__remove_structures: aborting because there are no channels to prune") return 0 # Use the mask to prune self.zeros_mask_dict[conv_pname].apply_mask(conv_p) if PERFORM_THINNING: - remove_structures(self.model, self.zeros_mask_dict, self.arch, self.dataset, optimizer=None) + remove_structures(self.model, self.zeros_mask_dict, self.app_args.dataset, self.app_args.dataset, optimizer=None) conv_p = distiller.model_find_param(self.model, conv_pname) return distiller.volume(conv_p) / layer.weights_vol actual_sparsity = calculate_sparsity(conv_p) @@ -470,13 +451,29 @@ class CNNEnvironment(gym.Env): def compute_reward(self): """The ADC paper defines reward = -Error""" distiller.log_weights_sparsity(self.model, -1, loggers=[self.pylogger]) - compression = distiller.model_numel(self.model, param_dims=[4]) / self.dense_model_size - _, total_macs, total_nnz = collect_conv_details(self.model, self.dataset) + + if PERFORM_THINNING: + _, total_macs, total_nnz = collect_conv_details(self.model, self.app_args.dataset) + compression = distiller.model_numel(self.model, param_dims=[4]) / self.dense_model_size + else: + _, total_macs, total_nnz = collect_conv_details(self.model, self.app_args.dataset) + compression = 1 - distiller.model_sparsity(self.model)/100 + # What a hack! + total_nnz *= compression + msglogger.info("Total parameters left: %.2f%%" % (compression*100)) msglogger.info("Total compute left: %.2f%%" % (total_macs/self.dense_model_macs*100)) - - top1, top5, vloss = self.validate_fn(model=self.model, epoch=self.debug_stats['episode']) - reward = self.reward_fn(top1, top5, vloss, total_macs) + # Train for zero or more epochs + optimizer = torch.optim.SGD(self.model.parameters(), lr=self.app_args.optimizer_data['lr'], + momentum=self.app_args.optimizer_data['momentum'], + weight_decay=self.app_args.optimizer_data['weight_decay']) + for _ in range(NUM_TRAINING_EPOCHS): + self.services.train_fn(model=self.model, compression_scheduler=self.create_scheduler(), + optimizer=optimizer, + epoch=self.debug_stats['episode']) + # Validate + top1, top5, vloss = self.services.validate_fn(model=self.model, epoch=self.debug_stats['episode']) + reward = self.amc_cfg.reward_fn(top1, top5, vloss, total_macs) stats = ('Peformance/Validation/', OrderedDict([('Loss', vloss), @@ -484,8 +481,8 @@ class CNNEnvironment(gym.Env): ('Top5', top5), ('reward', reward), ('total_macs', int(total_macs)), + ('macs_normalized', total_macs/self.dense_model_macs*100), ('log(total_macs)', math.log(total_macs)), - #('log(total_macs/self.dense_model_macs)', math.log(total_macs/self.dense_model_macs)), ('total_nnz', int(total_nnz))])) distiller.log_training_progress(stats, None, self.debug_stats['episode'], steps_completed=0, total_steps=1, log_freq=1, loggers=[self.tflogger, self.pylogger]) @@ -507,7 +504,7 @@ def collect_conv_details(model, dataset): g = SummaryGraph(model.cuda(), dummy_input.cuda()) conv_layers = OrderedDict() total_macs = 0 - total_nnz = 0 + total_params = 0 for id, (name, m) in enumerate(model.named_modules()): if isinstance(m, torch.nn.Conv2d): conv = SimpleNamespace() @@ -520,11 +517,14 @@ def collect_conv_details(model, dataset): assert conv_op is not None conv.weights_vol = conv_op['attrs']['weights_vol'] - total_nnz += conv.weights_vol + total_params += conv.weights_vol conv.macs = conv_op['attrs']['MACs'] conv_pname = name + ".weight" conv_p = distiller.model_find_param(model, conv_pname) - conv.macs *= distiller.density_ch(conv_p) + if not PERFORM_THINNING: + #conv.macs *= distiller.density_ch(conv_p) # Channel pruning + conv.macs *= distiller.density_3D(conv_p) # Filter pruning + #assert distiller.density_ch(conv_p) == 1 total_macs += conv.macs conv.ofm_h = g.param_shape(conv_op['outputs'][0])[2] @@ -535,14 +535,14 @@ def collect_conv_details(model, dataset): conv.name = name conv.id = id conv_layers[len(conv_layers)] = conv - return conv_layers, total_macs, total_nnz + return conv_layers, total_macs, total_params from examples.automated_deep_compression.adc_controlled_envs import * -def random_adc(model, dataset, arch, data_loader, validate_fn, save_checkpoint_fn): +def random_adc(model, dataset, arch, optimizer_data, validate_fn, save_checkpoint_fn): """Random ADC agent""" action_range = (0.0, 1.0) - env = CNNEnvironment(model, dataset, arch, data_loader, + env = CNNEnvironment(model, dataset, arch, optimizer_data, validate_fn, save_checkpoint_fn, action_range, onehot_encoding=False, normalize_obs=False, desired_reduction=None, reward_fn=lambda top1, total_macs: top1/100) @@ -573,32 +573,32 @@ def random_adc(model, dataset, arch, data_loader, validate_fn, save_checkpoint_f best_episode = [-1000, None] -import os -import pandas as pd -from tabulate import tabulate -import apputils -from models import create_model - - -def summarize_experiment(experiment_dir, dataset, arch, validate_fn): - df = pd.DataFrame(columns=['File', 'NNZ', 'MACs', 'Top1']) - for file in os.listdir(experiment_dir): - if file.endswith(".pth.tar"): - cnt_macs, cnt_params, top1 = get_experiment_performance_summary(os.path.join(experiment_dir, file), dataset, arch, validate_fn) - df.loc[len(df.index)] = [file, cnt_params, cnt_macs, top1] - t = tabulate(df, headers='keys', tablefmt='psql', floatfmt=".2f") - print(t) - csv_fname = os.path.join(experiment_dir, "arch_space" + ".csv") - print("Saving results to: {}".format(csv_fname)) - df.to_csv(csv_fname, sep=',') - - -def get_experiment_performance_summary(chkpt_fname, dataset, arch, validate_fn): - model = create_model(False, dataset, arch) - model, compression_scheduler, start_epoch = apputils.load_checkpoint(model, chkpt_fname) - - dummy_input = get_dummy_input(dataset) - perf_df = distiller.model_performance_summary(model, dummy_input, 1) - total_macs = perf_df['MACs'].sum() - top1, top5, vloss = validate_fn(model=model, epoch=-1) - return total_macs, distiller.model_numel(model), top1 +# import os +# import pandas as pd +# from tabulate import tabulate +# import apputils +# from models import create_model +# +# +# def summarize_experiment(experiment_dir, dataset, arch, validate_fn): +# df = pd.DataFrame(columns=['File', 'NNZ', 'MACs', 'Top1']) +# for file in os.listdir(experiment_dir): +# if file.endswith(".pth.tar"): +# cnt_macs, cnt_params, top1 = get_experiment_performance_summary(os.path.join(experiment_dir, file), dataset, arch, validate_fn) +# df.loc[len(df.index)] = [file, cnt_params, cnt_macs, top1] +# t = tabulate(df, headers='keys', tablefmt='psql', floatfmt=".2f") +# print(t) +# csv_fname = os.path.join(experiment_dir, "arch_space" + ".csv") +# print("Saving results to: {}".format(csv_fname)) +# df.to_csv(csv_fname, sep=',') +# +# +# def get_experiment_performance_summary(chkpt_fname, dataset, arch, validate_fn): +# model = create_model(False, dataset, arch) +# model, compression_scheduler, start_epoch = apputils.load_checkpoint(model, chkpt_fname) +# +# dummy_input = get_dummy_input(dataset) +# perf_df = distiller.model_performance_summary(model, dummy_input, 1) +# total_macs = perf_df['MACs'].sum() +# top1, top5, vloss = validate_fn(model=model, epoch=-1) +# return total_macs, distiller.model_numel(model), top1 diff --git a/examples/automated_deep_compression/amc-results.ipynb b/examples/automated_deep_compression/amc-results.ipynb index 5e6a1907b357722a0389f5d4a49f91467507a8a3..231e40f9c05521ce61c35dd641e5c6ace3c3e273 100644 --- a/examples/automated_deep_compression/amc-results.ipynb +++ b/examples/automated_deep_compression/amc-results.ipynb @@ -1,62 +1,217 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# AutoML for Model Compression\n", + "\n", + "This notebook will help us visualize and review the results of the DDPG agent's sub-space search.\n", + "It contains two visualizations of the process of discovering networks during the exploration and exploitation phases. Each discovered network is projected on a 2D subspace that maps the network's compute complexity (normalized to a percentage of the dense-network's compute budget) against its Top1 accuracy.\n", + "\n", + "The Top1 value is either the Test dataset Top1 measured without any fine-tuning, or after one epoch of fine-tuning (this depends on how the AMC algorithm is configured)." + ] + }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ + "%matplotlib inline\n", + "\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", - "import csv" + "import matplotlib \n", + "import csv\n", + "from matplotlib.ticker import FuncFormatter\n", + "#from matplotlib.animation import FuncAnimation\n", + "\n", + "\n", + "\n", + "import matplotlib.pylab as pylab\n", + "params = {'legend.fontsize': 'x-large',\n", + " 'figure.figsize': (15, 7),\n", + " 'axes.labelsize': 'x-large',\n", + " 'axes.titlesize':'xx-large',\n", + " 'xtick.labelsize':'x-large',\n", + " 'ytick.labelsize':'x-large'}\n", + "pylab.rcParams.update(params)\n", + "\n", + "\n", + "def to_percent(y, position):\n", + " # Ignore the passed in position. This has the effect of scaling the default\n", + " # tick locations.\n", + " if y < 1:\n", + " y = str(100 * y)\n", + " s = str(y)\n", + "\n", + " # The percent symbol needs escaping in latex\n", + " if matplotlib.rcParams['text.usetex'] is True:\n", + " return s + r'$\\%$'\n", + " else:\n", + " return s + '%'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Static diagram" ] }, { "cell_type": "code", - "execution_count": 94, + "execution_count": null, "metadata": { "scrolled": false }, - "outputs": [ - { - "data": { - "image/png": "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Vk52GSIiIiIiIiIil42PPvqow1o7/ULjLonwqLKykt27d092GSIiIiIiIiIilw1jzKmLGadlayIiIiIiIiIikpHCIxERERERERERyUjhkYiIiIiIiIiIZKTwSEREREREREREMlJ4JCIiIiIiIiIiGSk8EhERERERERGRjBQeiYiIiIiIiIhIRgqPREREREREREQkI4VHIiIiIiIiIiKSkcIjERERERERERHJSOGRiIiIiIiIiIhkpPBIREREREREREQyUngkIiIiIiIiIiIZKTwSEREREREREZGMFB6JiIiIiIiIiEhGCo9ERERERERERCQjhUciIiIiIiIiIpLRuIZHxph/bYw5ZIw5bIz5fupYsTFmizHmROo/i8azBhERERERERGRT8NaO9klTAmu8bqwMWYZ8CiwBogAbxhj/hl4DPiNtfYvjDH/AfgPwL8frzpERERERERE5MqTSCQYGBggKyuL9vZ2uru7iUQieL1enE4nFRUVRCIROjo6MMbQ1NTEiRMn8Pv9BINBotEoDocDh8NBPB4fNUj64Q9/OAlPNvHGLTwCqoEPrbX9AMaYd4AvAfcBN6XG/COwFYVHIiIiIiIiIhdlMMQwxkxyJeMrFoulw57BAOfo0aPs3r2bvr4+cnNzWbFiBZFIhKNHj9LX14cxhv7+/nTYE4/HM17f4XBgjCEvL49YLEYoFMJaSyKRwO124/V6WbJkCXv27MHj8WCtZfHixbhcLo4fP04kEuFP//RPr4gAyYzXFCxjTDXwCrAOCAG/AXYDD1trC1NjDNA9+P05n3+M5CwlKioqak6dOjUudYqIiIiIiIhMddZajhw5wvbt22ltbQVg5syZrF+/nsWLF19SQVI8Hqe2tpazZ8/icrlYuHAhM2fOTJ9va2vjnXfe4fjx4yMCIGMMxcXFFBcXEw6HOXv2LNba9Di32421FqfTiTGGJUuWkJ2dTUNDA+3t7elrDQZHlZWVLF++HJ/PR3d3N++//z79/f2UlZVx22238cwzzxAOh1m5ciW33norLldyDo61ln379vH6668Ti8Uu2QDJGPORtXb1hcaN28wja+1RY8x/A94EgsA+IH7OGGuMGTW9stb+BPgJwOrVq7XIUERERERERKYMay1+v594PE5+fn46VBive23evJn9+/cTDAZJJBIAnDp1ik2bNrFy5UruvPPOTxwg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AsCkSlgtblnWCcuyVlmWtUrSWklDkv4k6d8lfWBZVo2kD85/DQAAAABTqre3V42NjTpz5oyi0egVXWNZll588UU1Njaqr69PgUBAw8PD6u3tVXd3t1577TW1trYmODkATK2pemztFkmnLcs6a4z5rqQbzx9/QdKHkv7LFOUAAAAA5pxQKKSDBw+qsbFRknTNNddo5cqVSklJSXKy5PB6vfrTn/4kj8ejWCwmm80mu92u66+/Xt/4xjdkjIl7bVNTkzwejwKBwCVj0WhUgUBA7777rh577LFEfgQAmFJTVR79UNJr539fbFlWx/nfd0oqHusCY8wTkp6QpIqKioQHBAAAAGajpqYmvf766xoeHpbP55MkNTY26oMPPtD27dtVVVWV5IRTq7u7W88884w8Ho8GBgZGjzscDoXDYfn9ft15551xr9+3b99F1/2zcDiszs5OBQIBZWZmTmp2AEiWhJdHxhiXpLsk/e//PGZZlmWMsca6zrKspyU9LUl1dXVjngMAAAAgvp6eHr322mtqa2tTKBQaPT40NCS3263XX39dP/3pT1VQUHDZe3V2durAgQPy+/3Ky8vT2rVrlZ+fn8j4CfHOO++oq6vrkgIoEomotbVVNptN1113nYqKisa8vr+//7KPuNlsNg0ODlIeAZg1pmLl0bclfWZZluf81x5jTKllWR3GmFJJXVOQAQAAAJhzdu7cKZ/Pd1FxdEEoFFJvb6927typ733ve3HvEYlE9Pvf/15NTU3q7u5WMBhUWlqa9uzZoxUrVuiuu+6aMW8YGxgYUEtLS9yVQ5Zlye/3a+/evbrjjjvGPCc7O1t2u33cAikWiyk9PX1SMgPAdDAVf8vfp//1yJok/Yekh87//iFJf56CDAAAAMCcMDIyoubmZp05c0ZHjhxRf39/3HMDgYCOHj067v3eeustHT58WEePHpXH45Hf71dHR4eOHTum/fv36+9///tkf4SE8fl8MsbIsuI/2BAMBtXVFf/n2+vWrVNGRkbccafTqbKyMlYdAZhVErryyBiTLulWST/9yuH/JukNY8yjks5K2pbIDAAAAMBcEIlE9O677+rgwYOKxWKSvtzAOSsrS319fWMWJrFYTJFIJO49fT6fTpw4oebm5kuuj8Viampqktvt1o033jgjNt++kox2u12pqalxxxctWqSysjKFw+FLNs12OBzK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/CMQAmCt/V/AO8ATQCXQB3xzdloqIhPdxr37VeC7xphhoB942lprZ6m5IvIna4DdwCfGmI/Hlv17IBP03isy04zeC0VEREREREREJBBNWxMRERERERERkYAUPBIRERERERERkYAUPBIRERERERERkYAUPBIRERERERERkYAUPBIREREREREReYAYY14xxjQbY87dxraZxpjDxpgzxpgyY8wT0z2egkciIiIiARhjrDHm5xN+DzbGtBhjfnvTdm8ZY074efxfGmPOGWM+GfvA9nf3o90iIiLymfcqsP02t/0PwK+stcuBp4EfTfdgCh6JiIiIBNYLLDHGuMd+3wY0TNzAGBMDrACijTHzJyz/AvC3wOPW2qXAaqDzvrRaREREPtOstUeBtonLjDG5xpjfG2NOGWPeM8YsGt8ciBr7ORponO7xFDwSERERmdo7wJNjPz8D7Llp/VeAfcAvGf02b9wPgb+z1jYCWGsHrLUvAxhj/sYYc2Fs6PgvZ7T1IiIi8nnxEvDX1toVwN/xpxFG/wn4hjGmntHPNX893R0reCQiIiIytV8CTxtjwoGHgA9vWj8eUNoz9vO4JcCpAPv8B2C5tfYh4Dv3trkiIiLyeWOMiQAeA/6vMeZj4H8DKWOrnwFetdamA08APzPGTCseFHwvGysiIiLyWWOtLTPGZDP6weudieuMMfOAfOB9a601xgwZY5ZYa2+VvLIMeMMY8xbw1gw0W0RERD5fXECHtXaZn3XPMZYfyVr7wdgXYglA83R2LiIiIiJT2wv8dyZPWXsKiAWqjTE1QDZ/Gn10ntFcSP48CfwLUAR8ZIzRF3oiIiJyx6y1XYx+HvkagBn18NjqWmDL2PLFQDjQMp39K3gkIiIicmuvAP/ZWvvJTcufAbZba7OttdmMBovG8x79F+C/GWOSAYwxocaY58eGiWdYaw8Df89o4sqI+3ESIiIi8tlgjNkDfAAsNMbUG2OeA54FnjPGnGX0S6wdY5v/APj22PI9wF9Za+10jqdvuURERERuwVpbD/zzxGVjU9mygBMTtqs2xnQaY1ZZa98Zm9b2rjHGMFrp5BUgCPi5MSYaMMA/W2s77s+ZiIiIyGeBtfaZAKu2+9n2ArDmbo5nphlsEhERERERERGRzxFNWxMRERERERERkYAUPBIRERERERERkYAUPBIRERERERERkYAUPBIRERERERERkYAUPBIRERERERERkYAUPBIRERERERERkYAUPBIRERERERERkYD+P7rWaBapUoQZAAAAAElFTkSuQmCC\n", - "text/plain": [ - "<matplotlib.figure.Figure at 0x7f2c38a97240>" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "top1 = []\n", "macs = []\n", - "\n", - "with open('../examples/classifier_compression/amc.csv', 'r') as csv_file:\n", + "normalized_macs = []\n", + "with open('../classifier_compression/amc.csv', 'r') as csv_file:\n", " csv_reader = csv.reader(csv_file, delimiter=',')\n", " is_header = True\n", " for row in csv_reader:\n", " if not is_header:\n", - " #print(row[0], row[2])\n", - " top1.append(row[0])\n", - " macs.append(row[2])\n", + " top1.append(float(row[0]))\n", + " macs.append(float(row[2]))\n", + " normalized_macs.append(float(row[3]))\n", " else:\n", " is_header = False\n", " \n", - "plt.figure(figsize=(20,10))\n", - "plt.title('Projection of Discovered Networks') \n", - "plt.xlabel('MACs')\n", - "plt.ylabel('Top1')\n", + "plt.figure(figsize=(15,7)) \n", + "plt.title('Projection of Discovered Networks ({})'.format(len(top1))) \n", + "plt.xlabel('Normalized MACs')\n", + "plt.ylabel('Top1 Accuracy')\n", + "\n", + "# Create the formatter using the function to_percent. This multiplies all the\n", + "# default labels by 100, making them all percentages\n", + "formatter = FuncFormatter(to_percent)\n", + "\n", + "# Set the formatter\n", + "plt.gca().yaxis.set_major_formatter(formatter)\n", + "plt.gca().xaxis.set_major_formatter(formatter)\n", "\n", "# Use color gradients to show the \"age\" of the network:\n", - "# Darker networks were discovered earlier than lighter ones.\n", - "color_grad = [str(i/len(top1)) for i in range(len(top1))]\n", - "plt.scatter(macs, top1, color=color_grad, s=80, edgecolors='gray');\n", + "# Lighter networks were discovered earlier than darker ones.\n", + "color_grad = [str(1-i/len(top1)) for i in range(len(top1))]\n", + "plt.scatter(normalized_macs, top1, color=color_grad, s=80, edgecolors='gray');\n", "\n", "#plt.hlines(90, 1.5*10**8, 2.5*10**8, color='b')\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Video animation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "# Based on these two helpful example code: \n", + "# https://stackoverflow.com/questions/9401658/how-to-animate-a-scatter-plot\n", + "# http://louistiao.me/posts/notebooks/embedding-matplotlib-animations-in-jupyter-notebooks/.\n", + "# Specifically, the use of IPython.display is missing from the first example, but most of the animation code\n", + "# leverages code from there.\n", + "import matplotlib.pyplot as plt\n", + "import matplotlib.animation as animation\n", + "import numpy as np\n", + "\n", + "from matplotlib import animation, rc\n", + "from IPython.display import HTML\n", + "\n", + "INTERVAL = 100 # Animation speed\n", + "POINT_AGING_SPEED = 20\n", + "\n", + "class AnimatedScatter(object):\n", + " \"\"\"An animated scatter plot using matplotlib.animations.FuncAnimation.\"\"\"\n", + " def __init__(self, xdata, ydata):\n", + " assert len(xdata) == len(ydata)\n", + " self.numpoints = len(xdata)\n", + " self.xdata = xdata\n", + " self.ydata = ydata\n", + " self.stream = self.data_stream()\n", + "\n", + " # Setup the figure and axes...\n", + " self.fig, self.ax = plt.subplots(figsize=(15,7))\n", + " # Then setup FuncAnimation.\n", + " self.ani = animation.FuncAnimation(self.fig, self.update, interval=INTERVAL,\n", + " frames=self.numpoints-2, \n", + " init_func=self.setup_plot, blit=True)\n", + "\n", + " def setup_plot(self):\n", + " \"\"\"Initialize drawing of the scatter plot.\"\"\"\n", + " x, y, s, c = next(self.stream)\n", + " self.scat = self.ax.scatter(x, y, c=c, s=s, animated=False)\n", + " self.scat.set_edgecolors('gray')\n", + " self.scat.set_cmap('gray')\n", + " self.ax.axis([min(self.xdata)-2, max(self.xdata)+2, \n", + " min(self.ydata)-2, max(self.ydata)+2])\n", + " \n", + " # For FuncAnimation's sake, we need to return the artist we'll be using\n", + " # Note that it expects a sequence of artists, thus the trailing comma.\n", + " return self.scat,\n", + "\n", + " def data_stream(self):\n", + " numpoints = 0#len(self.xdata)\n", + " colors = []\n", + " xxx = 0\n", + " while True:\n", + " numpoints += 1\n", + " data = np.ndarray((4, numpoints))\n", + " data[0:1, : ] = self.xdata[:numpoints]\n", + " data[1:2, : ] = self.ydata[:numpoints]\n", + " data[2:3, : ] = [70] * numpoints # point size\n", + " #data[3:4, : ] = [np.random.random() for p in range(numpoints)] # color\n", + " # The color of the points is a gradient with larger values for \"younger\" points.\n", + " # At each new frame we show one more point, and \"age\" each existing point by incrementaly \n", + " # reducing its color gradient.\n", + " data[3:4, : ] = [(1-i/(numpoints+1)) for i in range(numpoints)] \n", + " #data[3:4, : ] = [max(0, (1-i/(xxx+1))) for i in range(numpoints)]\n", + " #numpoints = (numpoints) % len(self.xdata)\n", + " xxx = (xxx + 1) % (self.numpoints/4)\n", + " yield data\n", + "\n", + " def update(self, i): \n", + " \"\"\"Update the scatter plot.\"\"\"\n", + " data = next(self.stream)\n", + " i = i % len(data)\n", + " \n", + " # Set x and y data...\n", + " xy = [(data[0,i], data[1,i]) for i in range(len(data[0,:]))]\n", + " self.scat.set_offsets(xy)\n", + " \n", + " # Set sizes...\n", + " #self.scat._sizes = 300 * abs(data[2])**1.5 + 100\n", + " # Set colors..\n", + " self.scat.set_array(data[3])\n", + " \n", + " # We need to return the updated artist for FuncAnimation to draw..\n", + " # Note that it expects a sequence of artists, thus the trailing comma.\n", + " return self.scat,\n", + "\n", + " def show(self):\n", + " plt.show()\n", + "\n", + "a = AnimatedScatter(normalized_macs, top1)\n", + "plt.title('Projection of Discovered Networks ({})'.format(len(top1))) \n", + "plt.xlabel('Normalized MACs')\n", + "plt.ylabel('Top1 Accuracy')\n", + "#a.ani.save('amc_vgg16.mp4', fps=10, dpi=80) #Frame per second controls speed, dpi controls the quality \n", + "rc('animation', html='html5')\n", + "a.ani" + ] + }, { "cell_type": "code", "execution_count": null, diff --git a/examples/classifier_compression/compress_classifier.py b/examples/classifier_compression/compress_classifier.py index 486c84a850dde32134ceffe988ec4921f754281b..ce36cc873164486803c150f56637fd9dd0b7f972 100755 --- a/examples/classifier_compression/compress_classifier.py +++ b/examples/classifier_compression/compress_classifier.py @@ -240,7 +240,8 @@ def create_activation_stats_collectors(model, collection_phase): distiller.utils.activation_channels_l1), "apoz_channels": SummaryActivationStatsCollector(model, "apoz_channels", distiller.utils.activation_channels_apoz), - "records": RecordsActivationStatsCollector(model, classes=[torch.nn.Conv2d])}) + "records": RecordsActivationStatsCollector(model, classes=[torch.nn.Conv2d]) + }) activations_collectors[collection_phase] = collectors return activations_collectors @@ -342,7 +343,7 @@ def main(): msglogger.info('Optimizer Args: %s', optimizer.defaults) if args.ADC: - return automated_deep_compression(model, criterion, pylogger, args) + return automated_deep_compression(model, criterion, optimizer, pylogger, args) # This sample application can be invoked to produce various summary reports. if args.summary: @@ -481,7 +482,7 @@ def train(train_loader, model, criterion, optimizer, epoch, if compression_scheduler: compression_scheduler.on_minibatch_begin(epoch, train_step, steps_per_epoch, optimizer) - if args.kd_policy is None: + if not hasattr(args, 'kd_policy') or args.kd_policy is None: output = model(inputs) else: output = args.kd_policy.forward(inputs) @@ -503,6 +504,7 @@ def train(train_loader, model, criterion, optimizer, epoch, optimizer=optimizer, return_loss_components=True) loss = agg_loss.overall_loss losses[OVERALL_LOSS_KEY].add(loss.item()) + for lc in agg_loss.loss_components: if lc.name not in losses: losses[lc.name] = tnt.AverageValueMeter() @@ -685,7 +687,7 @@ def earlyexit_validate_loss(output, target, criterion, args): if args.loss_exits[exitnum][batch_index] < args.earlyexit_thresholds[exitnum]: # take the results from early exit since lower than threshold args.exiterrors[exitnum].add(torch.tensor(np.array(output[exitnum].data[batch_index], ndmin=2)), - torch.full([1], target[batch_index], dtype=torch.long)) + torch.full([1], target[batch_index], dtype=torch.long)) args.exit_taken[exitnum] += 1 earlyexit_taken = True break # since exit was taken, do not affect the stats of subsequent exits @@ -696,6 +698,7 @@ def earlyexit_validate_loss(output, target, criterion, args): torch.full([1], target[batch_index], dtype=torch.long)) args.exit_taken[exitnum] += 1 + def earlyexit_validate_stats(args): # Print some interesting summary stats for number of data points that could exit early top1k_stats = [0] * args.num_exits @@ -722,6 +725,7 @@ def earlyexit_validate_stats(args): msglogger.info("Totals for entire network with early exits: top1 = %.3f, top5 = %.3f", total_top1, total_top5) return(total_top1, total_top5, losses_exits_stats) + def evaluate_model(model, criterion, test_loader, loggers, activations_collectors, args, scheduler=None): # This sample application can be invoked to evaluate the accuracy of your model on # the test dataset. @@ -777,7 +781,7 @@ def sensitivity_analysis(model, criterion, data_loader, loggers, args, sparsitie distiller.sensitivities_to_csv(sensitivity, 'sensitivity.csv') -def automated_deep_compression(model, criterion, loggers, args): +def automated_deep_compression(model, criterion, optimizer, loggers, args): import examples.automated_deep_compression.ADC as ADC HAVE_COACH_INSTALLED = True if not HAVE_COACH_INSTALLED: @@ -793,13 +797,16 @@ def automated_deep_compression(model, criterion, loggers, args): args.display_confusion = True validate_fn = partial(validate, val_loader=test_loader, criterion=criterion, loggers=loggers, args=args) + train_fn = partial(train, train_loader=train_loader, criterion=criterion, + loggers=loggers, args=args) if args.ADC_params is not None: ADC.summarize_experiment(args.ADC_params, args.dataset, args.arch, validate_fn) exit() save_checkpoint_fn = partial(apputils.save_checkpoint, arch=args.arch, dir=msglogger.logdir) - ADC.do_adc(model, args.dataset, args.arch, val_loader, validate_fn, save_checkpoint_fn) + optimizer_data = {'lr': args.lr, 'momentum': args.momentum, 'weight_decay': args.weight_decay} + ADC.do_adc(model, args.dataset, args.arch, optimizer_data, validate_fn, save_checkpoint_fn, train_fn) if __name__ == '__main__':