@Override public void doWork() throws OperatorException { ExampleSet exampleSetOriginal = exampleSetInput.getData(ExampleSet.class); ExampleSet exampleSet = (ExampleSet) exampleSetOriginal.clone(); int numberOfAttributes = exampleSet.getAttributes().size(); Attributes attributes = exampleSet.getAttributes(); int maxNumberOfAttributes = Math.min(getParameterAsInt(PARAMETER_MAX_ATTRIBUTES), numberOfAttributes - 1); int maxNumberOfFails = getParameterAsInt(PARAMETER_ALLOWED_CONSECUTIVE_FAILS); int behavior = getParameterAsInt(PARAMETER_STOPPING_BEHAVIOR); boolean useRelativeIncrease = (behavior == WITH_DECREASE_EXCEEDS) ? getParameterAsBoolean(PARAMETER_USE_RELATIVE_DECREASE) : false; double maximalDecrease = 0; if (useRelativeIncrease) maximalDecrease = useRelativeIncrease ? getParameterAsDouble(PARAMETER_MAX_RELATIVE_DECREASE) : getParameterAsDouble(PARAMETER_MAX_ABSOLUT_DECREASE); double alpha = (behavior == WITH_DECREASE_SIGNIFICANT) ? getParameterAsDouble(PARAMETER_ALPHA) : 0d; // remembering attributes and removing all from example set Attribute[] attributeArray = new Attribute[numberOfAttributes]; int i = 0; Iterator<Attribute> iterator = attributes.iterator(); while (iterator.hasNext()) { Attribute attribute = iterator.next(); attributeArray[i] = attribute; i++; } boolean[] selected = new boolean[numberOfAttributes]; Arrays.fill(selected, true); boolean earlyAbort = false; List<Integer> speculativeList = new ArrayList<Integer>(maxNumberOfFails); int numberOfFails = maxNumberOfFails; currentNumberOfFeatures = numberOfAttributes; currentAttributes = attributes; PerformanceVector lastPerformance = getPerformance(exampleSet); PerformanceVector bestPerformanceEver = lastPerformance; for (i = 0; i < maxNumberOfAttributes && !earlyAbort; i++) { // setting values for logging currentNumberOfFeatures = numberOfAttributes - i - 1; // performing a round int bestIndex = 0; PerformanceVector currentBestPerformance = null; for (int current = 0; current < numberOfAttributes; current++) { if (selected[current]) { // switching off attributes.remove(attributeArray[current]); currentAttributes = attributes; // evaluate performance PerformanceVector performance = getPerformance(exampleSet); if (currentBestPerformance == null || performance.compareTo(currentBestPerformance) > 0) { bestIndex = current; currentBestPerformance = performance; } // switching on attributes.addRegular(attributeArray[current]); currentAttributes = null; // removing reference } } double currentFitness = currentBestPerformance.getMainCriterion().getFitness(); if (i != 0) { double lastFitness = lastPerformance.getMainCriterion().getFitness(); // switch stopping behavior switch (behavior) { case WITH_DECREASE: if (lastFitness >= currentFitness) earlyAbort = true; break; case WITH_DECREASE_EXCEEDS: if (useRelativeIncrease) { // relative increase testing if (currentFitness < lastFitness - Math.abs(lastFitness * maximalDecrease)) earlyAbort = true; } else { // absolute increase testing if (currentFitness < lastFitness - maximalDecrease) earlyAbort = true; } break; case WITH_DECREASE_SIGNIFICANT: AnovaCalculator calculator = new AnovaCalculator(); calculator.setAlpha(alpha); PerformanceCriterion pc = currentBestPerformance.getMainCriterion(); calculator.addGroup(pc.getAverageCount(), pc.getAverage(), pc.getVariance()); pc = lastPerformance.getMainCriterion(); calculator.addGroup(pc.getAverageCount(), pc.getAverage(), pc.getVariance()); SignificanceTestResult result; try { result = calculator.performSignificanceTest(); } catch (SignificanceCalculationException e) { throw new UserError(this, 920, e.getMessage()); } if (lastFitness > currentFitness && result.getProbability() < alpha) earlyAbort = true; } } if (earlyAbort) { // check if there are some free tries left if (numberOfFails == 0) { break; } numberOfFails--; speculativeList.add(bestIndex); earlyAbort = false; // needs performance increase compared to better performance of current and last! if (currentBestPerformance.compareTo(lastPerformance) > 0) lastPerformance = currentBestPerformance; } else { // resetting maximal number of fails. numberOfFails = maxNumberOfFails; speculativeList.clear(); lastPerformance = currentBestPerformance; bestPerformanceEver = currentBestPerformance; } // switching best index off attributes.remove(attributeArray[bestIndex]); selected[bestIndex] = false; } // add predictively removed attributes: speculative execution did not yield good result for (Integer removeIndex : speculativeList) { selected[removeIndex] = true; attributes.addRegular(attributeArray[removeIndex]); } AttributeWeights weights = new AttributeWeights(); i = 0; for (Attribute attribute : attributeArray) { if (selected[i]) weights.setWeight(attribute.getName(), 1d); else weights.setWeight(attribute.getName(), 0d); i++; } exampleSetOutput.deliver(exampleSet); performanceOutput.deliver(bestPerformanceEver); weightsOutput.deliver(weights); }
// start @Override public void doWork() throws OperatorException { getParametersToOptimize(); if (numberOfCombinations <= 1) { throw new UserError(this, 922); } int ifExceedsRegion = getParameterAsInt(PARAMETER_IF_EXCEEDS_REGION); int ifExceedsRange = getParameterAsInt(PARAMETER_IF_EXCEEDS_RANGE); // sort parameter values String[] valuesToSort; String s; double val1; double val2; int ind1; int ind2; for (int index = 0; index < numberOfParameters; index++) { valuesToSort = values[index]; // straight-insertion-sort of valuesToSort for (ind1 = 0; ind1 < valuesToSort.length; ind1++) { val1 = Double.parseDouble(valuesToSort[ind1]); for (ind2 = ind1 + 1; ind2 < valuesToSort.length; ind2++) { val2 = Double.parseDouble(valuesToSort[ind2]); if (val1 > val2) { s = valuesToSort[ind1]; valuesToSort[ind1] = valuesToSort[ind2]; valuesToSort[ind2] = s; val1 = val2; } } } } int[] bestIndex = new int[numberOfParameters]; ParameterSet[] allParameters = new ParameterSet[numberOfCombinations]; int paramIndex = 0; // Test all parameter combinations best = null; // init operator progress (+ 1 for work after loop) getProgress().setTotal(allParameters.length + 1); while (true) { getLogger().fine("Using parameter set"); // set all parameter values for (int j = 0; j < operators.length; j++) { operators[j].getParameters().setParameter(parameters[j], values[j][currentIndex[j]]); getLogger().fine(operators[j] + "." + parameters[j] + " = " + values[j][currentIndex[j]]); } PerformanceVector performance = getPerformanceVector(); String[] currentValues = new String[parameters.length]; for (int j = 0; j < parameters.length; j++) { currentValues[j] = values[j][currentIndex[j]]; } allParameters[paramIndex] = new ParameterSet(operators, parameters, currentValues, performance); if (best == null || performance.compareTo(best.getPerformance()) > 0) { best = allParameters[paramIndex]; // bestIndex = currentIndex; for (int j = 0; j < numberOfParameters; j++) { bestIndex[j] = currentIndex[j]; } } getProgress().step(); // next parameter values int k = 0; boolean ok = true; while (!(++currentIndex[k] < values[k].length)) { currentIndex[k] = 0; k++; if (k >= currentIndex.length) { ok = false; break; } } if (!ok) { break; } paramIndex++; } // start quadratic optimization int nrParameters = 0; for (int i = 0; i < numberOfParameters; i++) { if (values[i].length > 2) { log("Param " + i + ", bestI = " + bestIndex[i]); nrParameters++; if (bestIndex[i] == 0) { bestIndex[i]++; } if (bestIndex[i] == values[i].length - 1) { bestIndex[i]--; } } else { getLogger().warning("Parameter " + parameters[i] + " has less than 3 values, skipped."); } } if (nrParameters > 3) { getLogger() .warning("Optimization not recommended for more than 3 values. Check results carefully!"); } if (nrParameters > 0) { // Designmatrix A fuer den 3^nrParameters-Plan aufstellen, // A*x=y loesen lassen // x = neue Parameter // check, ob neuen Parameter in zulaessigem Bereich // - Okay, wenn in Kubus von 3^k-Plan // - Warnung wenn in gegebenem Parameter-Bereich // - Fehler sonst int threetok = 1; for (int i = 0; i < nrParameters; i++) { threetok *= 3; } log("Optimising " + nrParameters + " parameters"); Matrix designMatrix = new Matrix(threetok, nrParameters + nrParameters * (nrParameters + 1) / 2 + 1); Matrix y = new Matrix(threetok, 1); paramIndex = 0; for (int i = numberOfParameters - 1; i >= 0; i--) { if (values[i].length > 2) { currentIndex[i] = bestIndex[i] - 1; } else { currentIndex[i] = bestIndex[i]; } paramIndex = paramIndex * values[i].length + currentIndex[i]; } int row = 0; int c; while (row < designMatrix.getRowDimension()) { y.set(row, 0, allParameters[paramIndex].getPerformance().getMainCriterion().getFitness()); designMatrix.set(row, 0, 1.0); c = 1; // compute A for (int i = 0; i < nrParameters; i++) { if (values[i].length > 2) { designMatrix.set(row, c, Double.parseDouble(values[i][currentIndex[i]])); c++; } } // compute C for (int i = 0; i < nrParameters; i++) { if (values[i].length > 2) { for (int j = i + 1; j < nrParameters; j++) { if (values[j].length > 2) { designMatrix.set( row, c, Double.parseDouble(values[i][currentIndex[i]]) * Double.parseDouble(values[j][currentIndex[j]])); c++; } } } } // compute Q: for (int i = 0; i < nrParameters; i++) { if (values[i].length > 2) { designMatrix.set( row, c, Double.parseDouble(values[i][currentIndex[i]]) * Double.parseDouble(values[i][currentIndex[i]])); c++; } } // update currentIndex and paramIndex int k = 0; c = 1; while (k < numberOfParameters) { if (values[k].length > 2) { currentIndex[k]++; paramIndex += c; if (currentIndex[k] > bestIndex[k] + 1) { currentIndex[k] = bestIndex[k] - 1; paramIndex -= 3 * c; c *= values[k].length; k++; } else { break; } } else { c *= values[k].length; k++; } } row++; } // compute Designmatrix Matrix beta = designMatrix.solve(y); for (int i = 0; i < designMatrix.getColumnDimension(); i++) { logWarning(" -- Writing " + beta.get(i, 0) + " at position " + i + " in vector b"); } // generate Matrix P~ Matrix p = new Matrix(nrParameters, nrParameters); int betapos = nrParameters + 1; for (int j = 0; j < nrParameters - 1; j++) { for (int i = 1 + j; i < nrParameters; i++) { p.set(i, j, beta.get(betapos, 0) * 0.5); p.set(j, i, beta.get(betapos, 0) * 0.5); betapos++; } } for (int i = 0; i < nrParameters; i++) { p.set(i, i, beta.get(betapos, 0)); betapos++; } // generate Matrix y~ Matrix y2 = new Matrix(nrParameters, 1); for (int i = 0; i < nrParameters; i++) { y2.set(i, 0, beta.get(i + 1, 0)); } y2 = y2.times(-0.5); // get stationary point x Matrix x = new Matrix(nrParameters, 1); try { x = p.solve(y2); } catch (RuntimeException e) { logWarning("Quadratic optimization failed. (invalid matrix)"); } String[] Qvalues = new String[numberOfParameters]; int pc = 0; boolean ok = true; for (int j = 0; j < numberOfParameters; j++) { if (values[j].length > 2) { if (x.get(pc, 0) > Double.parseDouble(values[j][bestIndex[j] + 1]) || x.get(pc, 0) < Double.parseDouble(values[j][bestIndex[j] - 1])) { logWarning( "Parameter " + parameters[j] + " exceeds region of interest (" + x.get(pc, 0) + ")"); if (ifExceedsRegion == CLIP) { // clip to bound if (x.get(pc, 0) > Double.parseDouble(values[j][bestIndex[j] + 1])) { x.set(pc, 0, Double.parseDouble(values[j][bestIndex[j] + 1])); } else { x.set(pc, 0, Double.parseDouble(values[j][bestIndex[j] - 1])); } ; } else if (ifExceedsRegion == FAIL) { ok = false; } } if (x.get(pc, 0) < Double.parseDouble(values[j][0]) || x.get(pc, 0) > Double.parseDouble(values[j][values[j].length - 1])) { logWarning("Parameter " + parameters[j] + " exceeds range (" + x.get(pc, 0) + ")"); if (ifExceedsRange == IGNORE) { // ignore error logWarning(" but no measures taken. Check parameters manually!"); } else if (ifExceedsRange == CLIP) { // clip to bound if (x.get(pc, 0) > Double.parseDouble(values[j][0])) { x.set(pc, 0, Double.parseDouble(values[j][0])); } else { x.set(pc, 0, Double.parseDouble(values[j][values[j].length - 1])); } ; } else { ok = false; } } Qvalues[j] = x.get(pc, 0) + ""; pc++; } else { Qvalues[j] = values[j][bestIndex[j]]; } } getLogger().info("Optimised parameter set:"); for (int j = 0; j < operators.length; j++) { operators[j].getParameters().setParameter(parameters[j], Qvalues[j]); getLogger().info(" " + operators[j] + "." + parameters[j] + " = " + Qvalues[j]); } if (ok) { PerformanceVector qPerformance = super.getPerformanceVector(); log("Old: " + best.getPerformance().getMainCriterion().getFitness()); log("New: " + qPerformance.getMainCriterion().getFitness()); if (qPerformance.compareTo(best.getPerformance()) > 0) { best = new ParameterSet(operators, parameters, Qvalues, qPerformance); // log log("Optimised parameter set does increase the performance"); } else { // different log log("Could not increase performance by quadratic optimization"); } } else { // not ok getLogger() .warning("Parameters outside admissible range, not using optimised parameter set."); } } else { // Warning: no parameters to optimize getLogger().warning("No parameters to optimize"); } // end quadratic optimization deliver(best); getProgress().complete(); }