https://github.com/Klimmasch/AEC
Tip revision: 96e9ae2336937469a8f1602c178ea5e0cb8564b6 authored by Lukas Klimmasch on 13 August 2021, 14:16:04 UTC
Merge branch 'alternateRearing' of https://github.com/Klimmasch/AEC into alternateRearing
Merge branch 'alternateRearing' of https://github.com/Klimmasch/AEC into alternateRearing
Tip revision: 96e9ae2
configVar.m
% Model object configuration and generation with support of variable
% parameter vector
%
% @param varParamArray: variable parameter cell array
% {'paramName1', value1, 'paramName2', value2, ...}
% return model: handle (pointer) to generated model instance
function model = configVar(varParamArray)
% ---------------------
% Experiment parameters
% ---------------------
% save parameter vector for documentation (model.varParamArray)
inputParams = varParamArray;
% stimulus file name
[found, textureFile, varParamArray] = parseparam(varParamArray, 'textureFile');
if (~found)
textureFile = {'Textures_mcgillManMade40.mat', 'Textures_mcgillManMade100.mat'};
end
% training duration
[found, trainTime, varParamArray] = parseparam(varParamArray, 'trainTime');
if (~found)
trainTime = 500000;
% trainTime = 1000000; % for training with metabolic costs
end
if (~isscalar(trainTime) || trainTime < 1)
error('trainTime must be scalar > 0');
end
% points in time of intermediate test procedure during training
[found, testAt, varParamArray] = parseparam(varParamArray, 'testAt');
if (~found)
testAt = [250000 : 250000 : trainTime];
% testAt = [500000 : 500000 : trainTime];
% testAt = [100000 : 100000 : trainTime]; % for training without metCosts
end
% sparse coding type
[found, sparseCodingType, varParamArray] = parseparam(varParamArray, 'sparseCodingType');
if (~found)
sparseCodingType = uint8(0);
end
if (~isscalar(sparseCodingType) || sparseCodingType < 0 || sparseCodingType > 1)
error('sparseCodingType must be scalar in {0, 1}');
end
% ----------------
% Model parameters
% ----------------
% period for changing the stimulus for the eyes at training | origin 10
[found, interval, varParamArray] = parseparam(varParamArray, 'interval');
if (~found)
interval = 10;
end
if (~isscalar(interval) || interval < 1)
error('interval must be scalar >= 1');
end
% period for changing the stimulus for the eyes at testing | origin 10
[found, testInterval, varParamArray] = parseparam(varParamArray, 'testInterval');
if (~found)
testInterval = interval * 2;
end
if (~isscalar(testInterval) || testInterval < 2)
error('testInterval must be scalar >= 2');
end
%%% Image processing variables
% patch size [pixel] of one basis functon, i.e. "receptive field" size | origin 8
[found, patchSize, varParamArray] = parseparam(varParamArray, 'patchSize');
if (~found)
patchSize = 8;
end
if (~isscalar(patchSize) || patchSize < 4)
error('patchSize must be scalar >= 4');
end
% [peripheral, intermediate ..., central vision]
% downsampling ratio, i.e. how many pixels in original image
% correspond to one pixels in downsampled image | origin [8, 2]
[found, dsRatio, varParamArray] = parseparam(varParamArray, 'dsRatio');
if (~found)
dsRatio = [4, 1];
end
% fields of view in original image [pixel] | origin [128, 80]
[found, pxFieldOfViewOrig, varParamArray] = parseparam(varParamArray, 'pxFieldOfViewOrig');
if (~found)
pxFieldOfViewOrig = [128, 40];
end
% fields of view in downsampled image [pixel] (previously called fovea)
% pxFieldOfView = FieldOfView in original image [pixel] / dsRatio
[found, pxFieldOfView, varParamArray] = parseparam(varParamArray, 'pxFieldOfView');
if (~found)
pxFieldOfView = pxFieldOfViewOrig ./ dsRatio;
end
if (~all(diff(pxFieldOfViewOrig) < 0))
error('pxFieldOfViewOrig must contain decreasing values,\ndue to convention it must hold [peripheral, intermediate ..., central vision].');
% TODO: needs to be inserted and checked when model.preprocessImageCutout() is integrated
% elseif (mod(pxFieldOfView(2 : end), dsRatio(1 : end - 1) ./ dsRatio(2 : end)))
% sprintf('pxFieldOfView(scale + 1) / (dsRatio(scale) / dsRatio(scale + 1)) must be an integer')
% return;
% elseif (mod(pxFieldOfView(1 : end - 1) - pxFieldOfView(2 : end) ./ dsRatio(1 : end - 1) ./ dsRatio(2 : end), 2))
% sprintf('pxFieldOfView(scale) - (pxFieldOfView(scale + 1) / (dsRatio(scale) / dsRatio(scale + 1))) must be an even integer')
% return;
end
% image patch strides | origin [1, patchSize / 2]
[found, stride, varParamArray] = parseparam(varParamArray, 'stride');
if (~found)
stride = [patchSize / 2, patchSize / 2];
end
% flag indicates whether cutout procedure is applied [1] or not [0]
[found, cutout, varParamArray] = parseparam(varParamArray, 'cutout');
if (~found)
cutout = uint8(0);
end
if (~isscalar(cutout) || cutout < 0 || cutout > 1)
error('cutout must be scalar in {0, 1}');
end
% overlap between the different layers measured in units of FINE scale,
% works only in conjunction with cutout
[found, overlap, varParamArray] = parseparam(varParamArray, 'overlap');
if (~found)
overlap = 0;
end
if (length(dsRatio) > 1 && (length(overlap) ~= length(dsRatio) - 1))
error('For usage of #%d scales overlap needs to have length %d.', length(dsRatio) - 1);
end
[found, whitening, varParamArray] = parseparam(varParamArray, 'whitening');
if (~found)
whitening = 0;
end
%%% Camera parameters
% vertical offset between left and right (0 in the iCub Simulator!)
% [found, offset, varParamArray] = parseparam(varParamArray, 'offset');
% if (~found)
% offset = 0;
% end
% focal length [px]
[found, focalLength, varParamArray] = parseparam(varParamArray, 'focalLength');
if (~found)
focalLength = 257.34;
end
% interocular distance [m]
[found, baseline, varParamArray] = parseparam(varParamArray, 'baseline');
if (~found)
baseline = 0.056;
end
% Object distance to eyes [m]
[found, objDistMin, varParamArray] = parseparam(varParamArray, 'objDistMin');
if (~found)
objDistMin = 0.5; % origin 0.5
end
[found, objDistMax, varParamArray] = parseparam(varParamArray, 'objDistMax');
if (~found)
objDistMax = 6; % origin 2
end
% Fixation distance [m]
% used for eye fixation initialization
[found, fixDistMin, varParamArray] = parseparam(varParamArray, 'fixDistMin');
if (~found)
fixDistMin = 0.3379;
end
[found, fixDistMax, varParamArray] = parseparam(varParamArray, 'fixDistMax');
if (~found)
fixDistMax = 10; % 3.2219 for objDistMax = 2m
end
% object plane size where the stimuli are projected on
[found, objSize, varParamArray] = parseparam(varParamArray, 'objSize');
if (~found)
objSize = 3; % 3 m fills coarse and fine scale at 6 m
end
% maximal yaw angle of object plane
[found, maxYaw, varParamArray] = parseparam(varParamArray, 'maxYaw');
if (~found)
maxYaw = 0;
end
% maximal tilt angle of object plane
[found, maxTilt, varParamArray] = parseparam(varParamArray, 'maxTilt');
if (~found)
maxTilt = 0;
end
% maximal roll angle of object plane
[found, maxRoll, varParamArray] = parseparam(varParamArray, 'maxRoll');
if (~found)
maxRoll = 0;
end
% Muscle initialization [%]: correspond now to the minimum and maximum distance
% the eyes should be looking at. [lateral rectus, medial rectus]
% some correspondances (distance: [lateral, medial] activation):
% 0.5m : [0, 0.0726], 1.5m : [0, 0.0166], 1.5m-2deg : [0, 0.0441], 2m : [0, 0.0089], 3m : [0, 0.0011], 3.22m : [0, 0],
% 4m : [0.0027, 0], 6m : [0.0064, 0], 10m : [0.0093, 0], Inf : [0.0136, 0]
% minimal initial muscle innervation
% orig: 0.00807 corr. to vergAngleMin | 0 corr. to 1 deg
[found, muscleInitMin, varParamArray] = parseparam(varParamArray, 'muscleInitMin');
if (~found)
muscleInitMin = [0, 0];
end
% maximal initial muscle innervation
% orig: 0.07186 corr. to vergAngleMax | 0.1 corrs. to 12.7 deg
[found, muscleInitMax, varParamArray] = parseparam(varParamArray, 'muscleInitMax');
if (~found)
muscleInitMax = [0.0064, 0.0166];
end
%%% Factor of Muscle activity feedback in RL feature vector
% here the % corresponds to the mean of all single components of the feature vector
% mean(mean(model.feature_hist(:, 1 : 576), 2)) = 0.0059
% mean(sum(model.feature_hist(:, 1 : 576), 2)) = 3.3721
% mean(model.cmd_hist) = [0.0229, 0.0465], 0.0465 / 0.0059 = 1 / lambdaMuscleFB
%
% 1% = 0.001268817 | 5% = 0.0063
% 10% = 0.0127 | 20% = 0.0254 | 30% = 0.0381 | 40% = 0.0508 | 50% = 0.0634
% 60% = 0.0761 | 70% = 0.0888 | 80% = 0.1015 | 90% = 0.1142 | 100% = 0.1269
% 150% = 0.1903 | 200% = 0.2538 | 250% = 0.3172 | 300% = 0.3806
% standard before normalization: 0.1269
[found, lambdaMuscleFB, varParamArray] = parseparam(varParamArray, 'lambdaMuscleFB');
if (~found)
lambdaMuscleFB = 1;
end
%%% Reward function parameters, i.e. their "proportions" to the whole reward signal
%%% Reconstruction error factor
% the % is in respect to the reconstruction error, i.e. 100% X means signal X is as strong as
% 6.391 * mean reconstruction error on average, whereby 6.391 * mean reconstruction error ~= 1
% pure 15.647% = 1 | privious 77.12% = 4.929 | 100% = 6.391 | set to 1 for simplicity
%
[found, lambdaRec, varParamArray] = parseparam(varParamArray, 'lambdaRec');
if (~found)
lambdaRec = 1;
end
% due to recError reduction at dsRatio = [8, 2], lambdaRec needs to be scaled accordingly
% this is a temporary solution, you should recalculate everything if you introduce 3 scales!
if (dsRatio(end) > 1)
lambdaRec = lambdaRec * 1.7706;
end
%%% Metabolic costs factor (range)
% per_cent = mean(model.metCost_hist) * model.lambdaMet / model.lambdaRec
%
% mean(model.metCost_hist) = 1.0380
% meanR=mean(sum(model.recerr_hist,2)) = 0.1038
% mean(model.metCost_hist) = 0.5727
% 0.5% = 0.0014435 | 0.25% = 0.00072175 | 0.1% = 0.0002887
% 1% = 0.0029 | 2% = 0.0058 | 3% = 0.0087 | 4% = 0.0114 | 5% = 0.0144
% 6% = 0.0173 | 7% = 0.0203 | 8% = 0.0232 | 9% = 0.0261 | 10% = 0.0289 | 12.5% = 0.0360875
% 15% = 0.0435 | 17.5% = 0.0505225 | 20% = 0.05774 | 25% = 0.0722 | 30% = 0.0866 | 50% = 0.1443 | 100% = 0.2887
%%%%%
%
% 0% = 0, 5.2632% = 0.0085, 10.5263% = 0.0171, 15.7895% = 0.0256, 21.0526% = 0.0341, 26.3158% = 0.0427,
% 31.5789% = 0.0512, 36.8421% = 0.0598, 42.1053% = 0.0683, 47.3684% = 0.0768, 52.6316% = 0.0854,
% 57.8947% = 0.0939, 63.1579% = 0.1024, 68.4211% = 0.1110, 73.6842% = 0.1195, 78.9474% = 0.1281,
% 84.2105% = 0.1366, 89.4737% = 0.1451, 94.7368% = 0.1537, 100.0000% = 0.1622
%
[found, metCostRange, varParamArray] = parseparam(varParamArray, 'metCostRange');
if (~found)
metCostRange = [0, 0];
end
% due to the dependancy of mean(model.metCost_hist) * metCostRange * lambdaRec / mean(recError) * lambdaRec = x%
% metCostRange needs to be scaled accordingly
metCostRange = metCostRange .* lambdaRec; % #hack
% Metabolic costs decay factor
if (length(metCostRange) == 1 || metCostRange(1) == metCostRange(2))
metCostDec = 0; % no decay
elseif (metCostRange(1) < metCostRange(2))
error('It must hold metCostRange(1) >= metCostRange(2)');
else
% metCostDec = -(log(2) * trainTime) / log(metCostRange(2) / metCostRange(1)); % exponential decay factor
metCostDec = metCostRange(1) - metCostRange(2); % linear decay factor
end
%%% muscle initialization / reset method
% 0 ('simple') : use random muscle commands out of [0, 0.1] for lateral and [0,
% 0.2] for medial rectus
% 1 ('advanced') : first, uniformly draw a object distance, then set one
% muscle actity to 0 and calculate the other muscle activity
% 2 ('moreAdvanced'): first, uniformly draw a object distance, then uniformly draw
% a point from all possible mucle commands that fixate this distance
% 3 ('perturbed') : take the last command and add a random vector with radius
% uniformly drawn from [0, 0.02] (max 2 % muscle activity for both muscles)
% 4 ('laplacian') : draw fixation distances that produce laplacian distributed disparities
%%%
[found, initMethod, varParamArray] = parseparam(varParamArray, 'initMethod');
if (~found)
initMethod = 2;
end
% Keep(0) or normalize(1) feature fector by z-transform
[found, normFeatVect, varParamArray] = parseparam(varParamArray, 'normFeatVect');
if (~found)
normFeatVect = 1;
end
if ((normFeatVect ~= 0) && (normFeatVect ~= 1))
error('normFeatVect must be a scalar in {0, 1}');
end
% Desired standard deviation of each z-transformed variable
[found, desiredStdZT, varParamArray] = parseparam(varParamArray, 'desiredStdZT');
if (~found)
desiredStdZT = 0.02;
end
if (desiredStdZT <= 0)
error('desiredStdZT must be a scalar in ]0, inf[');
end
[found, lapSig, varParamArray] = parseparam(varParamArray, 'lapSig');
if (~found)
lapSig = 1; % if initMethod == 4, this produces disparities mostly between -2 and 2 deg
% lapSig = 0.5; % mostly between [-1, 1]
end
[found, strabAngle, varParamArray] = parseparam(varParamArray, 'strabAngle');
if (~found)
strabAngle = 0;
end
%%% filters for left and right images to simulate altered rearing conditions
% and the probabilities at which they should occur.
% Leave empty if no filters should be applied.
[found, filterLeft, varParamArray] = parseparam(varParamArray, 'filterLeft');
if (~found)
filterLeft = [];
filterRight = []; % hotfix for certain parameters
elseif filterLeft == 1
% filterLeft = orientedGaussian(9,9,0.1); % leaves only vertical edges
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(9,9,0.1); % leaves only vertical edges
elseif filterLeft == 2
% filterLeft = orientedGaussian(9,0.1,9); % leaves only horizontal edges
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(9,0.1,9);
elseif filterLeft == 3
%filterLeft = orientedGaussian(240,240,240); % blurrs the whole image (monocular deprivation)
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(240,240,240);
elseif filterLeft == 4
%filterLeft = orientedGaussian(17,17,0.1);
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(17,17,0.1);
elseif filterLeft == 5
%filterLeft = orientedGaussian(17,0.1,17);
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(17,0.1,17);
elseif filterLeft == 6
% filterLeft = orientedGaussian(33,33,0.1);
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(33,33,0.1); % only verticals
elseif filterLeft == 7
% filterLeft = orientedGaussian(33,0.1,33);
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(33,0.1,33); % only horizontals
elseif filterLeft == 8
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(33,0.1,0.1);
elseif filterLeft == 9
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(33,0.2,0.2);
elseif filterLeft == 10
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(33,0.5,0.5);
elseif filterLeft == 11
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(33,1,1);
elseif filterLeft == 12
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(33,2,2);
elseif filterLeft == 13
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(33,5,5);
elseif filterLeft == 14
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(100,1,1);
elseif filterLeft == 15
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(100,5,5);
elseif filterLeft == 16
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(100,10,10);
elseif filterLeft == 17
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(100,50,50);
elseif filterLeft == 18
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(100,100,100);
elseif filterLeft == 19
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(240,0.1,33); % only horizontals
elseif filterLeft == 20
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(240,0.1,100); % only horizontals
elseif filterLeft == 21
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(240,0.1,240); % only horizontals
elseif filterLeft == 22
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(240,0.1,1000); % only horizontals
elseif filterLeft == 23
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(33,0.1,6); % only horizontals
elseif filterLeft == 24
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(33,0.1,10); % only horizontals
elseif filterLeft == 25
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(33,0.1,1); % only horizontals
%%%%%%%%%%%%%%%% Journal Paper Params %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif filterLeft == 26 % vertical
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(240,240,0.1); % only verticals
filterRight = filterLeft;
elseif filterLeft == 27 % horizontal
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(240,0.1,240); % only horizontals
filterRight = filterLeft;
elseif filterLeft == 28 % orthogonal
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(240,240,0.1); % only verticals
filterRight = {};
[filterRight{1}, filterRight{2}] = orientedGaussianVectors(240,0.1,240); % only horizontals
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif filterLeft == 29 % normal case
% add a little blurr in both eyes to make up for the non-zero distortion
% in the other cases
sdd = 0.1;
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(10,0.1,0.1);
filterRight = filterLeft;
%%%%%%%%%%%%%%%%%%%%%%%%% vertical %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif filterLeft == 30 % vertical 33
sdd = 33;
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(6*sdd,sdd,0.1);
filterRight = filterLeft;
elseif filterLeft == 31 %vertical 100
sdd = 100;
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(6*sdd,sdd,0.1);
filterRight = filterLeft;
elseif filterLeft == 32 % vertical 240
sdd = 240;
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(6*sdd,sdd,0.1);
filterRight = filterLeft;
elseif filterLeft == 33 %vertical 500
sdd = 500;
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(6*sdd,sdd,0.1);
filterRight = filterLeft;
%%%%%%%%%%%%%%%%%%%%%%%% horizontal %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif filterLeft == 34 % horizontal 33
sdd = 33;
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(6*sdd,0.1,sdd);
filterRight = filterLeft;
elseif filterLeft == 35 % horizontal 100
sdd = 100;
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(6*sdd,0.1,sdd);
filterRight = filterLeft;
elseif filterLeft == 36 % horizontal 240
sdd = 240;
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(6*sdd,0.1,sdd);
filterRight = filterLeft;
elseif filterLeft == 37 % horizontal 500
sdd = 500;
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(6*sdd,0.1,sdd);
filterRight = filterLeft;
%%%%%%%%%%%%%%%%%%% finer grained filter size %%%%%%%%%%%%%%%%%%%%%%
elseif filterLeft == 38 % vertical 9
sdd = 9;
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(6*sdd,sdd,0.1);
filterRight = filterLeft;
elseif filterLeft == 39 % vertical 17
sdd = 17;
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(6*sdd,sdd,0.1);
filterRight = filterLeft;
elseif filterLeft == 40 % horizontal 9
sdd = 9;
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(6*sdd,0.1,sdd);
filterRight = filterLeft;
elseif filterLeft == 41 % horizontal 17
sdd = 17;
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(6*sdd,0.1,sdd);
filterRight = filterLeft;
%%%%%%%%%%%%%%%%%%% orthogonal filters %%%%%%%%%%%%%%%%%%%%%%%%%%
elseif filterLeft == 42
sdd = 33;
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(6*sdd,0.1,sdd);
filterRight = {};
[filterRight{1}, filterRight{2}] = orientedGaussianVectors(6*sdd,sdd,0.1);
elseif filterLeft == 43
sdd = 17;
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(6*sdd,0.1,sdd);
filterRight = {};
[filterRight{1}, filterRight{2}] = orientedGaussianVectors(6*sdd,sdd,0.1);
elseif filterLeft == 44
sdd = 100;
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(6*sdd,0.1,sdd);
filterRight = {};
[filterRight{1}, filterRight{2}] = orientedGaussianVectors(6*sdd,sdd,0.1);
%%%%%%%%%%%%%%%%%% monocular filters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif filterLeft == 45
sdd = 33;
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(6*sdd,0.1,0.1);
filterRight = {};
[filterRight{1}, filterRight{2}] = orientedGaussianVectors(6*sdd,sdd,sdd);
%%%%%%%%%%%%%%%%%%% orthogonal filters %%%%%%%%%%%%%%%%%%%%%%%%%%
elseif filterLeft == 46
sdd = 33;
filterLeft = {};
[filterLeft{1}, filterLeft{2}] = orientedGaussianVectors(6*sdd,sdd,0.1);
filterRight = {};
[filterRight{1}, filterRight{2}] = orientedGaussianVectors(6*sdd,0.1,sdd);
end
[found, filterLeftProb, varParamArray] = parseparam(varParamArray, 'filterLeftProb');
if (~found)
filterLeftProb = 1;
end
% just a workaround to test multiple different same filters for left and
% right eyes
% filterRight = filterLeft;
% filterRightProb = filterLeftProb;
% [found, filterRight, varParamArray] = parseparam(varParamArray, 'filterRight');
% if (~found)
% filterRight = filterLeft;
% elseif filterRight == 1
% % filterRight = orientedGaussian(240,240,240);
% filterRight = {};
% [filterRight{1}, filterRight{2}] = orientedGaussianVectors(240,33,33);
% % [filterRight{1}, filterRight{2}] = orientedGaussianVectors(240,1000,1000);
% elseif filterRight == 2
% % filterRight = orientedGaussian(240,240,240);
% filterRight = {};
% [filterRight{1}, filterRight{2}] = orientedGaussianVectors(240,240,240);
% % [filterRight{1}, filterRight{2}] = orientedGaussianVectors(240,1000,1000);
% elseif filterRight == 3
% % filterRight = orientedGaussian(240,240,240);
% filterRight = {};
% [filterRight{1}, filterRight{2}] = orientedGaussianVectors(240,1000,1000);
% % [filterRight{1}, filterRight{2}] = orientedGaussianVectors(240,1000,1000);
% end
[found, filterRightProb, varParamArray] = parseparam(varParamArray, 'filterRightProb');
if (~found)
filterRightProb = filterLeftProb;
end
% [found, filterRight, varParamArray] = parseparam(varParamArray, 'filterRight');
% if (~found)
% filterRight = [];
% end
% if filterRight == 1
% % filterRight = orientedGaussian(9,9,0.1);
% filterRight = {};
% [filterRight{1}, filterRight{2}] = orientedGaussianVectors(9,9,0.1);
% elseif filterRight == 2
% % filterRight = orientedGaussian(9,0.1,9);
% filterRight = {};
% [filterRight{1}, filterRight{2}] = orientedGaussianVectors(9,0.1,9);
% elseif filterRight == 3
% % filterRight = orientedGaussian(240,240,240);
% filterRight = {};
% [filterRight{1}, filterRight{2}] = orientedGaussianVectors(240,240,240);
% elseif filterRight == 4
% % filterRight = orientedGaussian(17,17,0.1);
% filterRight = {};
% [filterRight{1}, filterRight{2}] = orientedGaussianVectors(17,17,0.1);
% elseif filterRight == 5
% % filterRight = orientedGaussian(17,0.1,17);
% filterRight = {};
% [filterRight{1}, filterRight{2}] = orientedGaussianVectors(17,0.1,17);
% elseif filterRight == 6
% % filterRight = orientedGaussian(33,33,0.1);
% filterRight = {};
% [filterRight{1}, filterRight{2}] = orientedGaussianVectors(33,33,0.1);
% elseif filterRight == 7
% % filterRight = orientedGaussian(33,0.1,33);
% filterRight = {};
% [filterRight{1}, filterRight{2}] = orientedGaussianVectors(33,0.1,33);
% elseif filterRight == 8
% filterRight = {};
% [filterRight{1}, filterRight{2}] = orientedGaussianVectors(33,0.1,0.1);
% end
%
% [found, filterRightProb, varParamArray] = parseparam(varParamArray, 'filterRightProb');
% if (~found)
% filterRightProb = 1;
% end
[found, aniseikonia, varParamArray] = parseparam(varParamArray, 'aniseikonia');
if (~found)
aniseikonia = [0, 0]; % "zoom" factor for left and right eye (0.1 = 10%)
end
PARAMModel = {textureFile, trainTime, testAt, sparseCodingType, focalLength, baseline, ...
objDistMin, objDistMax, muscleInitMin, muscleInitMax, interval, ...
lambdaMuscleFB, lambdaRec, metCostRange, patchSize, pxFieldOfView, ...
dsRatio, stride, fixDistMin, fixDistMax, overlap, cutout, metCostDec, ...
initMethod, inputParams, normFeatVect, desiredStdZT, testInterval, ...
filterLeft, filterLeftProb, filterRight, filterRightProb, ...
whitening, lapSig, strabAngle, objSize, maxYaw, maxTilt, maxRoll,...
aniseikonia};
% ------------------------
% Sparse Coding parameters
% ------------------------
% Scales := [coarse, less_coarse, ..., fine], i.e. [peripheral vision, ..., central vision]
% total number of basis | origin [288, 288]
[found, nBasis, varParamArray] = parseparam(varParamArray, 'nBasis');
if (~found)
nBasis = [400, 400];
end
% number of basis used to encode in sparse mode | origin [10, 10]
[found, nBasisUsed, varParamArray] = parseparam(varParamArray, 'nBasisUsed');
if (~found)
nBasisUsed = [10, 10];
end
% size of each (binocular) base vector: patchSize * patchSize * 2 (left + right eye) | origin [128, 128]
[found, basisSize, varParamArray] = parseparam(varParamArray, 'basisSize');
if (~found)
basisSize = [(patchSize ^ 2) * 2, (patchSize ^ 2) * 2];
end
% SC learning rate(s)
% origin 0.01 | Lukas 0.1 | Alex P 0.5, origin 0.01 | Lukas 0.1 | Alex P 0.5 | Chong 0.2
[found, sc_eta, varParamArray] = parseparam(varParamArray, 'sc_eta');
if (~found)
sc_eta = [0.2, 0.2];
end
% temperature in softmax | origin 0.01
[found, temperature, varParamArray] = parseparam(varParamArray, 'temperature');
if (~found)
temperature = [0.01, 0.01];
end
% initialization of basis functions
[found, BFinit, varParamArray] = parseparam(varParamArray, 'BFinit');
if (~found)
BFinit = [2, 2]; % initialization with non-aligned Gabor wavelets
% BFinit = [1, 1]; % initialization with random white noise
end
% fitting of basis functions
[found, BFfitFreq, varParamArray] = parseparam(varParamArray, 'BFfitFreq');
if (~found)
BFfitFreq = 1; % fitting of basis functions uses frequency instead of wavelength
end
% auxiliary variable for scale identification
[found, scaleIdent, varParamArray] = parseparam(varParamArray, 'scaleIdent');
if (~found)
scaleIdent = [1, 2];
end
if ((length(pxFieldOfViewOrig) ~= length(dsRatio)) ...
|| (length(stride) ~= length(dsRatio)) ...
|| (length(nBasis) ~= length(dsRatio)) ...
|| (length(nBasisUsed) ~= length(dsRatio)) ...
|| (length(basisSize) ~= length(dsRatio)) ...
|| (length(sc_eta) ~= length(dsRatio)) ...
|| (length(temperature) ~= length(dsRatio)))
error('For usage of #%d scales all respective SC and model parameters needs to have length %d.', ...
length(dsRatio), length(dsRatio));
end
PARAMSC = {nBasis, nBasisUsed, basisSize, sc_eta, temperature, BFinit, [BFfitFreq, BFfitFreq], scaleIdent};
% ---------------------------------
% Reinforcement Learning parameters
% ---------------------------------
% Critic and Actor implementation rlFlavour = [Critic, Actor]
% 0 = CACLA Critic Continuous Actor Critic Learning Automaton
% 1 = CRG Critic Continuous Regular Gradient
%
% 0 = CACLAVarLu Actor Continuous Actor Critic Learning Automaton with (delta std) * update [Lukas's interpretation of CACLA appoach]
% 1 = CACLAVarAl Actor Continuous Actor Critic Learning Automaton with (delta std) * update [Alex L's interpretation of CACLA appoach]
% 2 = CACLAVarBp Actor Continuous Actor Critic Learning Automaton with (delta std) * update [CACLA appoach with std. Backpropagation]
% 3 = CACLAVar Actor Continuous Actor Critic Learning Automaton with (delta std) * update
% 4 = CACLAVar2 Actor Continuous Actor Critic Learning Automaton with (delta std) * update [non-linear output layer]
% # = CNGACFI Actor Continuous Natural-Gradient Actor-Critc with Fisher Information matrix TODO: unsupported yet
[found, rlFlavour, varParamArray] = parseparam(varParamArray, 'rlFlavour');
if (~found)
rlFlavour = [uint8(0), uint8(0)];
end
if (length(rlFlavour) ~= 2)
error('It must hold length(rlFlavour) = 2, as rlFlavour = [Critic, Actor]');
end
if (rlFlavour(1) < 0 || rlFlavour(1) > 1)
error('rlFlavour(1) must be scalar in {0, 1}');
end
if (rlFlavour(2) < 0 || rlFlavour(2) > 4)
error('rlFlavour(2) must be scalar in {0, 1, ..., 4}');
end
% indicates if the policy is discrete (= 0) or continuous (= 1)
[found, continuous, varParamArray] = parseparam(varParamArray, 'continuous');
if (~found)
continuous = uint8(1);
end
% vergence angles (discrete policy) enable half pixel resolution
[found, actionSpace, varParamArray] = parseparam(varParamArray, 'actionSpace');
if (~found)
actionSpace = [-8, -4, -2, -1, -0.5, -0.2, -0.1, ...
0, 0.1, 0.2, 0.5, 1, 2, 4, 8];
end
% Critic learning rate (value function)
% origin 0.05 | Chong 1 | Lukas 0.9 | Alex P 0.4
% [found, alpha_v, varParamArray] = parseparam(varParamArray, 'alpha_v');
% if (~found)
% alpha_v = 0.75;
% end
% Critic learning rate range (value function)
% origin 0.05 | Chong 1 | Lukas 0.9 | Alex P 0.4
[found, criticLRRange, varParamArray] = parseparam(varParamArray, 'criticLRRange');
if (~found)
criticLRRange = [0.75];
end
% Critic learning rate decay factor
if (length(criticLRRange) == 1 || criticLRRange(1) == criticLRRange(2))
critLRDec = 0; % no variance decay
elseif (criticLRRange(1) < criticLRRange(2))
error('It must hold criticLRRange(1) >= criticLRRange(2)');
else
% critLRDec = -(log(2) * trainTime) / log(criticLRRange(2) / criticLRRange(1)); % exponential decay factor
critLRDec = criticLRRange(1) - criticLRRange(2); % linear decay factor
end
% CRG Critic discount factor
% origin 0.3 | Alex P 0.3
[found, xi, varParamArray] = parseparam(varParamArray, 'xi');
if (~found)
xi = 0.3;
end
% CACLA Critic discount factor
% origin 1
% TODO: fuse both discounting factors
[found, gamma, varParamArray] = parseparam(varParamArray, 'gamma');
if (~found)
gamma = 0.3;
end
% Actor learning rate of natural policy gradient
% origin 0.05 | Chong 0.025 | Lukas 0.1 | Alex P 0.4
[found, alpha_n, varParamArray] = parseparam(varParamArray, 'alpha_n');
if (~found)
alpha_n = 0.025;
end
% % Actor learning rate of Gaussian policy
% % origin 1 | Chong 0.002 | Lukas 0.01 | Alex P 0.4 | linear 0.002
% [found, alpha_p, varParamArray] = parseparam(varParamArray, 'alpha_p');
% if (~found)
% alpha_p = 0.5;
% end
% Actor learning rate of Gaussian policy
% origin 1 | Chong 0.002 | Lukas 0.01 | Alex P 0.4 | linear 0.002
[found, actorLRRange, varParamArray] = parseparam(varParamArray, 'actorLRRange');
if (~found)
actorLRRange = [0.5, 0];
end
% Actor learning rate decay factor
if (length(actorLRRange) == 1 || actorLRRange(1) == actorLRRange(2))
actLRDec = 0; % no variance decay
elseif (actorLRRange(1) < actorLRRange(2))
error('It must hold actorLRRange(1) >= actorLRRange(2)');
else
% actLRDec = -(log(2) * trainTime) / log(actorLRRange(2) / actorLRRange(1)); % exponential decay factor
actLRDec = actorLRRange(1) - actorLRRange(2); % linear decay factor
end
% Actor weight regularization via factorial downscaling
% how it works: actor.wp_ji = (1 - (actor.actorRegularizer * actor.learnRate)) * actor.wp_ji;
% previously 1e-4 | 1e-3 / actorLRRange(1); ensures a regularization factor of 1-1e-3 at the beginning of the simulation.
[found, actorRegularizer, varParamArray] = parseparam(varParamArray, 'actorRegularizer');
if (~found)
actorRegularizer = 1e-5;
end
% critic weight regularization via factorial downscaling
% works as in the actor
[found, criticRegularizer, varParamArray] = parseparam(varParamArray, 'criticRegularizer');
if (~found)
criticRegularizer = 0;
end
% Variance of action output, i.e. variance of Gaussian policy [training_start, training_end]
% corresponds to softMax temperature in discrete RL models
[found, varianceRange, varParamArray] = parseparam(varParamArray, 'varianceRange');
if (~found)
varianceRange = [1e-5, 1e-5];
end
% Action variance decay factor
if (length(varianceRange) == 1 || varianceRange(1) == varianceRange(2))
% no variance decay
varDec = 0;
elseif (varianceRange(1) < varianceRange(2))
error('It must hold varianceRange(1) >= varianceRange(2)');
else
% varDec = -(log(2) * trainTime) / log(varianceRange(2) / varianceRange(1)); % exponential decay factor
varDec = varianceRange(1) - varianceRange(2); % linear decay factor
end
% Actor`s number of neurons in the output layer and amount of eye muscles
[found, outputDim, varParamArray] = parseparam(varParamArray, 'outputDim');
if (~found)
outputDim = 2;
end
% Constant bias in input vector/feature vector (0 := off, >0 := take that value as bias)
[found, bias, varParamArray] = parseparam(varParamArray, 'bias');
if (~found)
bias = desiredStdZT; % 0 before, 0.02 in curr. approach
end
% Critic`s and Actor`s number of neurons in the input layer (Small + Large scale + Muscle activities)
% note: if you specify a bias and define the input dimension, remember to
% add the bias to that!
[found, inputDim, varParamArray] = parseparam(varParamArray, 'inputDim');
if (~found)
if (continuous == 1)
inputDim = sum(PARAMSC{1}) + outputDim; % number of neurons in the input layer (Small + Large scale + Muscle activities) 802
else
inputDim = sum(PARAMSC{1}); % only small + large scale basis function inputs in discrete models
varianceRange = 1;
outputDim = 1; % only one delta angle output in discrete models
end
if (bias > 0)
inputDim = inputDim + 1;
end
end
% Actor`s number of neurons in the hidden layer
[found, hiddenDim, varParamArray] = parseparam(varParamArray, 'hiddenDim');
if (~found)
hiddenDim = 50;
end
% all network dimensions at once
[found, dimensions, varParamArray] = parseparam(varParamArray, 'dimensions');
if (~found)
dimensions = [inputDim, hiddenDim, outputDim];
end
% initial network weights
[found, weight_range, varParamArray] = parseparam(varParamArray, 'weight_range');
if (~found)
weight_range = [1 / inputDim, ... % maximum initial weight [critic_ji, actor_ji, actor_kj]
1 / (inputDim * hiddenDim), ... % origin [0.05, 0.4, 0.4] | Lukas [0.1, 0.05, 0.05] | AL 100 / (inputDim * hiddenDim)
1 / (hiddenDim * outputDim)]; % linear [1/inputDim, 1/inputDim, -]
end
% Actor`s reguralization factor
% origin 0.01
% TODO: DEPRICATED because it became obsolet, cleanup needed
[found, lambda, varParamArray] = parseparam(varParamArray, 'lambda');
if (~found)
lambda = 0.01;
end
% TD error variance tracking/approximating (CACLAVar)
[found, deltaVar, varParamArray] = parseparam(varParamArray, 'deltaVar');
if (~found)
deltaVar = 1;
end
% TD error variance scaling factor (CACLAVar)
[found, rl_eta, varParamArray] = parseparam(varParamArray, 'rl_eta');
if (~found)
rl_eta = 0.001;
end
% scaling factor of Fisher Information matrix (CNGFI)
[found, fiScale, varParamArray] = parseparam(varParamArray, 'fiScale');
if (~found)
fiScale = 1e-5;
end
PARAMRL = {actionSpace, criticLRRange, alpha_n, actorLRRange, xi, gamma, varianceRange, lambda, dimensions, weight_range, ...
continuous, deltaVar, rl_eta, fiScale, rlFlavour, varDec, actorRegularizer, critLRDec, actLRDec, bias, criticRegularizer};
if (~isempty(varParamArray))
error('varParamArray contains unrecognized elements, p.e. %s', varParamArray{1});
end
PARAM = {PARAMModel, PARAMSC, PARAMRL};
model = Model(PARAM);
end
% -------------------------
% Parameter vector handling
% -------------------------
% Parses parameter vector and prunes it on successful find
% @param paramVector: parameter vector
% @param param: searched paramter name
%
% return found: [0, 1] success flag
% return val: value of parameter
% return paramVector: updated parameter vector
function [found, val, paramVector] = parseparam(paramVector, param)
% search param name
isvar = cellfun(@(x) ischar(x) && strcmpi(x, param), paramVector);
if (sum(isvar) > 1)
error('Parameters can only be passed once');
end
if (any(isvar))
found = true;
idx = find(isvar);
val = paramVector{idx + 1};
paramVector([idx, idx + 1]) = []; % prune param vector
else
found = false;
val = [];
end
end