Вычислить сверточный слой в реализации CNN
Я пытаюсь обучить Сверточную нейронную сеть, используя Sparse autoenconders, чтобы вычислить фильтры для слоя свертки. Я использую код UFLDL для создания патчей и обучения сети CNN. Мой код следующий:
===========================================================================
imageDim = 30; % image dimension
imageChannels = 3; % number of channels (rgb, so 3)
patchDim = 10; % patch dimension
numPatches = 100000; % number of patches
visibleSize = patchDim * patchDim * imageChannels; % number of input units
outputSize = visibleSize; % number of output units
hiddenSize = 400; % number of hidden units
epsilon = 0.1; % epsilon for ZCA whitening
poolDim = 10; % dimension of pooling region
optTheta = zeros(2*hiddenSize*visibleSize+hiddenSize+visibleSize, 1);
ZCAWhite = zeros(visibleSize, visibleSize);
meanPatch = zeros(visibleSize, 1);
load patches_16_1
===========================================================================
% Display and check to see that the features look good
W = reshape(optTheta(1:visibleSize * hiddenSize), hiddenSize, visibleSize);
b = optTheta(2*hiddenSize*visibleSize+1:2*hiddenSize*visibleSize+hiddenSize);
displayColorNetwork( (W*ZCAWhite));
stepSize = 100;
assert(mod(hiddenSize, stepSize) == 0, stepSize should divide hiddenSize);
load train.mat % loads numTrainImages, trainImages, trainLabels
load train.mat % loads numTestImages, testImages, testLabels
% size 30x30x3x8862
numTestImages = 8862;
numTrainImages = 8862;
pooledFeaturesTrain = zeros(hiddenSize, numTrainImages, floor((imageDim - patchDim + 1) / poolDim), floor((imageDim - patchDim + 1) / poolDim) );
pooledFeaturesTest = zeros(hiddenSize, numTestImages, ...
floor((imageDim - patchDim + 1) / poolDim), ...
floor((imageDim - patchDim + 1) / poolDim) );
tic();
testImages = trainImages;
for convPart = 1:(hiddenSize / stepSize)
featureStart = (convPart - 1) * stepSize + 1;
featureEnd = convPart * stepSize;
fprintf('Step %d: features %d to %d\n', convPart, featureStart, featureEnd);
Wt = W(featureStart:featureEnd, :);
bt = b(featureStart:featureEnd);
fprintf('Convolving and pooling train images\n');
convolvedFeaturesThis = cnnConvolve(patchDim, stepSize, ...
trainImages, Wt, bt, ZCAWhite, meanPatch);
pooledFeaturesThis = cnnPool(poolDim, convolvedFeaturesThis);
pooledFeaturesTrain(featureStart:featureEnd, :, :, :) = pooledFeaturesThis;
toc();
clear convolvedFeaturesThis pooledFeaturesThis;
fprintf('Convolving and pooling test images\n');
convolvedFeaturesThis = cnnConvolve(patchDim, stepSize, ...
testImages, Wt, bt, ZCAWhite, meanPatch);
pooledFeaturesThis = cnnPool(poolDim, convolvedFeaturesThis);
pooledFeaturesTest(featureStart:featureEnd, :, :, :) = pooledFeaturesThis;
toc();
clear convolvedFeaturesThis pooledFeaturesThis;
end
У меня проблемы с вычислением уровней свертки и объединения. Я получаю pooledFeaturesTrain (featureStart: featureEnd,:,:,:) = pooledFeaturesThis; несоразмерность размеров подзапросов. Обычно траектории вычисляются так:
![enter image description here]()
Я пытаюсь понять, что именно делает переменная convPart и какие объединенныеFeaturesThis. Во-вторых, я замечаю, что моя проблема - несоответствие в этой строке pooledFeaturesTrain(featureStart:featureEnd, :, :, :) = pooledFeaturesThis;
где я получил сообщение о том, что переменные несовместимы. Размер объединенных элементов. Это 100x3x2x2, где размер объединенного элементаFeaturesTrain равен 400x8862x2x2. Что именно представляет собой объединение? Результат 2x2 для каждого фильтра? CnnConvolve можно найти здесь:
EDIT: Я немного изменил свой код, и он работает. Однако я немного обеспокоен пониманием кода.
Ответы
Ответ 1
Итак, в этой строке вы устанавливаете область объединения.
poolDim = 10; % dimension of pooling region
Эта часть означает, что для каждого ядра в каждом слое вы берете изображение и пул, а площадь - 10x10 пикселей. Из вашего кода это похоже на то, что вы применяете среднюю функцию, а это значит, что это патч и вычисляет среднее значение и выводит его на следующий уровень... aka, принимает изображение от 100x100 до 10x10. В вашей сети вы повторяете свертку + объединение до тех пор, пока не получите изображение 2x2, основанное на этом выходе (кстати, это не является хорошей практикой в моем опыте).
400x8862x2x2
В любом случае вернитесь к своему коду. Обратите внимание, что в начале вашего обучения вы выполните следующую инициализацию:
pooledFeaturesTrain = zeros(hiddenSize, numTrainImages, floor((imageDim - patchDim + 1) / poolDim), floor((imageDim - patchDim + 1) / poolDim) );
Итак, ваша ошибка довольно проста и правильная - размер матрицы, которая содержит вывод свертки + пула, не является размером инициализированной матрицы.
Вопрос в том, как это исправить. Я предположил, что ленивый способ исправить это - вывести инициализацию. Это резко снизит ваш код и не будет гарантированно работать, если у вас более 1 слоя.
Я предлагаю вам вместо этого pooledFeaturesTrain быть структурой 3-мерного массива. Поэтому вместо этого
pooledFeaturesTrain(featureStart:featureEnd, :, :, :) = pooledFeaturesThis;
вы делаете что-то большее в соответствии с этим:
pooledFeaturesTrain{n}(:, :, :) = pooledFeaturesThis;
где n - текущий слой.
Сети CNN не так просты, как они взломаны, и даже когда они не справляются с ситуацией, чтобы заставить их хорошо тренироваться, это подвиг. Я настоятельно рекомендую прочитать теорию CNN - это значительно упростит кодирование и отладку.
Удачи вам!:)