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