Ограничение памяти при извлечении VLAD из SIFT-дескрипторов в VLFeat с Matlab
Я недавно спросил, как извлечь VLAD из SIFT дескрипторов в VLFeat с Matlab здесь.
Однако я сталкиваюсь с ограничениями памяти. У меня 64 ГБ оперативной памяти и 64 ГБ подкачки.
all_descr = single([sift_descr{:}]);
... выдает ошибку памяти:
Запрошенный массив 128x258438583 (123,2 ГБ) превышает максимальный размер предпочтительного размера. Создание массивов, превышающих этот предел, может занять много времени и привести к тому, что MATLAB перестанет отвечать на запросы. См. Ограничение размера массива или панель настроек для получения дополнительной информации.
Как правильно извлечь VLAD, когда у нас очень большой тренировочный набор данных? Например, я мог бы установить подмножество SIFT дескрипторов перед запуском vl_kmeans
, как это:
all_descr = single([sift_descr{1:100000}]);
Это работает в памяти, но как это повлияет на мои функции VLAD? Спасибо.
1 ответ
Основная проблема здесь не в том, как извлечь VLAD для такой матрицы: вы вычисляете вектор VLAD для каждого изображения, зацикливаясь на всех изображениях и вычисляя VLAD один за другим, то есть проблема с памятью там не возникает.,
Вам не хватает памяти, когда вы пытаетесь объединить SIFT дескрипторы всех изображений, чтобы сгруппировать их в визуальные слова, используя поиск ближайшего соседа:
all_descr = single([sift_descr{:}]);
centroids = vl_kmeans(all_descr, 64);
Самый простой способ, который я могу придумать, - это переключиться на собственный MATLAB. kmeans
функция, которая входит в набор инструментов статистики и машинного обучения. Он поставляется с поддержкой Tall Arrays, то есть типа данных MATLAB для массивов, которые не помещаются в память.
Для этого вы можете сохранить дескрипторы SIFT каждого изображения в CSV-файл, используя csvwrite
:
for k = 1:size(filelist, 1)
I = imread([repo filelist(k).name]) ;
I = single(rgb2gray(I)) ;
[f,d] = vl_sift(I) ;
csvwrite(sprintf('sift/im_%d.csv', k), single(d.'));
end
Затем вы можете загрузить дескрипторы как высокий массив, используя datastore
функция и преобразование его в tall
, В результате будет table
, ты можешь использовать table2array
преобразовать его в высокий массив.
ds = datastore('sift/*.csv');
all_descriptors = table2array(tall(ds));
Наконец, вы можете позвонить kmeans
работать на этом, и получить ваши центроиды
[~, centroids] = kmeans(all_descriptors, 64);
Теперь вы можете продолжить вычисление вектора VLAD как обычно.