Skip to content

Commit

Permalink
Cleanup cnn3d variables. TODO: Clean numberOfImageChannelsPath1 and _…
Browse files Browse the repository at this point in the history
…inp_shapes_per_path.
  • Loading branch information
Kamnitsask committed Jan 18, 2020
1 parent a324d4b commit 58ed2f6
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 64 deletions.
6 changes: 3 additions & 3 deletions deepmedic/dataManagement/sampling.py
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ def extractSegmentGivenSliceCoords(train_val_or_test,

if cnn3d.pathways[path_idx].pType() == pt.FC:
continue
subSamplingFactor = cnn3d.pathways[path_idx].subsFactor()
subSamplingFactor = cnn3d.pathways[path_idx].subs_factor()
pathwayInputShapeRcz = cnn3d.get_inp_shape_of_path(path_idx, train_val_or_test)
leftBoundaryRcz = [coord_center[0] - subSamplingFactor[0] * (pathwayInputShapeRcz[0] - 1) // 2,
coord_center[1] - subSamplingFactor[1] * (pathwayInputShapeRcz[1] - 1) // 2,
Expand Down Expand Up @@ -771,7 +771,7 @@ def extractSegmentGivenSliceCoords(train_val_or_test,
recFieldCnn=cnn3d.recFieldCnn,
subsampledImageChannels=channels,
image_part_slices_coords=slicesCoordsOfSegmForPrimaryPathway,
subSamplingFactor=cnn3d.pathways[pathway_i].subsFactor(),
subSamplingFactor=cnn3d.pathways[pathway_i].subs_factor(),
subsampledImagePartDimensions=cnn3d.get_inp_shape_of_path(pathway_i, train_val_or_test)
)

Expand Down Expand Up @@ -915,7 +915,7 @@ def extractSegmentsGivenSliceCoords(cnn3d,
recFieldCnn=recFieldCnn,
subsampledImageChannels=channelsOfImageNpArray,
image_part_slices_coords=slicesCoordsOfSegmForPrimaryPathway,
subSamplingFactor=cnn3d.pathways[pathway_i].subsFactor(),
subSamplingFactor=cnn3d.pathways[pathway_i].subs_factor(),
subsampledImagePartDimensions=cnn3d.get_inp_shape_of_path(pathway_i, 'test')
)
channsForSegmentsPerPathToReturn[pathway_i].append(channsForThisSubsPathForThisSegm)
Expand Down
1 change: 1 addition & 0 deletions deepmedic/frontEnd/testSession.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ def run_session(self, *args):
self._log.print3("=======================================================\n")

cnn3d.setup_ops_n_feeds_to_test( self._log,
inp_plchldrs_test,
self._params.indices_fms_per_pathtype_per_layer_to_save )
# Create the saver
collection_vars_net = tf.compat.v1.get_collection(tf.compat.v1.GraphKeys.GLOBAL_VARIABLES, scope="net")
Expand Down
6 changes: 4 additions & 2 deletions deepmedic/frontEnd/trainSession.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,16 +131,18 @@ def run_session(self, *args):
self._log.print3("=========== Compiling the Training Function ===========")
self._log.print3("=======================================================\n")
cnn3d.setup_ops_n_feeds_to_train(self._log,
inp_plchldrs_train,
trainer.get_total_cost(),
trainer.get_param_updates_wrt_total_cost() # list of ops
)

self._log.print3("=========== Compiling the Validation Function =========")
cnn3d.setup_ops_n_feeds_to_val(self._log)
cnn3d.setup_ops_n_feeds_to_val(self._log, inp_plchldrs_val)

self._log.print3("=========== Compiling the Testing Function ============")
# For validation with full segmentation
cnn3d.setup_ops_n_feeds_to_test(self._log,
# For validation with full segmentation
inp_plchldrs_test,
self._params.indices_fms_per_pathtype_per_layer_to_save)

# Create the savers
Expand Down
65 changes: 18 additions & 47 deletions deepmedic/neuralnet/cnn3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,26 +39,7 @@ def __init__(self):
#=====================================
self.recFieldCnn = ""

# self.patchesToTrainPerImagePart = ""
self.nkerns = "" # number of feature maps.
self.nkernsSubsampled = ""

# Fully Connected Layers
self.kernelDimensionsFirstFcLayer = ""

# Residual Learning
self.indicesOfLayersToConnectResidualsInOutput = ""

# Lower rank convolutional layers
self.indicesOfLowerRankLayersPerPathway = ""
self.ranksOfLowerRankLayersForEachPathway = ""

#======= Input tensors X. Placeholders OR given tensors =======
# Symbolic variables, which stand for the input. Will be loaded by the compiled trainining/val/test function. Can also be pre-set by an existing tensor if required in future extensions.
self._inp_x = {'train': {},
'val': {},
'test': {} }

#======= Input tensors X. Placeholders OR given tensors =======
self._inp_shapes_per_path = {'train': None,
'val': None,
'test': None} # TODO: For sampling. In eager, remove updating calc_inp_dims_of_paths_from_hr_inp
Expand Down Expand Up @@ -145,7 +126,7 @@ def get_main_feeds(self, str_train_val_test):
return self._feeds_main[str_train_val_test]


def setup_ops_n_feeds_to_train(self, log, total_cost, updates_of_params_wrt_total_cost) :
def setup_ops_n_feeds_to_train(self, log, inp_plchldrs_train, total_cost, updates_of_params_wrt_total_cost) :
log.print3("...Building the training function...")

y_gt = self._output_gt_tensor_feeds['train']['y_gt']
Expand All @@ -161,14 +142,14 @@ def setup_ops_n_feeds_to_train(self, log, total_cost, updates_of_params_wrt_tota
self._ops_main['train']['list_rp_rn_tp_tn'] = self.finalTargetLayer.get_rp_rn_tp_tn(self.finalTargetLayer.output['train'], y_gt)
self._ops_main['train']['updates_grouped_op'] = updates_grouped_op

self._feeds_main['train']['x'] = self._inp_x['train']['x']
self._feeds_main['train']['x'] = inp_plchldrs_train['x']
for subpath_i in range(self.numSubsPaths) : # if there are subsampled paths...
self._feeds_main['train']['x_sub_'+str(subpath_i)] = self._inp_x['train']['x_sub_'+str(subpath_i)]
self._feeds_main['train']['x_sub_'+str(subpath_i)] = inp_plchldrs_train['x_sub_'+str(subpath_i)]
self._feeds_main['train']['y_gt'] = y_gt

log.print3("Done.")

def setup_ops_n_feeds_to_val(self, log):
def setup_ops_n_feeds_to_val(self, log, inp_plchldrs_val):
log.print3("...Building the validation function...")

y_gt = self._output_gt_tensor_feeds['val']['y_gt']
Expand All @@ -179,15 +160,15 @@ def setup_ops_n_feeds_to_val(self, log):
self._ops_main['val']['list_rp_rn_tp_tn'] = self.finalTargetLayer.get_rp_rn_tp_tn(self.finalTargetLayer.output['val'], y_gt)

self._feeds_main['val'] = {}
self._feeds_main['val']['x'] = self._inp_x['val']['x']
self._feeds_main['val']['x'] = inp_plchldrs_val['x']
for subpath_i in range(self.numSubsPaths) : # if there are subsampled paths...
self._feeds_main['val']['x_sub_'+str(subpath_i)] = self._inp_x['val']['x_sub_'+str(subpath_i)]
self._feeds_main['val']['x_sub_'+str(subpath_i)] = inp_plchldrs_val['x_sub_'+str(subpath_i)]
self._feeds_main['val']['y_gt'] = y_gt

log.print3("Done.")


def setup_ops_n_feeds_to_test(self, log, indices_fms_per_pathtype_per_layer_to_save=None) :
def setup_ops_n_feeds_to_test(self, log, inp_plchldrs_test, indices_fms_per_pathtype_per_layer_to_save=None) :
log.print3("...Building the function for testing and visualisation of FMs...")

listToReturnWithAllTheFmActivationsPerLayer = []
Expand All @@ -208,19 +189,20 @@ def setup_ops_n_feeds_to_test(self, log, indices_fms_per_pathtype_per_layer_to_s
self._ops_main['test']['pred_probs'] = self.finalTargetLayer.output["test"]

self._feeds_main['test'] = {}
self._feeds_main['test']['x'] = self._inp_x['test']['x']
self._feeds_main['test']['x'] = inp_plchldrs_test['x']
for subpath_i in range(self.numSubsPaths) : # if there are subsampled paths...
self._feeds_main['test']['x_sub_'+str(subpath_i)] = self._inp_x['test']['x_sub_'+str(subpath_i)]
self._feeds_main['test']['x_sub_'+str(subpath_i)] = inp_plchldrs_test['x_sub_'+str(subpath_i)]

log.print3("Done.")


def _setup_inp_plchldrs(self, train_val_test): # TODO: REMOVE for eager
assert train_val_test in ['train', 'val', 'test']
self._inp_x[train_val_test]['x'] = tf.compat.v1.placeholder(dtype="float32", shape=[None, self.numberOfImageChannelsPath1]+self._inp_shapes_per_path[train_val_test][0], name='inp_x_'+train_val_test)
inp_plchldrs = {}
inp_plchldrs['x'] = tf.compat.v1.placeholder(dtype="float32", shape=[None, self.numberOfImageChannelsPath1]+self._inp_shapes_per_path[train_val_test][0], name='inp_x_'+train_val_test)
for subpath_i in range(self.numSubsPaths): # if there are subsampled paths...
self._inp_x[train_val_test]['x_sub_'+str(subpath_i)] = tf.compat.v1.placeholder(dtype="float32", shape=[None, self.numberOfImageChannelsPath2]+self._inp_shapes_per_path[train_val_test][subpath_i+1], name="inp_x_sub_"+str(subpath_i)+'_' + train_val_test)
return self._inp_x[train_val_test]
inp_plchldrs['x_sub_'+str(subpath_i)] = tf.compat.v1.placeholder(dtype="float32", shape=[None, self.numberOfImageChannelsPath2]+self._inp_shapes_per_path[train_val_test][subpath_i+1], name="inp_x_sub_"+str(subpath_i)+'_' + train_val_test)
return inp_plchldrs

def create_inp_plchldrs(self, inp_dims, train_val_test): # TODO: Remove for eager
self._inp_shapes_per_path[train_val_test] = self.calc_inp_dims_of_paths_from_hr_inp(inp_dims)
Expand Down Expand Up @@ -277,20 +259,9 @@ def make_cnn_model( self,
self.numberOfImageChannelsPath1 = numberOfImageChannelsPath1
self.numberOfImageChannelsPath2 = numberOfImageChannelsPath2
# === Architecture ===
self.nkerns = nkerns # Useless?
self.nkernsSubsampled = nkernsSubsampled # Useless?
self.numSubsPaths = len(subsampleFactorsPerSubPath) # do I want this as attribute? Or function is ok?

# fcLayersFMs???
self.kernelDimensionsFirstFcLayer = kernelDimensionsFirstFcLayer

# == Other Architectural Params ==
self.indicesOfLayersToConnectResidualsInOutput = indicesOfLayersToConnectResidualsInOutput
self.indicesOfLowerRankLayersPerPathway = indicesOfLowerRankLayersPerPathway
# pooling?

# == Others ==
self.dropoutRatesForAllPathways = dropoutRatesForAllPathways
self._kernelDimensionsFirstFcLayer = kernelDimensionsFirstFcLayer # TODO: REMOVE. Temporary for 1st fc padding!

#==============================
rng = np.random.RandomState(seed=None)
Expand Down Expand Up @@ -378,9 +349,9 @@ def make_cnn_model( self,
# Originally it was 1x1x1 only. The pathways themselves where taking care of the receptive field.
# However I can now define it larger (eg 3x3x3), in case it helps combining the multiresolution features better/smoother.
# The convolution is seamless, ie same shape output/input, by mirror padding the input.
log.print3("DEBUG: Shape of the kernel of the first FC layer is : " + str(self.kernelDimensionsFirstFcLayer))
log.print3("DEBUG: Shape of the kernel of the first FC layer is : " + str(kernelDimensionsFirstFcLayer))
thisPathWayNKerns = fcLayersFMs + [self.num_classes]
thisPathWayKernelDimensions = [self.kernelDimensionsFirstFcLayer] + [[1, 1, 1]] * (len(thisPathWayNKerns) - 1)
thisPathWayKernelDimensions = [kernelDimensionsFirstFcLayer] + [[1, 1, 1]] * (len(thisPathWayNKerns) - 1)

thisPathwayNumOfLayers = len(thisPathWayNKerns)
thisPathwayUseBnPerLayer = [movingAvForBnOverXBatches > 0] * thisPathwayNumOfLayers
Expand Down Expand Up @@ -445,7 +416,7 @@ def apply(self, inputs_per_pathw, mode, train_val_test, verbose=True, log=None):

# ===== Concatenate and final convs ========
conc_inp_fms = tf.concat(fms_from_paths_to_concat, axis=1)
n_voxels_pad_per_dim = [kern_dim - 1 for kern_dim in self.kernelDimensionsFirstFcLayer]
n_voxels_pad_per_dim = [kern_dim - 1 for kern_dim in self._kernelDimensionsFirstFcLayer]
log.print3("DEBUG: Input to the FC Pathway will be padded by that many voxels per dimension: " + str(n_voxels_pad_per_dim))
conc_inp_fms = ops.pad_by_mirroring(conc_inp_fms, n_voxels_pad_per_dim) # TODO: SHOULD BE SIMPLY A PADDED-CONV LAYER.
this_pathway = self.pathways[-1] # Fc path
Expand Down
8 changes: 4 additions & 4 deletions deepmedic/neuralnet/pathways.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def get_blocks(self):
return self._blocks
def get_block(self, index):
return self._blocks[index]
def subsFactor(self):
def subs_factor(self):
return self._subs_factor

# Other API :
Expand All @@ -188,14 +188,14 @@ def __init__(self, subsamplingFactor, pName=None):

def upsample_to_high_res(self, input, shape_to_match, upsampl_type="repeat"):
# shape_to_match: list of dimensions x,y,z to match, eg by cropping after upsampling. [dimx, dimy, dimz]
return ops.upsample_5D_tens_and_crop(input, self.subsFactor(), upsampl_type, shape_to_match)
return ops.upsample_5D_tens_and_crop(input, self.subs_factor(), upsampl_type, shape_to_match)

# OVERRIDING parent's classes.
def getStringType(self):
return "SUBSAMPLED" + str(self.subsFactor())
return "SUBSAMPLED" + str(self.subs_factor())

def calc_inp_dims_given_outp_after_upsample(self, outp_dims_in_hr):
outp_dims_in_lr = [int(ceil(outp_dims_in_hr[d]/ self.subsFactor()[d])) for d in range(3)]
outp_dims_in_lr = [int(ceil(outp_dims_in_hr[d]/ self.subs_factor()[d])) for d in range(3)]
inp_dims_req = self.calc_inp_dims_given_outp(outp_dims_in_lr)
return inp_dims_req

Expand Down
6 changes: 3 additions & 3 deletions deepmedic/neuralnet/wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ class PathwayWrapperForSampling(object):
# For CnnWrapperForSampling class.
def __init__(self, pathwayInstance) :
self._pType = pathwayInstance.pType()
self._subsFactor = pathwayInstance.subsFactor()
self._subs_factor = pathwayInstance.subs_factor()

def pType(self):
return self._pType
def subsFactor(self):
return self._subsFactor
def subs_factor(self):
return self._subs_factor

class CnnWrapperForSampling(object):
# Only for the parallel process used during training. So that it won't re-load theano/tensorflow etc.
Expand Down
10 changes: 5 additions & 5 deletions deepmedic/routines/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def calculate_num_voxels_sub(num_central_voxels, pathway):
num_voxels_sub = np.zeros(3)
for i in range(3):
num_voxels_sub[i] = num_central_voxels[i] - 1 if pathway.pType() != pt.SUBS else \
int(math.ceil((num_central_voxels[i] * 1.0) / pathway.subsFactor()[i]) - 1)
int(math.ceil((num_central_voxels[i] * 1.0) / pathway.subs_factor()[i]) - 1)

return [int(a) for a in num_voxels_sub]

Expand All @@ -76,7 +76,7 @@ def calculate_num_central_voxels_dir(num_central_voxels, pathway):
# Eg 9/2=4.5 => Get 5. Combined with the trick at repeat,
# I get my correct number of central voxels hopefully.
for i in range(3):
num_voxels_dir[i] = int(math.ceil((num_central_voxels[i] * 1.0) / pathway.subsFactor()[i])) \
num_voxels_dir[i] = int(math.ceil((num_central_voxels[i] * 1.0) / pathway.subs_factor()[i])) \
if pathway.pType() == pt.SUBS else int(num_central_voxels[i])

return [int(a) for a in num_voxels_dir]
Expand Down Expand Up @@ -149,9 +149,9 @@ def stitch_predicted_to_fms(array_fms_to_save, idx_next_tile_in_fm_vols,
# because it works in the subsampled space.
# I need to repeat it, to bring it to the dimensions of the normal-voxel-space.
if pathway.pType() == pt.SUBS:
expanded_output_r = np.repeat(central_voxels_all_fms, pathway.subsFactor()[0], axis=2)
expanded_output_rc = np.repeat(expanded_output_r, pathway.subsFactor()[1], axis=3)
expanded_output_rcz = np.repeat(expanded_output_rc, pathway.subsFactor()[2], axis=4)
expanded_output_r = np.repeat(central_voxels_all_fms, pathway.subs_factor()[0], axis=2)
expanded_output_rc = np.repeat(expanded_output_r, pathway.subs_factor()[1], axis=3)
expanded_output_rcz = np.repeat(expanded_output_rc, pathway.subs_factor()[2], axis=4)
# The below is a trick to get correct number of voxels even when subsampling factor is
# even or not exact divisor of the number of central voxels.
# ...This trick is coupled with the ceil() when getting the
Expand Down

0 comments on commit 58ed2f6

Please sign in to comment.