Example #1
0
        /// <summary>
        /// Solves the optimization problem
        /// </summary>
        /// <param name="minusOnes"></param>
        /// <param name="y_"></param>
        /// <param name="alpha_"></param>
        /// <param name="si"></param>
        /// <param name="shrinking"></param>
        private void Solve(float[] minusOnes, sbyte[] y_, float[] alpha_, SolutionInfo si, bool shrinking)
        {
            #region initialization
            //this.l = l;
            //this.Q = Q;

            p     = (float[])minusOnes.Clone();
            y     = (sbyte[])y_.Clone();
            alpha = (float[])alpha_.Clone();
            //this.Cp = Cp;
            //this.Cn = Cn;



            this.unshrink = false;



            // initialize alpha_status
            {
                alpha_status = new byte[problemSize];
                for (int i = 0; i < problemSize; i++)
                {
                    update_alpha_status(i);
                }
            }

            // initialize active set (for shrinking)
            {
                active_set = new int[problemSize];
                for (int i = 0; i < problemSize; i++)
                {
                    active_set[i] = i;
                }
                active_size = problemSize;
            }

            // initialize gradient
            {
                G     = new float[problemSize];
                G_bar = new float[problemSize];
                int i;
                for (i = 0; i < problemSize; i++)
                {
                    G[i]     = p[i];
                    G_bar[i] = 0;
                }
                for (i = 0; i < problemSize; i++)
                {
                    if (!is_lower_bound(i))
                    {
                        float[] Q_i     = Q.GetQ(i, problemSize);
                        float   alpha_i = alpha[i];
                        int     j;
                        for (j = 0; j < problemSize; j++)
                        {
                            G[j] += alpha_i * Q_i[j];
                        }
                        if (is_upper_bound(i))
                        {
                            for (j = 0; j < problemSize; j++)
                            {
                                G_bar[j] += get_C(i) * Q_i[j];
                            }
                        }
                    }
                }
            }
            #endregion


            // optimization step
            int   iter        = 0;
            int   counter     = Math.Min(problemSize, 1000) + 1;
            int[] working_set = new int[2];

            int processors = Environment.ProcessorCount;


            while (iter < IterMaX)
            {
                if (--counter == 0)
                {
                    counter = Math.Min(problemSize, 1000);
                    if (shrinking)
                    {
                        do_shrinking();
                    }
                    //Procedures.info(".");
                }

                if (select_working_set(working_set, processors) != 0)
                {
                    // reconstruct the whole gradient
                    reconstruct_gradient();
                    // reset active set size and check
                    active_size = problemSize;
                    // Procedures.info("*");
                    if (select_working_set(working_set, processors) != 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
                float[] Q_i = Q.GetQ(i, active_size);
                float[] Q_j = Q.GetQ(j, active_size);


                float C_i = get_C(i);
                float C_j = get_C(j);

                float old_alpha_i = alpha[i];
                float old_alpha_j = alpha[j];

                if (y[i] != y[j])
                {
                    float quad_coef = Q_i[i] + Q_j[j] + 2 * Q_i[j];
                    if (quad_coef <= 0)
                    {
                        quad_coef = 1e-12f;
                    }
                    float delta = (-G[i] - G[j]) / quad_coef;
                    float 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
                {
                    float quad_coef = Q_i[i] + Q_j[j] - 2 * Q_i[j];
                    if (quad_coef <= 0)
                    {
                        quad_coef = 1e-12f;
                    }
                    float delta = (G[i] - G[j]) / quad_coef;
                    float 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

                float delta_alpha_i = alpha[i] - old_alpha_i;
                float delta_alpha_j = alpha[j] - old_alpha_j;



                UpdateGradients(Q_i, Q_j, delta_alpha_i, delta_alpha_j);

                //  Parallel.ForEach(partition, UpdateGradient);

                // update alpha_status and G_bar

                {
                    bool ui = is_upper_bound(i);
                    bool uj = is_upper_bound(j);
                    update_alpha_status(i);
                    update_alpha_status(j);
                    int k;
                    if (ui != is_upper_bound(i))
                    {
                        Q_i = Q.GetQ(i, problemSize);
                        if (ui)
                        {
                            for (k = 0; k < problemSize; k++)
                            {
                                G_bar[k] -= C_i * Q_i[k];
                            }
                        }
                        else
                        {
                            for (k = 0; k < problemSize; k++)
                            {
                                G_bar[k] += C_i * Q_i[k];
                            }
                        }
                    }

                    if (uj != is_upper_bound(j))
                    {
                        Q_j = Q.GetQ(j, problemSize);
                        if (uj)
                        {
                            for (k = 0; k < problemSize; k++)
                            {
                                G_bar[k] -= C_j * Q_j[k];
                            }
                        }
                        else
                        {
                            for (k = 0; k < problemSize; k++)
                            {
                                G_bar[k] += C_j * Q_j[k];
                            }
                        }
                    }
                }
            }//end while



            // calculate rho


            si.rho  = calculate_rho();
            si.iter = iter;

            // calculate objective value
            {
                double v = ObjVal();


                si.obj = (float)v;
            }

            // put back the solution
            {
                for (int i = 0; i < problemSize; i++)
                {
                    //alpha_[active_set[i]] = alpha[i];
                    //we don't set indexes to previous order
                    alpha_[i] = alpha[i];
                }
            }

            si.upper_bound_p = Cp;
            si.upper_bound_n = Cn;
        }
Example #2
0
        /// <summary>
        /// Solves the optimization problem
        /// </summary>
        /// <param name="minusOnes"></param>
        /// <param name="y_"></param>
        /// <param name="alpha_"></param>
        /// <param name="si"></param>
        /// <param name="shrinking"></param>
        private void Solve(float[] minusOnes, sbyte[] y_, float[] alpha_, SolutionInfo si, bool shrinking)
        {
            //this.l = l;
            //this.Q = Q;

            p     = (float[])minusOnes.Clone();
            y     = (sbyte[])y_.Clone();
            alpha = (float[])alpha_.Clone();
            //this.Cp = Cp;
            //this.Cn = Cn;

            this.unshrink = false;



            // initialize alpha_status
            {
                alpha_status = new byte[problemSize];
                for (int i = 0; i < problemSize; i++)
                {
                    update_alpha_status(i);
                }
            }

            // initialize active set (for shrinking)
            {
                active_set = new int[problemSize];
                for (int i = 0; i < problemSize; i++)
                {
                    active_set[i] = i;
                }
                active_size = problemSize;
            }

            // initialize gradient
            {
                G     = new float[problemSize];
                G_bar = new float[problemSize];
                int i;
                for (i = 0; i < problemSize; i++)
                {
                    G[i]     = p[i];
                    G_bar[i] = 0;
                }
                for (i = 0; i < problemSize; i++)
                {
                    if (!is_lower_bound(i))
                    {
                        float[] Q_i     = Q.GetQ(i, problemSize);
                        float   alpha_i = alpha[i];
                        int     j;
                        for (j = 0; j < problemSize; j++)
                        {
                            G[j] += alpha_i * Q_i[j];
                        }
                        if (is_upper_bound(i))
                        {
                            for (j = 0; j < problemSize; j++)
                            {
                                G_bar[j] += get_C(i) * Q_i[j];
                            }
                        }
                    }
                }
            }

            // optimization step

            int iter    = 0;
            int counter = Math.Min(problemSize, 1000) + 1;

            int[] working_set = new int[2];


            Random rand = new Random();

            while (true)
            {
                // show progress and do shrinking

                int i = rand.Next(active_size);
                int j = i;
                while (j == i)
                {
                    j = rand.Next(active_size);
                }

                ++iter;

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

                float[] Q_i = Q.GetQ(i, active_size);
                float[] Q_j = Q.GetQ(j, active_size);

                float C_i = get_C(i);
                float C_j = get_C(j);

                float old_alpha_i = alpha[i];
                float old_alpha_j = alpha[j];

                if (y[i] != y[j])
                {
                    float quad_coef = Q_i[i] + Q_j[j] + 2 * Q_i[j];
                    if (quad_coef <= 0)
                    {
                        quad_coef = 1e-12f;
                    }
                    float delta = (-G[i] - G[j]) / quad_coef;
                    float 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
                {
                    float quad_coef = Q_i[i] + Q_j[j] - 2 * Q_i[j];
                    if (quad_coef <= 0)
                    {
                        quad_coef = 1e-12f;
                    }
                    float delta = (G[i] - G[j]) / quad_coef;
                    float 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

                float delta_alpha_i = alpha[i] - old_alpha_i;
                float delta_alpha_j = alpha[j] - old_alpha_j;

                update_alpha_status(i);
                update_alpha_status(j);



                double nG    = 0;
                double nL1G  = 0;
                double nMaxG = double.NegativeInfinity;

                float GMax  = -INF;
                float GMax2 = -INF;

                for (int k = 0; k < active_size; k++)
                {
                    G[k] += Q_i[k] * delta_alpha_i + Q_j[k] * delta_alpha_j;
                    //nG += G[k] * G[k];
                    //nL1G += Math.Abs( G[k]);
                    //nMaxG = Math.Max(nMaxG, Math.Abs(G[k]));

                    if (y[k] == +1)
                    {
                        if (!is_upper_bound(k))
                        {
                            if (-G[k] >= GMax)
                            {
                                GMax = -G[k];
                            }
                        }
                        if (!is_lower_bound(k))
                        {
                            if (G[k] >= GMax2)
                            {
                                GMax2 = G[k];
                            }
                        }
                    }
                    else
                    {
                        if (!is_lower_bound(k))
                        {
                            if (G[k] >= GMax)
                            {
                                GMax = G[k];
                            }
                        }
                        if (!is_upper_bound(k))
                        {
                            if (-G[k] >= GMax2)
                            {
                                GMax2 = -G[k];
                            }
                        }
                    }
                }

                if (GMax + GMax2 < EPS)
                {
                    break;
                }
            }

            // calculate rho

            si.rho  = calculate_rho();
            si.iter = iter;

            // calculate objective value
            {
                float v = 0;
                int   i;
                for (i = 0; i < problemSize; i++)
                {
                    v += alpha[i] * (G[i] + p[i]);
                }

                si.obj = v / 2;
            }

            // put back the solution
            {
                for (int i = 0; i < problemSize; i++)
                {
                    alpha_[i] = alpha[i];
                    //alpha_[active_set[i]] = alpha[i];

                    //kernel.SwapIndex(i, active_set[i]);
                }
            }

            si.upper_bound_p = Cp;
            si.upper_bound_n = Cn;

            // Procedures.info("\noptimization finished, #iter = " + iter + "\n");
        }
Example #3
0
        /// <summary>
        /// Solves the optimization problem
        /// </summary>
        /// <param name="minusOnes"></param>
        /// <param name="y_"></param>
        /// <param name="alpha_"></param>
        /// <param name="si"></param>
        /// <param name="shrinking"></param>
        private void Solve(float[] minusOnes, sbyte[] y_, float[] alpha_, SolutionInfo si, bool shrinking)
        {
            //this.l = l;
            //this.Q = Q;

            p     = (float[])minusOnes.Clone();
            y     = (sbyte[])y_.Clone();
            alpha = (float[])alpha_.Clone();
            //this.Cp = Cp;
            //this.Cn = Cn;

            this.unshrink = false;



            // initialize alpha_status
            {
                alpha_status = new byte[problemSize];
                for (int i = 0; i < problemSize; i++)
                {
                    update_alpha_status(i);
                }
            }

            // initialize active set (for shrinking)
            {
                active_set = new int[problemSize];
                for (int i = 0; i < problemSize; i++)
                {
                    active_set[i] = i;
                }
                active_size = problemSize;
            }

            // initialize gradient
            {
                G     = new float[problemSize];
                G_bar = new float[problemSize];
                int i;
                for (i = 0; i < problemSize; i++)
                {
                    G[i]     = p[i];
                    G_bar[i] = 0;
                }
                for (i = 0; i < problemSize; i++)
                {
                    if (!is_lower_bound(i))
                    {
                        float[] Q_i     = Q.GetQ(i, problemSize);
                        float   alpha_i = alpha[i];
                        int     j;
                        for (j = 0; j < problemSize; j++)
                        {
                            G[j] += alpha_i * Q_i[j];
                        }
                        if (is_upper_bound(i))
                        {
                            for (j = 0; j < problemSize; j++)
                            {
                                G_bar[j] += get_C(i) * Q_i[j];
                            }
                        }
                    }
                }
            }

            // optimization step

            int iter    = 0;
            int counter = Math.Min(problemSize, 1000) + 1;

            int[] working_set = new int[2];

            float[][] ker2Cols = new float[2][];
            ker2Cols[0] = new float[problem.ElementsCount];
            ker2Cols[1] = new float[problem.ElementsCount];


            while (true)
            {
                // show progress and do shrinking

                if (--counter == 0)
                {
                    counter = Math.Min(problemSize, 1000);
                    if (shrinking)
                    {
                        do_shrinking();
                    }
                    //Procedures.info(".");
                }

                if (select_working_set(working_set) != 0)
                {
                    // reconstruct the whole gradient
                    reconstruct_gradient();
                    // reset active set size and check
                    active_size = problemSize;
                    // Procedures.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


                kernel.AllProducts(i, j, ker2Cols);
                float[] Q_i = ker2Cols[0];
                float[] Q_j = ker2Cols[1];

                //float[] Q_i = Q.GetQ(i, active_size);
                //float[] Q_j = Q.GetQ(j, active_size);

                float C_i = get_C(i);
                float C_j = get_C(j);

                float old_alpha_i = alpha[i];
                float old_alpha_j = alpha[j];

                if (y[i] != y[j])
                {
                    float quad_coef = Q_i[i] + Q_j[j] + 2 * Q_i[j];
                    if (quad_coef <= 0)
                    {
                        quad_coef = 1e-12f;
                    }
                    float delta = (-G[i] - G[j]) / quad_coef;
                    float 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
                {
                    float quad_coef = Q_i[i] + Q_j[j] - 2 * Q_i[j];
                    if (quad_coef <= 0)
                    {
                        quad_coef = 1e-12f;
                    }
                    float delta = (G[i] - G[j]) / quad_coef;
                    float 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

                float delta_alpha_i = alpha[i] - old_alpha_i;
                float delta_alpha_j = alpha[j] - old_alpha_j;


                for (int k = 0; k < active_size; 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);
                    update_alpha_status(i);
                    update_alpha_status(j);
                    int k;
                    if (ui != is_upper_bound(i))
                    {
                        //Q_i = Q.GetQ(i, problemSize);
                        if (ui)
                        {
                            for (k = 0; k < problemSize; k++)
                            {
                                G_bar[k] -= C_i * Q_i[k];
                            }
                        }
                        else
                        {
                            for (k = 0; k < problemSize; k++)
                            {
                                G_bar[k] += C_i * Q_i[k];
                            }
                        }
                    }

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

            // calculate rho

            si.rho  = calculate_rho();
            si.iter = iter;

            // calculate objective value
            {
                float v = 0;
                int   i;
                for (i = 0; i < problemSize; i++)
                {
                    v += alpha[i] * (G[i] + p[i]);
                }

                si.obj = v / 2;
            }

            // put back the solution
            {
                for (int i = 0; i < problemSize; i++)
                {
                    alpha_[i] = alpha[i];
                    //alpha_[active_set[i]] = alpha[i];

                    //kernel.SwapIndex(i, active_set[i]);
                }
            }

            si.upper_bound_p = Cp;
            si.upper_bound_n = Cn;
        }