source: trunk/CrossPare/src/de/ugoe/cs/cpdp/execution/AbstractCrossProjectExperiment.java @ 102

Last change on this file since 102 was 98, checked in by sherbold, 9 years ago
  • added the new configuration parameter repetitions and implemented its usage in the AbstractCrossProjectExperiment?. It now allows for multiple storages of the same result in an IResultContainer to allow for repetitions of experiments with random components.
  • Property svn:mime-type set to text/plain
File size: 17.4 KB
Line 
1// Copyright 2015 Georg-August-Universität Göttingen, Germany
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15package de.ugoe.cs.cpdp.execution;
16
17import java.io.File;
18import java.util.Collections;
19import java.util.LinkedList;
20import java.util.List;
21import java.util.logging.Level;
22
23import org.apache.commons.collections4.list.SetUniqueList;
24
25import de.ugoe.cs.cpdp.ExperimentConfiguration;
26import de.ugoe.cs.cpdp.dataprocessing.IProcessesingStrategy;
27import de.ugoe.cs.cpdp.dataprocessing.ISetWiseProcessingStrategy;
28import de.ugoe.cs.cpdp.dataselection.IPointWiseDataselectionStrategy;
29import de.ugoe.cs.cpdp.dataselection.ISetWiseDataselectionStrategy;
30import de.ugoe.cs.cpdp.eval.IEvaluationStrategy;
31import de.ugoe.cs.cpdp.eval.IResultStorage;
32import de.ugoe.cs.cpdp.loader.IVersionLoader;
33import de.ugoe.cs.cpdp.training.ISetWiseTestdataAwareTrainingStrategy;
34import de.ugoe.cs.cpdp.training.ISetWiseTrainingStrategy;
35import de.ugoe.cs.cpdp.training.ITestAwareTrainingStrategy;
36import de.ugoe.cs.cpdp.training.ITrainer;
37import de.ugoe.cs.cpdp.training.ITrainingStrategy;
38import de.ugoe.cs.cpdp.versions.IVersionFilter;
39import de.ugoe.cs.cpdp.versions.SoftwareVersion;
40import de.ugoe.cs.util.console.Console;
41import weka.core.Instances;
42
43/**
44 * Class responsible for executing an experiment according to an {@link ExperimentConfiguration}.
45 * The steps of an experiment are as follows:
46 * <ul>
47 * <li>load the data from the provided data path</li>
48 * <li>filter the data sets according to the provided version filters</li>
49 * <li>execute the following steps for each data sets as test data that is not ignored through the
50 * test version filter:
51 * <ul>
52 * <li>filter the data sets to setup the candidate training data:
53 * <ul>
54 * <li>remove all data sets from the same project</li>
55 * <li>filter all data sets according to the training data filter
56 * </ul>
57 * </li>
58 * <li>apply the setwise preprocessors</li>
59 * <li>apply the setwise data selection algorithms</li>
60 * <li>apply the setwise postprocessors</li>
61 * <li>train the setwise training classifiers</li>
62 * <li>unify all remaining training data into one data set</li>
63 * <li>apply the preprocessors</li>
64 * <li>apply the pointwise data selection algorithms</li>
65 * <li>apply the postprocessors</li>
66 * <li>train the normal classifiers</li>
67 * <li>evaluate the results for all trained classifiers on the training data</li>
68 * </ul>
69 * </li>
70 * </ul>
71 *
72 * Note that this class implements {@link Runnable}, i.e., each experiment can be started in its own
73 * thread.
74 *
75 * @author Steffen Herbold
76 */
77public abstract class AbstractCrossProjectExperiment implements IExecutionStrategy {
78
79    /**
80     * configuration of the experiment
81     */
82    protected final ExperimentConfiguration config;
83
84    /**
85     * Constructor. Creates a new experiment based on a configuration.
86     *
87     * @param config
88     *            configuration of the experiment
89     */
90    public AbstractCrossProjectExperiment(ExperimentConfiguration config) {
91        this.config = config;
92    }
93
94    /**
95     * <p>
96     * Defines which products are allowed for training.
97     * </p>
98     *
99     * @param trainingVersion
100     *            training version
101     * @param testVersion
102     *            test candidate
103     * @return true if test candidate can be used for training
104     */
105    protected abstract boolean isTrainingVersion(SoftwareVersion trainingVersion,
106                                                 SoftwareVersion testVersion);
107
108    /**
109     * Helper method that combines a set of Weka {@link Instances} sets into a single
110     * {@link Instances} set.
111     *
112     * @param traindataSet
113     *            set of {@link Instances} to be combines
114     * @return single {@link Instances} set
115     */
116    public static Instances makeSingleTrainingSet(SetUniqueList<Instances> traindataSet) {
117        Instances traindataFull = null;
118        for (Instances traindata : traindataSet) {
119            if (traindataFull == null) {
120                traindataFull = new Instances(traindata);
121            }
122            else {
123                for (int i = 0; i < traindata.numInstances(); i++) {
124                    traindataFull.add(traindata.instance(i));
125                }
126            }
127        }
128        return traindataFull;
129    }
130
131    /**
132     * Executes the experiment with the steps as described in the class comment.
133     *
134     * @see Runnable#run()
135     */
136    @Override
137    public void run() {
138        final List<SoftwareVersion> versions = new LinkedList<>();
139
140        for (IVersionLoader loader : config.getLoaders()) {
141            versions.addAll(loader.load());
142        }
143
144        for (IVersionFilter filter : config.getVersionFilters()) {
145            filter.apply(versions);
146        }
147        boolean writeHeader = true;
148        int versionCount = 1;
149        int testVersionCount = 0;
150        int numTrainers = 0;
151
152        for (SoftwareVersion testVersion : versions) {
153            if (isVersion(testVersion, config.getTestVersionFilters())) {
154                testVersionCount++;
155            }
156        }
157       
158        numTrainers += config.getSetWiseTrainers().size();
159        numTrainers += config.getSetWiseTestdataAwareTrainers().size();
160        numTrainers += config.getTrainers().size();
161        numTrainers += config.getTestAwareTrainers().size();
162
163        // sort versions
164        Collections.sort(versions);
165
166        for (SoftwareVersion testVersion : versions) {
167            if (isVersion(testVersion, config.getTestVersionFilters())) {
168                Console.traceln(Level.INFO,
169                                String.format("[%s] [%02d/%02d] %s: starting",
170                                              config.getExperimentName(), versionCount,
171                                              testVersionCount, testVersion.getVersion()));
172                int numResultsAvailable = resultsAvailable(testVersion);
173                if (numResultsAvailable >= numTrainers*config.getRepetitions()) {
174                    Console.traceln(Level.INFO,
175                                    String.format(
176                                                  "[%s] [%02d/%02d] %s: results already available; skipped",
177                                                  config.getExperimentName(), versionCount,
178                                                  testVersionCount, testVersion.getVersion()));
179                    versionCount++;
180                    continue;
181                }
182
183                // Setup testdata and training data
184                Instances testdata = testVersion.getInstances();
185                SetUniqueList<Instances> traindataSet =
186                    SetUniqueList.setUniqueList(new LinkedList<Instances>());
187                for (SoftwareVersion trainingVersion : versions) {
188                    if (isVersion(trainingVersion, config.getTrainingVersionFilters())) {
189                        if (trainingVersion != testVersion) {
190                            if (isTrainingVersion(trainingVersion, testVersion)) {
191                                traindataSet.add(trainingVersion.getInstances());
192                            }
193                        }
194                    }
195                }
196
197                for (ISetWiseProcessingStrategy processor : config.getSetWisePreprocessors()) {
198                    Console.traceln(Level.FINE,
199                                    String.format(
200                                                  "[%s] [%02d/%02d] %s: applying setwise preprocessor %s",
201                                                  config.getExperimentName(), versionCount,
202                                                  testVersionCount, testVersion.getVersion(),
203                                                  processor.getClass().getName()));
204                    processor.apply(testdata, traindataSet);
205                }
206                for (ISetWiseDataselectionStrategy dataselector : config.getSetWiseSelectors()) {
207                    Console
208                        .traceln(Level.FINE,
209                                 String.format("[%s] [%02d/%02d] %s: applying setwise selection %s",
210                                               config.getExperimentName(), versionCount,
211                                               testVersionCount, testVersion.getVersion(),
212                                               dataselector.getClass().getName()));
213                    dataselector.apply(testdata, traindataSet);
214                }
215                for (ISetWiseProcessingStrategy processor : config.getSetWisePostprocessors()) {
216                    Console.traceln(Level.FINE,
217                                    String.format(
218                                                  "[%s] [%02d/%02d] %s: applying setwise postprocessor %s",
219                                                  config.getExperimentName(), versionCount,
220                                                  testVersionCount, testVersion.getVersion(),
221                                                  processor.getClass().getName()));
222                    processor.apply(testdata, traindataSet);
223                }
224                for (ISetWiseTrainingStrategy setwiseTrainer : config.getSetWiseTrainers()) {
225                    Console
226                        .traceln(Level.FINE,
227                                 String.format("[%s] [%02d/%02d] %s: applying setwise trainer %s",
228                                               config.getExperimentName(), versionCount,
229                                               testVersionCount, testVersion.getVersion(),
230                                               setwiseTrainer.getName()));
231                    setwiseTrainer.apply(traindataSet);
232                }
233                for (ISetWiseTestdataAwareTrainingStrategy setwiseTestdataAwareTrainer : config
234                    .getSetWiseTestdataAwareTrainers())
235                {
236                    Console.traceln(Level.FINE,
237                                    String.format(
238                                                  "[%s] [%02d/%02d] %s: applying testdata aware setwise trainer %s",
239                                                  config.getExperimentName(), versionCount,
240                                                  testVersionCount, testVersion.getVersion(),
241                                                  setwiseTestdataAwareTrainer.getName()));
242                    setwiseTestdataAwareTrainer.apply(traindataSet, testdata);
243                }
244                Instances traindata = makeSingleTrainingSet(traindataSet);
245                for (IProcessesingStrategy processor : config.getPreProcessors()) {
246                    Console.traceln(Level.FINE,
247                                    String.format("[%s] [%02d/%02d] %s: applying preprocessor %s",
248                                                  config.getExperimentName(), versionCount,
249                                                  testVersionCount, testVersion.getVersion(),
250                                                  processor.getClass().getName()));
251                    processor.apply(testdata, traindata);
252                }
253                for (IPointWiseDataselectionStrategy dataselector : config
254                    .getPointWiseSelectors())
255                {
256                    Console.traceln(Level.FINE,
257                                    String.format(
258                                                  "[%s] [%02d/%02d] %s: applying pointwise selection %s",
259                                                  config.getExperimentName(), versionCount,
260                                                  testVersionCount, testVersion.getVersion(),
261                                                  dataselector.getClass().getName()));
262                    traindata = dataselector.apply(testdata, traindata);
263                }
264                for (IProcessesingStrategy processor : config.getPostProcessors()) {
265                    Console.traceln(Level.FINE,
266                                    String.format(
267                                                  "[%s] [%02d/%02d] %s: applying setwise postprocessor %s",
268                                                  config.getExperimentName(), versionCount,
269                                                  testVersionCount, testVersion.getVersion(),
270                                                  processor.getClass().getName()));
271                    processor.apply(testdata, traindata);
272                }
273                for (ITrainingStrategy trainer : config.getTrainers()) {
274                    Console.traceln(Level.FINE,
275                                    String.format("[%s] [%02d/%02d] %s: applying trainer %s",
276                                                  config.getExperimentName(), versionCount,
277                                                  testVersionCount, testVersion.getVersion(),
278                                                  trainer.getName()));
279                    trainer.apply(traindata);
280                }
281                for (ITestAwareTrainingStrategy trainer : config.getTestAwareTrainers()) {
282                    Console.traceln(Level.FINE,
283                                    String.format("[%s] [%02d/%02d] %s: applying trainer %s",
284                                                  config.getExperimentName(), versionCount,
285                                                  testVersionCount, testVersion.getVersion(),
286                                                  trainer.getName()));
287                    trainer.apply(testdata, traindata);
288                }
289                File resultsDir = new File(config.getResultsPath());
290                if (!resultsDir.exists()) {
291                    resultsDir.mkdir();
292                }
293                for (IEvaluationStrategy evaluator : config.getEvaluators()) {
294                    Console.traceln(Level.FINE,
295                                    String.format("[%s] [%02d/%02d] %s: applying evaluator %s",
296                                                  config.getExperimentName(), versionCount,
297                                                  testVersionCount, testVersion.getVersion(),
298                                                  evaluator.getClass().getName()));
299                    List<ITrainer> allTrainers = new LinkedList<>();
300                    for (ISetWiseTrainingStrategy setwiseTrainer : config.getSetWiseTrainers()) {
301                        allTrainers.add(setwiseTrainer);
302                    }
303                    for (ISetWiseTestdataAwareTrainingStrategy setwiseTestdataAwareTrainer : config
304                        .getSetWiseTestdataAwareTrainers())
305                    {
306                        allTrainers.add(setwiseTestdataAwareTrainer);
307                    }
308                    for (ITrainingStrategy trainer : config.getTrainers()) {
309                        allTrainers.add(trainer);
310                    }
311                    for (ITestAwareTrainingStrategy trainer : config.getTestAwareTrainers()) {
312                        allTrainers.add(trainer);
313                    }
314                    if (writeHeader) {
315                        evaluator.setParameter(config.getResultsPath() + "/" +
316                            config.getExperimentName() + ".csv");
317                    }
318                    evaluator.apply(testdata, traindata, allTrainers, writeHeader,
319                                    config.getResultStorages());
320                    writeHeader = false;
321                }
322                Console.traceln(Level.INFO,
323                                String.format("[%s] [%02d/%02d] %s: finished",
324                                              config.getExperimentName(), versionCount,
325                                              testVersionCount, testVersion.getVersion()));
326                versionCount++;
327            }
328        }
329    }
330
331    /**
332     * Helper method that checks if a version passes all filters.
333     *
334     * @param version
335     *            version that is checked
336     * @param filters
337     *            list of the filters
338     * @return true, if the version passes all filters, false otherwise
339     */
340    private boolean isVersion(SoftwareVersion version, List<IVersionFilter> filters) {
341        boolean result = true;
342        for (IVersionFilter filter : filters) {
343            result &= !filter.apply(version);
344        }
345        return result;
346    }
347
348    private int resultsAvailable(SoftwareVersion version) {
349        if (config.getResultStorages().isEmpty()) {
350            return 0;
351        }
352        int available = Integer.MAX_VALUE;
353        for (IResultStorage storage : config.getResultStorages()) {
354            int curAvailable = storage.containsResult(config.getExperimentName(), version.getVersion());
355            if( curAvailable<available ) {
356                available = curAvailable;
357            }
358        }
359        return available;
360    }
361}
Note: See TracBrowser for help on using the repository browser.