<reponame>MattSkiff/cow_flow
'''This file configures the training procedure'''
proj_dir = "/home/matthew/Desktop/laptop_desktop/clones/cow_flow/data"

# device settings
import torch
import arguments as a

gpu = True
seed = 101

## Dataset Options ------
mnist = False 
load_stored_dmaps = False # speeds up precomputation (with RAM = True)
store_dmaps = False # this will save dmap objects (numpy arrays) to file
ram = False # load aerial imagery and precompute dmaps and load both into ram before training
counts = False # must be off for pretraining feature extractor (#TODO)

## Training Options ------
train_model = True # (if false, will only prep dataset,dataloaders)
balanced = False # whether to have a 1:1 mixture of empty:annotated images
weighted = False # whether to weight minibatch samples
annotations_only = True # whether to only use image patches that have annotations
test_run = False # use only a small fraction of data to check everything works
validation = True # whether to run validation per meta epoch
eval_n = 1
data_prop = 1 # proportion of the full dataset to use
test_train_split = 70 # percentage of data to allocate to train set

## Density Map Options ------
uniform_noise = 0 # amount of uniform noise to add (sample evenly from 0-x) | 0 for none
noise = 1e-3 # amount of noise to add
filter_size = 15 # as per single image mcnn paper
sigma = 4.0 # "   -----    " 
scale = 1 # 4, 2 = downscale dmaps four/two fold, 1 = unchanged

## Feature Extractor Options ------
pretrained = True
feat_extractor = "resnet18" # alexnet, vgg16_bn,resnet18, none # TODO mnist_resnet, efficient net
feat_extractor_epochs = 50
train_feat_extractor = False # whether to finetune or load finetuned model 
load_feat_extractor_str = '' # '' to train from scratch, loads FE  # final_eval_test_weka-13_BS2_LR_I[0.002]_NC5_E1_FE_resnet18_DIM608_JO_PT_PY_1_1x1_WD_0.001_FSZ_16_14_12_2021_21_49_14
# nb: pretraining FE saves regardless of save flag

## Architecture Options ------
fixed1x1conv = False 
freq_1x1 = 3 # 1 for always | how many x coupling blocks to have a 1x1 conv permutation layer
pyramid = True # only implemented for resnet18
n_pyramid_blocks = 3
gap = False # global average pooling
downsampling = True # whether to downsample (5 ds layers) dmaps by converting spatial dims to channel dims
n_coupling_blocks = 5 # if pyramid, total blocks will be n_pyramid_blocks x 5

## Subnet Architecture Options
subnet_type = 'conv' # options = fc, conv
filters = 32 # conv ('64' recommended min)
batchnorm = False # conv
width = 400 # fc ('128' recommended min)
dropout_p = 0.0 # fc only param - 0 for no dropout

# Hyper Params and Optimisation ------
joint_optim = True # jointly optimse feature extractor and flow
scheduler = 'none' # exponential, none
weight_decay = 1e-3 # differnet: 1e-5
clip_value = 1 # gradient clipping
clamp_alpha = 1.9 

# vectorised params must always be passed as lists
lr_init = [2e-3]
batch_size = [8] # actual batch size is this value multiplied by n_transforms(_test)

# total epochs = meta_epochs * sub_epochs
# evaluation after <sub_epochs> epochs
meta_epochs = 3
sub_epochs = 5 

## Output Settings ----
schema = 'splitting_full_test' # if debug, ignored
debug = False # report loads of info/debug info
tb = True # write metrics, hyper params to tb files
verbose = True # report stats per sub epoch and other info
report_freq = -1 # nth minibatch to report minibatch loss on (1 = always,-1 = turn off)
viz = True # visualise outputs and stats
hide_tqdm_bar = True
save_model = True # also saves a copy of the config file with the name of the model
checkpoints = False # saves after every meta epoch

# debug opts
debug_dataloader = False
debug_utils = False

# nb: same as the defaults specified for the pretrained pytorch model zoo
norm_mean, norm_std = [0.485, 0.456, 0.406], [0.229, 0.224, 0.225] 

# Logic # TODO - move out of config.py ------
if not gpu:
    device = 'cpu' 
else: 
    device = 'cuda' 
    torch.cuda.set_device(0)

# if dmap is scaled down outside of flow
# less downsample 'levels' are needed'
levels = 5
# if scale == 1:
#     levels = 5
# elif scale == 2:
#     levels = 4
# elif scale == 4:
#     levels = 3

# "condition dim"
if feat_extractor == "alexnet":
    n_feat = 256 
elif feat_extractor == "vgg16_bn":
    n_feat = 512 
elif feat_extractor == "resnet18":
    n_feat = 512
elif feat_extractor == "none":
    if mnist:
        n_feat = 1 
    else:
        # conditioning on raw RGB image
         n_feat = 3

if mnist:
    one_hot = True # only for MNIST
else:
    one_hot = False

if one_hot:
    channels = 10 # onehot 1 num -> 0,0,0,1 etc
elif mnist or feat_extractor != "none":
    channels = 1 # greyscale mnist, density maps
elif counts:
    channels = 1 # duplication not needed (linear subnets)
else:
    # TODO - this is a massive hack to test feature extractor-less  NF
    channels = 2 # duplicate dmap over channel dimension (1->2)

if debug:
    schema = 'debug' # aka ignore debugs

if mnist and feat_extractor == "none":
    img_size = (28,28)
elif mnist:
    img_size = (228,228) # (28,28)
else:
    img_size = (800, 600) # width, height (x-y)

img_dims = [3] + list(img_size) # RGB + x-y

# TODO: rename this parameter
# this effects the padding applied to the density maps
if not mnist and not counts and downsampling:
    density_map_w = 800//scale #img_size[0]
    if feat_extractor == 'resnet18':
        density_map_h = 608//scale #img_size[1]
    elif feat_extractor == 'alexnet':
         density_map_h = 544//scale #img_size[1]
         density_map_w = 768//scale
    elif feat_extractor == 'vgg16_bn':
        density_map_h = 576//scale #img_size[1]
    elif feat_extractor == 'none':
        density_map_h = 600//scale
elif not mnist and not counts and not downsampling:
    density_map_w = 800//scale
    density_map_h = 600//scale
elif not mnist:
    # size of count expanded to map spatial feature dimensions
    density_map_h = 19 * 2 # need at least 2 channels, expand x2, then downsample (haar)
    density_map_w = 25 * 2 # TODO - rework so this ties to ft_dims (vgg,alexnet, resnet, etc)
elif mnist and feat_extractor != "none":
    if gap:
        density_map_h = img_size[1] * 2
        density_map_w = img_size[0] * 2
    else:
        density_map_h = 6 * 2
        density_map_w = 6 * 2 # feature size x2 (account for downsampling)
elif mnist and feat_extractor == "none":
    # minimum possible dimensionality of flow possible with coupling layers
    density_map_h = 4
    density_map_w = 4

if gpu:
    device = torch.device("cuda:{}".format(a.args.gpu_number) if torch.cuda.is_available() else "cpu") # select gpu

if a.args.gpu_number != 0:
    assert gpu

# Checks ------ 
#assert not (pyramid and fixed1x1conv)
#assert not (weighted and annotations_only)
assert not (feat_extractor == 'none' and gap == True)
assert gap != downsampling

assert subnet_type in ['conv','fc']
assert feat_extractor in ['none' ,'alexnet','vgg16_bn','resnet18']
assert scheduler in ['exponential','none']

if subnet_type == 'fc':
    assert gap
    assert mnist or counts
    assert not fixed1x1conv

assert not (load_stored_dmaps and store_dmaps)

if load_stored_dmaps or store_dmaps:
    assert ram
 
if store_dmaps:
    assert not train_model 

if subnet_type == 'conv':
    assert dropout_p == 0
    
if mnist:
    assert not counts

if counts:
    assert subnet_type == 'fc' and gap or subnet_type == 'conv' and not gap

if pyramid:
    assert n_coupling_blocks == 5 # for recording purposes
    assert (pyramid and feat_extractor == 'resnet18')
    assert (pyramid and downsampling) # pyramid nf head has  downsmapling
    assert (pyramid and not train_feat_extractor) # TODO
    # TODO - get pyramid working with other scales!
    assert scale == 1

assert scale in (1,2,4)
assert freq_1x1 != 0

'''This file configures the training procedure'''
proj_dir = "/home/matthew/Desktop/laptop_desktop/clones/cow_flow/data"

# device settings
import torch
import arguments as a

gpu = True
seed = 101

## Dataset Options ------
mnist = False 
load_stored_dmaps = False # speeds up precomputation (with RAM = True)
store_dmaps = False # this will save dmap objects (numpy arrays) to file
ram = False # load aerial imagery and precompute dmaps and load both into ram before training
counts = False # must be off for pretraining feature extractor (#TODO)

## Training Options ------
train_model = True # (if false, will only prep dataset,dataloaders)
balanced = False # whether to have a 1:1 mixture of empty:annotated images
weighted = False # whether to weight minibatch samples
annotations_only = True # whether to only use image patches that have annotations
test_run = False # use only a small fraction of data to check everything works
validation = True # whether to run validation per meta epoch
eval_n = 1
data_prop = 1 # proportion of the full dataset to use
test_train_split = 70 # percentage of data to allocate to train set

## Density Map Options ------
uniform_noise = 0 # amount of uniform noise to add (sample evenly from 0-x) | 0 for none
noise = 1e-3 # amount of noise to add
filter_size = 15 # as per single image mcnn paper
sigma = 4.0 # "   -----    " 
scale = 1 # 4, 2 = downscale dmaps four/two fold, 1 = unchanged

## Feature Extractor Options ------
pretrained = True
feat_extractor = "resnet18" # alexnet, vgg16_bn,resnet18, none # TODO mnist_resnet, efficient net
feat_extractor_epochs = 50
train_feat_extractor = False # whether to finetune or load finetuned model 
load_feat_extractor_str = '' # '' to train from scratch, loads FE  # final_eval_test_weka-13_BS2_LR_I[0.002]_NC5_E1_FE_resnet18_DIM608_JO_PT_PY_1_1x1_WD_0.001_FSZ_16_14_12_2021_21_49_14
# nb: pretraining FE saves regardless of save flag

## Architecture Options ------
fixed1x1conv = False 
freq_1x1 = 3 # 1 for always | how many x coupling blocks to have a 1x1 conv permutation layer
pyramid = True # only implemented for resnet18
n_pyramid_blocks = 3
gap = False # global average pooling
downsampling = True # whether to downsample (5 ds layers) dmaps by converting spatial dims to channel dims
n_coupling_blocks = 5 # if pyramid, total blocks will be n_pyramid_blocks x 5

## Subnet Architecture Options
subnet_type = 'conv' # options = fc, conv
filters = 32 # conv ('64' recommended min)
batchnorm = False # conv
width = 400 # fc ('128' recommended min)
dropout_p = 0.0 # fc only param - 0 for no dropout

# Hyper Params and Optimisation ------
joint_optim = True # jointly optimse feature extractor and flow
scheduler = 'none' # exponential, none
weight_decay = 1e-3 # differnet: 1e-5
clip_value = 1 # gradient clipping
clamp_alpha = 1.9 

# vectorised params must always be passed as lists
lr_init = [2e-3]
batch_size = [8] # actual batch size is this value multiplied by n_transforms(_test)

# total epochs = meta_epochs * sub_epochs
# evaluation after <sub_epochs> epochs
meta_epochs = 3
sub_epochs = 5 

## Output Settings ----
schema = 'splitting_full_test' # if debug, ignored
debug = False # report loads of info/debug info
tb = True # write metrics, hyper params to tb files
verbose = True # report stats per sub epoch and other info
report_freq = -1 # nth minibatch to report minibatch loss on (1 = always,-1 = turn off)
viz = True # visualise outputs and stats
hide_tqdm_bar = True
save_model = True # also saves a copy of the config file with the name of the model
checkpoints = False # saves after every meta epoch

# debug opts
debug_dataloader = False
debug_utils = False

# nb: same as the defaults specified for the pretrained pytorch model zoo
norm_mean, norm_std = [0.485, 0.456, 0.406], [0.229, 0.224, 0.225] 

# Logic # TODO - move out of config.py ------
if not gpu:
    device = 'cpu' 
else: 
    device = 'cuda' 
    torch.cuda.set_device(0)

# if dmap is scaled down outside of flow
# less downsample 'levels' are needed'
levels = 5
# if scale == 1:
#     levels = 5
# elif scale == 2:
#     levels = 4
# elif scale == 4:
#     levels = 3

# "condition dim"
if feat_extractor == "alexnet":
    n_feat = 256 
elif feat_extractor == "vgg16_bn":
    n_feat = 512 
elif feat_extractor == "resnet18":
    n_feat = 512
elif feat_extractor == "none":
    if mnist:
        n_feat = 1 
    else:
        # conditioning on raw RGB image
         n_feat = 3

if mnist:
    one_hot = True # only for MNIST
else:
    one_hot = False

if one_hot:
    channels = 10 # onehot 1 num -> 0,0,0,1 etc
elif mnist or feat_extractor != "none":
    channels = 1 # greyscale mnist, density maps
elif counts:
    channels = 1 # duplication not needed (linear subnets)
else:
    # TODO - this is a massive hack to test feature extractor-less  NF
    channels = 2 # duplicate dmap over channel dimension (1->2)

if debug:
    schema = 'debug' # aka ignore debugs

if mnist and feat_extractor == "none":
    img_size = (28,28)
elif mnist:
    img_size = (228,228) # (28,28)
else:
    img_size = (800, 600) # width, height (x-y)

img_dims = [3] + list(img_size) # RGB + x-y

# TODO: rename this parameter
# this effects the padding applied to the density maps
if not mnist and not counts and downsampling:
    density_map_w = 800//scale #img_size[0]
    if feat_extractor == 'resnet18':
        density_map_h = 608//scale #img_size[1]
    elif feat_extractor == 'alexnet':
         density_map_h = 544//scale #img_size[1]
         density_map_w = 768//scale
    elif feat_extractor == 'vgg16_bn':
        density_map_h = 576//scale #img_size[1]
    elif feat_extractor == 'none':
        density_map_h = 600//scale
elif not mnist and not counts and not downsampling:
    density_map_w = 800//scale
    density_map_h = 600//scale
elif not mnist:
    # size of count expanded to map spatial feature dimensions
    density_map_h = 19 * 2 # need at least 2 channels, expand x2, then downsample (haar)
    density_map_w = 25 * 2 # TODO - rework so this ties to ft_dims (vgg,alexnet, resnet, etc)
elif mnist and feat_extractor != "none":
    if gap:
        density_map_h = img_size[1] * 2
        density_map_w = img_size[0] * 2
    else:
        density_map_h = 6 * 2
        density_map_w = 6 * 2 # feature size x2 (account for downsampling)
elif mnist and feat_extractor == "none":
    # minimum possible dimensionality of flow possible with coupling layers
    density_map_h = 4
    density_map_w = 4

if gpu:
    device = torch.device("cuda:{}".format(a.args.gpu_number) if torch.cuda.is_available() else "cpu") # select gpu

if a.args.gpu_number != 0:
    assert gpu

# Checks ------ 
#assert not (pyramid and fixed1x1conv)
#assert not (weighted and annotations_only)
assert not (feat_extractor == 'none' and gap == True)
assert gap != downsampling

assert subnet_type in ['conv','fc']
assert feat_extractor in ['none' ,'alexnet','vgg16_bn','resnet18']
assert scheduler in ['exponential','none']

if subnet_type == 'fc':
    assert gap
    assert mnist or counts
    assert not fixed1x1conv

assert not (load_stored_dmaps and store_dmaps)

if load_stored_dmaps or store_dmaps:
    assert ram
 
if store_dmaps:
    assert not train_model 

if subnet_type == 'conv':
    assert dropout_p == 0
    
if mnist:
    assert not counts

if counts:
    assert subnet_type == 'fc' and gap or subnet_type == 'conv' and not gap

if pyramid:
    assert n_coupling_blocks == 5 # for recording purposes
    assert (pyramid and feat_extractor == 'resnet18')
    assert (pyramid and downsampling) # pyramid nf head has  downsmapling
    assert (pyramid and not train_feat_extractor) # TODO
    # TODO - get pyramid working with other scales!
    assert scale == 1

assert scale in (1,2,4)
assert freq_1x1 != 0
This file configures the training procedure # device settings ## Dataset Options ------ # speeds up precomputation (with RAM = True) # this will save dmap objects (numpy arrays) to file # load aerial imagery and precompute dmaps and load both into ram before training # must be off for pretraining feature extractor (#TODO) ## Training Options ------ # (if false, will only prep dataset,dataloaders) # whether to have a 1:1 mixture of empty:annotated images # whether to weight minibatch samples # whether to only use image patches that have annotations # use only a small fraction of data to check everything works # whether to run validation per meta epoch # proportion of the full dataset to use # percentage of data to allocate to train set ## Density Map Options ------ # amount of uniform noise to add (sample evenly from 0-x) | 0 for none # amount of noise to add # as per single image mcnn paper # "   -----    " # 4, 2 = downscale dmaps four/two fold, 1 = unchanged ## Feature Extractor Options ------ # alexnet, vgg16_bn,resnet18, none # TODO mnist_resnet, efficient net # whether to finetune or load finetuned model # '' to train from scratch, loads FE  # final_eval_test_weka-13_BS2_LR_I[0.002]_NC5_E1_FE_resnet18_DIM608_JO_PT_PY_1_1x1_WD_0.001_FSZ_16_14_12_2021_21_49_14 # nb: pretraining FE saves regardless of save flag ## Architecture Options ------ # 1 for always | how many x coupling blocks to have a 1x1 conv permutation layer # only implemented for resnet18 # global average pooling # whether to downsample (5 ds layers) dmaps by converting spatial dims to channel dims # if pyramid, total blocks will be n_pyramid_blocks x 5 ## Subnet Architecture Options # options = fc, conv # conv ('64' recommended min) # conv # fc ('128' recommended min) # fc only param - 0 for no dropout # Hyper Params and Optimisation ------ # jointly optimse feature extractor and flow # exponential, none # differnet: 1e-5 # gradient clipping # vectorised params must always be passed as lists # actual batch size is this value multiplied by n_transforms(_test) # total epochs = meta_epochs * sub_epochs # evaluation after <sub_epochs> epochs ## Output Settings ---- # if debug, ignored # report loads of info/debug info # write metrics, hyper params to tb files # report stats per sub epoch and other info # nth minibatch to report minibatch loss on (1 = always,-1 = turn off) # visualise outputs and stats # also saves a copy of the config file with the name of the model # saves after every meta epoch # debug opts # nb: same as the defaults specified for the pretrained pytorch model zoo # Logic # TODO - move out of config.py ------ # if dmap is scaled down outside of flow # less downsample 'levels' are needed' # if scale == 1: #     levels = 5 # elif scale == 2: #     levels = 4 # elif scale == 4: #     levels = 3 # "condition dim" # conditioning on raw RGB image # only for MNIST # onehot 1 num -> 0,0,0,1 etc # greyscale mnist, density maps # duplication not needed (linear subnets) # TODO - this is a massive hack to test feature extractor-less  NF # duplicate dmap over channel dimension (1->2) # aka ignore debugs # (28,28) # width, height (x-y) # RGB + x-y # TODO: rename this parameter # this effects the padding applied to the density maps #img_size[0] #img_size[1] #img_size[1] #img_size[1] # size of count expanded to map spatial feature dimensions # need at least 2 channels, expand x2, then downsample (haar) # TODO - rework so this ties to ft_dims (vgg,alexnet, resnet, etc) # feature size x2 (account for downsampling) # minimum possible dimensionality of flow possible with coupling layers # select gpu # Checks ------ #assert not (pyramid and fixed1x1conv) #assert not (weighted and annotations_only) # for recording purposes # pyramid nf head has  downsmapling # TODO # TODO - get pyramid working with other scales!