You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ImageRecognition/dim_activation_conv_recurre...

177 lines
6.3 KiB
Matlab

function [Y,E,R]=dim_activation_conv_recurrent(w,X,v,Y,iterations,trueRange)
% w = a cell array of size {N,M}, where N is the number of distinct neuron types
% and M is the number of input channels. Each element {i,j} of the cell
% array is a 2-dimensional matrix (a convolution mask) specifying the
% synaptic weights for neuron type i's RF in input channel j.
% X = a cell array of size {M}. Each element {j} of the cell array is a
% 2-dimensional matrix specifying the bottom-up input to that channel j of
% the current processing stage (external inputs targetting the error
% nodes). If inputs arrive from more than one source, then each source
% provides a different cell in the array. Input values that change over
% time can be presented using a 3-d matrix, where the 3rd dimension is time.
% w = synaptic weights, defined as for w, but strength normalised differently.
% Y = a cell array of size {N}. Each element {i} of the cell array is a
% 2-dimensional matrix specifying prediction node activations for type i
% neurons.
% R = a cell array of size {M}. Each element {j} of the cell array is a
% 2-dimensional matrix specifying the reconstruction of the input channel j.
% These values are also the top-down feedback that should modulate
% activity in preceeding processing stages of a hierarchy.
% E = a cell array of size {M}. Each element {j} of the cell array is a
% 2-dimensional matrix specifying the error in the reconstruction of the
% input channel j.
% iterations = the number of iterations of the DIM algorithm to perform. Default
% is 50.
% trueRange = range of Y, E, and R to keep at the end of processing. Used to try
% to avoid edge effects by having input (X) larger than original image, and
% then cropping edges of outputs, so that outputs are resized to be same
% size as the original image.
[a,b,z]=size(X{1});
[nMasks,nChannels]=size(w);
nInputChannels=length(X);
if nargin<3 || isempty(v)
%set feedback weights equal to feedforward weights normalized by maximum value
for i=1:nMasks
%calc normalisation values by taking into account all weights contributing to
%each RF type
maxVal=0;
for j=1:nChannels
if ~isempty(w{i,j})
maxVal=max(maxVal,max(max(max(0,w{i,j}))));
end
end
%apply normalisation to calculate feedback weight values
for j=1:nChannels
v{i,j}=max(0,w{i,j})./max(1e-6,maxVal);
end
end
end
if nargin<4 || isempty(Y)
%initialise prediction neuron outputs to zero
for i=1:nMasks
Y{i}=zeros(a,b,'single');
end
end
[c,d]=size(w{1,1});
sumV=zeros(1,nInputChannels,'single');
for i=1:nMasks
for j=1:nChannels
%masks should be an odd size, so that reconstruction isn't shifted with respect
%to the original image
w{i,j}=pad_to_make_odd(w{i,j});
v{i,j}=pad_to_make_odd(v{i,j});
%try to speed things up by removing symmetrical rows/columns of zeros from the
%edges of the weight masks
w{i,j}=trimarray_symmetrically(w{i,j});
v{i,j}=trimarray_symmetrically(v{i,j});
%rotate feedforward weights so that convolution can be used to apply the
%filtering (otherwise the mask gets rotated every iteration!)
w{i,j}=rot90(w{i,j},2);
c=max(c,size(w{i,j},1));
d=max(d,size(w{i,j},2));
end
for j=1:nInputChannels
sumV(j)=sumV(j)+sum(v{i,j}(:));
end
end
%try to speed things up further
if exist('convnfft')==2 && min(c,d)>50 && min(a,b)>50
conv_fft=1;%use fft version of convolution for large images and masks. see:
%www.mathworks.com/matlabcentral/fileexchange/24504-fft-based-convolution
else
conv_fft=0;%use standard MATLAB conv2 function for smaller images and masks,
%or if faster function is not installed
end
%set parameters
epsilon2=1e-2;
epsilon1=epsilon2./max(sumV);
if nargin<5 || isempty(iterations), iterations=50; end
%iterate DIM equations to determine neural responses
fprintf(1,'dim_conv(%i): ',conv_fft);
ediff=Inf; ymax=0; for j=1:nChannels, Eprev{j}=0; end
%t=0; while t<iterations && (ediff>0.1 || ymax<0.1), t=t+1;
for t=1:iterations
fprintf(1,'.%i.',t);
%copy previous output values to inputs, to provide recurrent input
%for i=1:nMasks
% X{nInputChannels+i}=Y{i};
%end
%update error-detecting neuron responses
ediff=0;
for j=1:nChannels
if (isempty(X{j}) || iszero(X{j})) && t<iterations
%speed things up by ignoring empty inputs: however, calculate R{j} on the last
%iteration, incase it needs to be returned
E{j}=X{j};
else
%calc predictive reconstruction of the input
R{j}=single(0);%reset reconstruction of input
for i=1:nMasks
%sum reconstruction over each RF type
if ~(isempty(v{i,j}) || iszero(v{i,j}) || isempty(Y{i}) || iszero(Y{i})) %skip empty filters and response arrays: they don't add anything
if conv_fft==1
R{j}=R{j}+convnfft(Y{i},v{i,j},'same');
else
R{j}=R{j}+conv2(Y{i},v{i,j},'same');
end
end
end
R{j}(R{j}<0)=0;
%calc error between reconstruction and actual input: using values of input
%that change over time (if these are provided)
%E{j}=X{j}(:,:,min(t,size(X{j},3)))./(epsilon2+R{j});
E{j}=X{j}(:,:,min(t,size(X{j},3)))./max(epsilon2,R{j});
end
ediff=max(ediff,max(max(abs(E{j}-Eprev{j}))));
Eprev{j}=E{j};
end
%update prediction neuron responses
ymax=0;
for i=1:nMasks
input=single(0);
for j=1:nChannels
%sum inputs to prediction neurons from each channel
if ~(isempty(w{i,j}) || iszero(w{i,j}) || isempty(E{j}) || iszero(E{j})) %skip empty filters and error arrays: they don't add anything
if conv_fft==1
input=input+convnfft(E{j},w{i,j},'same');
else
input=input+conv2(E{j},w{i,j},'same');
end
end
end
%modulate prediction neuron response by current input:
%Y{i}=(epsilon1(i)+Y{i}).*input;
Y{i}=max(epsilon1,Y{i}).*input;
Y{i}(Y{i}<0)=0;
ymax=max(ymax,max(max(Y{i})));
end
end
disp(' ')
fprintf(1,'dim_conv(%i) complete: t=%i, ediff=%f, ymax=%f\n',conv_fft,t,ediff,ymax)
if nargin>=6 && ~isempty(trueRange)
if nargout>1
for j=1:nChannels
R{j}=R{j}(trueRange{1},trueRange{2});
E{j}=E{j}(trueRange{1},trueRange{2});
end
end
for i=1:nMasks
Y{i}=Y{i}(trueRange{1},trueRange{2});
end
end