GetQD() public abstract method

public abstract GetQD ( ) : double[]
return double[]
示例#1
0
        public virtual void Solve(int length, QMatrix Q, double[] p_, sbyte[] y_,
         double[] alpha_, double Cp, double Cn, double eps, SolutionInfo si, bool shrinking)
        {
            _length = length;
              _q = Q;
              _qd = Q.GetQD();
              _p = (double[]) p_.Clone();
              _y = (sbyte[]) y_.Clone();
              _alpha = (double[]) alpha_.Clone();
              _cp = Cp;
              _cn = Cn;
              _eps = eps;
              _unshrink = false;

              // initialize alpha_status
              _alphaStatus = new BoundType[length];
              for (int i = 0; i < length; i++)
              {
            UpdateAlphaStatus(i);
              }

              // initialize active set (for shrinking)
              _activeSet = new int[length];
              for (int i = 0; i < length; i++)
              {
            _activeSet[i] = i;
              }
              _activeSize = length;

              // initialize gradient
              _g = new double[length];
              _gBar = new double[length];

              for (int i = 0; i < length; i++)
              {
            _g[i] = _p[i];
            _gBar[i] = 0;
              }

              for (int i = 0; i < length; i++)
              {
            if (!IsLowerBound(i))
            {
              double[] Q_i = Q.GetQ(i, length);
              double alpha_i = _alpha[i];

              for (int j = 0; j < length; j++)
              {
            _g[j] += alpha_i * Q_i[j];
              }

              if (IsUpperBound(i))
              {
            for (int j = 0; j < length; j++)
            {
              _gBar[j] += GetC(i) * Q_i[j];
            }
              }
            }
              }

              // optimization step

              int iter = 0;
              int max_iter = Math.Max(10000000, length > int.MaxValue / 100 ? int.MaxValue : 100 * length);
              int counter = Math.Min(length, 1000) + 1;
              int[] working_set = new int[2];

              while (iter < max_iter)
              {
            // show progress and do shrinking

            if (--counter == 0)
            {
              counter = Math.Min(length, 1000);
              if (shrinking) DoShrinking();
              Svm.info(".");
            }

            if (SelectWorkingSet(working_set) != 0)
            {
              // reconstruct the whole gradient
              ReconstructGradient();
              // reset active set size and check
              _activeSize = length;
              Svm.info("*");
              if (SelectWorkingSet(working_set) != 0)
            break;
              else
            counter = 1; // do shrinking next iteration
            }

            int i = working_set[0];
            int j = working_set[1];

            ++iter;

            // update alpha[i] and alpha[j], handle bounds carefully

            double[] Q_i = Q.GetQ(i, _activeSize);
            double[] Q_j = Q.GetQ(j, _activeSize);

            double C_i = GetC(i);
            double C_j = GetC(j);

            double old_alpha_i = _alpha[i];
            double old_alpha_j = _alpha[j];

            if (_y[i] != _y[j])
            {
              double quad_coef = _qd[i] + _qd[j] + 2*Q_i[j];
              if (quad_coef <= 0)
            quad_coef = 1e-12;
              double delta = (-_g[i] - _g[j])/quad_coef;
              double diff = _alpha[i] - _alpha[j];
              _alpha[i] += delta;
              _alpha[j] += delta;

              if (diff > 0)
              {
            if (_alpha[j] < 0)
            {
              _alpha[j] = 0;
              _alpha[i] = diff;
            }
              }
              else
              {
            if (_alpha[i] < 0)
            {
              _alpha[i] = 0;
              _alpha[j] = -diff;
            }
              }
              if (diff > C_i - C_j)
              {
            if (_alpha[i] > C_i)
            {
              _alpha[i] = C_i;
              _alpha[j] = C_i - diff;
            }
              }
              else
              {
            if (_alpha[j] > C_j)
            {
              _alpha[j] = C_j;
              _alpha[i] = C_j + diff;
            }
              }
            }
            else
            {
              double quad_coef = _qd[i] + _qd[j] - 2*Q_i[j];
              if (quad_coef <= 0)
            quad_coef = 1e-12;
              double delta = (_g[i] - _g[j])/quad_coef;
              double sum = _alpha[i] + _alpha[j];
              _alpha[i] -= delta;
              _alpha[j] += delta;

              if (sum > C_i)
              {
            if (_alpha[i] > C_i)
            {
              _alpha[i] = C_i;
              _alpha[j] = sum - C_i;
            }
              }
              else
              {
            if (_alpha[j] < 0)
            {
              _alpha[j] = 0;
              _alpha[i] = sum;
            }
              }
              if (sum > C_j)
              {
            if (_alpha[j] > C_j)
            {
              _alpha[j] = C_j;
              _alpha[i] = sum - C_j;
            }
              }
              else
              {
            if (_alpha[i] < 0)
            {
              _alpha[i] = 0;
              _alpha[j] = sum;
            }
              }
            }

            // update G
            double delta_alpha_i = _alpha[i] - old_alpha_i;
            double delta_alpha_j = _alpha[j] - old_alpha_j;

            for (int k = 0; k < _activeSize; k++)
            {
              _g[k] += Q_i[k]*delta_alpha_i + Q_j[k]*delta_alpha_j;
            }

            // update alpha_status and G_bar
            bool ui = IsUpperBound(i);
            bool uj = IsUpperBound(j);
            UpdateAlphaStatus(i);
            UpdateAlphaStatus(j);
            //int k;
            if (ui != IsUpperBound(i))
            {
              Q_i = Q.GetQ(i, length);
              if (ui)
              {
            for (int k = 0; k < length; k++)
            {
              _gBar[k] -= C_i*Q_i[k];
            }
              }
              else
              {
            for (int k = 0; k < length; k++)
            {
              _gBar[k] += C_i*Q_i[k];
            }
              }
            }

            if (uj != IsUpperBound(j))
            {
              Q_j = Q.GetQ(j, length);
              if (uj)
              {
            for (int k = 0; k < length; k++)
            {
              _gBar[k] -= C_j*Q_j[k];
            }
              }
              else
              {
            for (int k = 0; k < length; k++)
            {
              _gBar[k] += C_j*Q_j[k];
            }
              }
            }
              }

              if (iter >= max_iter)
              {
            if (_activeSize < length)
            {
              // reconstruct the whole gradient to calculate objective value
              ReconstructGradient();
              _activeSize = length;
              Svm.info("*");
            }
            Console.Error.WriteLine("\nWARNING: reaching max number of iterations");
              }

              // calculate rho
              si.Rho = CalculateRho();

              // calculate objective value
              double v = 0;
              for (int i = 0; i < length; i++)
              {
            v += _alpha[i]*(_g[i] + _p[i]);
              }
              si.Obj = v/2;

              // put back the solution
              for (int i = 0; i < length; i++)
              {
            alpha_[_activeSet[i]] = _alpha[i];
              }

              si.UpperBoundP = Cp;
              si.UpperBoundN = Cn;

              Svm.info("\noptimization finished, #iter = " + iter + "\n");
        }
示例#2
0
        public virtual void Solve(int length, QMatrix Q, double[] p_, sbyte[] y_,
                                  double[] alpha_, double Cp, double Cn, double eps, SolutionInfo si, bool shrinking)
        {
            this._length   = length;
            this._q        = Q;
            _qd            = Q.GetQD();
            _p             = (double[])p_.Clone();
            _y             = (sbyte[])y_.Clone();
            _alpha         = (double[])alpha_.Clone();
            this._cp       = Cp;
            this._cn       = Cn;
            this._eps      = eps;
            this._unshrink = false;

            // initialize alpha_status
            {
                _alphaStatus = new BoundType[length];
                for (int i = 0; i < length; i++)
                {
                    UpdateAlphaStatus(i);
                }
            }

            // initialize active set (for shrinking)
            {
                _activeSet = new int[length];
                for (int i = 0; i < length; i++)
                {
                    _activeSet[i] = i;
                }
                _activeSize = length;
            }

            // initialize gradient
            {
                _g    = new double[length];
                _gBar = new double[length];
                int i;
                for (i = 0; i < length; i++)
                {
                    _g[i]    = _p[i];
                    _gBar[i] = 0;
                }
                for (i = 0; i < length; i++)
                {
                    if (!is_lower_bound(i))
                    {
                        double[] Q_i     = Q.GetQ(i, length);
                        double   alpha_i = _alpha[i];
                        int      j;
                        for (j = 0; j < length; j++)
                        {
                            _g[j] += alpha_i * Q_i[j];
                        }
                        if (is_upper_bound(i))
                        {
                            for (j = 0; j < length; j++)
                            {
                                _gBar[j] += GetC(i) * Q_i[j];
                            }
                        }
                    }
                }
            }

            // optimization step

            int iter     = 0;
            int max_iter = Math.Max(10000000, length > int.MaxValue / 100 ? int.MaxValue : 100 * length);
            int counter  = Math.Min(length, 1000) + 1;

            int[] working_set = new int[2];

            while (iter < max_iter)
            {
                // show progress and do shrinking

                if (--counter == 0)
                {
                    counter = Math.Min(length, 1000);
                    if (shrinking)
                    {
                        do_shrinking();
                    }
                    Svm.info(".");
                }

                if (select_working_set(working_set) != 0)
                {
                    // reconstruct the whole gradient
                    reconstruct_gradient();
                    // reset active set size and check
                    _activeSize = length;
                    Svm.info("*");
                    if (select_working_set(working_set) != 0)
                    {
                        break;
                    }
                    else
                    {
                        counter = 1; // do shrinking next iteration
                    }
                }

                int i = working_set[0];
                int j = working_set[1];

                ++iter;

                // update alpha[i] and alpha[j], handle bounds carefully

                double[] Q_i = Q.GetQ(i, _activeSize);
                double[] Q_j = Q.GetQ(j, _activeSize);

                double C_i = GetC(i);
                double C_j = GetC(j);

                double old_alpha_i = _alpha[i];
                double old_alpha_j = _alpha[j];

                if (_y[i] != _y[j])
                {
                    double quad_coef = _qd[i] + _qd[j] + 2 * Q_i[j];
                    if (quad_coef <= 0)
                    {
                        quad_coef = 1e-12;
                    }
                    double delta = (-_g[i] - _g[j]) / quad_coef;
                    double diff  = _alpha[i] - _alpha[j];
                    _alpha[i] += delta;
                    _alpha[j] += delta;

                    if (diff > 0)
                    {
                        if (_alpha[j] < 0)
                        {
                            _alpha[j] = 0;
                            _alpha[i] = diff;
                        }
                    }
                    else
                    {
                        if (_alpha[i] < 0)
                        {
                            _alpha[i] = 0;
                            _alpha[j] = -diff;
                        }
                    }
                    if (diff > C_i - C_j)
                    {
                        if (_alpha[i] > C_i)
                        {
                            _alpha[i] = C_i;
                            _alpha[j] = C_i - diff;
                        }
                    }
                    else
                    {
                        if (_alpha[j] > C_j)
                        {
                            _alpha[j] = C_j;
                            _alpha[i] = C_j + diff;
                        }
                    }
                }
                else
                {
                    double quad_coef = _qd[i] + _qd[j] - 2 * Q_i[j];
                    if (quad_coef <= 0)
                    {
                        quad_coef = 1e-12;
                    }
                    double delta = (_g[i] - _g[j]) / quad_coef;
                    double sum   = _alpha[i] + _alpha[j];
                    _alpha[i] -= delta;
                    _alpha[j] += delta;

                    if (sum > C_i)
                    {
                        if (_alpha[i] > C_i)
                        {
                            _alpha[i] = C_i;
                            _alpha[j] = sum - C_i;
                        }
                    }
                    else
                    {
                        if (_alpha[j] < 0)
                        {
                            _alpha[j] = 0;
                            _alpha[i] = sum;
                        }
                    }
                    if (sum > C_j)
                    {
                        if (_alpha[j] > C_j)
                        {
                            _alpha[j] = C_j;
                            _alpha[i] = sum - C_j;
                        }
                    }
                    else
                    {
                        if (_alpha[i] < 0)
                        {
                            _alpha[i] = 0;
                            _alpha[j] = sum;
                        }
                    }
                }

                // update G
                double delta_alpha_i = _alpha[i] - old_alpha_i;
                double delta_alpha_j = _alpha[j] - old_alpha_j;

                for (int k = 0; k < _activeSize; k++)
                {
                    _g[k] += Q_i[k] * delta_alpha_i + Q_j[k] * delta_alpha_j;
                }

                // update alpha_status and G_bar
                bool ui = is_upper_bound(i);
                bool uj = is_upper_bound(j);
                UpdateAlphaStatus(i);
                UpdateAlphaStatus(j);
                //int k;
                if (ui != is_upper_bound(i))
                {
                    Q_i = Q.GetQ(i, length);
                    if (ui)
                    {
                        for (int k = 0; k < length; k++)
                        {
                            _gBar[k] -= C_i * Q_i[k];
                        }
                    }
                    else
                    {
                        for (int k = 0; k < length; k++)
                        {
                            _gBar[k] += C_i * Q_i[k];
                        }
                    }
                }

                if (uj != is_upper_bound(j))
                {
                    Q_j = Q.GetQ(j, length);
                    if (uj)
                    {
                        for (int k = 0; k < length; k++)
                        {
                            _gBar[k] -= C_j * Q_j[k];
                        }
                    }
                    else
                    {
                        for (int k = 0; k < length; k++)
                        {
                            _gBar[k] += C_j * Q_j[k];
                        }
                    }
                }
            }

            if (iter >= max_iter)
            {
                if (_activeSize < length)
                {
                    // reconstruct the whole gradient to calculate objective value
                    reconstruct_gradient();
                    _activeSize = length;
                    Svm.info("*");
                }
                Svm.info("\nWARNING: reaching max number of iterations");
            }

            // calculate rho
            si.Rho = calculate_rho();

            // calculate objective value
            double v = 0;

            for (int i = 0; i < length; i++)
            {
                v += _alpha[i] * (_g[i] + _p[i]);
            }
            si.Obj = v / 2;

            // put back the solution
            for (int i = 0; i < length; i++)
            {
                alpha_[_activeSet[i]] = _alpha[i];
            }

            si.UpperBoundP = Cp;
            si.UpperBoundN = Cn;

            Svm.info("\noptimization finished, #iter = " + iter + "\n");
        }