Вычислить сверточный слой в реализации 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 - это значительно упростит кодирование и отладку.

Удачи вам!:)