Cosmetics.
authorFrancois Fleuret <francois@fleuret.org>
Tue, 22 Nov 2016 09:33:42 +0000 (10:33 +0100)
committerFrancois Fleuret <francois@fleuret.org>
Tue, 22 Nov 2016 09:33:42 +0000 (10:33 +0100)
Makefile
dyncnn.lua
flatland.cc
run.sh

index 304f403..974c08c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -25,8 +25,6 @@ else
  CXXFLAGS = -fPIC -Wall -g -O3
 endif
 
-LDFLAGS = -lz -ldl
-
 CXXFLAGS += -I/usr/include/cairo -DCAIRO_SUPPORT
 
 LDFLAGS += -lcairo
@@ -40,7 +38,7 @@ flatland:     flatland.o misc.o \
        universe.o \
        polygon.o \
        canvas.o canvas_cairo.o
-       $(CXX) $(CXXFLAGS) $(LDFLAGS) -lX11 -o $@ $^
+       $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $^
 
 Makefile.depend: *.h *.cc Makefile
        $(CC) $(CXXFLAGS) -M *.cc > Makefile.depend
index 5362593..c050344 100755 (executable)
@@ -28,7 +28,6 @@ require 'torch'
 require 'nn'
 require 'optim'
 require 'image'
-require 'pl'
 
 require 'img'
 
@@ -41,7 +40,7 @@ end
 colors = sys.COLORS
 
 function printfc(c, f, ...)
-   printf(c .. string.format(f, unpack({...})) .. colors.black)
+   print(c .. string.format(f, unpack({...})) .. colors.black)
 end
 
 function logCommand(c)
@@ -49,7 +48,7 @@ function logCommand(c)
 end
 
 ----------------------------------------------------------------------
--- Environment and command line arguments
+-- Environment variables
 
 local defaultNbThreads = 1
 local defaultUseGPU = false
@@ -58,21 +57,21 @@ if os.getenv('TORCH_NB_THREADS') then
    defaultNbThreads = os.getenv('TORCH_NB_THREADS')
    print('Environment variable TORCH_NB_THREADS is set and equal to ' .. defaultNbThreads)
 else
-   print('Environment variable TORCH_NB_THREADS is not set')
+   print('Environment variable TORCH_NB_THREADS is not set, default is ' .. defaultNbThreads)
 end
 
 if os.getenv('TORCH_USE_GPU') then
    defaultUseGPU = os.getenv('TORCH_USE_GPU') == 'yes'
    print('Environment variable TORCH_USE_GPU is set and evaluated as ' .. tostring(defaultUseGPU))
 else
-   print('Environment variable TORCH_USE_GPU is not set.')
+   print('Environment variable TORCH_USE_GPU is not set, default is ' .. tostring(defaultUseGPU))
 end
 
 ----------------------------------------------------------------------
+-- Command line arguments
 
 local cmd = torch.CmdLine()
 
-cmd:text('')
 cmd:text('General setup')
 
 cmd:option('-seed', 1, 'initial random seed')
@@ -83,17 +82,24 @@ cmd:text('')
 cmd:text('Log')
 
 cmd:option('-resultFreq', 100, 'at which epoch frequency should we save result images')
-cmd:option('-exampleInternals', -1, 'should we save inner activation images')
+cmd:option('-exampleInternals', '', 'list of comma-separated indices for inner activation images')
 cmd:option('-noLog', false, 'should we prevent logging')
 cmd:option('-rundir', '', 'the directory for results')
+cmd:option('-deltaImages', false, 'should we highlight the difference in result images')
+
+cmd:text('')
+cmd:text('Network structure')
+
+cmd:option('-filterSize', 5)
+cmd:option('-nbChannels', 16)
+cmd:option('-nbBlocks', 8)
 
 cmd:text('')
 cmd:text('Training')
 
-cmd:option('-nbEpochs', 1000, 'nb of epochs for the heavy setting')
+cmd:option('-nbEpochs', 2000, 'nb of epochs for the heavy setting')
 cmd:option('-learningRate', 0.1, 'learning rate')
 cmd:option('-batchSize', 128, 'size of the mini-batches')
-cmd:option('-filterSize', 5, 'convolution filter size')
 cmd:option('-nbTrainSamples', 32768)
 cmd:option('-nbValidationSamples', 1024)
 cmd:option('-nbTestSamples', 1024)
@@ -103,12 +109,6 @@ cmd:text('Problem to solve')
 
 cmd:option('-dataDir', './data/10p-mg', 'data directory')
 
-cmd:text('')
-cmd:text('Network structure')
-
-cmd:option('-nbChannels', 16)
-cmd:option('-nbBlocks', 8)
-
 ------------------------------
 -- Log and stuff
 
@@ -260,6 +260,16 @@ end
 
 ----------------------------------------------------------------------
 
+function highlightImage(a, b)
+   if params.deltaImages then
+      local h = torch.csub(a, b):abs()
+      h:div(1/h:max()):mul(0.9):add(0.1)
+      return torch.cmul(a, h)
+   else
+      return a
+   end
+end
+
 function saveResultImage(model, data, nbMax)
    local criterion = nn.MSECriterion()
 
@@ -294,40 +304,26 @@ function saveResultImage(model, data, nbMax)
 
       -- We use our magical img.lua to create the result images
 
-      local comp = {
-         {
-            { pad = 1, data.input[n][1] },
-            { pad = 1, data.input[n][2] },
-            { pad = 1, data.target[n][1] },
-            { pad = 1, output[1][1] },
-         }
-      }
+      local comp
 
-      --[[
-      local comp = {
+      comp = {
          {
             vertical = true,
             { pad = 1, data.input[n][1] },
-            { pad = 1, data.input[n][2] }
-         },
-         torch.Tensor(4, 4):fill(1.0),
-         {
-            vertical = true,
-            { pad = 1, data.target[n][1] },
-            { pad = 1, output[1][1] },
-            { pad = 1, torch.csub(data.target[n][1], output[1][1]):abs() }
+            { pad = 1, data.input[n][2] },
+            { pad = 1, highlightImage(data.target[n][1], data.input[n][1]) },
+            { pad = 1, highlightImage(output[1][1], data.input[n][1]) },
          }
       }
-      ]]--
 
-local result = combineImages(1.0, comp)
+      local result = combineImages(1.0, comp)
 
-result:mul(-1.0):add(1.0)
+      result:mul(-1.0):add(1.0)
 
-local fileName = string.format('result_%s_%06d.png', data.name, n)
-image.save(params.rundir .. '/' .. fileName, result)
-lossFile:write(string.format('%f %s\n', loss, fileName))
-end
+      local fileName = string.format('result_%s_%06d.png', data.name, n)
+      image.save(params.rundir .. '/' .. fileName, result)
+      lossFile:write(string.format('%f %s\n', loss, fileName))
+   end
 end
 
 ----------------------------------------------------------------------
@@ -434,14 +430,14 @@ function fillBatch(data, first, batch, permutation)
    end
 end
 
-function trainModel(model, trainData, validationData)
+function trainModel(model, trainSet, validationSet)
 
    local criterion = nn.MSECriterion()
    local batchSize = params.batchSize
 
    local batch = {}
-   batch.input = mynn.FastTensor(batchSize, 2, trainData.height, trainData.width)
-   batch.target = mynn.FastTensor(batchSize, 1, trainData.height, trainData.width)
+   batch.input = mynn.FastTensor(batchSize, 2, trainSet.height, trainSet.width)
+   batch.target = mynn.FastTensor(batchSize, 1, trainSet.height, trainSet.width)
 
    local startingEpoch = 1
 
@@ -450,6 +446,7 @@ function trainModel(model, trainData, validationData)
    end
 
    if model.RNGState then
+      printfc(colors.red, 'Using the RNG state from the loaded model.')
       torch.setRNGState(model.RNGState)
    end
 
@@ -479,15 +476,15 @@ function trainModel(model, trainData, validationData)
 
       model:training()
 
-      local permutation = torch.randperm(trainData.nbSamples)
+      local permutation = torch.randperm(trainSet.nbSamples)
 
       local accLoss = 0.0
       local nbBatches = 0
       local startTime = sys.clock()
 
-      for b = 1, trainData.nbSamples, batchSize do
+      for b = 1, trainSet.nbSamples, batchSize do
 
-         fillBatch(trainData, b, batch, permutation)
+         fillBatch(trainSet, b, batch, permutation)
 
          local opfunc = function(x)
             -- Surprisingly, copy() needs this check
@@ -526,8 +523,8 @@ function trainModel(model, trainData, validationData)
          local nbBatches = 0
          local startTime = sys.clock()
 
-         for b = 1, validationData.nbSamples, batchSize do
-            fillBatch(validationData, b, batch)
+         for b = 1, validationSet.nbSamples, batchSize do
+            fillBatch(validationSet, b, batch)
             local output = model:forward(batch.input)
             accLoss = accLoss + criterion:forward(output, batch.target)
             nbBatches = nbBatches + 1
@@ -537,13 +534,24 @@ function trainModel(model, trainData, validationData)
          averageValidationLoss = accLoss / nbBatches;
       end
 
-      printf('Epoch train %0.2fs (%0.2fms / sample), validation %0.2fs (%0.2fms / sample).',
-             trainTime,
-             1000 * trainTime / trainData.nbSamples,
-             validationTime,
-             1000 * validationTime / validationData.nbSamples)
+      ----------------------------------------------------------------------
+
+      printfc(colors.green,
+
+              'epoch %d acc_train_loss %f validation_loss %f [train %.02fs total %.02fms / sample, validation %.02fs total %.02fms / sample]',
+
+              e,
 
-      printfc(colors.green, 'LOSS %d %f %f', e, averageTrainLoss, averageValidationLoss)
+              averageTrainLoss,
+
+              averageValidationLoss,
+
+              trainTime,
+              1000 * trainTime / trainSet.nbSamples,
+
+              validationTime,
+              1000 * validationTime / validationSet.nbSamples
+      )
 
       ----------------------------------------------------------------------
       -- Save a persistent state so that we can restart from there
@@ -558,15 +566,15 @@ function trainModel(model, trainData, validationData)
 
       if params.resultFreq > 0 and e%params.resultFreq == 0 then
          torch.save(string.format('%s/model_%04d.t7', params.rundir, e), model)
-         saveResultImage(model, trainData)
-         saveResultImage(model, validationData)
+         saveResultImage(model, trainSet)
+         saveResultImage(model, validationSet)
       end
 
    end
 
 end
 
-function createAndTrainModel(trainData, validationData)
+function createAndTrainModel(trainSet, validationSet)
 
    -- Load the current training state, or create a new model from
    -- scratch
@@ -574,23 +582,25 @@ function createAndTrainModel(trainData, validationData)
    if pcall(function () model = torch.load(params.rundir .. '/model_last.t7') end) then
 
       printfc(colors.red,
-              'Found a learning state with %d epochs finished, starting from there.',
+              'Found a model with %d epochs completed, starting from there.',
               model.epoch)
 
-      if params.exampleInternals > 0 then
-         saveInternalsImage(model, validationData, params.exampleInternals)
+      if params.exampleInternals ~= '' then
+         for _, i in ipairs(string.split(params.exampleInternals, ',')) do
+            saveInternalsImage(model, validationSet, tonumber(i))
+         end
          os.exit(0)
       end
 
    else
 
-      model = createModel(trainData.width, trainData.height,
+      model = createModel(trainSet.width, trainSet.height,
                           params.filterSize, params.nbChannels,
                           params.nbBlocks)
 
    end
 
-   trainModel(model, trainData, validationData)
+   trainModel(model, trainSet, validationSet)
 
    return model
 
@@ -608,25 +618,25 @@ do
    logCommand(c)
 end
 
-local trainData = loadData(1,
-                           params.nbTrainSamples, 'train')
+local trainSet = loadData(1,
+                          params.nbTrainSamples, 'train')
 
-local validationData = loadData(params.nbTrainSamples + 1,
-                                params.nbValidationSamples, 'validation')
+local validationSet = loadData(params.nbTrainSamples + 1,
+                               params.nbValidationSamples, 'validation')
 
-local model = createAndTrainModel(trainData, validationData)
+local model = createAndTrainModel(trainSet, validationSet)
 
 ----------------------------------------------------------------------
 -- Test
 
-local testData = loadData(params.nbTrainSamples + params.nbValidationSamples + 1,
-                          params.nbTestSamples, 'test')
+local testSet = loadData(params.nbTrainSamples + params.nbValidationSamples + 1,
+                         params.nbTestSamples, 'test')
 
 if params.useGPU then
    print('Moving the model and criterion to the GPU.')
    model:cuda()
 end
 
-saveResultImage(model, trainData)
-saveResultImage(model, validationData)
-saveResultImage(model, testData, 1024)
+saveResultImage(model, trainSet)
+saveResultImage(model, validationSet)
+saveResultImage(model, testSet, 1024)
index 3a59e88..75e9862 100644 (file)
@@ -82,7 +82,6 @@ int main(int argc, char **argv) {
   const scalar_t world_width = 400;
   const scalar_t world_height = 400;
   const scalar_t scaling = 0.16; // So that 400 * 0.16 = 64
-  const scalar_t shape_size = 80;
 
   const scalar_t dt = 0.1;
   const int nb_iterations_per_steps = 5;
@@ -96,7 +95,8 @@ int main(int argc, char **argv) {
 
   int every_nth = 4;
   int nb_frames = 5;
-  int multi_grasp = 0;
+  int random_grasp = 0;
+  int random_shape_size = 0;
   int nb_shapes = 1;
   char data_dir[1024] = "/tmp/";
   int multi_images = 0;
@@ -134,8 +134,13 @@ int main(int argc, char **argv) {
       i++;
     }
 
-    else if(strcmp(argv[i], "--multi_grasp") == 0) {
-      multi_grasp = 1;
+    else if(strcmp(argv[i], "--random_grasp") == 0) {
+      random_grasp = 1;
+      i++;
+    }
+
+    else if(strcmp(argv[i], "--random_shape_size") == 0) {
+      random_shape_size = 1;
       i++;
     }
 
@@ -203,7 +208,7 @@ int main(int argc, char **argv) {
 
     scalar_t grab_start_x, grab_start_y;
 
-    if(multi_grasp) {
+    if(random_grasp) {
       grab_start_x = world_width * (0.1 + 0.8 * drand48());
       grab_start_y = world_height * (0.1 + 0.8 * drand48());
     } else {
@@ -229,6 +234,14 @@ int main(int argc, char **argv) {
 
         nb_attempts = 0;
 
+        scalar_t shape_size;
+
+        if(random_shape_size) {
+          shape_size = 40 + 80 * drand48();
+        } else {
+          shape_size = 80;
+        }
+
         do {
           scalar_t x[] = { - shape_size * 0.4, + shape_size * 0.4,
                            + shape_size * 0.4, - shape_size * 0.4 };
diff --git a/run.sh b/run.sh
index fe041f2..7ccfbb6 100755 (executable)
--- a/run.sh
+++ b/run.sh
@@ -27,55 +27,32 @@ set -o pipefail
 
 [[ "${TORCH_NB_THREADS}" ]] || echo "You can set \$TORCH_NB_THREADS to the proper value (default 1)."
 [[ "${TORCH_USE_GPU}" ]] || echo "You can set \$TORCH_USE_GPU to 'yes' or 'no' (default 'no')."
-[[ "${DYNCNN_DATA_DIR}" ]] || DYNCNN_DATA_DIR="./data/10p-mg"
 
+[[ "${DYNCNN_DATA_DIR}" ]] || DYNCNN_DATA_DIR="./data/10p-mg"
 [[ "${DYNCNN_RUNDIR}" ]] || DYNCNN_RUNDIR="./results"
 
-######################################################################
-# Create the data-set if the directory does not exist
-
 if [[ ! -d "${DYNCNN_DATA_DIR}" ]]; then
-    cat <<EOF
-***************************************************************************
-                          Generate the data-set
-***************************************************************************
-EOF
-
+    # Creating the data-base
     make -j -k
     mkdir -p "${DYNCNN_DATA_DIR}"
-    # 17 frames every 16 is two frames: t+0, t+16
+    # 17 frames every 16 is two frames: t+0 and t+16
     ./flatland 40000 \
                --nb_shapes 10 \
-               --multi_grasp --every_nth 16 --nb_frames 17 \
+               --random_grasp --every_nth 16 --nb_frames 17 \
                --dir "${DYNCNN_DATA_DIR}"
 fi
 
-######################################################################
-# Train the model (takes 15h on a GTX 1080 with cuda 8.0, cudnn 5.1,
+# Train the model (takes 30h on a GTX 1080 with cuda 8.0, cudnn 5.1,
 # and recent torch)
 
-if [[ ! -f "${DYNCNN_RUNDIR}"/model_1000.t7 ]]; then
-    cat <<EOF
-***************************************************************************
-                  Train the model (should take a while)
-***************************************************************************
-EOF
+if [[ ! -f "${DYNCNN_RUNDIR}"/scheme_02000.t7 ]]; then
     ./dyncnn.lua -rundir "${DYNCNN_RUNDIR}"
 fi
 
-######################################################################
 # Create the images of internal activations using the current.t7 in
 # the rundir
 
-cat <<EOF
-***************************************************************************
-                   Save the internal activation images
-***************************************************************************
-EOF
-
-for n in 2 12; do
-    ./dyncnn.lua -rundir "${DYNCNN_RUNDIR}" -noLog -exampleInternals "${n}"
-done
+./dyncnn.lua -rundir "${DYNCNN_RUNDIR}" -noLog -exampleInternals 3,7
 
 ######################################################################
 # Plot the loss curves if gnuplot is here