Search code examples
cluaneural-networkluajittorch

How to read Torch Tensor from C


I have to train a convolutional neural network using the Torch framework and then write the same network in C. To do so, I have to read somehow the learned parameters of the net from my C program, but I can't find a way to convert or write to a file the Torch Tensors to make them readable in C. Ideally, I want to convert the Tensors into arrays of double in C.

Does anyone know how to do that? Thanks in advance :)


Solution

  • I can't find a way to convert or write to a file the Torch Tensors to make them readable in C. Ideally, I want to convert the Tensors into arrays of double in C.

    The most basic (and direct) way is to directly fread in C the data you have previously written into a binary file. In such a case you would typically concatenate the weights and biases (if any) for each layer.

    On the Lua/Torch side you can use the File utilities to literally fwrite each tensor data. For example here is a basic function that does that:

    local fwrite = function(tensor, file)
      if not tensor then return false end
      local n = tensor:nElement()
      local s = tensor:storage()
      return assert(file:writeDouble(s) == n)
    end
    

    For example if m refers to a torch/nn module containing weights you would use it as follow:

    local file = torch.DiskFile("net.bin", "w"):binary()
    fwrite(m.weight, file)
    fwrite(m.bias, file)
    

    Of course you need to write your own logic to make sure you fwrite and concatenate all the weights from all your layers. On the C side, in addition to net.bin, you also need to know the structure of your network (nb. layers, parameters like kernel size, etc) to know how many block of double-s to fread.

    As an example (in Lua) you can have a look at overfeat-torch (non official project) that illustrates how to read such a plain binary file: see the ParamBank tool.

    Keep in mind that a robust solution would consist in using a proper binary serialization format like msgpack or Protocol Buffers that would make this export/import process clean and portable.

    --

    Here is a toy example:

    -- EXPORT
    require 'nn'
    
    local fwrite = function(tensor, file)
      if not tensor then return false end
      local n = tensor:nElement()
      local s = tensor:storage()
      return assert(file:writeDouble(s) == n)
    end
    
    local m = nn.Linear(2, 2)
    
    print(m.weight)
    print(m.bias)
    
    local file = torch.DiskFile("net.bin", "w"):binary()
    fwrite(m.weight, file)
    fwrite(m.bias, file)
    

    Then in C:

    /* IMPORT */
    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    
    int
    main(void)
    {
      const int N = 2; /* nb. neurons */
    
      double *w = malloc(N*N*sizeof(*w)); /* weights */
      double *b = malloc(N*sizeof(*w));   /* biases */
    
      FILE *f = fopen("net.bin", "rb");
      assert(fread(w, sizeof(*w), N*N, f) == N*N);
      assert(fread(b, sizeof(*w), N, f) == N);
      fclose(f);
    
      int i, j;
      for (i = 0; i < N; i++)
        for (j = 0; j < N; j++)
          printf("w[%d,%d] = %f\n", i, j, w[N*i+j]);
    
      for (i = 0; i < N; i++)
          printf("b[%d] = %f\n", i, b[i]);
    
      free(w);
      free(b);
    
      return 0;
    }