Как читать Torch Tensor из C

Мне нужно обучить сверточную нейронную сеть, используя структуру Torch, а затем написать ту же сеть на C. Для этого мне нужно каким-то образом прочитать изученные параметры сети из моей программы на C, но я не могу найти способ преобразовать или записать в файл тензоры Torch, чтобы сделать их читаемыми в C. В идеале я хочу преобразовать тензоры в массивы double в C.

Кто-нибудь знает как это сделать? Заранее спасибо :)


person Andre    schedule 05.05.2015    source источник


Ответы (1)


Я не могу найти способ преобразовать или записать в файл тензоры Torch, чтобы сделать их читаемыми в C. В идеале я хочу преобразовать тензоры в массивы double в C.

Самый простой (и прямой) способ - это напрямую fread на C данные, которые вы ранее записали в двоичный файл. В таком случае вы обычно объединяете веса и смещения (если есть) для каждого слоя.

На стороне Lua / Torch вы можете использовать утилиты File для буквально fwrite данные каждого тензора. Например, вот основная функция, которая это делает:

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

Например, если m относится к модулю torch/nn, содержащему веса, вы должны использовать его следующим образом:

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

Конечно, вам нужно написать свою собственную логику, чтобы убедиться, что вы fwrite и объедините все веса со всех ваших слоев. На стороне C, помимо net.bin, вам также необходимо знать структуру вашей сети (количество уровней, такие параметры, как размер ядра и т. Д.), Чтобы знать, сколько блоков от double-s до fread.

В качестве примера (в Lua) вы можете взглянуть на overfeat-torch (неофициальный проект) это иллюстрирует, как читать такой простой двоичный файл: см. Инструмент ParamBank.

Имейте в виду, что надежное решение будет заключаться в использовании правильного формата двоичной сериализации, такого как msgpack или Protocol Buffers, которые сделают этот процесс экспорта / импорта чистым и переносимым.

--

Вот игрушечный пример:

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

Затем в 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;
}
person deltheil    schedule 05.05.2015
comment
Спасибо за ваш ответ! Я уже пытался записать в файл из Lua, а затем прочитать из C, используя fread, как вы предложили, но я получил только мусор! Я попробовал сегодня снова с поплавками вместо двойников, и это работает: D Еще раз спасибо! - person Andre; 06.05.2015
comment
Просто добавил игрушечный пример, чтобы проиллюстрировать процесс. - person deltheil; 06.05.2015