/** * evaluates a subset of attributes * * @param subset a bitset representing the attribute subset to be evaluated * @return the merit * @throws Exception if the subset could not be evaluated */ public double evaluateSubset(BitSet subset, int decAttr) throws Exception { // need to set c_divisor appropriately double eval = 0.0; // This needs to be performed by the search method itself /*if (computeCore) { if (core==null) { core = computeCore(); } subset.or(core); }*/ if (subset.cardinality() > 0) { try { eval = m_FuzzyMeasure.calculate(subset, decAttr); } catch (Exception e) { System.err.println(e); } eval = Math.min(1, eval); } return eval; }
/** * Finds optimal point on line constrained by first (i1) and second (i2) candidate. Parameters * correspond to pseudocode (see technicalinformation) * * @param i1 * @param alpha1 * @param alpha1Star * @param C1 * @param i2 * @param alpha2 * @param alpha2Star * @param C2 * @param gamma * @param eta * @param deltaPhi * @return */ protected boolean findOptimalPointOnLine( int i1, double alpha1, double alpha1Star, double C1, int i2, double alpha2, double alpha2Star, double C2, double gamma, double eta, double deltaPhi) { if (eta <= 0) { // this may happen due to numeric instability // due to Mercer's condition, this should not happen, hence we give up return false; } boolean case1 = false; boolean case2 = false; boolean case3 = false; boolean case4 = false; boolean finished = false; // while !finished // % this loop is passed at most three times // % case variables needed to avoid attempting small changes twice while (!finished) { // if (case1 == 0) && // (alpha1 > 0 || (alpha1* == 0 && deltaPhi > 0)) && // (alpha2 > 0 || (alpha2* == 0 && deltaPhi < 0)) // compute L, H (wrt. alpha1, alpha2) // if L < H // a2 = alpha2 ? - deltaPhi/eta // a2 = min(a2, H) // a2 = max(L, a2) // a1 = alpha1 ? - (a2 ? alpha2) // update alpha1, alpha2 if change is larger than some eps // else // finished = 1 // endif // case1 = 1; if ((case1 == false) && (alpha1 > 0 || (alpha1Star == 0 && deltaPhi > 0)) && (alpha2 > 0 || (alpha2Star == 0 && deltaPhi < 0))) { // compute L, H (wrt. alpha1, alpha2) double L = Math.max(0, gamma - C1); double H = Math.min(C2, gamma); if (L < H) { double a2 = alpha2 - deltaPhi / eta; a2 = Math.min(a2, H); a2 = Math.max(L, a2); // To prevent precision problems if (a2 > C2 - m_Del * C2) { a2 = C2; } else if (a2 <= m_Del * C2) { a2 = 0; } double a1 = alpha1 - (a2 - alpha2); if (a1 > C1 - m_Del * C1) { a1 = C1; } else if (a1 <= m_Del * C1) { a1 = 0; } // update alpha1, alpha2 if change is larger than some eps if (Math.abs(alpha1 - a1) > m_eps) { deltaPhi += eta * (a2 - alpha2); alpha1 = a1; alpha2 = a2; } } else { finished = true; } case1 = true; } // elseif (case2 == 0) && // (alpha1 > 0 || (alpha1* == 0 && deltaPhi > 2 epsilon)) && // (alpha2* > 0 || (alpha2 == 0 && deltaPhi > 2 epsilon)) // compute L, H (wrt. alpha1, alpha2*) // if L < H // a2 = alpha2* + (deltaPhi ?- 2 epsilon)/eta // a2 = min(a2, H) // a2 = max(L, a2) // a1 = alpha1 + (a2 ? alpha2*) // update alpha1, alpha2* if change is larger than some eps // else // finished = 1 // endif // case2 = 1; else if ((case2 == false) && (alpha1 > 0 || (alpha1Star == 0 && deltaPhi > 2 * m_epsilon)) && (alpha2Star > 0 || (alpha2 == 0 && deltaPhi > 2 * m_epsilon))) { // compute L, H (wrt. alpha1, alpha2*) double L = Math.max(0, -gamma); double H = Math.min(C2, -gamma + C1); if (L < H) { double a2 = alpha2Star + (deltaPhi - 2 * m_epsilon) / eta; a2 = Math.min(a2, H); a2 = Math.max(L, a2); // To prevent precision problems if (a2 > C2 - m_Del * C2) { a2 = C2; } else if (a2 <= m_Del * C2) { a2 = 0; } double a1 = alpha1 + (a2 - alpha2Star); if (a1 > C1 - m_Del * C1) { a1 = C1; } else if (a1 <= m_Del * C1) { a1 = 0; } // update alpha1, alpha2* if change is larger than some eps if (Math.abs(alpha1 - a1) > m_eps) { deltaPhi += eta * (-a2 + alpha2Star); alpha1 = a1; alpha2Star = a2; } } else { finished = true; } case2 = true; } // elseif (case3 == 0) && // (alpha1* > 0 || (alpha1 == 0 && deltaPhi < -2 epsilon)) && // (alpha2 > 0 || (alpha2* == 0 && deltaPhi < -2 epsilon)) // compute L, H (wrt. alpha1*, alpha2) // if L < H // a2 = alpha2 ?- (deltaPhi ?+ 2 epsilon)/eta // a2 = min(a2, H) // a2 = max(L, a2) // a1 = alpha1* + (a2 ? alpha2) // update alpha1*, alpha2 if change is larger than some eps // else // finished = 1 // endif // case3 = 1; else if ((case3 == false) && (alpha1Star > 0 || (alpha1 == 0 && deltaPhi < -2 * m_epsilon)) && (alpha2 > 0 || (alpha2Star == 0 && deltaPhi < -2 * m_epsilon))) { // compute L, H (wrt. alpha1*, alpha2) double L = Math.max(0, gamma); double H = Math.min(C2, C1 + gamma); if (L < H) { // note Smola's psuedocode has a minus, where there should be a plus in the following // line, Keerthi's is correct double a2 = alpha2 - (deltaPhi + 2 * m_epsilon) / eta; a2 = Math.min(a2, H); a2 = Math.max(L, a2); // To prevent precision problems if (a2 > C2 - m_Del * C2) { a2 = C2; } else if (a2 <= m_Del * C2) { a2 = 0; } double a1 = alpha1Star + (a2 - alpha2); if (a1 > C1 - m_Del * C1) { a1 = C1; } else if (a1 <= m_Del * C1) { a1 = 0; } // update alpha1*, alpha2 if change is larger than some eps if (Math.abs(alpha1Star - a1) > m_eps) { deltaPhi += eta * (a2 - alpha2); alpha1Star = a1; alpha2 = a2; } } else { finished = true; } case3 = true; } // elseif (case4 == 0) && // (alpha1* > 0 || (alpha1 == 0 && deltaPhi < 0)) && // (alpha2* > 0 || (alpha2 == 0 && deltaPhi > 0)) // compute L, H (wrt. alpha1*, alpha2*) // if L < H // a2 = alpha2* + deltaPhi/eta // a2 = min(a2, H) // a2 = max(L, a2) // a1 = alpha1* ? (a2 ? alpha2*) // update alpha1*, alpha2* if change is larger than some eps // else // finished = 1 // endif // case4 = 1; // else // finished = 1 // endif else if ((case4 == false) && (alpha1Star > 0 || (alpha1 == 0 && deltaPhi < 0)) && (alpha2Star > 0 || (alpha2 == 0 && deltaPhi > 0))) { // compute L, H (wrt. alpha1*, alpha2*) double L = Math.max(0, -gamma - C1); double H = Math.min(C2, -gamma); if (L < H) { double a2 = alpha2Star + deltaPhi / eta; a2 = Math.min(a2, H); a2 = Math.max(L, a2); // To prevent precision problems if (a2 > C2 - m_Del * C2) { a2 = C2; } else if (a2 <= m_Del * C2) { a2 = 0; } double a1 = alpha1Star - (a2 - alpha2Star); if (a1 > C1 - m_Del * C1) { a1 = C1; } else if (a1 <= m_Del * C1) { a1 = 0; } // update alpha1*, alpha2* if change is larger than some eps if (Math.abs(alpha1Star - a1) > m_eps) { deltaPhi += eta * (-a2 + alpha2Star); alpha1Star = a1; alpha2Star = a2; } } else { finished = true; } case4 = true; } else { finished = true; } // update deltaPhi // using 4.36 from Smola's thesis: // deltaPhi = deltaPhi - eta * ((alpha1New-alpha1StarNew)-(alpha1-alpha1Star)); // the update is done inside the loop, saving us to remember old values of alpha1(*) // deltaPhi += eta * ((alpha2 - alpha2Star) - dAlpha2Old); // dAlpha2Old = (alpha2 - alpha2Star); // endwhile } if (Math.abs(alpha1 - m_alpha[i1]) > m_eps || Math.abs(alpha1Star - m_alphaStar[i1]) > m_eps || Math.abs(alpha2 - m_alpha[i2]) > m_eps || Math.abs(alpha2Star - m_alphaStar[i2]) > m_eps) { if (alpha1 > C1 - m_Del * C1) { alpha1 = C1; } else if (alpha1 <= m_Del * C1) { alpha1 = 0; } if (alpha1Star > C1 - m_Del * C1) { alpha1Star = C1; } else if (alpha1Star <= m_Del * C1) { alpha1Star = 0; } if (alpha2 > C2 - m_Del * C2) { alpha2 = C2; } else if (alpha2 <= m_Del * C2) { alpha2 = 0; } if (alpha2Star > C2 - m_Del * C2) { alpha2Star = C2; } else if (alpha2Star <= m_Del * C2) { alpha2Star = 0; } // store new alpha's m_alpha[i1] = alpha1; m_alphaStar[i1] = alpha1Star; m_alpha[i2] = alpha2; m_alphaStar[i2] = alpha2Star; // update supportvector set if (alpha1 != 0 || alpha1Star != 0) { if (!m_supportVectors.contains(i1)) { m_supportVectors.insert(i1); } } else { m_supportVectors.delete(i1); } if (alpha2 != 0 || alpha2Star != 0) { if (!m_supportVectors.contains(i2)) { m_supportVectors.insert(i2); } } else { m_supportVectors.delete(i2); } return true; } return false; }