% Version 1.000
%
% Code provided by Ruslan Salakhutdinov and Geoff Hinton
%
% Permission is granted for anyone to copy, use, modify, or distribute this
% program and accompanying programs and documents for any purpose, provided
% this copyright notice is retained and prominently displayed, along with
% a note saying that the original programs are available from our
% web page.
% The programs and documents are distributed without any warranty, express or
% implied.  As the programs were written for research purposes only, they have
% not been tested to the degree that would be advisable in any important
% application.  All use of these programs is entirely at the user's own risk.

% Version 1.100
%
% Updated by Computational Cognitive Neuroscience Lab
% University of Padova
% ccnl.psy.unipd.it
%
% Implementation on Cluster using MPITB for Octave

function deeptrain()
	
	%MPI Init functions
	MPI_Init;
	[info rnk]=MPI_Comm_rank(MPI_COMM_WORLD);
	[info siz]=MPI_Comm_size(MPI_COMM_WORLD);

	%deep network parameters
	maxepoch = 50;
	sizelayer=[500 500 2000];
	numlayer=length(sizelayer);
	batchsize = 125;
	fname = ['MNIST_data_' num2str(batchsize) '.mat'];

	%RBM parameters
	epsilonw      = 0.1;   % Learning rate for weights 
	epsilonvb     = 0.1;   % Learning rate for biases of visible units 
	epsilonhb     = 0.1;   % Learning rate for biases of hidden units 
	weightcost  = 0.0002;   
	initialmomentum  = 0.5;
	finalmomentum    = 0.9;

	% load training data
	if(rnk==0)
		load(fname);
   		A = size(batchdata);
		[numcases numdims numbatches]=size(batchdata);
		tic();
    		% STORE PROJECT INFO  
    		Proj.Layers=[numdims sizelayer]; 
    		Proj.nLayers=numlayer;
    		Proj.nPatterns=numcases*numbatches;
    		Proj.Batchsize=numcases;
    		Proj.nBatches=numbatches;
    		Proj.nCPU=siz;
    		Proj.nEpoch=maxepoch;
	end	
	
	% Pretrains a deep networks.

	for layer=1:numlayer
		% run new RBM
		numhid=sizelayer(layer);
	    	rbm_par;

	   	if(rnk==0)
		        % save the RBM weights
			rbmWeights.layer=layer;
			rbmWeights.weight=vishid;
			rbmWeights.hidbiases=hidbiases;
			rbmWeights.visbiases=visbiases;
			WeightsLayer{1,layer}=rbmWeights;
		
			% update input data and parameters for next layer
			batchdata=batchposhidprobs;
			A=size(batchdata);
			[numcases numdims numbatches]=size(batchdata);			
	    	end
	end

	if(rnk==0)
    		% SAVE Proj and WeightsLayer
		Proj.Time=toc();
		fname = ['DeepNet_MNIST_' num2str(batchsize) '.mat'];
    		save('-mat-binary', fname, 'Proj', 'WeightsLayer');
	end 

	MPI_Finalize;
	MPITB_Clean;
end

