Example #1
0
  /**
   * finds alpha and alpha* parameters that optimize the SVM target function
   *
   * @throws Exception
   */
  public void optimize() throws Exception {

    //	main routine:
    //		initialize threshold to zero
    //		numChanged = 0
    //		examineAll = 1
    //		SigFig = -100
    //		LoopCounter = 0
    int numChanged = 0;
    int examineAll = 1;
    int sigFig = -100;
    int loopCounter = 0;
    //		while ((numChanged > 0 | examineAll) | (SigFig < 3))
    while ((numChanged > 0 || (examineAll > 0)) | (sigFig < 3)) {
      //			LoopCounter++
      //			numChanged = 0;
      loopCounter++;
      numChanged = 0;
      //			if (examineAll)
      //				loop I over all training examples
      //				numChanged += examineExample(I)
      //			else
      //				loop I over examples where alpha is not 0 & not C
      //				numChanged += examineExample(I)
      //			endif
      int numSamples = 0;
      if (examineAll > 0) {
        for (int i = 0; i < m_nInstances; i++) {
          numChanged += examineExample(i);
        }
      } else {
        for (int i = 0; i < m_target.length; i++) {
          if ((m_alpha[i] > 0 && m_alpha[i] < m_C * m_data.instance(i).weight())
              || (m_alphaStar[i] > 0 && m_alphaStar[i] < m_C * m_data.instance(i).weight())) {
            numSamples++;
            numChanged += examineExample(i);
          }
        }
      }
      //
      //		if (mod(LoopCounter, 2) == 0)
      //				MinimumNumChanged = max(1, 0.1*NumSamples)
      //			else
      //				MinimumNumChanged = 1
      //			endif
      int minimumNumChanged = 1;
      if (loopCounter % 2 == 0) {
        minimumNumChanged = (int) Math.max(1, 0.1 * numSamples);
      }

      //			if (examineAll == 1)
      //				examineAll = 0
      //			elseif (numChanged < MinimumNumChanged)
      //				examineAll = 1
      //			endif
      if (examineAll == 1) {
        examineAll = 0;
      } else if (numChanged < minimumNumChanged) {
        examineAll = 1;
      }

      //		endwhile
      if (loopCounter == 2500) {
        break;
      }
    }
    //	endmain
  }
Example #2
0
  /**
   * 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;
  }