22 #include "base/Optionpk.h"
23 #include "fileclasses/FileReaderAscii.h"
24 #include "floatfann.h"
25 #include "algorithms/myfann_cpp.h"
28 int main(
int argc,
char *argv[])
33 Optionpk<int> inputCols_opt(
"ic",
"inputCols",
"input columns (e.g., for three dimensional input data in first three columns use: -ic 0 -ic 1 -ic 2");
34 Optionpk<int> outputCols_opt(
"oc",
"outputCols",
"output columns (e.g., for two dimensional output in columns 3 and 4 (starting from 0) use: -oc 3 -oc 4");
35 Optionpk<string> training_opt(
"t",
"training",
"training ASCII file (each row represents one sampling unit. Input features should be provided as columns, followed by output)");
36 Optionpk<double> from_opt(
"from",
"from",
"start from this row in training file (start from 0)",0);
37 Optionpk<double> to_opt(
"to",
"to",
"read until this row in training file (start from 0 or set leave 0 as default to read until end of file)", 0);
38 Optionpk<double> offset_opt(
"\0",
"offset",
"offset value for each spectral band input features: refl[band]=(DN[band]-offset[band])/scale[band]", 0.0);
39 Optionpk<double> scale_opt(
"\0",
"scale",
"scale value for each spectral band input features: refl=(DN[band]-offset[band])/scale[band] (use 0 if scale min and max in each band to -1.0 and 1.0)", 0.0);
41 Optionpk<unsigned int> nneuron_opt(
"nn",
"nneuron",
"number of neurons in hidden layers in neural network (multiple hidden layers are set by defining multiple number of neurons: -n 15 -n 1, default is one hidden layer with 5 neurons)", 5);
42 Optionpk<float> connection_opt(
"\0",
"connection",
"connection reate (default: 1.0 for a fully connected network)", 1.0);
44 Optionpk<float> learning_opt(
"l",
"learning",
"learning rate (default: 0.7)", 0.7);
45 Optionpk<unsigned int> maxit_opt(
"\0",
"maxit",
"number of maximum iterations (epoch) (default: 500)", 500);
46 Optionpk<short> verbose_opt(
"v",
"verbose",
"set to: 0 (results only), 1 (confusion matrix), 2 (debug)",0,2);
48 offset_opt.setHide(1);
50 connection_opt.setHide(1);
51 learning_opt.setHide(1);
56 doProcess=input_opt.retrieveOption(argc,argv);
57 training_opt.retrieveOption(argc,argv);
58 inputCols_opt.retrieveOption(argc,argv);
59 outputCols_opt.retrieveOption(argc,argv);
60 output_opt.retrieveOption(argc,argv);
61 from_opt.retrieveOption(argc,argv);
62 to_opt.retrieveOption(argc,argv);
63 cv_opt.retrieveOption(argc,argv);
64 nneuron_opt.retrieveOption(argc,argv);
65 offset_opt.retrieveOption(argc,argv);
66 scale_opt.retrieveOption(argc,argv);
67 connection_opt.retrieveOption(argc,argv);
69 learning_opt.retrieveOption(argc,argv);
70 maxit_opt.retrieveOption(argc,argv);
71 verbose_opt.retrieveOption(argc,argv);
73 catch(
string predefinedString){
74 std::cout << predefinedString << std::endl;
79 cout <<
"Usage: pkregann -i input -t training [-ic col]* [-oc col]* -o output" << endl;
81 std::cout <<
"short option -h shows basic options only, use long option --help to show all options" << std::endl;
85 unsigned int ninput=inputCols_opt.size();
86 unsigned int noutput=outputCols_opt.size();
89 vector< vector<float> > inputUnits;
90 vector< vector<float> > trainingUnits;
91 vector< vector<float> > trainingOutput;
93 unsigned int inputSize=0;
95 inputFile.open(input_opt[0]);
96 inputFile.setMinRow(from_opt[0]);
97 inputFile.setMaxRow(to_opt[0]);
98 inputFile.setComment(
'#');
99 inputFile.readData(inputUnits,inputCols_opt,1,0,
true,verbose_opt[0]);
101 inputSize=inputUnits.size();
104 unsigned int sampleSize=0;
105 trainingFile.setMinRow(from_opt[0]);
106 trainingFile.setMaxRow(to_opt[0]);
107 trainingFile.setComment(
'#');
108 trainingFile.readData(trainingUnits,inputCols_opt,1,0,
true,verbose_opt[0]);
109 trainingFile.readData(trainingOutput,outputCols_opt,1,0,
true,verbose_opt[0]);
110 trainingFile.close();
111 sampleSize=trainingUnits.size();
113 if(verbose_opt[0]>1){
114 std::cout <<
"sampleSize: " << sampleSize << std::endl;
115 std::cout <<
"ninput: " << ninput << std::endl;
116 std::cout <<
"noutput: " << noutput << std::endl;
117 std::cout <<
"trainingUnits[0].size(): " << trainingUnits[0].size() << std::endl;
118 std::cout <<
"trainingOutput[0].size(): " << trainingOutput[0].size() << std::endl;
119 std::cout <<
"trainingUnits.size(): " << trainingUnits.size() << std::endl;
120 std::cout <<
"trainingOutput.size(): " << trainingOutput.size() << std::endl;
123 assert(ninput==trainingUnits[0].size());
124 assert(noutput==trainingOutput[0].size());
125 assert(trainingUnits.size()==trainingOutput.size());
128 if(offset_opt.size()>1)
129 assert(offset_opt.size()==ninput);
130 if(scale_opt.size()>1)
131 assert(scale_opt.size()==ninput);
133 std::vector<float> offset_input(ninput);
134 std::vector<float> scale_input(ninput);
136 std::vector<float> offset_output(noutput);
137 std::vector<float> scale_output(noutput);
139 for(
int iinput=0;iinput<ninput;++iinput){
140 if(verbose_opt[0]>=1)
141 cout <<
"scaling for input feature" << iinput << endl;
142 offset_input[iinput]=(offset_opt.size()==1)?offset_opt[0]:offset_opt[iinput];
143 scale_input[iinput]=(scale_opt.size()==1)?scale_opt[0]:scale_opt[iinput];
145 if(scale_input[iinput]<=0){
146 float theMin=trainingUnits[0][iinput];
147 float theMax=trainingUnits[0][iinput];
148 for(
int isample=0;isample<trainingUnits.size();++isample){
149 if(theMin>trainingUnits[isample][iinput])
150 theMin=trainingUnits[isample][iinput];
151 if(theMax<trainingUnits[isample][iinput])
152 theMax=trainingUnits[isample][iinput];
154 offset_input[iinput]=theMin+(theMax-theMin)/2.0;
155 scale_input[iinput]=(theMax-theMin)/2.0;
156 if(verbose_opt[0]>=1){
157 std::cout <<
"Extreme image values for input feature " << iinput <<
": [" << theMin <<
"," << theMax <<
"]" << std::endl;
158 std::cout <<
"Using offset, scale: " << offset_input[iinput] <<
", " << scale_input[iinput] << std::endl;
159 std::cout <<
"scaled values for input feature " << iinput <<
": [" << (theMin-offset_input[iinput])/scale_input[iinput] <<
"," << (theMax-offset_input[iinput])/scale_input[iinput] <<
"]" << std::endl;
164 for(
int ioutput=0;ioutput<noutput;++ioutput){
165 if(verbose_opt[0]>=1)
166 cout <<
"scaling for output feature" << ioutput << endl;
168 float theMin=trainingOutput[0][ioutput];
169 float theMax=trainingOutput[0][ioutput];
170 for(
int isample=0;isample<trainingOutput.size();++isample){
171 if(theMin>trainingOutput[isample][ioutput])
172 theMin=trainingOutput[isample][ioutput];
173 if(theMax<trainingOutput[isample][ioutput])
174 theMax=trainingOutput[isample][ioutput];
176 offset_output[ioutput]=theMin+(theMax-theMin)/2.0;
177 scale_output[ioutput]=(theMax-theMin)/2.0;
178 if(verbose_opt[0]>=1){
179 std::cout <<
"Extreme image values for output feature " << ioutput <<
": [" << theMin <<
"," << theMax <<
"]" << std::endl;
180 std::cout <<
"Using offset, scale: " << offset_output[ioutput] <<
", " << scale_output[ioutput] << std::endl;
181 std::cout <<
"scaled values for output feature " << ioutput <<
": [" << (theMin-offset_output[ioutput])/scale_output[ioutput] <<
"," << (theMax-offset_output[ioutput])/scale_output[ioutput] <<
"]" << std::endl;
189 const unsigned int num_layers = nneuron_opt.size()+2;
190 const float desired_error = 0.0003;
191 const unsigned int iterations_between_reports = (verbose_opt[0])? maxit_opt[0]+1:0;
192 if(verbose_opt[0]>=1){
193 cout <<
"creating artificial neural network with " << nneuron_opt.size() <<
" hidden layer, having " << endl;
194 for(
int ilayer=0;ilayer<nneuron_opt.size();++ilayer)
195 cout << nneuron_opt[ilayer] <<
" ";
196 cout <<
"neurons" << endl;
201 unsigned int layers[3];
203 layers[1]=nneuron_opt[0];
205 net.create_sparse_array(connection_opt[0],num_layers,layers);
210 unsigned int layers[3];
212 layers[1]=nneuron_opt[0];
213 layers[2]=nneuron_opt[1];
215 net.create_sparse_array(connection_opt[0],num_layers,layers);
220 cerr <<
"Only 1 or 2 hidden layers are supported!" << endl;
224 if(verbose_opt[0]>=1)
225 cout <<
"network created" << endl;
227 net.set_learning_rate(learning_opt[0]);
232 net.set_activation_function_hidden(FANN::SIGMOID_SYMMETRIC_STEPWISE);
233 net.set_activation_function_output(FANN::SIGMOID_SYMMETRIC_STEPWISE);
239 if(verbose_opt[0]>=1){
240 cout << endl <<
"Network Type : ";
241 switch (net.get_network_type())
244 cout <<
"LAYER" << endl;
247 cout <<
"SHORTCUT" << endl;
250 cout <<
"UNKNOWN" << endl;
253 net.print_parameters();
256 if(verbose_opt[0]>=1){
257 cout <<
"Max Epochs " << setw(8) << maxit_opt[0] <<
". "
258 <<
"Desired Error: " << left << desired_error << right << endl;
260 bool initWeights=
true;
263 for(
unsigned int isample=0;isample<sampleSize;++isample){
264 for(
unsigned int iinput=0;iinput<ninput;++iinput)
265 trainingFeatures[isample][iinput]=(trainingUnits[isample][iinput]-offset_input[iinput])/scale_input[iinput];
269 for(
unsigned int isample=0;isample<sampleSize;++isample){
270 for(
unsigned int ioutput=0;ioutput<noutput;++ioutput)
271 scaledOutput[isample][ioutput]=(trainingOutput[isample][ioutput]-offset_output[ioutput])/scale_output[ioutput];
276 std::cout <<
"cross validation" << std::endl;
277 std::vector< std::vector<float> > referenceVector;
278 std::vector< std::vector<float> > outputVector;
279 net.cross_validation(trainingFeatures,
286 assert(referenceVector.size()==outputVector.size());
287 vector<double> rmse(noutput);
288 for(
int isample=0;isample<referenceVector.size();++isample){
289 std::cout << isample <<
" ";
290 for(
int ioutput=0;ioutput<noutput;++ioutput){
293 double ref=scale_output[ioutput]*referenceVector[isample][ioutput]+offset_output[ioutput];
294 double val=scale_output[ioutput]*outputVector[isample][ioutput]+offset_output[ioutput];
295 rmse[ioutput]+=(ref-val)*(ref-val);
296 std::cout << ref <<
" " << val;
297 if(ioutput<noutput-1)
300 std::cout << std::endl;
303 for(
int ioutput=0;ioutput<noutput;++ioutput)
304 std::cout <<
"rmse output variable " << ioutput <<
": " << sqrt(rmse[ioutput]/referenceVector.size()) << std::endl;
308 net.train_on_data(trainingFeatures,
312 iterations_between_reports,
316 if(verbose_opt[0]>=2){
317 net.print_connections();
318 vector<fann_connection> convector;
319 net.get_connection_array(convector);
320 for(
int i_connection=0;i_connection<net.get_total_connections();++i_connection)
321 cout <<
"connection " << i_connection <<
": " << convector[i_connection].weight << endl;
325 ofstream outputStream;
326 if(!output_opt.empty())
327 outputStream.open(output_opt[0].c_str(),ios::out);
328 for(
unsigned int isample=0;isample<inputUnits.size();++isample){
329 std::vector<float> inputFeatures(ninput);
330 for(
unsigned int iinput=0;iinput<ninput;++iinput)
331 inputFeatures[iinput]=(inputUnits[isample][iinput]-offset_input[iinput])/scale_input[iinput];
332 vector<float> result(noutput);
333 result=net.run(inputFeatures);
335 if(!output_opt.empty())
336 outputStream << isample <<
" ";
338 std::cout << isample <<
" ";
340 for(
unsigned int iinput=0;iinput<ninput;++iinput){
341 if(output_opt.size())
342 outputStream << inputUnits[isample][iinput] <<
" ";
344 std::cout << inputUnits[isample][iinput] <<
" ";
347 for(
unsigned int ioutput=0;ioutput<noutput;++ioutput){
348 result[ioutput]=scale_output[ioutput]*result[ioutput]+offset_output[ioutput];
349 if(output_opt.size()){
350 outputStream << result[ioutput];
351 if(ioutput<noutput-1)
354 outputStream << std::endl;
357 std::cout << result[ioutput];
358 if(ioutput<noutput-1)
361 std::cout << std::endl;
365 if(!output_opt.empty())
366 outputStream.close();