trainPCA.cc
1 const char *help = "\
2 progname: trainPCA.cc\n\
3 code2html: This program computes PCA projection sub-space.\n\
4 version: Torch3 vision2.0, 2003-2005\n\
5 (c) Sebastien Marcel (marcel@idiap.ch)\n";
6
7 #include "FileBinDataSet.h"
8 #include "DiskBinDataSet.h"
9 #include "PCATrainer.h"
10 #include "MeanVarNorm.h"
11 #include "HistoEqualSmoothImagePreProcessing.h"
12 #include "FileListCmdOption.h"
13 #include "CmdLine.h"
14
15 using namespace Torch;
16
17 int main(int argc, char **argv)
18 {
19 int n_inputs;
20 int offset_window;
21 int n_inputs_window;
22 char *model_file;
23 bool verbose;
24 int verbose_level;
25 bool normalize;
26 bool forward;
27 bool saveCovar;
28 bool use_disk;
29 bool image_normalize;
30 int width, height;
31
32 Allocator *allocator = new Allocator;
33 DiskXFile::setLittleEndianMode();
34
35
36
37 //=================== The command-line ==========================
38 FileListCmdOption filelist("file name", "the list files or one data file");
39 filelist.isArgument(true);
40
41 // Construct the command line
42 CmdLine cmd;
43 cmd.setBOption("write log", false);
44
45 // Put the help line at the beginning
46 cmd.info(help);
47
48 cmd.addText("\nArguments:");
49 cmd.addCmdOption(&filelist);
50 cmd.addICmdArg("n_inputs", &n_inputs, "input dimension of the data", true);
51 cmd.addText("\nOptions:");
52 cmd.addICmdOption("-offset_window", &offset_window, 0, "offset window", true);
53 cmd.addICmdOption("-n_inputs_window", &n_inputs_window, -1, "input dimension of the window", true);
54 cmd.addBCmdOption("-saveCovar", &saveCovar, false, "save the covariance matrix", true);
55 cmd.addBCmdOption("-normalize", &normalize, false, "normalization", true);
56 cmd.addBCmdOption("-verbose", &verbose, false, "verbose", true);
57 cmd.addICmdOption("-verbose_level", &verbose_level, 0, "verbose level", true);
58 cmd.addBCmdOption("-forward", &forward, false, "project data into PCA sub-space", true);
59 cmd.addSCmdOption("-save", &model_file, "", "model file", true);
60 cmd.addBCmdOption("-use_disk", &use_disk, false, "use disk");
61 cmd.addBCmdOption("-imagenorm", &image_normalize, false, "considers the input pattern as an image and performs a photometric normalization");
62 cmd.addICmdOption("-width", &width, -1, "width");
63 cmd.addICmdOption("-height", &height, -1, "height");
64
65 // Read the command line
66 cmd.read(argc, argv);
67
68 if(n_inputs_window == -1) n_inputs_window = n_inputs;
69
70 if(image_normalize)
71 {
72 print("Perform photometric normalization ...\n");
73
74 print("The input pattern is an %dx%d image.\n", width, height);
75 }
76
77 //
78 if(verbose)
79 {
80 print(" + n_filenames = %d\n", filelist.n_files);
81 for(int i = 0 ; i < filelist.n_files ; i++)
82 print(" filename[%d] = %s\n", i, filelist.file_names[i]);
83 }
84
85
86 //
87 // The PCA Machine
88 PCAMachine *pca_machine = NULL;
89 pca_machine = new(allocator) PCAMachine(n_inputs_window);
90 pca_machine->setIOption("verbose_level", verbose_level);
91
92 //
93 // The PCA Trainer
94 Trainer *pca_trainer = NULL;
95
96 pca_trainer = new(allocator) PCATrainer(pca_machine);
97 pca_trainer->setBOption("saveCovar", saveCovar);
98 pca_trainer->setIOption("verbose_level", verbose_level);
99
100
101 //
102 // Load all the data in the same dataset
103 DataSet *bindata = NULL;
104
105 if(use_disk)
106 {
107 DiskBinDataSet *bindata_ = new(allocator) DiskBinDataSet(filelist.file_names, filelist.n_files, n_inputs, -1);
108 bindata_->info(false);
109
110 bindata = bindata_;
111 }
112 else
113 {
114 //FileBinDataSet *bindata = new(allocator) FileBinDataSet(filelist.file_names, filelist.n_files, 0.0, n_inputs);
115 //FileBinDataSet *bindata = new(allocator) FileBinDataSet(filelist.file_names, filelist.n_files, n_inputs, offset_window, n_inputs_window);
116 FileBinDataSet *bindata_ = new(allocator) FileBinDataSet(filelist.file_names, filelist.n_files, n_inputs, offset_window, n_inputs_window);
117 bindata_->info(false);
118
119 bindata = bindata_;
120 }
121
122 //
123 if(image_normalize)
124 {
125 print("Pre-processing image %dx%d ...\n", width, height);
126 PreProcessing *preprocess = new(allocator) HistoEqualSmoothImagePreProcessing(width, height);
127
128 bindata->preProcess(preprocess);
129 }
130
131 //
132 MeanVarNorm *mv_norm = NULL;
133 if(normalize)
134 {
135 print("Normalization ...\n");
136
137 mv_norm = new(allocator) MeanVarNorm(bindata);
138 bindata->preProcess(mv_norm);
139 }
140
141
142 //
143 // Computes PCA
144 pca_trainer->train(bindata, NULL);
145
146
147 //
148 // Project data into PCA sub-space
149 real *realinput = NULL;
150 Sequence *seq = NULL;
151
152 if(forward)
153 {
154 realinput = new real [n_inputs_window];
155 seq = new Sequence(&realinput, 1, n_inputs_window);
156
157 //
158 pca_machine->setROption("variance", 0.95);
159 pca_machine->init();
160
161 for(int i=0; i< bindata->n_examples; i++)
162 {
163 if(verbose)
164 print("[%d]:\n", i);
165
166 //
167 bindata->setExample(i);
168
169 if(verbose)
170 print(" Input = [%2.3f %2.3f %2.3f ...]\n", bindata->inputs->frames[0][0], bindata->inputs->frames[0][1], bindata->inputs->frames[0][2]);
171
172 //
173 bindata->inputs->copyTo(realinput);
174
175 if(verbose)
176 print(" Seq = [%2.3f %2.3f %2.3f ...]\n", realinput[0], realinput[1], realinput[2]);
177
178 //
179 pca_machine->forward(seq);
180
181 if(verbose)
182 print(" Output = [%2.3f %2.3f %2.3f ...]\n", pca_machine->outputs->frames[0][0], pca_machine->outputs->frames[0][1], pca_machine->outputs->frames[0][2]);
183 }
184 }
185
186
187 //
188 // Save the model
189 if(strcmp(model_file, "") != 0)
190 {
191 if(normalize)
192 {
193 print("Saving PCA model and its normalisation...\n");
194
195 pca_machine->save(model_file, mv_norm);
196 }
197 else
198 {
199 print("Saving PCA model ...\n");
200
201 DiskXFile *file = NULL;
202
203 file = new DiskXFile(model_file, "w");
204
205 pca_machine->saveXFile(file);
206
207 delete file;
208 }
209 }
210
211
212
213 //
214 // Free memory
215 if(forward)
216 {
217 delete [] realinput;
218 delete seq;
219 }
220 delete allocator;
221
222 return(0);
223 }