Switch to side-by-side view

--- a
+++ b/src/LiviaNet/LiviaNet3DConvLayer.py
@@ -0,0 +1,288 @@
+""" 
+Copyright (c) 2016, Jose Dolz .All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice,
+       this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice,
+       this list of conditions and the following disclaimer in the documentation
+       and/or other materials provided with the distribution.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+    OTHER DEALINGS IN THE SOFTWARE.
+
+Jose Dolz. Dec, 2016.
+email: jose.dolz.upv@gmail.com
+LIVIA Department, ETS, Montreal.
+"""
+
+
+import theano
+import theano.tensor as T
+from theano.tensor.nnet import conv2d
+import theano.tensor.nnet.conv3d2d
+import pdb
+
+import sys
+import os
+import numpy as np
+import numpy
+import random
+
+from Modules.General.Utils import initializeWeights
+from Modules.NeuralNetwork.ActivationFunctions import *
+from Modules.NeuralNetwork.layerOperations import *
+
+#################################################################
+#                         Layer Types                           #
+#################################################################
+
+class LiviaNet3DConvLayer(object):
+    """Convolutional Layer of the Livia network """
+    def __init__(self,
+                 rng,
+                 layerID,
+                 inputSample_Train, 
+                 inputSample_Test,
+                 inputToLayerShapeTrain,
+                 inputToLayerShapeTest,
+                 filterShape,
+                 useBatchNorm, 
+                 numberEpochApplyRolling, 
+                 maxPoolingParameters,
+                 weights_initMethodType,
+                 weights,
+                 activationType,
+                 dropoutRate=0.0) :
+        
+        self.inputTrain = None
+        self.inputTest = None
+        self.inputShapeTrain = None
+        self.inputShapeTest = None
+       
+        self._numberOfFeatureMaps = 0
+        self._maxPoolingParameters = None
+        self._appliedBnInLayer = None
+        self.params = [] 
+        self.W = None 
+        self._gBn = None 
+        self._b = None 
+        self._aPrelu = None 
+        self.numberOfTrainableParams = 0
+        
+        self.muBatchNorm = None 
+        self._varBnsArrayForRollingAverage = None 
+        self.numberEpochApplyRolling = numberEpochApplyRolling
+        self.rollingIndex = 0 
+        self._sharedNewMu_B = None 
+        self._sharedNewVar_B = None
+        self._newMu_B = None
+        self._newVar_B = None
+        
+        self.outputTrain = None
+        self.outputTest = None
+        self.outputShapeTrain = None
+        self.outputShapeTest = None
+
+        # === After all the parameters has been initialized, create the layer 
+        # Set all the inputs and parameters
+        self.inputTrain = inputSample_Train
+        self.inputTest = inputSample_Test
+        self.inputShapeTrain = inputToLayerShapeTrain
+        self.inputShapeTest = inputToLayerShapeTest
+        
+        self._numberOfFeatureMaps = filterShape[0] 
+        assert self.inputShapeTrain[1] == filterShape[1]
+        self._maxPoolingParameters = maxPoolingParameters
+
+        print(" --- [STATUS]  --------- Creating layer {} --------- ".format(layerID))
+        
+         ## Process the input layer through all the steps over the block
+             
+        (inputToConvTrain,
+         inputToConvTest) = self.passInputThroughLayerElements(inputSample_Train,
+                                                               inputToLayerShapeTrain,
+                                                               inputSample_Test,
+                                                               inputToLayerShapeTest,
+                                                               useBatchNorm, 
+                                                               numberEpochApplyRolling, 
+                                                               activationType,
+                                                               weights,  
+                                                               dropoutRate,
+                                                               rng
+                                                               )         
+        # input shapes for the convolutions
+        inputToConvShapeTrain = inputToLayerShapeTrain
+        inputToConvShapeTest  = inputToLayerShapeTest
+        
+        # --------------  Weights initialization -------------
+        # Initialize weights with random weights if W is empty
+        # Otherwise, use loaded weights
+
+        self.W = initializeWeights(filterShape,
+                                   weights_initMethodType,
+                                   weights)
+
+        self.params = [self.W] + self.params
+        self.numberOfTrainableParams += 1
+        
+        ##---------- Convolve --------------
+        (convolvedOutput_Train, convolvedOutputShape_Train) = convolveWithKernel(self.W, filterShape, inputToConvTrain, inputToConvShapeTrain) 
+        (convolvedOutput_Test, convolvedOutputShape_Test)   = convolveWithKernel(self.W , filterShape, inputToConvTest, inputToConvShapeTest) 
+        
+        self.outputTrain = convolvedOutput_Train
+        self.outputTest = convolvedOutput_Test
+        self.outputShapeTrain = convolvedOutputShape_Train
+        self.outputShapeTest = convolvedOutputShape_Test
+        
+    
+    def updateLayerMatricesBatchNorm(self):
+
+        if self._appliedBnInLayer :
+            muArrayValue = self.muBatchNorm.get_value()
+            muArrayValue[self.rollingIndex] = self._sharedNewMu_B.get_value()
+            self.muBatchNorm.set_value(muArrayValue, borrow=True)
+            
+            varArrayValue = self._varBnsArrayForRollingAverage.get_value()
+            varArrayValue[self.rollingIndex] = self._sharedNewVar_B.get_value()
+            self._varBnsArrayForRollingAverage.set_value(varArrayValue, borrow=True)
+            self.rollingIndex = (self.rollingIndex + 1) % self.numberEpochApplyRolling
+            
+    def getUpdatesForBnRollingAverage(self) :
+        if self._appliedBnInLayer :
+            return [(self._sharedNewMu_B, self._newMu_B),
+                    (self._sharedNewVar_B, self._newVar_B) ]
+        else :
+            return []
+    
+
+    def passInputThroughLayerElements(self,
+                                      inputSample_Train,
+                                      inputSampleShape_Train,
+                                      inputSample_Test,
+                                      inputSampleShape_Test,
+                                      useBatchNorm,
+                                      numberEpochApplyRolling,
+                                      activationType,
+                                      weights,
+                                      dropoutRate,
+                                      rndState):
+        """ Through each block the following steps are applied, according to Kamnitsas:
+            1 - Batch Normalization or biases
+            2 - Activation function
+            3 - Dropout
+            4 - (Optional) Max pooling
+
+            Ref:   He et al "Identity Mappings in Deep Residual Networks" 2016 
+            https://github.com/KaimingHe/resnet-1k-layers/blob/master/resnet-pre-act.lua """
+            
+        # ________________________________________________________
+        #      1 :  Batch Normalization 
+        # ________________________________________________________
+        """ Implemenation taken from Kamnitsas work.
+        
+        A batch normalization implementation in TensorFlow:
+
+        http://r2rt.com/implementing-batch-normalization-in-tensorflow.html
+
+        "Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift",
+         Proceedings of the 32nd International Conference on Machine Learning, Lille, France, 2015.
+         Journal of Machine Learning Research: W&CP volume 37
+        """
+        if useBatchNorm > 0 :
+           
+            self._appliedBnInLayer = True
+            
+            (inputToNonLinearityTrain,
+            inputToNonLinearityTest,
+            self._gBn,
+            self._b,
+            self.muBatchNorm,
+            self._varBnsArrayForRollingAverage,
+            self._sharedNewMu_B,
+            self._sharedNewVar_B,
+            self._newMu_B,
+            self._newVar_B) = applyBn( numberEpochApplyRolling,
+                                       inputSample_Train,
+                                       inputSample_Test,
+                                       inputSampleShape_Train)
+                         
+            self.params = self.params + [self._gBn, self._b]
+        else : 
+            self._appliedBnInLayer = False
+            numberOfInputFeatMaps = inputSampleShape_Train[1]
+
+            b_values = np.zeros( (self._numberOfFeatureMaps), dtype = 'float32')
+            self._b = theano.shared(value=b_values, borrow=True)
+    
+            inputToNonLinearityTrain = applyBiasToFeatureMaps( self._b, inputSample_Train )
+            inputToNonLinearityTest = applyBiasToFeatureMaps( self._b, inputSample_Test )
+
+            self.params = self.params + [self._b]
+            
+        # ________________________________________________________
+        #      2 :  Apply the corresponding activation function 
+        # ________________________________________________________
+        def Linear():
+            print " --- Activation function: Linear"
+            self.activationFunctionType = "Linear"
+            output_Train = inputToNonLinearityTrain
+            output_Test = inputToNonLinearityTest
+            return (output_Train, output_Test)
+            
+        def ReLU():
+            print " --- Activation function: ReLU"
+            self.activationFunctionType = "ReLU"
+            output_Train = applyActivationFunction_ReLU_v1(inputToNonLinearityTrain)
+            output_Test = applyActivationFunction_ReLU_v1(inputToNonLinearityTest)
+            return (output_Train, output_Test)
+        
+        def PReLU():
+            print " --- Activation function: PReLU"
+            self.activationFunctionType = "PReLU"
+            numberOfInputFeatMaps = inputSampleShape_Train[1]
+            PReLU_Values = np.ones( (numberOfInputFeatMaps), dtype = 'float32' )*0.01 
+            self._aPrelu = theano.shared(value=PReLU_Values, borrow=True) 
+
+            output_Train = applyActivationFunction_PReLU(inputToNonLinearityTrain, self._aPrelu)
+            output_Test  = applyActivationFunction_PReLU(inputToNonLinearityTest, self._aPrelu)
+            self.params = self.params + [self._aPrelu]
+            self.numberOfTrainableParams += 1
+            return (output_Train,output_Test)
+        
+        def LeakyReLU():
+            print " --- Activation function: Leaky ReLU "
+            self.activationFunctionType = "Leky ReLU"
+            leakiness = 0.2 # TODO. Introduce this value in the config.ini
+            output_Train = applyActivationFunction_LeakyReLU(inputToNonLinearityTrain,leakiness)
+            output_Test = applyActivationFunction_LeakyReLU(inputToNonLinearityTest,leakiness)
+            return (output_Train, output_Test)
+                
+        optionsActFunction = {0 : Linear,
+                              1 : ReLU,
+                              2 : PReLU,
+                              3 : LeakyReLU}
+
+        (inputToDropout_Train, inputToDropout_Test) = optionsActFunction[activationType]()
+            
+        # ________________________________________________________
+        #      3 :  Apply Dropout
+        # ________________________________________________________
+        output_Train = apply_Dropout(rndState,dropoutRate,inputSampleShape_Train,inputToDropout_Train, 0)
+        output_Test  = apply_Dropout(rndState,dropoutRate,inputSampleShape_Train,inputToDropout_Test, 1)
+          
+        # ________________________________________________________
+        #      This will go as input to the convolutions
+        # ________________________________________________________   
+
+        return (output_Train, output_Test)
+        
+