1 package yawn.ui.cli;
2
3 import java.io.FileNotFoundException;
4 import java.io.FileReader;
5
6 import org.apache.commons.cli.CommandLine;
7 import org.apache.commons.cli.GnuParser;
8 import org.apache.commons.cli.HelpFormatter;
9 import org.apache.commons.cli.MissingArgumentException;
10 import org.apache.commons.cli.MissingOptionException;
11 import org.apache.commons.cli.Option;
12 import org.apache.commons.cli.Options;
13 import org.apache.commons.cli.ParseException;
14 import org.apache.commons.cli.UnrecognizedOptionException;
15 import org.apache.commons.lang.StringUtils;
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18 import org.apache.log4j.Level;
19 import org.apache.log4j.Logger;
20
21 import yawn.config.ValidationException;
22 import yawn.envs.EnvironmentException;
23 import yawn.io.DuplicateKeyException;
24 import yawn.io.Experiment;
25 import yawn.io.IStorage;
26 import yawn.io.StorageException;
27 import yawn.io.serialization.SerializationException;
28 import yawn.io.serialization.xml.CastorXmlSerializer;
29 import yawn.io.xml.XmlStorage;
30 import yawn.nn.NeuralNetwork;
31 import yawn.util.InputOutputPattern;
32 import yawn.util.Pattern;
33
34 /***
35 * Trains and tests a neural network using a given test environment. It reads
36 * its configuration from an XML file.
37 *
38 * <p>$Id: RunExperiment.java,v 1.9 2005/05/09 11:04:54 supermarti Exp $</p>
39 *
40 * @author Luis Martí (luis dot marti at uc3m dot es)
41 * @version $Revision: 1.9 $
42 */
43
44 public class RunExperiment implements Runnable {
45
46 private static final Log log = LogFactory.getLog(RunExperiment.class);
47
48 protected static void printHelpMessage(String usageMessage, Options options) {
49 HelpFormatter hf = new HelpFormatter();
50
51 hf.printHelp(usageMessage, options, true);
52 }
53
54 protected static void printErrorMessage(String error) {
55 log.fatal("Application error message: " + error);
56 }
57
58 private static Option EXPERIMENT_OPTION = new Option("x", "experiment", true,
59 "Experiment config file to use");
60
61 private static Option HELP_OPTION = new Option("h", "help", false, "View this help message");
62
63 private static Option QUIET_OPTION = new Option("q", "quiet", false,
64 "Do not show welcome message");
65
66 private static String USAGE_MESG = "java yawn.ui.cli.RunExperiment";
67
68 private static Option VERB_OPTION = new Option("v", "verbose", false, "Show execution messages");
69
70 private static Option DEBUG_OPTION = new Option("d", "debug", false, "Show debug messages");
71
72 private static String WELCOME_MESG = "\nWelcome to RunExperiment: A simple interface to the Yawn library.\n"
73 + "Distributed under the GNU license (see http://www.gnu.org/licenses/gpl.html).\n"
74 + "Check http://yawn2.sourceforge.net for updates.\n";
75
76 /***
77 *
78 */
79 protected String experimentFileName = null;
80
81 /***
82 *
83 */
84 protected boolean verbose = false;
85
86 /***
87 *
88 */
89 protected boolean debug = false;
90
91 /***
92 * @return Returns the debug.
93 */
94 public boolean isDebug() {
95 return debug;
96 }
97
98 /***
99 * @param debug
100 * The debug to set.
101 */
102 public void setDebug(boolean debug) {
103 this.debug = debug;
104 }
105
106 /***
107 *
108 * @uml.property name="welcomeMsgEnabled"
109 */
110 protected boolean welcomeMsgEnabled = false;
111
112
113 public static void main(String args[]) {
114 CommandLine cl = null;
115 try {
116 cl = parseCommandLine(args);
117 } catch (CommandLineHaltRequestedException e) {
118 System.exit(1);
119 }
120
121 RunExperiment re = new RunExperiment();
122 re.setPropertiesFromCommandLine(cl);
123 re.run();
124 }
125
126 private static CommandLine parseCommandLine(String[] args)
127 throws CommandLineHaltRequestedException {
128 EXPERIMENT_OPTION.setRequired(true);
129 EXPERIMENT_OPTION.setArgs(1);
130 EXPERIMENT_OPTION.setArgName("conf-file");
131
132 Options options = new Options();
133 options.addOption(EXPERIMENT_OPTION);
134 options.addOption(QUIET_OPTION);
135 options.addOption(VERB_OPTION);
136 options.addOption(DEBUG_OPTION);
137
138
139 for (int i = 0; i < args.length; i++) {
140 if (args[i].equals("-" + HELP_OPTION.getOpt())
141 || args[i].equals("--" + HELP_OPTION.getLongOpt())) {
142 printHelpMessage(USAGE_MESG, options);
143 throw new CommandLineHaltRequestedException();
144 }
145 }
146
147 CommandLine cl = null;
148
149 try {
150 return (new GnuParser()).parse(options, args);
151 } catch (ParseException e) {
152 if (e instanceof MissingOptionException) {
153 printErrorMessage("Missing required option `" + e.getMessage() + "'.");
154 } else if (e instanceof MissingArgumentException) {
155 printErrorMessage("Missing required argument.");
156 } else if (e instanceof UnrecognizedOptionException) {
157 printErrorMessage("Unrecognized option `" + e.getMessage() + "'.");
158 } else {
159 printErrorMessage(e.getMessage());
160 }
161 printHelpMessage(USAGE_MESG, options);
162 throw new CommandLineHaltRequestedException();
163 }
164 }
165
166 /***
167 *
168 */
169 public RunExperiment() {
170 super();
171 }
172
173 /***
174 * @return Returns the experimentFileName.
175 *
176 * @uml.property name="experimentFileName"
177 */
178 public String getExperimentFileName() {
179 return experimentFileName;
180 }
181
182 /***
183 * @return Returns the verbose.
184 *
185 * @uml.property name="verbose"
186 */
187 public boolean isVerbose() {
188 return verbose;
189 }
190
191 /***
192 * @return Returns the welcomeMsgEnabled.
193 *
194 * @uml.property name="welcomeMsgEnabled"
195 */
196 public boolean isWelcomeMsgEnabled() {
197 return welcomeMsgEnabled;
198 }
199
200
201 /***
202 *
203 * @see java.lang.Runnable#run()
204 */
205 public void run() {
206
207 if (isWelcomeMsgEnabled()) {
208 System.out.println(WELCOME_MESG);
209 }
210
211 if (isVerbose()) {
212 Logger.getRootLogger().setLevel(Level.INFO);
213 }
214
215 if (isDebug()) {
216 Logger.getRootLogger().setLevel(Level.DEBUG);
217 }
218
219 Experiment experiment = null;
220 FileReader reader;
221
222 try {
223 reader = new FileReader(getExperimentFileName());
224 experiment = (Experiment) (new CastorXmlSerializer()).deSerialize(Experiment.class,
225 reader);
226 } catch (SerializationException e2) {
227 log.debug(e2);
228 printErrorMessage("Unable to parse the experiment file.");
229 return;
230 } catch (FileNotFoundException e1) {
231 log.debug(e1);
232 printErrorMessage("The experiment file supplied does not exists.");
233 return;
234 }
235
236 try {
237 experiment.getEnvironment().validate();
238 } catch (ValidationException e4) {
239 printErrorMessage("The test environment is not set up correctly, check your configuration file.");
240 return;
241 }
242
243 experiment.getNeuralNetwork().setEnvironment(experiment.getEnvironment());
244
245 log.info("Configuration loaded, everything seems to be ok...");
246 log.debug("Using " + experiment.getNeuralNetwork().getBindedNetworkClass()
247 + " as learning method.");
248 log.debug("Using " + experiment.getEnvironment() + " as test environment.");
249
250 int numberOfRuns = experiment.getEnvironment().getNumberOfSystemRuns();
251
252 if (numberOfRuns == 0) {
253 printErrorMessage("According to your configuration the number of system run is zero, therefore I wont run ;).");
254 }
255
256 int padding = numberOfRuns / 10;
257
258 for (int run = 0; run < numberOfRuns; run++) {
259 log.info("Starting system run number: " + String.valueOf(run + 1) + " of "
260 + numberOfRuns + ".");
261
262 log.debug("Loading datasets...");
263
264 InputOutputPattern[] trainPatterns = null;
265 Pattern[] testPatterns = null;
266
267 try {
268 trainPatterns = experiment.getEnvironment().getTrainingDataset(run);
269 testPatterns = experiment.getEnvironment().getTestDatasetInputs(run);
270 } catch (EnvironmentException e) {
271 log.debug(e);
272 printErrorMessage("The specified problem dataset location is invalid.");
273 return;
274 }
275
276 log.debug("Training set size: " + trainPatterns.length + ", test set size: "
277 + testPatterns.length + ".");
278
279 NeuralNetwork nn = experiment.getNeuralNetwork().configuredNetworkFactory();
280
281 log.debug("Training (this may take a while)...");
282
283 nn.train(trainPatterns);
284
285 log.debug("Testing... ");
286
287 Pattern[] predictions = new Pattern[testPatterns.length];
288 for (int i = 0; i < testPatterns.length; i++) {
289 predictions[i] = nn.predict(testPatterns[i]);
290 }
291
292 log.debug("Writing results...");
293
294 try {
295 experiment.getEnvironment().writeResults(predictions, run);
296 } catch (EnvironmentException e) {
297 log.debug(e);
298 printErrorMessage("Imposible to write prediction results.");
299 return;
300 }
301
302 if (experiment.getStorage() != null) {
303 log.info("Saving network...");
304 IStorage storage = experiment.getStorage();
305
306 if (storage instanceof XmlStorage) {
307 XmlStorage xmlStorage = (XmlStorage) storage;
308 String origSuffix = xmlStorage.getFileNameSuffix();
309 xmlStorage.setFileNameSuffix(StringUtils.leftPad(String.valueOf(run), padding,
310 "0")
311 + origSuffix);
312 String key = storage.generateKey(nn);
313 try {
314 storage.insert(nn, key);
315 } catch (DuplicateKeyException e3) {
316
317 e3.printStackTrace();
318 } catch (StorageException e3) {
319 log.debug(e3);
320 printErrorMessage("Unable to store network. Probable cause: "
321 + e3.getMessage() + ".");
322 }
323 }
324 }
325 }
326 if (isWelcomeMsgEnabled()) {
327 System.out.println("I have finished without errors, bye, bye...");
328 }
329 }
330
331 /***
332 * @param experimentFileName
333 * The experimentFileName to set.
334 */
335 public void setExperimentFileName(String experimentFileName) {
336 this.experimentFileName = experimentFileName;
337 }
338
339
340 private void setPropertiesFromCommandLine(CommandLine cl) {
341 setExperimentFileName(cl.getOptionValue(EXPERIMENT_OPTION.getOpt()));
342 setVerbose(cl.hasOption(VERB_OPTION.getOpt()));
343 setDebug(cl.hasOption(DEBUG_OPTION.getOpt()));
344 setWelcomeMsgEnabled(!cl.hasOption(QUIET_OPTION.getOpt()));
345 }
346
347 /***
348 * @param verbose
349 * The verbose to set.
350 */
351 public void setVerbose(boolean verbose) {
352 this.verbose = verbose;
353 }
354
355 /***
356 * @param welcomeMsgEnabled
357 * The welcomeMsgEnabled to set.
358 */
359 public void setWelcomeMsgEnabled(boolean welcomeMsgEnabled) {
360 this.welcomeMsgEnabled = welcomeMsgEnabled;
361 }
362
363 }