22 #include "base/Optionpk.h" 23 #include "fileclasses/FileReaderAscii.h" 24 #include "floatfann.h" 25 #include "algorithms/myfann_cpp.h" 72 int main(
int argc,
char *argv[])
77 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");
78 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");
79 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)");
80 Optionpk<double> from_opt(
"from",
"from",
"start from this row in training file (start from 0)",0);
81 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);
82 Optionpk<double> offset_opt(
"\0",
"offset",
"offset value for each spectral band input features: refl[band]=(DN[band]-offset[band])/scale[band]", 0.0);
83 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);
85 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);
86 Optionpk<float> connection_opt(
"\0",
"connection",
"connection reate (default: 1.0 for a fully connected network)", 1.0);
88 Optionpk<float> learning_opt(
"l",
"learning",
"learning rate (default: 0.7)", 0.7);
89 Optionpk<unsigned int> maxit_opt(
"\0",
"maxit",
"number of maximum iterations (epoch) (default: 500)", 500);
90 Optionpk<short> verbose_opt(
"v",
"verbose",
"set to: 0 (results only), 1 (confusion matrix), 2 (debug)",0,2);
92 offset_opt.setHide(1);
94 connection_opt.setHide(1);
95 learning_opt.setHide(1);
100 doProcess=input_opt.retrieveOption(argc,argv);
101 training_opt.retrieveOption(argc,argv);
102 inputCols_opt.retrieveOption(argc,argv);
103 outputCols_opt.retrieveOption(argc,argv);
104 output_opt.retrieveOption(argc,argv);
105 from_opt.retrieveOption(argc,argv);
106 to_opt.retrieveOption(argc,argv);
107 cv_opt.retrieveOption(argc,argv);
108 nneuron_opt.retrieveOption(argc,argv);
109 offset_opt.retrieveOption(argc,argv);
110 scale_opt.retrieveOption(argc,argv);
111 connection_opt.retrieveOption(argc,argv);
113 learning_opt.retrieveOption(argc,argv);
114 maxit_opt.retrieveOption(argc,argv);
115 verbose_opt.retrieveOption(argc,argv);
117 catch(
string predefinedString){
118 std::cout << predefinedString << std::endl;
123 cout <<
"Usage: pkregann -i input -t training [-ic col]* [-oc col]* -o output" << endl;
125 std::cout <<
"short option -h shows basic options only, use long option --help to show all options" << std::endl;
129 unsigned int ninput=inputCols_opt.size();
130 unsigned int noutput=outputCols_opt.size();
133 vector< vector<float> > inputUnits;
134 vector< vector<float> > trainingUnits;
135 vector< vector<float> > trainingOutput;
137 unsigned int inputSize=0;
138 if(input_opt.size()){
139 inputFile.open(input_opt[0]);
140 inputFile.setMinRow(from_opt[0]);
141 inputFile.setMaxRow(to_opt[0]);
142 inputFile.setComment(
'#');
143 inputFile.readData(inputUnits,inputCols_opt,1,0,
true,verbose_opt[0]);
145 inputSize=inputUnits.size();
148 unsigned int sampleSize=0;
149 trainingFile.setMinRow(from_opt[0]);
150 trainingFile.setMaxRow(to_opt[0]);
151 trainingFile.setComment(
'#');
152 trainingFile.readData(trainingUnits,inputCols_opt,1,0,
true,verbose_opt[0]);
153 trainingFile.readData(trainingOutput,outputCols_opt,1,0,
true,verbose_opt[0]);
154 trainingFile.close();
155 sampleSize=trainingUnits.size();
157 if(verbose_opt[0]>1){
158 std::cout <<
"sampleSize: " << sampleSize << std::endl;
159 std::cout <<
"ninput: " << ninput << std::endl;
160 std::cout <<
"noutput: " << noutput << std::endl;
161 std::cout <<
"trainingUnits[0].size(): " << trainingUnits[0].size() << std::endl;
162 std::cout <<
"trainingOutput[0].size(): " << trainingOutput[0].size() << std::endl;
163 std::cout <<
"trainingUnits.size(): " << trainingUnits.size() << std::endl;
164 std::cout <<
"trainingOutput.size(): " << trainingOutput.size() << std::endl;
167 assert(ninput==trainingUnits[0].size());
168 assert(noutput==trainingOutput[0].size());
169 assert(trainingUnits.size()==trainingOutput.size());
172 if(offset_opt.size()>1)
173 assert(offset_opt.size()==ninput);
174 if(scale_opt.size()>1)
175 assert(scale_opt.size()==ninput);
177 std::vector<float> offset_input(ninput);
178 std::vector<float> scale_input(ninput);
180 std::vector<float> offset_output(noutput);
181 std::vector<float> scale_output(noutput);
183 for(
int iinput=0;iinput<ninput;++iinput){
184 if(verbose_opt[0]>=1)
185 cout <<
"scaling for input feature" << iinput << endl;
186 offset_input[iinput]=(offset_opt.size()==1)?offset_opt[0]:offset_opt[iinput];
187 scale_input[iinput]=(scale_opt.size()==1)?scale_opt[0]:scale_opt[iinput];
189 if(scale_input[iinput]<=0){
190 float theMin=trainingUnits[0][iinput];
191 float theMax=trainingUnits[0][iinput];
192 for(
int isample=0;isample<trainingUnits.size();++isample){
193 if(theMin>trainingUnits[isample][iinput])
194 theMin=trainingUnits[isample][iinput];
195 if(theMax<trainingUnits[isample][iinput])
196 theMax=trainingUnits[isample][iinput];
198 offset_input[iinput]=theMin+(theMax-theMin)/2.0;
199 scale_input[iinput]=(theMax-theMin)/2.0;
200 if(verbose_opt[0]>=1){
201 std::cout <<
"Extreme image values for input feature " << iinput <<
": [" << theMin <<
"," << theMax <<
"]" << std::endl;
202 std::cout <<
"Using offset, scale: " << offset_input[iinput] <<
", " << scale_input[iinput] << std::endl;
203 std::cout <<
"scaled values for input feature " << iinput <<
": [" << (theMin-offset_input[iinput])/scale_input[iinput] <<
"," << (theMax-offset_input[iinput])/scale_input[iinput] <<
"]" << std::endl;
208 for(
int ioutput=0;ioutput<noutput;++ioutput){
209 if(verbose_opt[0]>=1)
210 cout <<
"scaling for output feature" << ioutput << endl;
212 float theMin=trainingOutput[0][ioutput];
213 float theMax=trainingOutput[0][ioutput];
214 for(
int isample=0;isample<trainingOutput.size();++isample){
215 if(theMin>trainingOutput[isample][ioutput])
216 theMin=trainingOutput[isample][ioutput];
217 if(theMax<trainingOutput[isample][ioutput])
218 theMax=trainingOutput[isample][ioutput];
220 offset_output[ioutput]=theMin+(theMax-theMin)/2.0;
221 scale_output[ioutput]=(theMax-theMin)/2.0;
222 if(verbose_opt[0]>=1){
223 std::cout <<
"Extreme image values for output feature " << ioutput <<
": [" << theMin <<
"," << theMax <<
"]" << std::endl;
224 std::cout <<
"Using offset, scale: " << offset_output[ioutput] <<
", " << scale_output[ioutput] << std::endl;
225 std::cout <<
"scaled values for output feature " << ioutput <<
": [" << (theMin-offset_output[ioutput])/scale_output[ioutput] <<
"," << (theMax-offset_output[ioutput])/scale_output[ioutput] <<
"]" << std::endl;
233 const unsigned int num_layers = nneuron_opt.size()+2;
234 const float desired_error = 0.0003;
235 const unsigned int iterations_between_reports = (verbose_opt[0])? maxit_opt[0]+1:0;
236 if(verbose_opt[0]>=1){
237 cout <<
"creating artificial neural network with " << nneuron_opt.size() <<
" hidden layer, having " << endl;
238 for(
int ilayer=0;ilayer<nneuron_opt.size();++ilayer)
239 cout << nneuron_opt[ilayer] <<
" ";
240 cout <<
"neurons" << endl;
245 unsigned int layers[3];
247 layers[1]=nneuron_opt[0];
249 net.create_sparse_array(connection_opt[0],num_layers,layers);
254 unsigned int layers[3];
256 layers[1]=nneuron_opt[0];
257 layers[2]=nneuron_opt[1];
259 net.create_sparse_array(connection_opt[0],num_layers,layers);
264 cerr <<
"Only 1 or 2 hidden layers are supported!" << endl;
268 if(verbose_opt[0]>=1)
269 cout <<
"network created" << endl;
271 net.set_learning_rate(learning_opt[0]);
276 net.set_activation_function_hidden(FANN::SIGMOID_SYMMETRIC_STEPWISE);
277 net.set_activation_function_output(FANN::SIGMOID_SYMMETRIC_STEPWISE);
283 if(verbose_opt[0]>=1){
284 cout << endl <<
"Network Type : ";
285 switch (net.get_network_type())
288 cout <<
"LAYER" << endl;
291 cout <<
"SHORTCUT" << endl;
294 cout <<
"UNKNOWN" << endl;
297 net.print_parameters();
300 if(verbose_opt[0]>=1){
301 cout <<
"Max Epochs " << setw(8) << maxit_opt[0] <<
". " 302 <<
"Desired Error: " << left << desired_error << right << endl;
304 bool initWeights=
true;
307 for(
unsigned int isample=0;isample<sampleSize;++isample){
308 for(
unsigned int iinput=0;iinput<ninput;++iinput)
309 trainingFeatures[isample][iinput]=(trainingUnits[isample][iinput]-offset_input[iinput])/scale_input[iinput];
313 for(
unsigned int isample=0;isample<sampleSize;++isample){
314 for(
unsigned int ioutput=0;ioutput<noutput;++ioutput)
315 scaledOutput[isample][ioutput]=(trainingOutput[isample][ioutput]-offset_output[ioutput])/scale_output[ioutput];
320 std::cout <<
"cross validation" << std::endl;
321 std::vector< std::vector<float> > referenceVector;
322 std::vector< std::vector<float> > outputVector;
323 net.cross_validation(trainingFeatures,
330 assert(referenceVector.size()==outputVector.size());
331 vector<double> rmse(noutput);
332 for(
int isample=0;isample<referenceVector.size();++isample){
333 std::cout << isample <<
" ";
334 for(
int ioutput=0;ioutput<noutput;++ioutput){
337 double ref=scale_output[ioutput]*referenceVector[isample][ioutput]+offset_output[ioutput];
338 double val=scale_output[ioutput]*outputVector[isample][ioutput]+offset_output[ioutput];
339 rmse[ioutput]+=(ref-val)*(ref-val);
340 std::cout << ref <<
" " << val;
341 if(ioutput<noutput-1)
344 std::cout << std::endl;
347 for(
int ioutput=0;ioutput<noutput;++ioutput)
348 std::cout <<
"rmse output variable " << ioutput <<
": " << sqrt(rmse[ioutput]/referenceVector.size()) << std::endl;
352 net.train_on_data(trainingFeatures,
356 iterations_between_reports,
360 if(verbose_opt[0]>=2){
361 net.print_connections();
362 vector<fann_connection> convector;
363 net.get_connection_array(convector);
364 for(
int i_connection=0;i_connection<net.get_total_connections();++i_connection)
365 cout <<
"connection " << i_connection <<
": " << convector[i_connection].weight << endl;
369 ofstream outputStream;
370 if(!output_opt.empty())
371 outputStream.open(output_opt[0].c_str(),ios::out);
372 for(
unsigned int isample=0;isample<inputUnits.size();++isample){
373 std::vector<float> inputFeatures(ninput);
374 for(
unsigned int iinput=0;iinput<ninput;++iinput)
375 inputFeatures[iinput]=(inputUnits[isample][iinput]-offset_input[iinput])/scale_input[iinput];
376 vector<float> result(noutput);
377 result=net.run(inputFeatures);
379 if(!output_opt.empty())
380 outputStream << isample <<
" ";
382 std::cout << isample <<
" ";
384 for(
unsigned int iinput=0;iinput<ninput;++iinput){
385 if(output_opt.size())
386 outputStream << inputUnits[isample][iinput] <<
" ";
388 std::cout << inputUnits[isample][iinput] <<
" ";
391 for(
unsigned int ioutput=0;ioutput<noutput;++ioutput){
392 result[ioutput]=scale_output[ioutput]*result[ioutput]+offset_output[ioutput];
393 if(output_opt.size()){
394 outputStream << result[ioutput];
395 if(ioutput<noutput-1)
398 outputStream << std::endl;
401 std::cout << result[ioutput];
402 if(ioutput<noutput-1)
405 std::cout << std::endl;
409 if(!output_opt.empty())
410 outputStream.close();