% a reprodukálhatóság érdekében 
rng(0)
% beolvasom az adatokat egy imageDatestore formátumba, beállítva, hogy a 
% target az alkönyvtár neve legyen
imds=imageDatastore('att_faces',...
    'IncludeSubfolders',true,'FileExtensions','.pgm',...
    'LabelSource','foldernames');

% ha kíváncsiak vagyunk egy képre, akkor pl 
%imshow(imds.Files{1})


%szétvágom az adatokat train és test adatokra, minden alkönyvtár elsõ 7
%képe tanulóadat, a maradék 3 tesztadat lesz
[imds1,imds2] = splitEachLabel(imds,7); 

%definiálom a layer-eket
%Az elsõ kötelezõen az inputlayer, a paraméterei a képek mérete, ill a 
%képcsatornák száma (szürkeskála esetén 1, színesnél 3) 
%az utolsó fullyconnectedlayer paramétere kötelezõen az 
%osztályok száma
%Itt érdemes kísérletezgetni azzal, 
%hogy kihagyjuk a dropout layert, ill állítgatjuk a paraméterét
%a mostani egy elég jó beállítás 
layers = [imageInputLayer([112 92 1])
          convolution2dLayer(5,6,'Padding',2)
          reluLayer
          maxPooling2dLayer(4,'Stride',2)
          convolution2dLayer(5,20,'Padding',2)
          reluLayer
          maxPooling2dLayer(4,'Stride',2)
          dropoutLayer(.4)
          fullyConnectedLayer(80)
          fullyConnectedLayer(40)
          softmaxLayer
          classificationLayer()];
     
     %ha egyszer már lefutott a kód, akkor a parancsablakba begépelve a
     %hálózat nevét (convnet, ld lejjebb)megtudjuk, hogy hány Layer van a
     %hálózatban. A convnet.Layers kifejezést beírva részletes leírást 
     %kapunk a Layer-ekrõl. Ott a sorok elején lévõ számok segítségével
     %hivatkozhatunk az egyes Layer-ekre, így pl a két konvolúciós 
     %layer esetén (amelyeknek a sorszáma 2 és 5) így állíthatjuk 
     %be a kezdõsúlyokat (feltéve, hogy a gépünk alkalmas arra, hogy 
     %gpu-n számoljon -ekkor automatikusan azon számol-, ha nem alkalmas, 
     %akkor a gpuArray és single utasításokat ki kell hagyni)
     %nekem kezdõsúly beállítás nélkül is jól fut, de idetettem kommentbe, 
     %az elvi lehetõség miatt
     % layers(2).Weights = gpuArray(single(unifrnd(-0.05,0.05,[5 5 1 6])));
     % layers(5).Weights = gpuArray(single(unifrnd(-0.05,0.05,[5 5 6 20])));
      
     %paraméterezzük a tanítást
 options = trainingOptions('sgdm','MaxEpochs',50, ...
	'InitialLearnRate',0.001,'LearnRateSchedule','piecewise',...
    'LearnRateDropFactor', 0.6, ... 
    'LearnRateDropPeriod', 5,'MinibatchSize',40,...
    'L2Regularization',0.005);

%a tanítás
convnet = trainNetwork(imds1,layers,options);

%teszteljük a tanulóadatokkal
predTrain=classify(convnet,imds1);

%accuracy on the train set
accuracy1=sum(imds1.Labels==predTrain)/numel(predTrain) 

%teszteljük a tesztadatokkal
predTraint=classify(convnet,imds2);

%accuracy on the test set
accuracy2=sum(imds2.Labels==predTraint)/numel(predTraint)

