Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
10/07/09 11:58:21 (15 years ago)
Author:
gkronber
Message:

Updated LibSVM project to latest version. #774

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/LibSVM/Solver.cs

    r1819 r2415  
    1919
    2020using System;
     21using System.Linq;
    2122using System.Collections.Generic;
    2223using System.Diagnostics;
     24using System.IO;
    2325
    2426namespace SVM
    2527{
    26     //
    27     // Kernel evaluation
    28     //
    29     // the static method k_function is for doing single kernel evaluation
    30     // the constructor of Kernel prepares to calculate the l*l kernel matrix
    31     // the member function get_Q is for getting one column from the Q Matrix
    32     //
    33     internal abstract class QMatrix
    34     {
    35         public abstract float[] get_Q(int column, int len);
    36         public abstract float[] get_QD();
    37         public abstract void swap_index(int i, int j);
    38     }
    39 
    40     internal abstract class Kernel : QMatrix
    41     {
    42         private Node[][] _x;
    43         private double[] _x_square;
    44 
    45         // Parameter
    46         private KernelType kernel_type;
    47         private int degree;
    48         private double gamma;
    49         private double coef0;
    50 
    51         public override void swap_index(int i, int j)
    52         {
    53             do { Node[] _ = _x[i]; _x[i] = _x[j]; _x[j] = _; } while (false);
    54             if (_x_square != null) do { double _ = _x_square[i]; _x_square[i] = _x_square[j]; _x_square[j] = _; } while (false);
    55         }
    56 
    57         private static double powi(double baseValue, int times)
    58         {
    59             double tmp = baseValue, ret = 1.0;
    60 
    61             for (int t = times; t > 0; t /= 2)
    62             {
    63                 if (t % 2 == 1) ret *= tmp;
    64                 tmp = tmp * tmp;
    65             }
    66             return ret;
    67         }
    68 
    69         private static double tanh(double x)
    70         {
    71             double e = Math.Exp(x);
    72             return 1.0 - 2.0 / (e * e + 1);
    73         }
    74 
    75         public double kernel_function(int i, int j)
    76         {
    77             switch (kernel_type)
    78             {
    79                 case KernelType.LINEAR:
    80                     return dot(_x[i], _x[j]);
    81                 case KernelType.POLY:
    82                     return powi(gamma * dot(_x[i], _x[j]) + coef0, degree);
    83                 case KernelType.RBF:
    84                     return Math.Exp(-gamma * (_x_square[i] + _x_square[j] - 2 * dot(_x[i], _x[j])));
    85                 case KernelType.SIGMOID:
    86                     return tanh(gamma * dot(_x[i], _x[j]) + coef0);
    87                 case KernelType.PRECOMPUTED:
    88                     return _x[i][(int)(_x[j][0].Value)].Value;
    89                 default:
    90                     return 0;
    91             }
    92         }
    93 
    94         public Kernel(int l, Node[][] x_, Parameter param)
    95         {
    96             this.kernel_type = param.KernelType;
    97             this.degree = param.Degree;
    98             this.gamma = param.Gamma;
    99             this.coef0 = param.Coefficient0;
    100 
    101             _x = (Node[][])x_.Clone();
    102 
    103             if (kernel_type == KernelType.RBF)
    104             {
    105                 _x_square = new double[l];
    106                 for (int i = 0; i < l; i++)
    107                     _x_square[i] = dot(_x[i], _x[i]);
    108             }
    109             else _x_square = null;
    110         }
    111 
    112         public static double dot(Node[] x, Node[] y)
    113         {
    114             double sum = 0;
    115             int xlen = x.Length;
    116             int ylen = y.Length;
    117             int i = 0;
    118             int j = 0;
    119             while (i < xlen && j < ylen)
    120             {
    121                 if (x[i].Index == y[j].Index)
    122                     sum += x[i++].Value * y[j++].Value;
    123                 else
    124                 {
    125                     if (x[i].Index > y[j].Index)
    126                         ++j;
    127                     else
    128                         ++i;
    129                 }
    130             }
    131             return sum;
    132         }
    133 
    134         public static double k_function(Node[] x, Node[] y, Parameter param)
    135         {
    136             switch (param.KernelType)
    137             {
    138                 case KernelType.LINEAR:
    139                     return dot(x, y);
    140                 case KernelType.POLY:
    141                     return powi(param.Gamma * dot(x, y) + param.Coefficient0, param.Degree);
    142                 case KernelType.RBF:
    143                     {
    144                         double sum = 0;
    145                         int xlen = x.Length;
    146                         int ylen = y.Length;
    147                         int i = 0;
    148                         int j = 0;
    149                         while (i < xlen && j < ylen)
    150                         {
    151                             if (x[i].Index == y[j].Index)
    152                             {
    153                                 double d = x[i++].Value - y[j++].Value;
    154                                 sum += d * d;
    155                             }
    156                             else if (x[i].Index > y[j].Index)
    157                             {
    158                                 sum += y[j].Value * y[j].Value;
    159                                 ++j;
    160                             }
    161                             else
    162                             {
    163                                 sum += x[i].Value * x[i].Value;
    164                                 ++i;
    165                             }
    166                         }
    167 
    168                         while (i < xlen)
    169                         {
    170                             sum += x[i].Value * x[i].Value;
    171                             ++i;
    172                         }
    173 
    174                         while (j < ylen)
    175                         {
    176                             sum += y[j].Value * y[j].Value;
    177                             ++j;
    178                         }
    179 
    180                         return Math.Exp(-param.Gamma * sum);
    181                     }
    182                 case KernelType.SIGMOID:
    183                     return tanh(param.Gamma * dot(x, y) + param.Coefficient0);
    184                 case KernelType.PRECOMPUTED:
    185                     return x[(int)(y[0].Value)].Value;
    186                 default:
    187                     return 0;
    188             }
    189         }
    190     }
    19128
    19229    // An SMO algorithm in Fan et al., JMLR 6(2005), p. 1889--1918
    19330    // Solves:
    19431    //
    195     //  min 0.5(\alpha^T Q \alpha) + p^T \alpha
     32    //  Min 0.5(\alpha^T Q \alpha) + p^T \alpha
    19633    //
    19734    //    y^T \alpha = \delta
     
    21148    {
    21249        protected int active_size;
    213         protected short[] y;
     50        protected sbyte[] y;
    21451        protected double[] G;   // gradient of objective function
    215         protected const byte LOWER_BOUND = 0;
    216         protected const byte UPPER_BOUND = 1;
    217         protected const byte FREE = 2;
    218         protected byte[] alpha_status;  // LOWER_BOUND, UPPER_BOUND, FREE
    219         protected double[] alpha;
    220         protected QMatrix Q;
     52        private const byte LOWER_BOUND = 0;
     53        private const byte UPPER_BOUND = 1;
     54        private const byte FREE = 2;
     55        private byte[] alpha_status;  // LOWER_BOUND, UPPER_BOUND, FREE
     56        private double[] alpha;
     57        protected IQMatrix Q;
    22158        protected float[] QD;
    222         protected double eps;
    223         protected double Cp, Cn;
    224         protected double[] p;
    225         protected int[] active_set;
    226         protected double[] G_bar;   // gradient, if we treat free variables as 0
     59        protected double EPS;
     60        private double Cp, Cn;
     61        private double[] p;
     62        private int[] active_set;
     63        private double[] G_bar;   // gradient, if we treat free variables as 0
    22764        protected int l;
    228         protected bool unshrinked;  // XXX
     65        protected bool unshrink;  // XXX
    22966
    23067        protected const double INF = double.PositiveInfinity;
    23168
    232         protected double get_C(int i)
     69        private double get_C(int i)
    23370        {
    23471            return (y[i] > 0) ? Cp : Cn;
    23572        }
    236         protected void update_alpha_status(int i)
     73
     74        private void update_alpha_status(int i)
    23775        {
    23876            if (alpha[i] >= get_C(i))
     
    24280            else alpha_status[i] = FREE;
    24381        }
     82
    24483        protected bool is_upper_bound(int i) { return alpha_status[i] == UPPER_BOUND; }
    24584        protected bool is_lower_bound(int i) { return alpha_status[i] == LOWER_BOUND; }
    246         protected bool is_free(int i) { return alpha_status[i] == FREE; }
    247 
    248         // java: information about solution except alpha,
    249         // because we cannot return multiple values otherwise...
    250         internal class SolutionInfo
     85
     86        private bool is_free(int i) { return alpha_status[i] == FREE; }
     87
     88        public class SolutionInfo
    25189        {
    25290            public double obj;
     
    25997        protected void swap_index(int i, int j)
    26098        {
    261             Q.swap_index(i, j);
    262             do { short _ = y[i]; y[i] = y[j]; y[j] = _; } while (false);
    263             do { double _ = G[i]; G[i] = G[j]; G[j] = _; } while (false);
    264             do { byte _ = alpha_status[i]; alpha_status[i] = alpha_status[j]; alpha_status[j] = _; } while (false);
    265             do { double _ = alpha[i]; alpha[i] = alpha[j]; alpha[j] = _; } while (false);
    266             do { double _ = p[i]; p[i] = p[j]; p[j] = _; } while (false);
    267             do { int _ = active_set[i]; active_set[i] = active_set[j]; active_set[j] = _; } while (false);
    268             do { double _ = G_bar[i]; G_bar[i] = G_bar[j]; G_bar[j] = _; } while (false);
     99            Q.SwapIndex(i, j);
     100            y.SwapIndex(i, j);
     101            G.SwapIndex(i, j);
     102            alpha_status.SwapIndex(i, j);
     103            alpha.SwapIndex(i, j);
     104            p.SwapIndex(i, j);
     105            active_set.SwapIndex(i, j);
     106            G_bar.SwapIndex(i, j);
    269107        }
    270108
     
    275113            if (active_size == l) return;
    276114
    277             int i;
    278             for (i = active_size; i < l; i++)
    279                 G[i] = G_bar[i] + p[i];
    280 
    281             for (i = 0; i < active_size; i++)
    282                 if (is_free(i))
    283                 {
    284                     float[] Q_i = Q.get_Q(i, l);
    285                     double alpha_i = alpha[i];
    286                     for (int j = active_size; j < l; j++)
    287                         G[j] += alpha_i * Q_i[j];
    288                 }
    289         }
    290 
    291         public virtual void Solve(int l, QMatrix Q, double[] p_, short[] y_,
    292                double[] alpha_, double Cp, double Cn, double eps, SolutionInfo si, bool shrinking)
     115            int i, j;
     116            int nr_free = 0;
     117
     118            for (j = active_size; j < l; j++)
     119                G[j] = G_bar[j] + p[j];
     120
     121            for (j = 0; j < active_size; j++)
     122                if (is_free(j))
     123                    nr_free++;
     124
     125            if (2 * nr_free < active_size)
     126                Procedures.info("\nWarning: using -h 0 may be faster\n");
     127
     128            if (nr_free * l > 2 * active_size * (l - active_size))
     129            {
     130                for (i = active_size; i < l; i++)
     131                {
     132                    float[] Q_i = Q.GetQ(i, active_size);
     133                    for (j = 0; j < active_size; j++)
     134                        if (is_free(j))
     135                            G[i] += alpha[j] * Q_i[j];
     136                }
     137            }
     138            else
     139            {
     140                for (i = 0; i < active_size; i++)
     141                    if (is_free(i))
     142                    {
     143                        float[] Q_i = Q.GetQ(i, l);
     144                        double alpha_i = alpha[i];
     145                        for (j = active_size; j < l; j++)
     146                            G[j] += alpha_i * Q_i[j];
     147                    }
     148            }
     149        }
     150
     151        public virtual void Solve(int l, IQMatrix Q, double[] p_, sbyte[] y_, double[] alpha_, double Cp, double Cn, double eps, SolutionInfo si, bool shrinking)
    293152        {
    294153            this.l = l;
    295154            this.Q = Q;
    296             QD = Q.get_QD();
     155            QD = Q.GetQD();
    297156            p = (double[])p_.Clone();
    298             y = (short[])y_.Clone();
     157            y = (sbyte[])y_.Clone();
    299158            alpha = (double[])alpha_.Clone();
    300159            this.Cp = Cp;
    301160            this.Cn = Cn;
    302             this.eps = eps;
    303             this.unshrinked = false;
     161            this.EPS = eps;
     162            this.unshrink = false;
    304163
    305164            // initialize alpha_status
     
    331190                    if (!is_lower_bound(i))
    332191                    {
    333                         float[] Q_i = Q.get_Q(i, l);
     192                        float[] Q_i = Q.GetQ(i, l);
    334193                        double alpha_i = alpha[i];
    335194                        int j;
     
    356215                    counter = Math.Min(l, 1000);
    357216                    if (shrinking) do_shrinking();
    358                     Debug.Write(".");
     217                    Procedures.info(".");
    359218                }
    360219
     
    365224                    // reset active set size and check
    366225                    active_size = l;
    367                     Debug.Write("*");
     226                    Procedures.info("*");
    368227                    if (select_working_set(working_set) != 0)
    369228                        break;
     
    379238                // update alpha[i] and alpha[j], handle bounds carefully
    380239
    381                 float[] Q_i = Q.get_Q(i, active_size);
    382                 float[] Q_j = Q.get_Q(j, active_size);
     240                float[] Q_i = Q.GetQ(i, active_size);
     241                float[] Q_j = Q.GetQ(j, active_size);
    383242
    384243                double C_i = get_C(i);
     
    495354                    if (ui != is_upper_bound(i))
    496355                    {
    497                         Q_i = Q.get_Q(i, l);
     356                        Q_i = Q.GetQ(i, l);
    498357                        if (ui)
    499358                            for (k = 0; k < l; k++)
     
    506365                    if (uj != is_upper_bound(j))
    507366                    {
    508                         Q_j = Q.get_Q(j, l);
     367                        Q_j = Q.GetQ(j, l);
    509368                        if (uj)
    510369                            for (k = 0; k < l; k++)
     
    541400            si.upper_bound_n = Cn;
    542401
    543             Debug.Write("\noptimization finished, #iter = " + iter + "\n");
     402            Procedures.info("\noptimization finished, #iter = " + iter + "\n");
    544403        }
    545404
    546405        // return 1 if already optimal, return 0 otherwise
    547         protected virtual int select_working_set(int[] working_set)
     406        int select_working_set(int[] working_set)
    548407        {
    549408            // return i,j such that
    550             // i: maximizes -y_i * grad(f)_i, i in I_up(\alpha)
     409            // i: Maximizes -y_i * grad(f)_i, i in I_up(\alpha)
    551410            // j: mimimizes the decrease of obj value
    552411            //    (if quadratic coefficeint <= 0, replace it with tau)
    553412            //    -y_j*grad(f)_j < -y_i*grad(f)_i, j in I_low(\alpha)
    554413
    555             double Gmax = -INF;
    556             double Gmax2 = -INF;
    557             int Gmax_idx = -1;
    558             int Gmin_idx = -1;
    559             double obj_diff_min = INF;
     414            double GMax = -INF;
     415            double GMax2 = -INF;
     416            int GMax_idx = -1;
     417            int GMin_idx = -1;
     418            double obj_diff_Min = INF;
    560419
    561420            for (int t = 0; t < active_size; t++)
     
    563422                {
    564423                    if (!is_upper_bound(t))
    565                         if (-G[t] >= Gmax)
    566                         {
    567                             Gmax = -G[t];
    568                             Gmax_idx = t;
     424                        if (-G[t] >= GMax)
     425                        {
     426                            GMax = -G[t];
     427                            GMax_idx = t;
    569428                        }
    570429                }
     
    572431                {
    573432                    if (!is_lower_bound(t))
    574                         if (G[t] >= Gmax)
    575                         {
    576                             Gmax = G[t];
    577                             Gmax_idx = t;
    578                         }
    579                 }
    580 
    581             int i = Gmax_idx;
     433                        if (G[t] >= GMax)
     434                        {
     435                            GMax = G[t];
     436                            GMax_idx = t;
     437                        }
     438                }
     439
     440            int i = GMax_idx;
    582441            float[] Q_i = null;
    583             if (i != -1) // null Q_i not accessed: Gmax=-INF if i=-1
    584                 Q_i = Q.get_Q(i, active_size);
     442            if (i != -1) // null Q_i not accessed: GMax=-INF if i=-1
     443                Q_i = Q.GetQ(i, active_size);
    585444
    586445            for (int j = 0; j < active_size; j++)
     
    590449                    if (!is_lower_bound(j))
    591450                    {
    592                         double grad_diff = Gmax + G[j];
    593                         if (G[j] >= Gmax2)
    594                             Gmax2 = G[j];
     451                        double grad_diff = GMax + G[j];
     452                        if (G[j] >= GMax2)
     453                            GMax2 = G[j];
    595454                        if (grad_diff > 0)
    596455                        {
    597456                            double obj_diff;
    598                             double quad_coef = Q_i[i] + QD[j] - 2 * y[i] * Q_i[j];
     457                            double quad_coef = Q_i[i] + QD[j] - 2.0 * y[i] * Q_i[j];
    599458                            if (quad_coef > 0)
    600459                                obj_diff = -(grad_diff * grad_diff) / quad_coef;
     
    602461                                obj_diff = -(grad_diff * grad_diff) / 1e-12;
    603462
    604                             if (obj_diff <= obj_diff_min)
     463                            if (obj_diff <= obj_diff_Min)
    605464                            {
    606                                 Gmin_idx = j;
    607                                 obj_diff_min = obj_diff;
     465                                GMin_idx = j;
     466                                obj_diff_Min = obj_diff;
    608467                            }
    609468                        }
     
    614473                    if (!is_upper_bound(j))
    615474                    {
    616                         double grad_diff = Gmax - G[j];
    617                         if (-G[j] >= Gmax2)
    618                             Gmax2 = -G[j];
     475                        double grad_diff = GMax - G[j];
     476                        if (-G[j] >= GMax2)
     477                            GMax2 = -G[j];
    619478                        if (grad_diff > 0)
    620479                        {
    621480                            double obj_diff;
    622                             double quad_coef = Q_i[i] + QD[j] + 2 * y[i] * Q_i[j];
     481                            double quad_coef = Q_i[i] + QD[j] + 2.0 * y[i] * Q_i[j];
    623482                            if (quad_coef > 0)
    624483                                obj_diff = -(grad_diff * grad_diff) / quad_coef;
     
    626485                                obj_diff = -(grad_diff * grad_diff) / 1e-12;
    627486
    628                             if (obj_diff <= obj_diff_min)
     487                            if (obj_diff <= obj_diff_Min)
    629488                            {
    630                                 Gmin_idx = j;
    631                                 obj_diff_min = obj_diff;
     489                                GMin_idx = j;
     490                                obj_diff_Min = obj_diff;
    632491                            }
    633492                        }
     
    636495            }
    637496
    638             if (Gmax + Gmax2 < eps)
     497            if (GMax + GMax2 < EPS)
    639498                return 1;
    640499
    641             working_set[0] = Gmax_idx;
    642             working_set[1] = Gmin_idx;
     500            working_set[0] = GMax_idx;
     501            working_set[1] = GMin_idx;
    643502            return 0;
    644503        }
    645504
    646         private bool be_shrunken(int i, double Gmax1, double Gmax2)
     505        private bool be_shrunk(int i, double GMax1, double GMax2)
    647506        {
    648507            if (is_upper_bound(i))
    649508            {
    650509                if (y[i] == +1)
    651                     return (-G[i] > Gmax1);
     510                    return (-G[i] > GMax1);
    652511                else
    653                     return (-G[i] > Gmax2);
     512                    return (-G[i] > GMax2);
    654513            }
    655514            else if (is_lower_bound(i))
    656515            {
    657516                if (y[i] == +1)
    658                     return (G[i] > Gmax2);
     517                    return (G[i] > GMax2);
    659518                else
    660                     return (G[i] > Gmax1);
     519                    return (G[i] > GMax1);
    661520            }
    662521            else
     
    664523        }
    665524
    666         protected virtual void do_shrinking()
     525        void do_shrinking()
    667526        {
    668527            int i;
    669             double Gmax1 = -INF;    // max { -y_i * grad(f)_i | i in I_up(\alpha) }
    670             double Gmax2 = -INF;    // max { y_i * grad(f)_i | i in I_low(\alpha) }
    671 
    672             // find maximal violating pair first
     528            double GMax1 = -INF;    // Max { -y_i * grad(f)_i | i in I_up(\alpha) }
     529            double GMax2 = -INF;    // Max { y_i * grad(f)_i | i in I_low(\alpha) }
     530
     531            // find Maximal violating pair first
    673532            for (i = 0; i < active_size; i++)
    674533            {
     
    677536                    if (!is_upper_bound(i))
    678537                    {
    679                         if (-G[i] >= Gmax1)
    680                             Gmax1 = -G[i];
     538                        if (-G[i] >= GMax1)
     539                            GMax1 = -G[i];
    681540                    }
    682541                    if (!is_lower_bound(i))
    683542                    {
    684                         if (G[i] >= Gmax2)
    685                             Gmax2 = G[i];
     543                        if (G[i] >= GMax2)
     544                            GMax2 = G[i];
    686545                    }
    687546                }
     
    690549                    if (!is_upper_bound(i))
    691550                    {
    692                         if (-G[i] >= Gmax2)
    693                             Gmax2 = -G[i];
     551                        if (-G[i] >= GMax2)
     552                            GMax2 = -G[i];
    694553                    }
    695554                    if (!is_lower_bound(i))
    696555                    {
    697                         if (G[i] >= Gmax1)
    698                             Gmax1 = G[i];
    699                     }
    700                 }
    701             }
    702 
    703             // shrink
     556                        if (G[i] >= GMax1)
     557                            GMax1 = G[i];
     558                    }
     559                }
     560            }
     561
     562            if (unshrink == false && GMax1 + GMax2 <= EPS * 10)
     563            {
     564                unshrink = true;
     565                reconstruct_gradient();
     566                active_size = l;
     567            }
    704568
    705569            for (i = 0; i < active_size; i++)
    706                 if (be_shrunken(i, Gmax1, Gmax2))
     570                if (be_shrunk(i, GMax1, GMax2))
    707571                {
    708572                    active_size--;
    709573                    while (active_size > i)
    710574                    {
    711                         if (!be_shrunken(active_size, Gmax1, Gmax2))
     575                        if (!be_shrunk(active_size, GMax1, GMax2))
    712576                        {
    713577                            swap_index(i, active_size);
     
    717581                    }
    718582                }
    719 
    720             // unshrink, check all variables again before sealed iterations
    721 
    722             if (unshrinked || Gmax1 + Gmax2 > eps * 10) return;
    723 
    724             unshrinked = true;
    725             reconstruct_gradient();
    726 
    727             for (i = l - 1; i >= active_size; i--)
    728                 if (!be_shrunken(i, Gmax1, Gmax2))
    729                 {
    730                     while (active_size < i)
    731                     {
    732                         if (be_shrunken(active_size, Gmax1, Gmax2))
    733                         {
    734                             swap_index(i, active_size);
    735                             break;
    736                         }
    737                         active_size++;
    738                     }
    739                     active_size++;
    740                 }
    741         }
    742 
    743         protected virtual double calculate_rho()
     583        }
     584
     585        double calculate_rho()
    744586        {
    745587            double r;
     
    786628    // additional constraint: e^T \alpha = constant
    787629    //
    788     sealed class Solver_NU : Solver
     630    class Solver_NU : Solver
    789631    {
    790632        private SolutionInfo si;
    791633
    792         public override void Solve(int l, QMatrix Q, double[] p, short[] y,
     634        public sealed override void Solve(int l, IQMatrix Q, double[] p, sbyte[] y,
    793635               double[] alpha, double Cp, double Cn, double eps,
    794636               SolutionInfo si, bool shrinking)
     
    799641
    800642        // return 1 if already optimal, return 0 otherwise
    801         protected override int select_working_set(int[] working_set)
     643        private int select_working_set(int[] working_set)
    802644        {
    803645            // return i,j such that y_i = y_j and
    804             // i: maximizes -y_i * grad(f)_i, i in I_up(\alpha)
    805             // j: minimizes the decrease of obj value
     646            // i: Maximizes -y_i * grad(f)_i, i in I_up(\alpha)
     647            // j: Minimizes the decrease of obj value
    806648            //    (if quadratic coefficeint <= 0, replace it with tau)
    807649            //    -y_j*grad(f)_j < -y_i*grad(f)_i, j in I_low(\alpha)
    808650
    809             double Gmaxp = -INF;
    810             double Gmaxp2 = -INF;
    811             int Gmaxp_idx = -1;
    812 
    813             double Gmaxn = -INF;
    814             double Gmaxn2 = -INF;
    815             int Gmaxn_idx = -1;
    816 
    817             int Gmin_idx = -1;
    818             double obj_diff_min = INF;
     651            double GMaxp = -INF;
     652            double GMaxp2 = -INF;
     653            int GMaxp_idx = -1;
     654
     655            double GMaxn = -INF;
     656            double GMaxn2 = -INF;
     657            int GMaxn_idx = -1;
     658
     659            int GMin_idx = -1;
     660            double obj_diff_Min = INF;
    819661
    820662            for (int t = 0; t < active_size; t++)
     
    822664                {
    823665                    if (!is_upper_bound(t))
    824                         if (-G[t] >= Gmaxp)
    825                         {
    826                             Gmaxp = -G[t];
    827                             Gmaxp_idx = t;
     666                        if (-G[t] >= GMaxp)
     667                        {
     668                            GMaxp = -G[t];
     669                            GMaxp_idx = t;
    828670                        }
    829671                }
     
    831673                {
    832674                    if (!is_lower_bound(t))
    833                         if (G[t] >= Gmaxn)
    834                         {
    835                             Gmaxn = G[t];
    836                             Gmaxn_idx = t;
    837                         }
    838                 }
    839 
    840             int ip = Gmaxp_idx;
    841             int iN = Gmaxn_idx;
     675                        if (G[t] >= GMaxn)
     676                        {
     677                            GMaxn = G[t];
     678                            GMaxn_idx = t;
     679                        }
     680                }
     681
     682            int ip = GMaxp_idx;
     683            int iN = GMaxn_idx;
    842684            float[] Q_ip = null;
    843685            float[] Q_in = null;
    844             if (ip != -1) // null Q_ip not accessed: Gmaxp=-INF if ip=-1
    845                 Q_ip = Q.get_Q(ip, active_size);
     686            if (ip != -1) // null Q_ip not accessed: GMaxp=-INF if ip=-1
     687                Q_ip = Q.GetQ(ip, active_size);
    846688            if (iN != -1)
    847                 Q_in = Q.get_Q(iN, active_size);
     689                Q_in = Q.GetQ(iN, active_size);
    848690
    849691            for (int j = 0; j < active_size; j++)
     
    853695                    if (!is_lower_bound(j))
    854696                    {
    855                         double grad_diff = Gmaxp + G[j];
    856                         if (G[j] >= Gmaxp2)
    857                             Gmaxp2 = G[j];
     697                        double grad_diff = GMaxp + G[j];
     698                        if (G[j] >= GMaxp2)
     699                            GMaxp2 = G[j];
    858700                        if (grad_diff > 0)
    859701                        {
     
    865707                                obj_diff = -(grad_diff * grad_diff) / 1e-12;
    866708
    867                             if (obj_diff <= obj_diff_min)
     709                            if (obj_diff <= obj_diff_Min)
    868710                            {
    869                                 Gmin_idx = j;
    870                                 obj_diff_min = obj_diff;
     711                                GMin_idx = j;
     712                                obj_diff_Min = obj_diff;
    871713                            }
    872714                        }
     
    877719                    if (!is_upper_bound(j))
    878720                    {
    879                         double grad_diff = Gmaxn - G[j];
    880                         if (-G[j] >= Gmaxn2)
    881                             Gmaxn2 = -G[j];
     721                        double grad_diff = GMaxn - G[j];
     722                        if (-G[j] >= GMaxn2)
     723                            GMaxn2 = -G[j];
    882724                        if (grad_diff > 0)
    883725                        {
     
    889731                                obj_diff = -(grad_diff * grad_diff) / 1e-12;
    890732
    891                             if (obj_diff <= obj_diff_min)
     733                            if (obj_diff <= obj_diff_Min)
    892734                            {
    893                                 Gmin_idx = j;
    894                                 obj_diff_min = obj_diff;
     735                                GMin_idx = j;
     736                                obj_diff_Min = obj_diff;
    895737                            }
    896738                        }
     
    899741            }
    900742
    901             if (Math.Max(Gmaxp + Gmaxp2, Gmaxn + Gmaxn2) < eps)
     743            if (Math.Max(GMaxp + GMaxp2, GMaxn + GMaxn2) < EPS)
    902744                return 1;
    903745
    904             if (y[Gmin_idx] == +1)
    905                 working_set[0] = Gmaxp_idx;
     746            if (y[GMin_idx] == +1)
     747                working_set[0] = GMaxp_idx;
    906748            else
    907                 working_set[0] = Gmaxn_idx;
    908             working_set[1] = Gmin_idx;
     749                working_set[0] = GMaxn_idx;
     750            working_set[1] = GMin_idx;
    909751
    910752            return 0;
    911753        }
    912754
    913         private bool be_shrunken(int i, double Gmax1, double Gmax2, double Gmax3, double Gmax4)
     755        private bool be_shrunk(int i, double GMax1, double GMax2, double GMax3, double GMax4)
    914756        {
    915757            if (is_upper_bound(i))
    916758            {
    917759                if (y[i] == +1)
    918                     return (-G[i] > Gmax1);
     760                    return (-G[i] > GMax1);
    919761                else
    920                     return (-G[i] > Gmax4);
     762                    return (-G[i] > GMax4);
    921763            }
    922764            else if (is_lower_bound(i))
    923765            {
    924766                if (y[i] == +1)
    925                     return (G[i] > Gmax2);
     767                    return (G[i] > GMax2);
    926768                else
    927                     return (G[i] > Gmax3);
     769                    return (G[i] > GMax3);
    928770            }
    929771            else
     
    931773        }
    932774
    933         protected override void do_shrinking()
    934         {
    935             double Gmax1 = -INF;  // max { -y_i * grad(f)_i | y_i = +1, i in I_up(\alpha) }
    936             double Gmax2 = -INF;  // max { y_i * grad(f)_i | y_i = +1, i in I_low(\alpha) }
    937             double Gmax3 = -INF;  // max { -y_i * grad(f)_i | y_i = -1, i in I_up(\alpha) }
    938             double Gmax4 = -INF;  // max { y_i * grad(f)_i | y_i = -1, i in I_low(\alpha) }
    939 
    940             // find maximal violating pair first
     775        private void do_shrinking()
     776        {
     777            double GMax1 = -INF;  // Max { -y_i * grad(f)_i | y_i = +1, i in I_up(\alpha) }
     778            double GMax2 = -INF;  // Max { y_i * grad(f)_i | y_i = +1, i in I_low(\alpha) }
     779            double GMax3 = -INF;  // Max { -y_i * grad(f)_i | y_i = -1, i in I_up(\alpha) }
     780            double GMax4 = -INF;  // Max { y_i * grad(f)_i | y_i = -1, i in I_low(\alpha) }
     781
     782            // find Maximal violating pair first
    941783            int i;
    942784            for (i = 0; i < active_size; i++)
     
    946788                    if (y[i] == +1)
    947789                    {
    948                         if (-G[i] > Gmax1) Gmax1 = -G[i];
    949                     }
    950                     else if (-G[i] > Gmax4) Gmax4 = -G[i];
     790                        if (-G[i] > GMax1) GMax1 = -G[i];
     791                    }
     792                    else if (-G[i] > GMax4) GMax4 = -G[i];
    951793                }
    952794                if (!is_lower_bound(i))
     
    954796                    if (y[i] == +1)
    955797                    {
    956                         if (G[i] > Gmax2) Gmax2 = G[i];
    957                     }
    958                     else if (G[i] > Gmax3) Gmax3 = G[i];
    959                 }
    960             }
    961 
    962             // shrinking
     798                        if (G[i] > GMax2) GMax2 = G[i];
     799                    }
     800                    else if (G[i] > GMax3) GMax3 = G[i];
     801                }
     802            }
     803
     804            if (unshrink == false && Math.Max(GMax1 + GMax2, GMax3 + GMax4) <= EPS * 10)
     805            {
     806                unshrink = true;
     807                reconstruct_gradient();
     808                active_size = l;
     809            }
    963810
    964811            for (i = 0; i < active_size; i++)
    965                 if (be_shrunken(i, Gmax1, Gmax2, Gmax3, Gmax4))
     812                if (be_shrunk(i, GMax1, GMax2, GMax3, GMax4))
    966813                {
    967814                    active_size--;
    968815                    while (active_size > i)
    969816                    {
    970                         if (!be_shrunken(active_size, Gmax1, Gmax2, Gmax3, Gmax4))
     817                        if (!be_shrunk(active_size, GMax1, GMax2, GMax3, GMax4))
    971818                        {
    972819                            swap_index(i, active_size);
     
    976823                    }
    977824                }
    978 
    979             if (unshrinked || Math.Max(Gmax1 + Gmax2, Gmax3 + Gmax4) > eps * 10) return;
    980 
    981             unshrinked = true;
    982             reconstruct_gradient();
    983 
    984             for (i = l - 1; i >= active_size; i--)
    985                 if (!be_shrunken(i, Gmax1, Gmax2, Gmax3, Gmax4))
    986                 {
    987                     while (active_size < i)
    988                     {
    989                         if (be_shrunken(active_size, Gmax1, Gmax2, Gmax3, Gmax4))
    990                         {
    991                             swap_index(i, active_size);
    992                             break;
    993                         }
    994                         active_size++;
    995                     }
    996                     active_size++;
    997                 }
    998         }
    999 
    1000         protected override double calculate_rho()
     825        }
     826
     827        private double calculate_rho()
    1001828        {
    1002829            int nr_free1 = 0, nr_free2 = 0;
     
    1054881    class SVC_Q : Kernel
    1055882    {
    1056         private short[] y;
     883        private sbyte[] y;
    1057884        private Cache cache;
    1058885        private float[] QD;
    1059886
    1060         public SVC_Q(Problem prob, Parameter param, short[] y_) : base(prob.Count, prob.X, param)
    1061         {
    1062             y = (short[])y_.Clone();
     887        public SVC_Q(Problem prob, Parameter param, sbyte[] y_) : base(prob.Count, prob.X, param)
     888        {
     889            y = (sbyte[])y_.Clone();
    1063890            cache = new Cache(prob.Count, (long)(param.CacheSize * (1 << 20)));
    1064891            QD = new float[prob.Count];
    1065892            for (int i = 0; i < prob.Count; i++)
    1066                 QD[i] = (float)kernel_function(i, i);
    1067         }
    1068 
    1069         public override float[] get_Q(int i, int len)
    1070         {
    1071             float[][] data = new float[1][];
    1072             int start;
    1073             if ((start = cache.get_data(i, data, len)) < len)
    1074             {
    1075                 for (int j = start; j < len; j++)
    1076                     data[0][j] = (float)(y[i] * y[j] * kernel_function(i, j));
    1077             }
    1078             return data[0];
    1079         }
    1080 
    1081         public override float[] get_QD()
     893                QD[i] = (float)KernelFunction(i, i);
     894        }
     895
     896        public override sealed float[] GetQ(int i, int len)
     897        {
     898            float[] data = null;
     899            int start, j;
     900            if ((start = cache.GetData(i, ref data, len)) < len)
     901            {
     902                for (j = start; j < len; j++)
     903                    data[j] = (float)(y[i] * y[j] * KernelFunction(i, j));
     904            }
     905            return data;
     906        }
     907
     908        public override sealed float[] GetQD()
    1082909        {
    1083910            return QD;
    1084911        }
    1085912
    1086         public override void swap_index(int i, int j)
    1087         {
    1088             cache.swap_index(i, j);
    1089             base.swap_index(i, j);
    1090             do { short _ = y[i]; y[i] = y[j]; y[j] = _; } while (false);
    1091             do { float _ = QD[i]; QD[i] = QD[j]; QD[j] = _; } while (false);
     913        public override sealed void SwapIndex(int i, int j)
     914        {
     915            cache.SwapIndex(i, j);
     916            base.SwapIndex(i, j);
     917            y.SwapIndex(i, j);
     918            QD.SwapIndex(i, j);
    1092919        }
    1093920    }
     
    1098925        private float[] QD;
    1099926
    1100         public ONE_CLASS_Q(Problem prob, Parameter param) : base(prob.Count, prob.X, param)
     927        public ONE_CLASS_Q(Problem prob, Parameter param) :  base(prob.Count, prob.X, param)
    1101928        {
    1102929            cache = new Cache(prob.Count, (long)(param.CacheSize * (1 << 20)));
    1103930            QD = new float[prob.Count];
    1104931            for (int i = 0; i < prob.Count; i++)
    1105                 QD[i] = (float)kernel_function(i, i);
    1106         }
    1107 
    1108         public override float[] get_Q(int i, int len)
    1109         {
    1110             float[][] data = new float[1][];
    1111             int start;
    1112             if ((start = cache.get_data(i, data, len)) < len)
    1113             {
    1114                 for (int j = start; j < len; j++)
    1115                     data[0][j] = (float)kernel_function(i, j);
    1116             }
    1117             return data[0];
    1118         }
    1119 
    1120         public override float[] get_QD()
     932                QD[i] = (float)KernelFunction(i, i);
     933        }
     934
     935        public override sealed float[] GetQ(int i, int len)
     936        {
     937            float[] data = null;
     938            int start, j;
     939            if ((start = cache.GetData(i, ref data, len)) < len)
     940            {
     941                for (j = start; j < len; j++)
     942                    data[j] = (float)KernelFunction(i, j);
     943            }
     944            return data;
     945        }
     946
     947        public override sealed float[] GetQD()
    1121948        {
    1122949            return QD;
    1123950        }
    1124951
    1125         public override void swap_index(int i, int j)
    1126         {
    1127             cache.swap_index(i, j);
    1128             base.swap_index(i, j);
    1129             do { float _ = QD[i]; QD[i] = QD[j]; QD[j] = _; } while (false);
     952        public override sealed void SwapIndex(int i, int j)
     953        {
     954            cache.SwapIndex(i, j);
     955            base.SwapIndex(i, j);
     956            QD.SwapIndex(i, j);
    1130957        }
    1131958    }
     
    1135962        private int l;
    1136963        private Cache cache;
    1137         private short[] sign;
     964        private sbyte[] sign;
    1138965        private int[] index;
    1139966        private int next_buffer;
     
    1141968        private float[] QD;
    1142969
    1143         public SVR_Q(Problem prob, Parameter param)
    1144             : base(prob.Count, prob.X, param)
     970        public SVR_Q(Problem prob, Parameter param) : base(prob.Count, prob.X, param)
    1145971        {
    1146972            l = prob.Count;
    1147973            cache = new Cache(l, (long)(param.CacheSize * (1 << 20)));
    1148974            QD = new float[2 * l];
    1149             sign = new short[2 * l];
     975            sign = new sbyte[2 * l];
    1150976            index = new int[2 * l];
    1151977            for (int k = 0; k < l; k++)
     
    1155981                index[k] = k;
    1156982                index[k + l] = k;
    1157                 QD[k] = (float)kernel_function(k, k);
     983                QD[k] = (float)KernelFunction(k, k);
    1158984                QD[k + l] = QD[k];
    1159985            }
     
    1164990        }
    1165991
    1166         public override void swap_index(int i, int j)
    1167         {
    1168             do { short _ = sign[i]; sign[i] = sign[j]; sign[j] = _; } while (false);
    1169             do { int _ = index[i]; index[i] = index[j]; index[j] = _; } while (false);
    1170             do { float _ = QD[i]; QD[i] = QD[j]; QD[j] = _; } while (false);
    1171         }
    1172 
    1173         public override float[] get_Q(int i, int len)
    1174         {
    1175             float[][] data = new float[1][];
    1176             int real_i = index[i];
    1177             if (cache.get_data(real_i, data, l) < l)
    1178             {
    1179                 for (int j = 0; j < l; j++)
    1180                     data[0][j] = (float)kernel_function(real_i, j);
     992        public override sealed void SwapIndex(int i, int j)
     993        {
     994            sign.SwapIndex(i, j);
     995            index.SwapIndex(i, j);
     996            QD.SwapIndex(i, j);
     997        }
     998
     999        public override sealed float[] GetQ(int i, int len)
     1000        {
     1001            float[] data = null;
     1002            int j, real_i = index[i];
     1003            if (cache.GetData(real_i, ref data, l) < l)
     1004            {
     1005                for (j = 0; j < l; j++)
     1006                    data[j] = (float)KernelFunction(real_i, j);
    11811007            }
    11821008
     
    11841010            float[] buf = buffer[next_buffer];
    11851011            next_buffer = 1 - next_buffer;
    1186             short si = sign[i];
    1187             for (int j = 0; j < len; j++)
    1188                 buf[j] = si * sign[j] * data[0][index[j]];
     1012            sbyte si = sign[i];
     1013            for (j = 0; j < len; j++)
     1014                buf[j] = (float)si * sign[j] * data[index[j]];
    11891015            return buf;
    11901016        }
    11911017
    1192         public override float[] get_QD()
     1018        public override sealed float[] GetQD()
    11931019        {
    11941020            return QD;
     
    11961022    }
    11971023
    1198     internal static class Procedures
     1024    internal class Procedures
    11991025    {
     1026        private static bool _verbose;
     1027        public static bool IsVerbose
     1028        {
     1029            get
     1030            {
     1031                return _verbose;
     1032            }
     1033            set
     1034            {
     1035                _verbose = value;
     1036            }
     1037        }
    12001038        //
    12011039        // construct and solve various formulations
    12021040        //
     1041        public const int LIBSVM_VERSION = 289;
     1042
     1043        public static TextWriter svm_print_string = Console.Out;
     1044
     1045        public static void info(string s)
     1046        {
     1047            if(_verbose)
     1048                svm_print_string.Write(s);
     1049        }
     1050
    12031051        private static void solve_c_svc(Problem prob, Parameter param,
    12041052                        double[] alpha, Solver.SolutionInfo si,
     
    12061054        {
    12071055            int l = prob.Count;
    1208             double[] minus_ones = new double[l];
    1209             short[] y = new short[l];
     1056            double[] Minus_ones = new double[l];
     1057            sbyte[] y = new sbyte[l];
    12101058
    12111059            int i;
     
    12141062            {
    12151063                alpha[i] = 0;
    1216                 minus_ones[i] = -1;
     1064                Minus_ones[i] = -1;
    12171065                if (prob.Y[i] > 0) y[i] = +1; else y[i] = -1;
    12181066            }
    12191067
    12201068            Solver s = new Solver();
    1221             s.Solve(l, new SVC_Q(prob, param, y), minus_ones, y,
     1069            s.Solve(l, new SVC_Q(prob, param, y), Minus_ones, y,
    12221070                alpha, Cp, Cn, param.EPS, si, param.Shrinking);
    12231071
     
    12271075
    12281076            if (Cp == Cn)
    1229                 Debug.Write("nu = " + sum_alpha / (Cp * prob.Count) + "\n");
     1077                Procedures.info("nu = " + sum_alpha / (Cp * prob.Count) + "\n");
    12301078
    12311079            for (i = 0; i < l; i++)
     
    12401088            double nu = param.Nu;
    12411089
    1242             short[] y = new short[l];
     1090            sbyte[] y = new sbyte[l];
    12431091
    12441092            for (i = 0; i < l; i++)
     
    12691117
    12701118            Solver_NU s = new Solver_NU();
    1271             s.Solve(l, new SVC_Q(prob, param, y), zeros, y,
    1272                 alpha, 1.0, 1.0, param.EPS, si, param.Shrinking);
     1119            s.Solve(l, new SVC_Q(prob, param, y), zeros, y, alpha, 1.0, 1.0, param.EPS, si, param.Shrinking);
    12731120            double r = si.r;
    12741121
    1275             Debug.Write("C = " + 1 / r + "\n");
     1122            Procedures.info("C = " + 1 / r + "\n");
    12761123
    12771124            for (i = 0; i < l; i++)
     
    12851132
    12861133        private static void solve_one_class(Problem prob, Parameter param,
    1287                             double[] alpha, Solver.SolutionInfo si)
     1134                        double[] alpha, Solver.SolutionInfo si)
    12881135        {
    12891136            int l = prob.Count;
    12901137            double[] zeros = new double[l];
    1291             short[] ones = new short[l];
     1138            sbyte[] ones = new sbyte[l];
    12921139            int i;
    12931140
     
    13081155
    13091156            Solver s = new Solver();
    1310             s.Solve(l, new ONE_CLASS_Q(prob, param), zeros, ones,
    1311                 alpha, 1.0, 1.0, param.EPS, si, param.Shrinking);
    1312         }
    1313 
    1314         private static void solve_epsilon_svr(Problem prob, Parameter param,
    1315                         double[] alpha, Solver.SolutionInfo si)
     1157            s.Solve(l, new ONE_CLASS_Q(prob, param), zeros, ones, alpha, 1.0, 1.0, param.EPS, si, param.Shrinking);
     1158        }
     1159
     1160        private static void solve_epsilon_svr(Problem prob, Parameter param, double[] alpha, Solver.SolutionInfo si)
    13161161        {
    13171162            int l = prob.Count;
    13181163            double[] alpha2 = new double[2 * l];
    13191164            double[] linear_term = new double[2 * l];
    1320             short[] y = new short[2 * l];
     1165            sbyte[] y = new sbyte[2 * l];
    13211166            int i;
    13221167
     
    13331178
    13341179            Solver s = new Solver();
    1335             s.Solve(2 * l, new SVR_Q(prob, param), linear_term, y,
    1336                 alpha2, param.C, param.C, param.EPS, si, param.Shrinking);
     1180            s.Solve(2 * l, new SVR_Q(prob, param), linear_term, y, alpha2, param.C, param.C, param.EPS, si, param.Shrinking);
    13371181
    13381182            double sum_alpha = 0;
     
    13421186                sum_alpha += Math.Abs(alpha[i]);
    13431187            }
    1344             Debug.Write("nu = " + sum_alpha / (param.C * l) + "\n");
     1188            Procedures.info("nu = " + sum_alpha / (param.C * l) + "\n");
    13451189        }
    13461190
     
    13521196            double[] alpha2 = new double[2 * l];
    13531197            double[] linear_term = new double[2 * l];
    1354             short[] y = new short[2 * l];
     1198            sbyte[] y = new sbyte[2 * l];
    13551199            int i;
    13561200
     
    13711215            s.Solve(2 * l, new SVR_Q(prob, param), linear_term, y, alpha2, C, C, param.EPS, si, param.Shrinking);
    13721216
    1373             Debug.Write("epsilon = " + (-si.r) + "\n");
     1217            Procedures.info("epsilon = " + (-si.r) + "\n");
    13741218
    13751219            for (i = 0; i < l; i++)
     
    13801224        // decision_function
    13811225        //
    1382         private class decision_function
     1226        internal class decision_function
    13831227        {
    13841228            public double[] alpha;
     
    13861230        };
    13871231
    1388         static decision_function svm_train_one(
    1389             Problem prob, Parameter param,
    1390             double Cp, double Cn)
     1232        static decision_function svm_train_one(Problem prob, Parameter param, double Cp, double Cn)
    13911233        {
    13921234            double[] alpha = new double[prob.Count];
     
    14111253            }
    14121254
    1413             Debug.Write("obj = " + si.obj + ", rho = " + si.rho + "\n");
     1255            Procedures.info("obj = " + si.obj + ", rho = " + si.rho + "\n");
    14141256
    14151257            // output SVs
     
    14351277            }
    14361278
    1437             Debug.Write("nSV = " + nSV + ", nBSV = " + nBSV + "\n");
     1279            Procedures.info("nSV = " + nSV + ", nBSV = " + nBSV + "\n");
    14381280
    14391281            decision_function f = new decision_function();
     
    14551297                else prior0 += 1;
    14561298
    1457             int max_iter = 100;   // Maximal number of iterations
    1458             double min_step = 1e-10;  // Minimal step taken in line search
    1459             double sigma = 1e-3;  // For numerically strict PD of Hessian
     1299            int Max_iter = 100; // Maximal number of iterations
     1300            double Min_step = 1e-10;  // Minimal step taken in line search
     1301            double sigma = 1e-12; // For numerically strict PD of Hessian
    14601302            double eps = 1e-5;
    14611303            double hiTarget = (prior1 + 1.0) / (prior1 + 2.0);
     
    14801322                    fval += (t[i] - 1) * fApB + Math.Log(1 + Math.Exp(fApB));
    14811323            }
    1482             for (iter = 0; iter < max_iter; iter++)
     1324            for (iter = 0; iter < Max_iter; iter++)
    14831325            {
    14841326                // Update Gradient and Hessian (use H' = H + sigma I)
     
    15191361
    15201362
    1521                 stepsize = 1;     // Line Search
    1522                 while (stepsize >= min_step)
     1363                stepsize = 1;   // Line Search
     1364                while (stepsize >= Min_step)
    15231365                {
    15241366                    newA = A + stepsize * dA;
     
    15451387                }
    15461388
    1547                 if (stepsize < min_step)
    1548                 {
    1549                     Debug.Write("Line search fails in two-class probability estimates\n");
     1389                if (stepsize < Min_step)
     1390                {
     1391                    Procedures.info("Line search fails in two-class probability estimates\n");
    15501392                    break;
    15511393                }
    15521394            }
    15531395
    1554             if (iter >= max_iter)
    1555                 Debug.Write("Reaching maximal iterations in two-class probability estimates\n");
     1396            if (iter >= Max_iter)
     1397                Procedures.info("Reaching Maximal iterations in two-class probability estimates\n");
    15561398            probAB[0] = A; probAB[1] = B;
    15571399        }
     
    15681410        // Method 2 from the multiclass_prob paper by Wu, Lin, and Weng
    15691411        private static void multiclass_probability(int k, double[,] r, double[] p)
    1570   {
    1571     int t,j;
    1572     int iter = 0, max_iter=Math.Max(100,k);
    1573     double[,] Q=new double[k,k];
    1574     double[] Qp= new double[k];
    1575     double pQp, eps=0.005/k;
    1576  
    1577     for (t=0;t<k;t++)
    1578     {
    1579       p[t]=1.0/k;  // Valid if k = 1
    1580       Q[t,t]=0;
    1581       for (j=0;j<t;j++)
    1582       {
    1583         Q[t,t]+=r[j,t]*r[j,t];
    1584         Q[t,j]=Q[j,t];
    1585       }
    1586       for (j=t+1;j<k;j++)
    1587       {
    1588         Q[t,t]+=r[j,t]*r[j,t];
    1589         Q[t,j]=-r[j,t]*r[t,j];
    1590       }
    1591     }
    1592     for (iter=0;iter<max_iter;iter++)
    1593     {
    1594       // stopping condition, recalculate QP,pQP for numerical accuracy
    1595       pQp=0;
    1596       for (t=0;t<k;t++)
    1597       {
    1598         Qp[t]=0;
    1599         for (j=0;j<k;j++)
    1600           Qp[t]+=Q[t,j]*p[j];
    1601         pQp+=p[t]*Qp[t];
    1602       }
    1603       double max_error=0;
    1604       for (t=0;t<k;t++)
    1605       {
    1606         double error=Math.Abs(Qp[t]-pQp);
    1607         if (error>max_error)
    1608           max_error=error;
    1609       }
    1610       if (max_error<eps) break;
    1611    
    1612       for (t=0;t<k;t++)
    1613       {
    1614         double diff=(-Qp[t]+pQp)/Q[t,t];
    1615         p[t]+=diff;
    1616         pQp=(pQp+diff*(diff*Q[t,t]+2*Qp[t]))/(1+diff)/(1+diff);
    1617         for (j=0;j<k;j++)
    1618         {
    1619           Qp[j]=(Qp[j]+diff*Q[t,j])/(1+diff);
    1620           p[j]/=(1+diff);
    1621         }
    1622       }
    1623     }
    1624     if (iter>=max_iter)
    1625       Debug.Write("Exceeds max_iter in multiclass_prob\n");
    1626   }
     1412        {
     1413            int t, j;
     1414            int iter = 0, Max_iter = Math.Max(100, k);
     1415            double[,] Q = new double[k,k];
     1416            double[] Qp = new double[k];
     1417            double pQp, eps = 0.005 / k;
     1418
     1419            for (t = 0; t < k; t++)
     1420            {
     1421                p[t] = 1.0 / k;  // Valid if k = 1
     1422                Q[t,t] = 0;
     1423                for (j = 0; j < t; j++)
     1424                {
     1425                    Q[t,t] += r[j,t] * r[j,t];
     1426                    Q[t,j] = Q[j,t];
     1427                }
     1428                for (j = t + 1; j < k; j++)
     1429                {
     1430                    Q[t,t] += r[j,t] * r[j,t];
     1431                    Q[t,j] = -r[j,t] * r[t,j];
     1432                }
     1433            }
     1434            for (iter = 0; iter < Max_iter; iter++)
     1435            {
     1436                // stopping condition, recalculate QP,pQP for numerical accuracy
     1437                pQp = 0;
     1438                for (t = 0; t < k; t++)
     1439                {
     1440                    Qp[t] = 0;
     1441                    for (j = 0; j < k; j++)
     1442                        Qp[t] += Q[t,j] * p[j];
     1443                    pQp += p[t] * Qp[t];
     1444                }
     1445                double Max_error = 0;
     1446                for (t = 0; t < k; t++)
     1447                {
     1448                    double error = Math.Abs(Qp[t] - pQp);
     1449                    if (error > Max_error)
     1450                        Max_error = error;
     1451                }
     1452                if (Max_error < eps) break;
     1453
     1454                for (t = 0; t < k; t++)
     1455                {
     1456                    double diff = (-Qp[t] + pQp) / Q[t,t];
     1457                    p[t] += diff;
     1458                    pQp = (pQp + diff * (diff * Q[t,t] + 2 * Qp[t])) / (1 + diff) / (1 + diff);
     1459                    for (j = 0; j < k; j++)
     1460                    {
     1461                        Qp[j] = (Qp[j] + diff * Q[t,j]) / (1 + diff);
     1462                        p[j] /= (1 + diff);
     1463                    }
     1464                }
     1465            }
     1466            if (iter >= Max_iter)
     1467                Procedures.info("Exceeds Max_iter in multiclass_prob\n");
     1468        }
    16271469
    16281470        // Cross-validation decision values for probability estimates
    16291471        private static void svm_binary_svc_probability(Problem prob, Parameter param, double Cp, double Cn, double[] probAB)
    16301472        {
    1631             Random rand = new Random();
    16321473            int i;
    16331474            int nr_fold = 5;
     
    16361477
    16371478            // random shuffle
     1479            Random rand = new Random();
    16381480            for (i = 0; i < prob.Count; i++) perm[i] = i;
    16391481            for (i = 0; i < prob.Count; i++)
     
    16871529                    subparam.Probability = false;
    16881530                    subparam.C = 1.0;
    1689                     subparam.WeightCount = 2;
    1690                     subparam.WeightLabels = new int[2];
    1691                     subparam.Weights = new double[2];
    1692                     subparam.WeightLabels[0] = +1;
    1693                     subparam.WeightLabels[1] = -1;
    1694                     subparam.Weights[0] = Cp;
    1695                     subparam.Weights[1] = Cn;
     1531                    subparam.Weights[1] = Cp;
     1532                    subparam.Weights[-1] = Cn;
    16961533                    Model submodel = svm_train(subprob, subparam);
    16971534                    for (j = begin; j < end; j++)
     
    17181555            Parameter newparam = (Parameter)param.Clone();
    17191556            newparam.Probability = false;
    1720             svm_cross_validation(prob, newparam, nr_fold, ymv, null);
     1557            svm_cross_validation(prob, newparam, nr_fold, ymv);
    17211558            for (i = 0; i < prob.Count; i++)
    17221559            {
     
    17341571                    mae += Math.Abs(ymv[i]);
    17351572            mae /= (prob.Count - count);
    1736             Debug.Write("Prob. model for test data: target value = predicted value + z,\nz: Laplace distribution e^(-|z|/sigma)/(2sigma),sigma=" + mae + "\n");
     1573            Procedures.info("Prob. model for test data: target value = predicted value + z,\nz: Laplace distribution e^(-|z|/sigma)/(2sigma),sigma=" + mae + "\n");
    17371574            return mae;
    17381575        }
     
    17431580        {
    17441581            int l = prob.Count;
    1745             int max_nr_class = 16;
     1582            int Max_nr_class = 16;
    17461583            int nr_class = 0;
    1747             int[] label = new int[max_nr_class];
    1748             int[] count = new int[max_nr_class];
     1584            int[] label = new int[Max_nr_class];
     1585            int[] count = new int[Max_nr_class];
    17491586            int[] data_label = new int[l];
    17501587            int i;
     
    17651602                if (j == nr_class)
    17661603                {
    1767                     if (nr_class == max_nr_class)
    1768                     {
    1769                         max_nr_class *= 2;
    1770                         int[] new_data = new int[max_nr_class];
     1604                    if (nr_class == Max_nr_class)
     1605                    {
     1606                        Max_nr_class *= 2;
     1607                        int[] new_data = new int[Max_nr_class];
    17711608                        Array.Copy(label, 0, new_data, 0, label.Length);
    17721609                        label = new_data;
    1773                         new_data = new int[max_nr_class];
     1610                        new_data = new int[Max_nr_class];
    17741611                        Array.Copy(count, 0, new_data, 0, count.Length);
    17751612                        count = new_data;
     
    18081645            model.Parameter = param;
    18091646
    1810             if (param.SvmType == SvmType.ONE_CLASS ||
     1647            if (param.SvmType == SvmType.ONE_CLASS || 
    18111648               param.SvmType == SvmType.EPSILON_SVR ||
    18121649               param.SvmType == SvmType.NU_SVR)
    18131650            {
    18141651                // regression or one-class-svm
    1815                 model.NumberOfClasses = 2;
     1652                model.NumberOfClasses = 2;               
    18161653                model.ClassLabels = null;
    18171654                model.NumberOfSVPerClass = null;
    18181655                model.PairwiseProbabilityA = null; model.PairwiseProbabilityB = null;
    18191656                model.SupportVectorCoefficients = new double[1][];
    1820 
     1657               
    18211658                if (param.Probability &&
    18221659                   (param.SvmType == SvmType.EPSILON_SVR ||
     
    18341671                int i;
    18351672                for (i = 0; i < prob.Count; i++)
    1836                     if (Math.Abs(f.alpha[i]) > 0) ++nSV;
     1673                    if (Math.Abs(f.alpha[i]) > 0) ++nSV;               
    18371674                model.SupportVectorCount = nSV;
    18381675                model.SupportVectors = new Node[nSV][];
     
    18731710                for (i = 0; i < nr_class; i++)
    18741711                    weighted_C[i] = param.C;
    1875                 for (i = 0; i < param.WeightCount; i++)
    1876                 {
    1877                     int j;
    1878                     for (j = 0; j < nr_class; j++)
    1879                         if (param.WeightLabels[i] == label[j])
    1880                             break;
    1881                     if (j == nr_class)
    1882                         Debug.Write("warning: class label " + param.WeightLabels[i] + " specified in weight is not found\n");
    1883                     else
    1884                         weighted_C[j] *= param.Weights[i];
     1712                foreach (int weightedLabel in param.Weights.Keys)
     1713                {
     1714                    int index = Array.IndexOf<int>(label, weightedLabel);
     1715                    if (index < 0)
     1716                        Console.Error.WriteLine("warning: class label " + weightedLabel + " specified in weight is not found");
     1717                    else weighted_C[index] *= param.Weights[weightedLabel];
    18851718                }
    18861719
     
    19831816                }
    19841817
    1985                 Debug.Write("Total nSV = " + nnz + "\n");
     1818                Procedures.info("Total nSV = " + nnz + "\n");
    19861819
    19871820                model.SupportVectorCount = nnz;
     
    20291862
    20301863        // Stratified cross validation
    2031         public static void svm_cross_validation(Problem prob, Parameter param, int nr_fold, double[] target, Dictionary<int,double>[] confidence)
     1864        public static void svm_cross_validation(Problem prob, Parameter param, int nr_fold, double[] target)
    20321865        {
    20331866            Random rand = new Random();
     
    21311964                    param.SvmType == SvmType.NU_SVC))
    21321965                {
     1966                    double[] prob_estimates = new double[svm_get_nr_class(submodel)];
    21331967                    for (j = begin; j < end; j++)
    2134                     {
    2135                         double[] prob_estimates = new double[svm_get_nr_class(submodel)];
    21361968                        target[perm[j]] = svm_predict_probability(submodel, prob.X[perm[j]], prob_estimates);
    2137                         confidence[perm[j]] = new Dictionary<int, double>();
    2138                         for (int label = 0; label < prob_estimates.Length; label++)
    2139                             confidence[perm[j]][submodel.ClassLabels[label]] = prob_estimates[label];
    2140 
    2141                     }
    21421969                }
    21431970                else
     
    21711998            else
    21721999            {
    2173                 Debug.Write("Model doesn't contain information for SVR probability inference\n");
     2000                Console.Error.WriteLine("Model doesn't contain information for SVR probability inference");
    21742001                return 0;
    21752002            }
     
    21852012                double sum = 0;
    21862013                for (int i = 0; i < model.SupportVectorCount; i++)
    2187                     sum += sv_coef[i] * Kernel.k_function(x, model.SupportVectors[i], model.Parameter);
     2014                    sum += sv_coef[i] * Kernel.KernelFunction(x, model.SupportVectors[i], model.Parameter);
    21882015                sum -= model.Rho[0];
    21892016                dec_values[0] = sum;
     
    21972024                double[] kvalue = new double[l];
    21982025                for (i = 0; i < l; i++)
    2199                     kvalue[i] = Kernel.k_function(x, model.SupportVectors[i], model.Parameter);
     2026                    kvalue[i] = Kernel.KernelFunction(x, model.SupportVectors[i], model.Parameter);
    22002027
    22012028                int[] start = new int[nr_class];
     
    22622089                    }
    22632090
    2264                 int vote_max_idx = 0;
     2091                int vote_Max_idx = 0;
    22652092                for (i = 1; i < nr_class; i++)
    2266                     if (vote[i] > vote[vote_max_idx])
    2267                         vote_max_idx = i;
    2268                 return model.ClassLabels[vote_max_idx];
     2093                    if (vote[i] > vote[vote_Max_idx])
     2094                        vote_Max_idx = i;
     2095                return model.ClassLabels[vote_Max_idx];
    22692096            }
    22702097        }
    22712098
    22722099        public static double svm_predict_probability(Model model, Node[] x, double[] prob_estimates)
    2273   {
    2274         if ((model.Parameter.SvmType == SvmType.C_SVC || model.Parameter.SvmType == SvmType.NU_SVC) &&
    2275         model.PairwiseProbabilityA!=null && model.PairwiseProbabilityB!=null)
    2276     {
    2277       int i;
    2278       int nr_class = model.NumberOfClasses;
    2279       double[] dec_values = new double[nr_class*(nr_class-1)/2];
    2280       svm_predict_values(model, x, dec_values);
    2281 
    2282       double min_prob=1e-7;
    2283       double[,] pairwise_prob=new double[nr_class,nr_class];
    2284      
    2285       int k=0;
    2286       for(i=0;i<nr_class;i++)
    2287         for(int j=i+1;j<nr_class;j++)
    2288         {
    2289           pairwise_prob[i,j]=Math.Min(Math.Max(sigmoid_predict(dec_values[k],model.PairwiseProbabilityA[k],model.PairwiseProbabilityB[k]),min_prob),1-min_prob);
    2290           pairwise_prob[j,i]=1-pairwise_prob[i,j];
    2291           k++;
    2292         }
    2293       multiclass_probability(nr_class,pairwise_prob,prob_estimates);
    2294 
    2295       int prob_max_idx = 0;
    2296       for(i=1;i<nr_class;i++)
    2297         if(prob_estimates[i] > prob_estimates[prob_max_idx])
    2298           prob_max_idx = i;
    2299       return model.ClassLabels[prob_max_idx];
    2300     }
    2301     else
    2302       return svm_predict(model, x);
    2303   }
    2304 
    2305         private static double atof(string s)
    2306         {
    2307             return double.Parse(s);
    2308         }
    2309 
    2310         private static int atoi(string s)
    2311         {
    2312             return int.Parse(s);
     2100        {
     2101            if ((model.Parameter.SvmType == SvmType.C_SVC || model.Parameter.SvmType == SvmType.NU_SVC) &&
     2102                model.PairwiseProbabilityA != null && model.PairwiseProbabilityB != null)
     2103            {
     2104                int i;
     2105                int nr_class = model.NumberOfClasses;
     2106                double[] dec_values = new double[nr_class * (nr_class - 1) / 2];
     2107                svm_predict_values(model, x, dec_values);
     2108
     2109                double Min_prob = 1e-7;
     2110                double[,] pairwise_prob = new double[nr_class, nr_class];
     2111
     2112                int k = 0;
     2113                for (i = 0; i < nr_class; i++)
     2114                {
     2115                    for (int j = i + 1; j < nr_class; j++)
     2116                    {
     2117                        pairwise_prob[i, j] = Math.Min(Math.Max(sigmoid_predict(dec_values[k], model.PairwiseProbabilityA[k], model.PairwiseProbabilityB[k]), Min_prob), 1 - Min_prob);
     2118                        pairwise_prob[j, i] = 1 - pairwise_prob[i, j];
     2119                        k++;
     2120                    }
     2121                }
     2122                multiclass_probability(nr_class, pairwise_prob, prob_estimates);
     2123
     2124                int prob_Max_idx = 0;
     2125                for (i = 1; i < nr_class; i++)
     2126                    if (prob_estimates[i] > prob_estimates[prob_Max_idx])
     2127                        prob_Max_idx = i;
     2128                return model.ClassLabels[prob_Max_idx];
     2129            }
     2130            else
     2131                return svm_predict(model, x);
    23132132        }
    23142133
     
    23182137
    23192138            SvmType svm_type = param.SvmType;
    2320             if (svm_type != SvmType.C_SVC &&
    2321                svm_type != SvmType.NU_SVC &&
    2322                svm_type != SvmType.ONE_CLASS &&
    2323                svm_type != SvmType.EPSILON_SVR &&
    2324                svm_type != SvmType.NU_SVR)
    2325                 return "unknown svm type";
    23262139
    23272140            // kernel_type, degree
    23282141
    23292142            KernelType kernel_type = param.KernelType;
    2330             if (kernel_type != KernelType.LINEAR &&
    2331                kernel_type != KernelType.POLY &&
    2332                kernel_type != KernelType.RBF &&
    2333                kernel_type != KernelType.SIGMOID &&
    2334                kernel_type != KernelType.PRECOMPUTED)
    2335                 return "unknown kernel type";
    23362143
    23372144            if (param.Degree < 0)
     
    23452152            if (param.EPS <= 0)
    23462153                return "eps <= 0";
     2154
     2155            if (param.Gamma == 0)
     2156                param.Gamma = 1.0 / prob.MaxIndex;
    23472157
    23482158            if (svm_type == SvmType.C_SVC ||
     
    23622172                    return "p < 0";
    23632173
    2364             if (param.Probability && svm_type == SvmType.ONE_CLASS)
     2174            if (param.Probability &&
     2175               svm_type == SvmType.ONE_CLASS)
    23652176                return "one-class SVM probability output not supported yet";
    23662177
     
    23702181            {
    23712182                int l = prob.Count;
    2372                 int max_nr_class = 16;
     2183                int Max_nr_class = 16;
    23732184                int nr_class = 0;
    2374                 int[] label = new int[max_nr_class];
    2375                 int[] count = new int[max_nr_class];
     2185                int[] label = new int[Max_nr_class];
     2186                int[] count = new int[Max_nr_class];
    23762187
    23772188                int i;
     
    23892200                    if (j == nr_class)
    23902201                    {
    2391                         if (nr_class == max_nr_class)
    2392                         {
    2393                             max_nr_class *= 2;
    2394                             int[] new_data = new int[max_nr_class];
     2202                        if (nr_class == Max_nr_class)
     2203                        {
     2204                            Max_nr_class *= 2;
     2205                            int[] new_data = new int[Max_nr_class];
    23952206                            Array.Copy(label, 0, new_data, 0, label.Length);
    23962207                            label = new_data;
    23972208
    2398                             new_data = new int[max_nr_class];
     2209                            new_data = new int[Max_nr_class];
    23992210                            Array.Copy(count, 0, new_data, 0, count.Length);
    24002211                            count = new_data;
     
    24322243        }
    24332244    }
    2434 
    24352245}
Note: See TracChangeset for help on using the changeset viewer.