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

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