How to read Torch Tensor from C [closed]

2019-05-29 11:55发布

问题:

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 :)

回答1:

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;
}