Free cookie consent management tool by TermsFeed Policy Generator

Changeset 2415 for trunk/sources


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

Updated LibSVM project to latest version. #774

Location:
trunk/sources
Files:
3 added
1 deleted
23 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.SupportVectorMachines/3.2/Predictor.cs

    r2414 r2415  
    7979      Problem p = SVMHelper.CreateSVMProblem(input, input.GetVariableIndex(targetVariable), newIndex,
    8080        start, end, minTimeOffset, maxTimeOffset);
    81       Problem scaledProblem = SVM.Scaling.Scale(p, transform);
     81      Problem scaledProblem = transform.Scale(p);
    8282
    8383      int targetVariableIndex = input.GetVariableIndex(targetVariable);
     
    155155      }
    156156    }
     157
     158    public static void Export(Predictor p, Stream s) {
     159      StreamWriter writer = new StreamWriter(s);
     160      writer.Write("Targetvariable: "); writer.WriteLine(p.targetVariable);
     161      writer.Write("LowerPredictionLimit: "); writer.WriteLine(p.LowerPredictionLimit.ToString());
     162      writer.Write("UpperPredictionLimit: "); writer.WriteLine(p.UpperPredictionLimit.ToString());
     163      writer.Write("MaxTimeOffset: "); writer.WriteLine(p.MaxTimeOffset.ToString());
     164      writer.Write("MinTimeOffset: "); writer.WriteLine(p.MinTimeOffset.ToString());
     165      writer.Write("InputVariables :");
     166      writer.Write(p.GetInputVariables().First());
     167      foreach (string variable in p.GetInputVariables().Skip(1)) {
     168        writer.Write("; "); writer.Write(variable);
     169      }
     170      writer.WriteLine();
     171      writer.Flush();
     172      using (MemoryStream memStream = new MemoryStream()) {
     173        SVMModel.Export(p.Model, memStream);
     174        memStream.WriteTo(s);
     175      }
     176    }
     177
     178    public static Predictor Import(Stream s) {
     179      Predictor p = new Predictor();
     180      StreamReader reader = new StreamReader(s);
     181      string[] targetVariableLine = reader.ReadLine().Split(':');
     182      string[] lowerPredictionLimitLine = reader.ReadLine().Split(':');
     183      string[] upperPredictionLimitLine = reader.ReadLine().Split(':');
     184      string[] maxTimeOffsetLine = reader.ReadLine().Split(':');
     185      string[] minTimeOffsetLine = reader.ReadLine().Split(':');
     186      string[] inputVariableLine = reader.ReadLine().Split(':', ';');
     187
     188      p.targetVariable = targetVariableLine[1].Trim();
     189      p.LowerPredictionLimit = double.Parse(lowerPredictionLimitLine[1]);
     190      p.UpperPredictionLimit = double.Parse(upperPredictionLimitLine[1]);
     191      p.maxTimeOffset = int.Parse(maxTimeOffsetLine[1]);
     192      p.minTimeOffset = int.Parse(minTimeOffsetLine[1]);
     193      int i = 1;
     194      foreach (string inputVariable in inputVariableLine.Skip(1)) {
     195        p.variableNames[inputVariable.Trim()] = i++;
     196      }
     197      p.svmModel = SVMModel.Import(s);
     198      return p;
     199    }
    157200  }
    158201}
  • trunk/sources/HeuristicLab.SupportVectorMachines/3.2/PredictorView.cs

    r2413 r2415  
    2929using System.Windows.Forms;
    3030using HeuristicLab.Core;
     31using System.IO;
    3132
    3233namespace HeuristicLab.SupportVectorMachines {
     
    5051    }
    5152
    52     protected override string GetModelString() {
    53       StringBuilder builder = new StringBuilder();
    54       builder.Append("LowerPredictionLimit: ").AppendLine(predictor.LowerPredictionLimit.ToString());
    55       builder.Append("UpperPredictionLimit: ").AppendLine(predictor.UpperPredictionLimit.ToString());
    56       builder.Append("MaxTimeOffset: ").AppendLine(predictor.MaxTimeOffset.ToString());
    57       builder.Append("MinTimeOffset: ").AppendLine(predictor.MinTimeOffset.ToString());
    58       builder.Append("InputVariables :");
    59       builder.Append(predictor.GetInputVariables().First());
    60       foreach (string variable in predictor.GetInputVariables().Skip(1)) {
    61         builder.Append("; ").Append(variable);
     53    protected override void UpdateControls() {
     54      base.UpdateControls();
     55      textBox.Text = GetModelString();
     56    }
     57
     58    private string GetModelString() {
     59      if (predictor == null) return "";
     60      using (MemoryStream s = new MemoryStream()) {
     61        Predictor.Export(predictor, s);
     62        s.Flush();
     63        s.Seek(0, System.IO.SeekOrigin.Begin);
     64        StreamReader reader = new StreamReader(s);
     65        return reader.ReadToEnd();
    6266      }
    63       builder.AppendLine();
    64       builder.Append(base.GetModelString());
    65       return builder.ToString();
    6667    }
    6768  }
  • trunk/sources/HeuristicLab.SupportVectorMachines/3.2/SVMModel.cs

    r2322 r2415  
    116116      }
    117117    }
     118
     119    public static void Export(SVMModel model, Stream s) {
     120      StreamWriter writer = new StreamWriter(s);
     121      writer.WriteLine("RangeTransform:");
     122      using (MemoryStream memStream = new MemoryStream()) {
     123        SVM.RangeTransform.Write(memStream, model.RangeTransform);
     124        memStream.Seek(0, SeekOrigin.Begin);
     125        memStream.WriteTo(s);
     126      }
     127      writer.WriteLine("Model:");
     128
     129      using (MemoryStream memStream = new MemoryStream()) {
     130        SVM.Model.Write(memStream, model.Model);
     131        memStream.Seek(0, SeekOrigin.Begin);
     132        memStream.WriteTo(s);
     133      }
     134      s.Flush();
     135    }
     136
     137    public static SVMModel Import(Stream s) {
     138      SVMModel model = new SVMModel();
     139      StreamReader reader = new StreamReader(s);
     140      while (reader.ReadLine().Trim() != "RangeTransform:") ; // read until line "RangeTransform";
     141      model.RangeTransform = SVM.RangeTransform.Read(s);
     142
     143      // read until "Model:"
     144      while (reader.ReadLine().Trim() != "Model:") ;
     145      model.Model = SVM.Model.Read(s);
     146      return model;
     147    }
    118148  }
    119149}
  • trunk/sources/HeuristicLab.SupportVectorMachines/3.2/SVMModelView.cs

    r2413 r2415  
    4949      kernelType.DataBindings.Add(new Binding("Text", model.Model.Parameter, "KernelType"));
    5050      gamma.DataBindings.Add(new Binding("Text", model.Model.Parameter, "Gamma"));
     51      UpdateControls();
    5152    }
    5253
     
    5657    }
    5758
    58     protected virtual string GetModelString() {
    59       StringBuilder builder = new StringBuilder();
    60       builder.AppendLine("RangeTransform:");
    61       using (MemoryStream stream = new MemoryStream()) {
    62         SVM.RangeTransform.Write(stream, model.RangeTransform);
    63         stream.Seek(0, System.IO.SeekOrigin.Begin);
    64         StreamReader reader = new StreamReader(stream);
    65         builder.AppendLine(reader.ReadToEnd());
     59    private string GetModelString() {
     60      using (MemoryStream s = new MemoryStream()) {
     61        SVMModel.Export(model, s);
     62        s.Flush();
     63        s.Seek(0, System.IO.SeekOrigin.Begin);
     64        StreamReader reader = new StreamReader(s);
     65        return reader.ReadToEnd();
    6666      }
    67       builder.AppendLine("Model:");
    68       using (MemoryStream stream = new MemoryStream()) {
    69         SVM.Model.Write(stream, model.Model);
    70         stream.Seek(0, System.IO.SeekOrigin.Begin);
    71         StreamReader reader = new StreamReader(stream);
    72         builder.AppendLine(reader.ReadToEnd());
    73       }
    74       return builder.ToString();
    7567    }
    7668  }
  • trunk/sources/HeuristicLab.SupportVectorMachines/3.2/SupportVectorCreator.cs

    r2349 r2415  
    2828using HeuristicLab.DataAnalysis;
    2929using System.Threading;
     30using SVM;
    3031
    3132namespace HeuristicLab.SupportVectorMachines {
     
    8586      parameter.Nu = GetVariableValue<DoubleData>("SVMNu", scope, true).Data;
    8687      parameter.Gamma = GetVariableValue<DoubleData>("SVMGamma", scope, true).Data;
     88      parameter.CacheSize = 500;
     89      parameter.Probability = false;
    8790
    8891      SVM.Problem problem = SVMHelper.CreateSVMProblem(dataset, targetVariable, start, end, minTimeOffset, maxTimeOffset);
    89       SVM.RangeTransform rangeTransform = SVM.Scaling.DetermineRange(problem);
    90       SVM.Problem scaledProblem = SVM.Scaling.Scale(problem, rangeTransform);
     92      SVM.RangeTransform rangeTransform = SVM.RangeTransform.Compute(problem);
     93      SVM.Problem scaledProblem = rangeTransform.Scale(problem);
    9194
    9295      SVM.Model model = StartTraining(scaledProblem, parameter);
  • trunk/sources/HeuristicLab.SupportVectorMachines/3.2/SupportVectorEvaluator.cs

    r2357 r2415  
    2727using HeuristicLab.Data;
    2828using HeuristicLab.DataAnalysis;
     29using SVM;
    2930
    3031namespace HeuristicLab.SupportVectorMachines {
     
    5657      SVMModel modelData = GetVariableValue<SVMModel>("SVMModel", scope, true);
    5758      SVM.Problem problem = SVMHelper.CreateSVMProblem(dataset, targetVariable, start, end, minTimeOffset, maxTimeOffset);
    58       SVM.Problem scaledProblem = SVM.Scaling.Scale(problem, modelData.RangeTransform);
     59      SVM.Problem scaledProblem = modelData.RangeTransform.Scale(problem);
    5960
    6061      double[,] values = new double[scaledProblem.Count, 2];
  • trunk/sources/LibSVM/Cache.cs

    r1819 r2415  
    4949        private head_t lru_head;
    5050
    51         internal Cache(int count, long size)
     51        public Cache(int count, long size)
    5252        {
    5353            _count = count;
     
    7878        }
    7979
     80        private static void swap<T>(ref T lhs, ref T rhs)
     81        {
     82            T tmp = lhs;
     83            lhs = rhs;
     84            rhs = tmp;
     85        }
     86
    8087        // request data [0,len)
    8188        // return some position p where [p,len) need to be filled
    8289        // (p >= len if nothing needs to be filled)
    8390        // java: simulate pointer using single-element array
    84         internal virtual int get_data(int index, float[][] data, int len)
     91        public int GetData(int index, ref float[] data, int len)
    8592        {
    8693            head_t h = head[index];
     
    107114                h.data = new_data;
    108115                _size -= more;
    109                 do
    110                 {
    111                     int _ = h.len; h.len = len; len = _;
    112                 }
    113                 while (false);
     116                swap(ref h.len, ref len);
    114117            }
    115118
    116119            lru_insert(h);
    117             data[0] = h.data;
     120            data = h.data;
    118121            return len;
    119122        }
    120123
    121         internal virtual void swap_index(int i, int j)
     124        public void SwapIndex(int i, int j)
    122125        {
    123126            if (i == j)
     
    128131            if (head[j].len > 0)
    129132                lru_delete(head[j]);
    130             do
    131             {
    132                 float[] _ = head[i].data; head[i].data = head[j].data; head[j].data = _;
    133             }
    134             while (false);
    135             do
    136             {
    137                 int _ = head[i].len; head[i].len = head[j].len; head[j].len = _;
    138             }
    139             while (false);
     133            swap(ref head[i].data, ref head[j].data);
     134            swap(ref head[i].len, ref head[j].len);
    140135            if (head[i].len > 0)
    141136                lru_insert(head[i]);
     
    144139
    145140            if (i > j)
    146                 do
    147                 {
    148                     int _ = i; i = j; j = _;
    149                 }
    150                 while (false);
     141                swap(ref i, ref j);
     142
    151143            for (head_t h = lru_head.next; h != lru_head; h = h.next)
    152144            {
     
    154146                {
    155147                    if (h.len > j)
    156                         do
    157                         {
    158                             float _ = h.data[i]; h.data[i] = h.data[j]; h.data[j] = _;
    159                         }
    160                         while (false);
     148                        swap(ref h.data[i], ref h.data[j]);
    161149                    else
    162150                    {
  • trunk/sources/LibSVM/GaussianTransform.cs

    r1819 r2415  
    2121using System.Collections.Generic;
    2222using System.IO;
     23using System.Globalization;
     24using System.Threading;
    2325
    2426namespace SVM
    2527{
    26     /// <remarks>
     28    /// <summary>
    2729    /// A transform which learns the mean and variance of a sample set and uses these to transform new data
    2830    /// so that it has zero mean and unit variance.
    29     /// </remarks>
     31    /// </summary>
    3032    public class GaussianTransform : IRangeTransform
    3133    {
    32         private List<Node[]> _samples;
    33         private int _maxIndex;
    34 
    3534        private double[] _means;
    3635        private double[] _stddevs;
    3736
    3837        /// <summary>
     38        /// Determines the Gaussian transform for the provided problem.
     39        /// </summary>
     40        /// <param name="prob">The Problem to analyze</param>
     41        /// <returns>The Gaussian transform for the problem</returns>
     42        public static GaussianTransform Compute(Problem prob)
     43        {
     44            int[] counts = new int[prob.MaxIndex];
     45            double[] means = new double[prob.MaxIndex];
     46            foreach (Node[] sample in prob.X)
     47            {
     48                for (int i = 0; i < sample.Length; i++)
     49                {
     50                    means[sample[i].Index-1] += sample[i].Value;
     51                    counts[sample[i].Index-1]++;
     52                }
     53            }
     54            for (int i = 0; i < prob.MaxIndex; i++)
     55            {
     56                if (counts[i] == 0)
     57                    counts[i] = 2;
     58                means[i] /= counts[i];
     59            }
     60
     61            double[] stddevs = new double[prob.MaxIndex];
     62            foreach (Node[] sample in prob.X)
     63            {
     64                for (int i = 0; i < sample.Length; i++)
     65                {
     66                    double diff = sample[i].Value - means[sample[i].Index - 1];
     67                    stddevs[sample[i].Index - 1] += diff * diff;
     68                }
     69            }
     70            for (int i = 0; i < prob.MaxIndex; i++)
     71            {
     72                if (stddevs[i] == 0)
     73                    continue;
     74                stddevs[i] /= (counts[i] - 1);
     75                stddevs[i] = Math.Sqrt(stddevs[i]);
     76            }
     77
     78            return new GaussianTransform(means, stddevs);
     79        }
     80
     81        /// <summary>
    3982        /// Constructor.
    4083        /// </summary>
    41         /// <param name="maxIndex">The maximum index of the vectors to be transformed</param>
    42         public GaussianTransform(int maxIndex)
    43         {
    44             _samples = new List<Node[]>();
    45         }
    46         private GaussianTransform(double[] means, double[] stddevs, int maxIndex)
     84        /// <param name="means">Means in each dimension</param>
     85        /// <param name="stddevs">Standard deviation in each dimension</param>
     86        public GaussianTransform(double[] means, double[] stddevs)
    4787        {
    4888            _means = means;
    4989            _stddevs = stddevs;
    50             _maxIndex = maxIndex;
    51         }
    52 
    53         /// <summary>
    54         /// Adds a sample to the data.  No computation is performed.  The maximum index of the
    55         /// sample must be less than MaxIndex.
    56         /// </summary>
    57         /// <param name="sample">The sample to add</param>
    58         public void Add(Node[] sample)
    59         {
    60             _samples.Add(sample);
    61         }
    62 
    63         /// <summary>
    64         /// Computes the statistics for the samples which have been obtained so far.
    65         /// </summary>
    66         public void ComputeStatistics()
    67         {
    68             int[] counts = new int[_maxIndex];
    69             _means = new double[_maxIndex];
    70             foreach(Node[] sample in _samples)
    71             {
    72                 for (int i = 0; i < sample.Length; i++)
    73                 {
    74                     _means[sample[i].Index] += sample[i].Value;
    75                     counts[sample[i].Index]++;
    76                 }
    77             }
    78             for (int i = 0; i < _maxIndex; i++)
    79             {
    80                 if (counts[i] == 0)
    81                     counts[i] = 2;
    82                 _means[i] /= counts[i];
    83             }
    84 
    85             _stddevs = new double[_maxIndex];
    86             foreach(Node[] sample in _samples)
    87             {
    88                 for (int i = 0; i < sample.Length; i++)
    89                 {
    90                     double diff = sample[i].Value - _means[sample[i].Index];
    91                     _stddevs[sample[i].Index] += diff * diff;
    92                 }
    93             }
    94             for (int i = 0; i < _maxIndex; i++)
    95             {
    96                 if (_stddevs[i] == 0)
    97                     continue;
    98                 _stddevs[i] /= (counts[i]-1);
    99                 _stddevs[i] = Math.Sqrt(_stddevs[i]);
    100             }
    10190        }
    10291
     
    10998        public static void Write(Stream stream, GaussianTransform transform)
    11099        {
     100            TemporaryCulture.Start();
     101
    111102            StreamWriter output = new StreamWriter(stream);
    112             output.WriteLine(transform._maxIndex);
    113             for (int i = 0; i < transform._maxIndex; i++)
     103            output.WriteLine(transform._means.Length);
     104            for (int i = 0; i < transform._means.Length; i++)
    114105                output.WriteLine("{0} {1}", transform._means[i], transform._stddevs[i]);
    115106            output.Flush();
     107
     108            TemporaryCulture.Stop();
    116109        }
    117110
     
    123116        public static GaussianTransform Read(Stream stream)
    124117        {
     118            TemporaryCulture.Start();
     119
    125120            StreamReader input = new StreamReader(stream);
    126             int length = int.Parse(input.ReadLine());
     121            int length = int.Parse(input.ReadLine(), CultureInfo.InvariantCulture);
    127122            double[] means = new double[length];
    128123            double[] stddevs = new double[length];
     
    130125            {
    131126                string[] parts = input.ReadLine().Split();
    132                 means[i] = double.Parse(parts[0]);
    133                 stddevs[i] = double.Parse(parts[1]);
    134             }
    135             return new GaussianTransform(means, stddevs, length);
     127                means[i] = double.Parse(parts[0], CultureInfo.InvariantCulture);
     128                stddevs[i] = double.Parse(parts[1], CultureInfo.InvariantCulture);
     129            }
     130
     131            TemporaryCulture.Stop();
     132
     133            return new GaussianTransform(means, stddevs);
    136134        }
    137135
     
    177175        /// <summary>
    178176        /// Transform the input value using the transform stored for the provided index.
    179         /// <see cref="ComputeStatistics"/> must be called first, or the transform must
    180         /// have been read from the disk.
    181177        /// </summary>
    182178        /// <param name="input">Input value</param>
     
    185181        public double Transform(double input, int index)
    186182        {
     183            index--;
    187184            if (_stddevs[index] == 0)
    188185                return 0;
     
    192189        }
    193190        /// <summary>
    194         /// Transforms the input array.  <see cref="ComputeStatistics"/> must be called
    195         /// first, or the transform must have been read from the disk.
     191        /// Transforms the input array.
    196192        /// </summary>
    197193        /// <param name="input">The array to transform</param>
  • trunk/sources/LibSVM/IRangeTransform.cs

    r1819 r2415  
    2020namespace SVM
    2121{
    22     /// <remarks>
     22    /// <summary>
    2323    /// Interface implemented by range transforms.
    24     /// </remarks>
     24    /// </summary>
    2525    public interface IRangeTransform
    2626    {
  • trunk/sources/LibSVM/LibSVM.csproj

    r1846 r2415  
    8080  </ItemGroup>
    8181  <ItemGroup>
     82    <Compile Include="Kernel.cs" />
    8283    <Compile Include="Properties\AssemblyInfo.cs" />
    8384    <Compile Include="Cache.cs" />
     
    9596    <Compile Include="Scaling.cs" />
    9697    <Compile Include="Solver.cs" />
    97     <Compile Include="SupportClass.cs" />
     98    <Compile Include="SVMExtensions.cs" />
     99    <Compile Include="TemporaryCulture.cs" />
    98100    <Compile Include="Training.cs" />
    99101  </ItemGroup>
  • trunk/sources/LibSVM/Model.cs

    r2411 r2415  
    2121using System;
    2222using System.IO;
    23 
    24 namespace SVM {
    25   /// <remarks>
    26   /// Encapsulates an SVM Model.
    27   /// </remarks>
    28   [Serializable]
    29   public class Model {
    30     private Parameter _parameter;
    31     private int _numberOfClasses;
    32     private int _supportVectorCount;
    33     private Node[][] _supportVectors;
    34     private double[][] _supportVectorCoefficients;
    35     private double[] _rho;
    36     private double[] _pairwiseProbabilityA;
    37     private double[] _pairwiseProbabilityB;
    38 
    39     private int[] _classLabels;
    40     private int[] _numberOfSVPerClass;
    41 
    42     internal Model() {
    43     }
    44 
     23using System.Threading;
     24using System.Globalization;
     25
     26namespace SVM
     27{
    4528    /// <summary>
    46     /// Parameter object.
     29    /// Encapsulates an SVM Model.
    4730    /// </summary>
    48     public Parameter Parameter {
    49       get {
    50         return _parameter;
    51       }
    52       set {
    53         _parameter = value;
    54       }
    55     }
    56 
    57     /// <summary>
    58     /// Number of classes in the model.
    59     /// </summary>
    60     public int NumberOfClasses {
    61       get {
    62         return _numberOfClasses;
    63       }
    64       set {
    65         _numberOfClasses = value;
    66       }
    67     }
    68 
    69     /// <summary>
    70     /// Total number of support vectors.
    71     /// </summary>
    72     public int SupportVectorCount {
    73       get {
    74         return _supportVectorCount;
    75       }
    76       set {
    77         _supportVectorCount = value;
    78       }
    79     }
    80 
    81     /// <summary>
    82     /// The support vectors.
    83     /// </summary>
    84     public Node[][] SupportVectors {
    85       get {
    86         return _supportVectors;
    87       }
    88       set {
    89         _supportVectors = value;
    90       }
    91     }
    92 
    93     /// <summary>
    94     /// The coefficients for the support vectors.
    95     /// </summary>
    96     public double[][] SupportVectorCoefficients {
    97       get {
    98         return _supportVectorCoefficients;
    99       }
    100       set {
    101         _supportVectorCoefficients = value;
    102       }
    103     }
    104 
    105     /// <summary>
    106     /// Rho values.
    107     /// </summary>
    108     public double[] Rho {
    109       get {
    110         return _rho;
    111       }
    112       set {
    113         _rho = value;
    114       }
    115     }
    116 
    117     /// <summary>
    118     /// First pairwise probability.
    119     /// </summary>
    120     public double[] PairwiseProbabilityA {
    121       get {
    122         return _pairwiseProbabilityA;
    123       }
    124       set {
    125         _pairwiseProbabilityA = value;
    126       }
    127     }
    128 
    129     /// <summary>
    130     /// Second pairwise probability.
    131     /// </summary>
    132     public double[] PairwiseProbabilityB {
    133       get {
    134         return _pairwiseProbabilityB;
    135       }
    136       set {
    137         _pairwiseProbabilityB = value;
    138       }
    139     }
    140 
    141     // for classification only
    142 
    143     /// <summary>
    144     /// Class labels.
    145     /// </summary>
    146     public int[] ClassLabels {
    147       get {
    148         return _classLabels;
    149       }
    150       set {
    151         _classLabels = value;
    152       }
    153     }
    154 
    155     /// <summary>
    156     /// Number of support vectors per class.
    157     /// </summary>
    158     public int[] NumberOfSVPerClass {
    159       get {
    160         return _numberOfSVPerClass;
    161       }
    162       set {
    163         _numberOfSVPerClass = value;
    164       }
    165     }
    166 
    167     /// <summary>
    168     /// Reads a Model from the provided file.
    169     /// </summary>
    170     /// <param name="filename">The name of the file containing the Model</param>
    171     /// <returns>the Model</returns>
    172     public static Model Read(string filename) {
    173       FileStream input = File.OpenRead(filename);
    174       try {
    175         return Read(input);
    176       }
    177       finally {
    178         input.Close();
    179       }
    180     }
    181 
    182     /// <summary>
    183     /// Reads a Model from the provided stream.
    184     /// </summary>
    185     /// <param name="stream">The stream from which to read the Model.</param>
    186     /// <returns>the Model</returns>
    187     public static Model Read(Stream stream) {
    188       StreamReader input = new StreamReader(stream);
    189 
    190       // read parameters
    191 
    192       Model model = new Model();
    193       Parameter param = new Parameter();
    194       model.Parameter = param;
    195       model.Rho = null;
    196       model.PairwiseProbabilityA = null;
    197       model.PairwiseProbabilityB = null;
    198       model.ClassLabels = null;
    199       model.NumberOfSVPerClass = null;
    200 
    201       bool headerFinished = false;
    202       while (!headerFinished) {
    203         string line = input.ReadLine();
    204         string cmd, arg;
    205         int splitIndex = line.IndexOf(' ');
    206         if (splitIndex >= 0) {
    207           cmd = line.Substring(0, splitIndex);
    208           arg = line.Substring(splitIndex + 1);
    209         } else {
    210           cmd = line;
    211           arg = "";
    212         }
    213         arg = arg.ToLower();
    214 
    215         int i, n;
    216         switch (cmd) {
    217           case "svm_type":
    218             param.SvmType = (SvmType)Enum.Parse(typeof(SvmType), arg.ToUpper());
    219             break;
    220 
    221           case "kernel_type":
    222             param.KernelType = (KernelType)Enum.Parse(typeof(KernelType), arg.ToUpper());
    223             break;
    224 
    225           case "degree":
    226             param.Degree = int.Parse(arg);
    227             break;
    228 
    229           case "gamma":
    230             param.Gamma = double.Parse(arg);
    231             break;
    232 
    233           case "coef0":
    234             param.Coefficient0 = double.Parse(arg);
    235             break;
    236 
    237           case "nr_class":
    238             model.NumberOfClasses = int.Parse(arg);
    239             break;
    240 
    241           case "total_sv":
    242             model.SupportVectorCount = int.Parse(arg);
    243             break;
    244 
    245           case "rho":
    246             n = model.NumberOfClasses * (model.NumberOfClasses - 1) / 2;
    247             model.Rho = new double[n];
    248             string[] rhoParts = arg.Split();
    249             for (i = 0; i < n; i++)
    250               model.Rho[i] = double.Parse(rhoParts[i]);
    251             break;
    252 
    253           case "label":
    254             n = model.NumberOfClasses;
    255             model.ClassLabels = new int[n];
    256             string[] labelParts = arg.Split();
    257             for (i = 0; i < n; i++)
    258               model.ClassLabels[i] = int.Parse(labelParts[i]);
    259             break;
    260 
    261           case "probA":
    262             n = model.NumberOfClasses * (model.NumberOfClasses - 1) / 2;
    263             model.PairwiseProbabilityA = new double[n];
    264             string[] probAParts = arg.Split();
    265             for (i = 0; i < n; i++)
    266               model.PairwiseProbabilityA[i] = double.Parse(probAParts[i]);
    267             break;
    268 
    269           case "probB":
    270             n = model.NumberOfClasses * (model.NumberOfClasses - 1) / 2;
    271             model.PairwiseProbabilityB = new double[n];
    272             string[] probBParts = arg.Split();
    273             for (i = 0; i < n; i++)
    274               model.PairwiseProbabilityB[i] = double.Parse(probBParts[i]);
    275             break;
    276 
    277           case "nr_sv":
    278             n = model.NumberOfClasses;
    279             model.NumberOfSVPerClass = new int[n];
    280             string[] nrsvParts = arg.Split();
    281             for (i = 0; i < n; i++)
    282               model.NumberOfSVPerClass[i] = int.Parse(nrsvParts[i]);
    283             break;
    284 
    285           case "SV":
    286             headerFinished = true;
    287             break;
    288 
    289           default:
    290             throw new Exception("Unknown text in model file");
    291         }
    292       }
    293 
    294       // read sv_coef and SV
    295 
    296       int m = model.NumberOfClasses - 1;
    297       int l = model.SupportVectorCount;
    298       model.SupportVectorCoefficients = new double[m][];
    299       for (int i = 0; i < m; i++) {
    300         model.SupportVectorCoefficients[i] = new double[l];
    301       }
    302       model.SupportVectors = new Node[l][];
    303 
    304       for (int i = 0; i < l; i++) {
    305         string[] parts = input.ReadLine().Trim().Split();
    306 
    307         for (int k = 0; k < m; k++)
    308           model.SupportVectorCoefficients[k][i] = double.Parse(parts[k]);
    309         int n = parts.Length - m;
    310         model.SupportVectors[i] = new Node[n];
    311         for (int j = 0; j < n; j++) {
    312           string[] nodeParts = parts[m + j].Split(':');
    313           model.SupportVectors[i][j] = new Node();
    314           model.SupportVectors[i][j].Index = int.Parse(nodeParts[0]);
    315           model.SupportVectors[i][j].Value = double.Parse(nodeParts[1]);
    316         }
    317       }
    318 
    319       return model;
    320     }
    321 
    322     /// <summary>
    323     /// Writes a model to the provided filename.  This will overwrite any previous data in the file.
    324     /// </summary>
    325     /// <param name="filename">The desired file</param>
    326     /// <param name="model">The Model to write</param>
    327     public static void Write(string filename, Model model) {
    328       FileStream stream = File.Open(filename, FileMode.Create);
    329       try {
    330         Write(stream, model);
    331       }
    332       finally {
    333         stream.Close();
    334       }
    335     }
    336 
    337     /// <summary>
    338     /// Writes a model to the provided stream.
    339     /// </summary>
    340     /// <param name="stream">The output stream</param>
    341     /// <param name="model">The model to write</param>
    342     public static void Write(Stream stream, Model model) {
    343       StreamWriter output = new StreamWriter(stream);
    344 
    345       Parameter param = model.Parameter;
    346 
    347       output.Write("svm_type " + param.SvmType + Environment.NewLine);
    348       output.Write("kernel_type " + param.KernelType + Environment.NewLine);
    349 
    350       if (param.KernelType == KernelType.POLY)
    351         output.Write("degree " + param.Degree + Environment.NewLine);
    352 
    353       if (param.KernelType == KernelType.POLY || param.KernelType == KernelType.RBF || param.KernelType == KernelType.SIGMOID)
    354         output.Write("gamma " + param.Gamma + Environment.NewLine);
    355 
    356       if (param.KernelType == KernelType.POLY || param.KernelType == KernelType.SIGMOID)
    357         output.Write("coef0 " + param.Coefficient0 + Environment.NewLine);
    358 
    359       int nr_class = model.NumberOfClasses;
    360       int l = model.SupportVectorCount;
    361       output.Write("nr_class " + nr_class + Environment.NewLine);
    362       output.Write("total_sv " + l + Environment.NewLine);
    363 
    364       {
    365         output.Write("rho");
    366         for (int i = 0; i < nr_class * (nr_class - 1) / 2; i++)
    367           output.Write(" " + model.Rho[i]);
    368         output.Write(Environment.NewLine);
    369       }
    370 
    371       if (model.ClassLabels != null) {
    372         output.Write("label");
    373         for (int i = 0; i < nr_class; i++)
    374           output.Write(" " + model.ClassLabels[i]);
    375         output.Write(Environment.NewLine);
    376       }
    377 
    378       if (model.PairwiseProbabilityA != null)
    379       // regression has probA only
    380             {
    381         output.Write("probA");
    382         for (int i = 0; i < nr_class * (nr_class - 1) / 2; i++)
    383           output.Write(" " + model.PairwiseProbabilityA[i]);
    384         output.Write(Environment.NewLine);
    385       }
    386       if (model.PairwiseProbabilityB != null) {
    387         output.Write("probB");
    388         for (int i = 0; i < nr_class * (nr_class - 1) / 2; i++)
    389           output.Write(" " + model.PairwiseProbabilityB[i]);
    390         output.Write(Environment.NewLine);
    391       }
    392 
    393       if (model.NumberOfSVPerClass != null) {
    394         output.Write("nr_sv");
    395         for (int i = 0; i < nr_class; i++)
    396           output.Write(" " + model.NumberOfSVPerClass[i]);
    397         output.Write(Environment.NewLine);
    398       }
    399 
    400       output.Write("SV\n");
    401       double[][] sv_coef = model.SupportVectorCoefficients;
    402       Node[][] SV = model.SupportVectors;
    403 
    404       for (int i = 0; i < l; i++) {
    405         for (int j = 0; j < nr_class - 1; j++)
    406           output.Write(sv_coef[j][i] + " ");
    407 
    408         Node[] p = SV[i];
    409         if (p.Length == 0) {
    410           output.WriteLine();
    411           continue;
    412         }
    413         if (param.KernelType == KernelType.PRECOMPUTED)
    414           output.Write("0:{0}", (int)p[0].Value);
    415         else {
    416           output.Write("{0}:{1}", p[0].Index, p[0].Value);
    417           for (int j = 1; j < p.Length; j++)
    418             output.Write(" {0}:{1}", p[j].Index, p[j].Value);
    419         }
    420         output.WriteLine();
    421       }
    422 
    423       output.Flush();
    424     }
    425   }
     31  [Serializable]
     32  public class Model
     33  {
     34        private Parameter _parameter;
     35        private int _numberOfClasses;
     36        private int _supportVectorCount;
     37        private Node[][] _supportVectors;
     38        private double[][] _supportVectorCoefficients;
     39        private double[] _rho;
     40        private double[] _pairwiseProbabilityA;
     41        private double[] _pairwiseProbabilityB;
     42
     43        private int[] _classLabels;
     44        private int[] _numberOfSVPerClass;
     45
     46        internal Model()
     47        {
     48        }
     49
     50        /// <summary>
     51        /// Parameter object.
     52        /// </summary>
     53        public Parameter Parameter
     54        {
     55            get
     56            {
     57                return _parameter;
     58            }
     59            set
     60            {
     61                _parameter = value;
     62            }
     63        }
     64
     65        /// <summary>
     66        /// Number of classes in the model.
     67        /// </summary>
     68        public int NumberOfClasses
     69        {
     70            get
     71            {
     72                return _numberOfClasses;
     73            }
     74            set
     75            {
     76                _numberOfClasses = value;
     77            }
     78        }
     79
     80        /// <summary>
     81        /// Total number of support vectors.
     82        /// </summary>
     83        public int SupportVectorCount
     84        {
     85            get
     86            {
     87                return _supportVectorCount;
     88            }
     89            set
     90            {
     91                _supportVectorCount = value;
     92            }
     93        }
     94
     95        /// <summary>
     96        /// The support vectors.
     97        /// </summary>
     98        public Node[][] SupportVectors
     99        {
     100            get
     101            {
     102                return _supportVectors;
     103            }
     104            set
     105            {
     106                _supportVectors = value;
     107            }
     108        }
     109
     110        /// <summary>
     111        /// The coefficients for the support vectors.
     112        /// </summary>
     113        public double[][] SupportVectorCoefficients
     114        {
     115            get
     116            {
     117                return _supportVectorCoefficients;
     118            }
     119            set
     120            {
     121                _supportVectorCoefficients = value;
     122            }
     123        }
     124
     125        /// <summary>
     126        /// Rho values.
     127        /// </summary>
     128        public double[] Rho
     129        {
     130            get
     131            {
     132                return _rho;
     133            }
     134            set
     135            {
     136                _rho = value;
     137            }
     138        }
     139
     140        /// <summary>
     141        /// First pairwise probability.
     142        /// </summary>
     143        public double[] PairwiseProbabilityA
     144        {
     145            get
     146            {
     147                return _pairwiseProbabilityA;
     148            }
     149            set
     150            {
     151                _pairwiseProbabilityA = value;
     152            }
     153        }
     154
     155        /// <summary>
     156        /// Second pairwise probability.
     157        /// </summary>
     158        public double[] PairwiseProbabilityB
     159        {
     160            get
     161            {
     162                return _pairwiseProbabilityB;
     163            }
     164            set
     165            {
     166                _pairwiseProbabilityB = value;
     167            }
     168        }
     169   
     170    // for classification only
     171
     172        /// <summary>
     173        /// Class labels.
     174        /// </summary>
     175        public int[] ClassLabels
     176        {
     177            get
     178            {
     179                return _classLabels;
     180            }
     181            set
     182            {
     183                _classLabels = value;
     184            }
     185        }
     186
     187        /// <summary>
     188        /// Number of support vectors per class.
     189        /// </summary>
     190        public int[] NumberOfSVPerClass
     191        {
     192            get
     193            {
     194                return _numberOfSVPerClass;
     195            }
     196            set
     197            {
     198                _numberOfSVPerClass = value;
     199            }
     200        }
     201
     202        /// <summary>
     203        /// Reads a Model from the provided file.
     204        /// </summary>
     205        /// <param name="filename">The name of the file containing the Model</param>
     206        /// <returns>the Model</returns>
     207        public static Model Read(string filename)
     208        {
     209            FileStream input = File.OpenRead(filename);
     210            try
     211            {
     212                return Read(input);
     213            }
     214            finally
     215            {
     216                input.Close();
     217            }
     218        }
     219
     220        /// <summary>
     221        /// Reads a Model from the provided stream.
     222        /// </summary>
     223        /// <param name="stream">The stream from which to read the Model.</param>
     224        /// <returns>the Model</returns>
     225        public static Model Read(Stream stream)
     226        {
     227            TemporaryCulture.Start();
     228
     229            StreamReader input = new StreamReader(stream);
     230
     231            // read parameters
     232
     233            Model model = new Model();
     234            Parameter param = new Parameter();
     235            model.Parameter = param;
     236            model.Rho = null;
     237            model.PairwiseProbabilityA = null;
     238            model.PairwiseProbabilityB = null;
     239            model.ClassLabels = null;
     240            model.NumberOfSVPerClass = null;
     241
     242            bool headerFinished = false;
     243            while (!headerFinished)
     244            {
     245                string line = input.ReadLine();
     246                string cmd, arg;
     247                int splitIndex = line.IndexOf(' ');
     248                if (splitIndex >= 0)
     249                {
     250                    cmd = line.Substring(0, splitIndex);
     251                    arg = line.Substring(splitIndex + 1);
     252                }
     253                else
     254                {
     255                    cmd = line;
     256                    arg = "";
     257                }
     258                arg = arg.ToLower();
     259
     260                int i,n;
     261                switch(cmd){
     262                    case "svm_type":
     263                        param.SvmType = (SvmType)Enum.Parse(typeof(SvmType), arg.ToUpper());
     264                        break;
     265                       
     266                    case "kernel_type":
     267                        param.KernelType = (KernelType)Enum.Parse(typeof(KernelType), arg.ToUpper());
     268                        break;
     269
     270                    case "degree":
     271                        param.Degree = int.Parse(arg);
     272                        break;
     273
     274                    case "gamma":
     275                        param.Gamma = double.Parse(arg);
     276                        break;
     277
     278                    case "coef0":
     279                        param.Coefficient0 = double.Parse(arg);
     280                        break;
     281
     282                    case "nr_class":
     283                        model.NumberOfClasses = int.Parse(arg);
     284                        break;
     285
     286                    case "total_sv":
     287                        model.SupportVectorCount = int.Parse(arg);
     288                        break;
     289
     290                    case "rho":
     291                        n = model.NumberOfClasses * (model.NumberOfClasses - 1) / 2;
     292                        model.Rho = new double[n];
     293                        string[] rhoParts = arg.Split();
     294                        for(i=0; i<n; i++)
     295                            model.Rho[i] = double.Parse(rhoParts[i]);
     296                        break;
     297
     298                    case "label":
     299                        n = model.NumberOfClasses;
     300                        model.ClassLabels = new int[n];
     301                        string[] labelParts = arg.Split();
     302                        for (i = 0; i < n; i++)
     303                            model.ClassLabels[i] = int.Parse(labelParts[i]);
     304                        break;
     305
     306                    case "probA":
     307                        n = model.NumberOfClasses * (model.NumberOfClasses - 1) / 2;
     308                        model.PairwiseProbabilityA = new double[n];
     309                            string[] probAParts = arg.Split();
     310                        for (i = 0; i < n; i++)
     311                            model.PairwiseProbabilityA[i] = double.Parse(probAParts[i]);
     312                        break;
     313
     314                    case "probB":
     315                        n = model.NumberOfClasses * (model.NumberOfClasses - 1) / 2;
     316                        model.PairwiseProbabilityB = new double[n];
     317                        string[] probBParts = arg.Split();
     318                        for (i = 0; i < n; i++)
     319                            model.PairwiseProbabilityB[i] = double.Parse(probBParts[i]);
     320                        break;
     321
     322                    case "nr_sv":
     323                        n = model.NumberOfClasses;
     324                        model.NumberOfSVPerClass = new int[n];
     325                        string[] nrsvParts = arg.Split();
     326                        for (i = 0; i < n; i++)
     327                            model.NumberOfSVPerClass[i] = int.Parse(nrsvParts[i]);
     328                        break;
     329
     330                    case "SV":
     331                        headerFinished = true;
     332                        break;
     333
     334                    default:
     335                        throw new Exception("Unknown text in model file"); 
     336                }
     337            }
     338
     339            // read sv_coef and SV
     340
     341            int m = model.NumberOfClasses - 1;
     342            int l = model.SupportVectorCount;
     343            model.SupportVectorCoefficients = new double[m][];
     344            for (int i = 0; i < m; i++)
     345            {
     346                model.SupportVectorCoefficients[i] = new double[l];
     347            }
     348            model.SupportVectors = new Node[l][];
     349
     350            for (int i = 0; i < l; i++)
     351            {
     352                string[] parts = input.ReadLine().Trim().Split();
     353
     354                for (int k = 0; k < m; k++)
     355                    model.SupportVectorCoefficients[k][i] = double.Parse(parts[k]);
     356                int n = parts.Length-m;
     357                model.SupportVectors[i] = new Node[n];
     358                for (int j = 0; j < n; j++)
     359                {
     360                    string[] nodeParts = parts[m + j].Split(':');
     361                    model.SupportVectors[i][j] = new Node();
     362                    model.SupportVectors[i][j].Index = int.Parse(nodeParts[0]);
     363                    model.SupportVectors[i][j].Value = double.Parse(nodeParts[1]);
     364                }
     365            }
     366
     367            TemporaryCulture.Stop();
     368
     369            return model;
     370        }
     371
     372        /// <summary>
     373        /// Writes a model to the provided filename.  This will overwrite any previous data in the file.
     374        /// </summary>
     375        /// <param name="filename">The desired file</param>
     376        /// <param name="model">The Model to write</param>
     377        public static void Write(string filename, Model model)
     378        {
     379            FileStream stream = File.Open(filename, FileMode.Create);
     380            try
     381            {
     382                Write(stream, model);
     383            }
     384            finally
     385            {
     386                stream.Close();
     387            }
     388        }
     389
     390        /// <summary>
     391        /// Writes a model to the provided stream.
     392        /// </summary>
     393        /// <param name="stream">The output stream</param>
     394        /// <param name="model">The model to write</param>
     395        public static void Write(Stream stream, Model model)
     396        {
     397            TemporaryCulture.Start();
     398
     399            StreamWriter output = new StreamWriter(stream);
     400
     401            Parameter param = model.Parameter;
     402
     403            output.Write("svm_type " + param.SvmType + "\n");
     404            output.Write("kernel_type " + param.KernelType + "\n");
     405
     406            if (param.KernelType == KernelType.POLY)
     407                output.Write("degree " + param.Degree + "\n");
     408
     409            if (param.KernelType == KernelType.POLY || param.KernelType == KernelType.RBF || param.KernelType == KernelType.SIGMOID)
     410                output.Write("gamma " + param.Gamma + "\n");
     411
     412            if (param.KernelType == KernelType.POLY || param.KernelType == KernelType.SIGMOID)
     413                output.Write("coef0 " + param.Coefficient0 + "\n");
     414
     415            int nr_class = model.NumberOfClasses;
     416            int l = model.SupportVectorCount;
     417            output.Write("nr_class " + nr_class + "\n");
     418            output.Write("total_sv " + l + "\n");
     419
     420            {
     421                output.Write("rho");
     422                for (int i = 0; i < nr_class * (nr_class - 1) / 2; i++)
     423                    output.Write(" " + model.Rho[i]);
     424                output.Write("\n");
     425            }
     426
     427            if (model.ClassLabels != null)
     428            {
     429                output.Write("label");
     430                for (int i = 0; i < nr_class; i++)
     431                    output.Write(" " + model.ClassLabels[i]);
     432                output.Write("\n");
     433            }
     434
     435            if (model.PairwiseProbabilityA != null)
     436            // regression has probA only
     437            {
     438                output.Write("probA");
     439                for (int i = 0; i < nr_class * (nr_class - 1) / 2; i++)
     440                    output.Write(" " + model.PairwiseProbabilityA[i]);
     441                output.Write("\n");
     442            }
     443            if (model.PairwiseProbabilityB != null)
     444            {
     445                output.Write("probB");
     446                for (int i = 0; i < nr_class * (nr_class - 1) / 2; i++)
     447                    output.Write(" " + model.PairwiseProbabilityB[i]);
     448                output.Write("\n");
     449            }
     450
     451            if (model.NumberOfSVPerClass != null)
     452            {
     453                output.Write("nr_sv");
     454                for (int i = 0; i < nr_class; i++)
     455                    output.Write(" " + model.NumberOfSVPerClass[i]);
     456                output.Write("\n");
     457            }
     458
     459            output.Write("SV\n");
     460            double[][] sv_coef = model.SupportVectorCoefficients;
     461            Node[][] SV = model.SupportVectors;
     462
     463            for (int i = 0; i < l; i++)
     464            {
     465                for (int j = 0; j < nr_class - 1; j++)
     466                    output.Write(sv_coef[j][i] + " ");
     467
     468                Node[] p = SV[i];
     469                if (p.Length == 0)
     470                {
     471                    output.WriteLine();
     472                    continue;
     473                }
     474                if (param.KernelType == KernelType.PRECOMPUTED)
     475                    output.Write("0:{0}", (int)p[0].Value);
     476                else
     477                {
     478                    output.Write("{0}:{1}", p[0].Index, p[0].Value);
     479                    for (int j = 1; j < p.Length; j++)
     480                        output.Write(" {0}:{1}", p[j].Index, p[j].Value);
     481                }
     482                output.WriteLine();
     483            }
     484
     485            output.Flush();
     486
     487            TemporaryCulture.Stop();
     488        }
     489  }
    426490}
  • trunk/sources/LibSVM/Node.cs

    r1819 r2415  
    2222namespace SVM
    2323{
    24     /// <remarks>
     24    /// <summary>
    2525    /// Encapsulates a node in a Problem vector, with an index and a value (for more efficient representation
    2626    /// of sparse data.
    27     /// </remarks>
     27    /// </summary>
    2828  [Serializable]
    2929  public class Node : IComparable<Node>
    3030  {
    31         private int _index;
    32         private double _value;
     31        internal int _index;
     32        internal double _value;
    3333
    3434        /// <summary>
  • trunk/sources/LibSVM/Parameter.cs

    r1819 r2415  
    1919
    2020using System;
     21using System.Linq;
     22using System.Collections.Generic;
    2123
    2224namespace SVM
    2325{
    24     /// <remarks>
     26    /// <summary>
    2527    /// Contains all of the types of SVM this library can model.
    26     /// </remarks>
     28    /// </summary>
    2729    public enum SvmType {
    2830        /// <summary>
     
    4749        NU_SVR
    4850    };
    49     /// <remarks>
     51    /// <summary>
    5052    /// Contains the various kernel types this library can use.
    51     /// </remarks>
     53    /// </summary>
    5254    public enum KernelType {
    5355        /// <summary>
     
    7375    };
    7476
    75     /// <remarks>
     77    /// <summary>
    7678    /// This class contains the various parameters which can affect the way in which an SVM
    7779    /// is learned.  Unless you know what you are doing, chances are you are best off using
    7880    /// the default values.
    79     /// </remarks>
     81    /// </summary>
    8082  [Serializable]
    8183  public class Parameter : ICloneable
     
    9193        private double _eps;
    9294
    93         private int _weightCount;
    94         private int[] _weightLabels;
    95         private double[] _weights;
     95        private Dictionary<int, double> _weights;
    9696        private double _nu;
    9797        private double _p;
     
    116116            _shrinking = true;
    117117            _probability = false;
    118             _weightCount = 0;
    119             _weightLabels = new int[0];
    120             _weights = new double[0];
     118            _weights = new Dictionary<int, double>();
    121119        }
    122120
     
    234232            }
    235233        }
    236         /// <summary>
    237         /// Number of weights.
    238         /// </summary>
    239         public int WeightCount
    240         {
    241             get
    242             {
    243                 return _weightCount;
    244             }
    245             set
    246             {
    247                 _weightCount = value;
    248             }
    249         }
    250         /// <summary>
    251         /// Array of indicies corresponding to the Weights array (for C-SVC)
    252         /// </summary>
    253         public int[] WeightLabels
    254         {
    255             get
    256             {
    257                 return _weightLabels;
    258             }
    259             set
    260             {
    261                 _weightLabels = value;
    262             }
    263         }
    264         /// <summary>
    265         /// The parameter C of class i to weight*C in C-SVC (default 1)
    266         /// </summary>
    267         public double[] Weights
    268         {
    269             get
    270             {
     234
     235        /// <summary>
     236        /// Contains custom weights for class labels.  Default weight value is 1.
     237        /// </summary>
     238        public Dictionary<int,double> Weights
     239        {
     240            get{
    271241                return _weights;
    272242            }
    273             set
    274             {
    275                 _weights = value;
    276             }
    277         }
     243        }
     244
    278245        /// <summary>
    279246        /// The parameter nu of nu-SVC, one-class SVM, and nu-SVR (default 0.5)
  • trunk/sources/LibSVM/ParameterSelection.cs

    r1819 r2415  
    2424namespace SVM
    2525{
    26     /// <remarks>
     26    /// <summary>
    2727    /// This class contains routines which perform parameter selection for a model which uses C-SVC and
    2828    /// an RBF kernel.
    29     /// </remarks>
     29    /// </summary>
    3030    public static class ParameterSelection
    3131    {
     
    142142            Gamma = 0;
    143143            double crossValidation = double.MinValue;
    144             StreamWriter output = new StreamWriter("graph.txt");
     144            StreamWriter output = null;
     145            if(outputFile != null)
     146                output = new StreamWriter(outputFile);
    145147            for(int i=0; i<CValues.Count; i++)
    146148                for (int j = 0; j < GammaValues.Count; j++)
     
    150152                    double test = Training.PerformCrossValidation(problem, parameters, nrfold);
    151153                    Console.Write("{0} {1} {2}", parameters.C, parameters.Gamma, test);
    152                     output.WriteLine("{0} {1} {2}", parameters.C, parameters.Gamma, test);
     154                    if(output != null)
     155                        output.WriteLine("{0} {1} {2}", parameters.C, parameters.Gamma, test);
    153156                    if (test > crossValidation)
    154157                    {
     
    160163                    else Console.WriteLine();
    161164                }
    162             output.Close();
     165            if(output != null)
     166                output.Close();
    163167        }
    164168        /// <summary>
     
    207211            Gamma = 0;
    208212            double maxScore = double.MinValue;
    209             StreamWriter output = new StreamWriter(outputFile);
     213            StreamWriter output = null;
     214            if(outputFile != null)
     215                output = new StreamWriter(outputFile);
    210216            for (int i = 0; i < CValues.Count; i++)
    211217                for (int j = 0; j < GammaValues.Count; j++)
     
    216222                    double test = Prediction.Predict(validation, "tmp.txt", model, false);
    217223                    Console.Write("{0} {1} {2}", parameters.C, parameters.Gamma, test);
    218                     output.WriteLine("{0} {1} {2}", parameters.C, parameters.Gamma, test);
     224                    if(output != null)
     225                        output.WriteLine("{0} {1} {2}", parameters.C, parameters.Gamma, test);
    219226                    if (test > maxScore)
    220227                    {
     
    226233                    else Console.WriteLine();
    227234                }
    228             output.Close();
     235            if(output != null)
     236                output.Close();
    229237        }
    230238    }
  • trunk/sources/LibSVM/PerformanceEvaluator.cs

    r1819 r2415  
    2121using System.Collections.Generic;
    2222using System.IO;
     23using System.Globalization;
    2324
    2425namespace SVM
    2526{
    26     /// <remarks>
     27    /// <summary>
    2728    /// Class encoding a member of a ranked set of labels.
    28     /// </remarks>
     29    /// </summary>
    2930    public class RankPair : IComparable<RankPair>
    3031    {
     
    138139    }
    139140
    140     /// <remarks>
     141    /// <summary>
    141142    /// Class which evaluates an SVM model using several standard techniques.
    142     /// </remarks>
     143    /// </summary>
    143144    public class PerformanceEvaluator
    144145    {
     
    185186        /// <param name="model">Model to evaluate</param>
    186187        /// <param name="problem">Problem to evaluate</param>
    187         /// <param name="label">Label to be evaluate for</param>
    188         public PerformanceEvaluator(Model model, Problem problem, double label) : this(model, problem, label, "tmp.results") { }
     188        /// <param name="category">Label to be evaluate for</param>
     189        public PerformanceEvaluator(Model model, Problem problem, double category) : this(model, problem, category, "tmp.results") { }
    189190        /// <summary>
    190191        /// Constructor.
     
    220221            int confidenceIndex = -1;
    221222            for (int i = 1; i < parts.Length; i++)
    222                 if (double.Parse(parts[i]) == category)
     223                if (double.Parse(parts[i], CultureInfo.InvariantCulture) == category)
    223224                {
    224225                    confidenceIndex = i;
     
    229230            {
    230231                parts = input.ReadLine().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
    231                 double confidence = double.Parse(parts[confidenceIndex]);
    232                 _data.Add(new RankPair(confidence, labels[i]));
     232                double confidence = double.Parse(parts[confidenceIndex], CultureInfo.InvariantCulture);
     233                _data.Add(new RankPair(confidence, labels[i] == category ? 1 : 0));
    233234            }
    234235            input.Close();
  • trunk/sources/LibSVM/PrecomputedKernel.cs

    r1819 r2415  
    2323namespace SVM
    2424{
    25     /// <remarks>
     25    /// <summary>
    2626    /// Class encapsulating a precomputed kernel, where each position indicates the similarity score for two items in the training data.
    27     /// </remarks>
     27    /// </summary>
    2828    [Serializable]
    2929    public class PrecomputedKernel
     
    4242            _rows = _similarities.GetLength(0);
    4343            _columns = _similarities.GetLength(1);
     44        }
     45
     46        /// <summary>
     47        /// Constructor.
     48        /// </summary>
     49        /// <param name="nodes">Nodes for self-similarity analysis</param>
     50        /// <param name="param">Parameters to use when computing similarities</param>
     51        public PrecomputedKernel(List<Node[]> nodes, Parameter param)
     52        {
     53            _rows = nodes.Count;
     54            _columns = _rows;
     55            _similarities = new float[_rows, _columns];
     56            for (int r = 0; r < _rows; r++)
     57            {
     58                for (int c = 0; c < r; c++)
     59                    _similarities[r, c] = _similarities[c, r];
     60                _similarities[r, r] = 1;
     61                for (int c = r + 1; c < _columns; c++)
     62                    _similarities[r, c] = (float)Kernel.KernelFunction(nodes[r], nodes[c], param);
     63            }
     64        }
     65
     66        /// <summary>
     67        /// Constructor.
     68        /// </summary>
     69        /// <param name="rows">Nodes to use as the rows of the matrix</param>
     70        /// <param name="columns">Nodes to use as the columns of the matrix</param>
     71        /// <param name="param">Parameters to use when compute similarities</param>
     72        public PrecomputedKernel(List<Node[]> rows, List<Node[]> columns, Parameter param)
     73        {
     74            _rows = rows.Count;
     75            _columns = columns.Count;
     76            _similarities = new float[_rows, _columns];
     77            for (int r = 0; r < _rows; r++)
     78                for (int c = 0; c < _columns; c++)
     79                    _similarities[r, c] = (float)Kernel.KernelFunction(rows[r], columns[c], param);
    4480        }
    4581
  • trunk/sources/LibSVM/Prediction.cs

    r1819 r2415  
    2424namespace SVM
    2525{
    26     /// <remarks>
     26    /// <summary>
    2727    /// Class containing the routines to perform class membership prediction using a trained SVM.
    28     /// </remarks>
     28    /// </summary>
    2929    public static class Prediction
    3030    {
  • trunk/sources/LibSVM/Problem.cs

    r1819 r2415  
    2121using System.IO;
    2222using System.Collections.Generic;
     23using System.Threading;
     24using System.Globalization;
    2325
    2426namespace SVM
    2527{
    26     /// <remarks>
     28    /// <summary>
    2729    /// Encapsulates a problem, or set of vectors which must be classified.
    28     /// </remarks>
     30    /// </summary>
    2931  [Serializable]
    3032  public class Problem
     
    119121        public static Problem Read(Stream stream)
    120122        {
     123            TemporaryCulture.Start();
     124
    121125            StreamReader input = new StreamReader(stream);
    122126            List<double> vy = new List<double>();
     
    143147            }
    144148
     149            TemporaryCulture.Stop();
     150
    145151            return new Problem(vy.Count, vy.ToArray(), vx.ToArray(), max_index);
    146152        }
     
    153159        public static void Write(Stream stream, Problem problem)
    154160        {
     161            TemporaryCulture.Start();
     162
    155163            StreamWriter output = new StreamWriter(stream);
    156164            for (int i = 0; i < problem.Count; i++)
     
    162170            }
    163171            output.Flush();
     172
     173            TemporaryCulture.Stop();
    164174        }
    165175
  • trunk/sources/LibSVM/Properties/AssemblyInfo.cs

    r1820 r2415  
    66// set of attributes. Change these attribute values to modify the information
    77// associated with an assembly.
    8 [assembly: AssemblyTitle("LibSVM")]
    9 [assembly: AssemblyDescription("")]
     8[assembly: AssemblyTitle("SVM.NET")]
     9[assembly: AssemblyDescription("A .NET Support Vector Machine library adapted from libsvm")]
    1010[assembly: AssemblyConfiguration("")]
    1111[assembly: AssemblyCompany("Matthew Johnson")]
    12 [assembly: AssemblyProduct("SVM.NET Library")]
    13 [assembly: AssemblyCopyright("Copyright (C) 2008 Matthew Johnson")]
     12[assembly: AssemblyProduct("SVM.NET")]
     13[assembly: AssemblyCopyright("Copyright ©  Matthew Johnson 2009")]
    1414[assembly: AssemblyTrademark("")]
    1515[assembly: AssemblyCulture("")]
     
    2121
    2222// The following GUID is for the ID of the typelib if this project is exposed to COM
    23 [assembly: Guid("1f115aaf-e714-4341-b2ad-5e84d30b6a1a")]
     23[assembly: Guid("803d4e74-70db-432e-a4da-32e7a021eec2")]
    2424
    2525// Version information for an assembly consists of the following four values:
     
    3030//      Revision
    3131//
    32 [assembly: AssemblyVersion("2.84")]
    33 [assembly: AssemblyFileVersion("2.84")]
     32// You can specify all the values or you can default the Revision and Build Numbers
     33// by using the '*' as shown below:
     34[assembly: AssemblyVersion("1.6.3")]
     35[assembly: AssemblyFileVersion("1.6.3")]
  • trunk/sources/LibSVM/RangeTransform.cs

    r1819 r2415  
    2020using System;
    2121using System.IO;
     22using System.Threading;
     23using System.Globalization;
    2224
    2325namespace SVM
    2426{
    25     /// <remarks>
     27    /// <summary>
    2628    /// Class which encapsulates a range transformation.
    27     /// </remarks>
     29    /// </summary>
    2830    public class RangeTransform : IRangeTransform
    2931    {
     32        /// <summary>
     33        /// Default lower bound for scaling (-1).
     34        /// </summary>
     35        public const int DEFAULT_LOWER_BOUND = -1;
     36        /// <summary>
     37        /// Default upper bound for scaling (1).
     38        /// </summary>
     39        public const int DEFAULT_UPPER_BOUND = 1;
     40
     41        /// <summary>
     42        /// Determines the Range transform for the provided problem.  Uses the default lower and upper bounds.
     43        /// </summary>
     44        /// <param name="prob">The Problem to analyze</param>
     45        /// <returns>The Range transform for the problem</returns>
     46        public static RangeTransform Compute(Problem prob)
     47        {
     48            return Compute(prob, DEFAULT_LOWER_BOUND, DEFAULT_UPPER_BOUND);
     49        }
     50        /// <summary>
     51        /// Determines the Range transform for the provided problem.
     52        /// </summary>
     53        /// <param name="prob">The Problem to analyze</param>
     54        /// <param name="lowerBound">The lower bound for scaling</param>
     55        /// <param name="upperBound">The upper bound for scaling</param>
     56        /// <returns>The Range transform for the problem</returns>
     57        public static RangeTransform Compute(Problem prob, double lowerBound, double upperBound)
     58        {
     59            double[] minVals = new double[prob.MaxIndex];
     60            double[] maxVals = new double[prob.MaxIndex];
     61            for (int i = 0; i < prob.MaxIndex; i++)
     62            {
     63                minVals[i] = double.MaxValue;
     64                maxVals[i] = double.MinValue;
     65            }
     66            for (int i = 0; i < prob.Count; i++)
     67            {
     68                for (int j = 0; j < prob.X[i].Length; j++)
     69                {
     70                    int index = prob.X[i][j].Index - 1;
     71                    double value = prob.X[i][j].Value;
     72                    minVals[index] = Math.Min(minVals[index], value);
     73                    maxVals[index] = Math.Max(maxVals[index], value);
     74                }
     75            }
     76            for (int i = 0; i < prob.MaxIndex; i++)
     77            {
     78                if (minVals[i] == double.MaxValue || maxVals[i] == double.MinValue)
     79                {
     80                    minVals[i] = 0;
     81                    maxVals[i] = 0;
     82                }
     83            }
     84            return new RangeTransform(minVals, maxVals, lowerBound, upperBound);
     85        }
     86
    3087        private double[] _inputStart;
    3188        private double[] _inputScale;
     
    72129        {
    73130            Node[] output = new Node[input.Length];
    74             for (int i = 0; i < _length; i++)
     131            for (int i = 0; i < output.Length; i++)
    75132            {
    76133                int index = input[i].Index;
     
    104161        public static void Write(Stream stream, RangeTransform r)
    105162        {
     163            TemporaryCulture.Start();
     164
    106165            StreamWriter output = new StreamWriter(stream);
    107166            output.WriteLine(r._length);
     
    116175            output.WriteLine("{0} {1}", r._outputStart, r._outputScale);
    117176            output.Flush();
     177
     178            TemporaryCulture.Stop();
    118179        }
    119180
     
    161222        public static RangeTransform Read(Stream stream)
    162223        {
     224            TemporaryCulture.Start();
     225
    163226            StreamReader input = new StreamReader(stream);
    164227            int length = int.Parse(input.ReadLine());
     
    174237            double outputStart = double.Parse(parts[0]);
    175238            double outputScale = double.Parse(parts[1]);
     239
     240            TemporaryCulture.Stop();
     241
    176242            return new RangeTransform(inputStart, inputScale, outputStart, outputScale, length);
    177243        }
  • trunk/sources/LibSVM/Scaling.cs

    r1819 r2415  
    2222namespace SVM
    2323{
    24     /// <remarks>
     24    /// <summary>
    2525    /// Deals with the scaling of Problems so they have uniform ranges across all dimensions in order to
    2626    /// result in better SVM performance.
    27     /// </remarks>
     27    /// </summary>
    2828    public static class Scaling
    2929    {
    30         /// <summary>
    31         /// Default lower bound for scaling (-1).
    32         /// </summary>
    33         public const int DEFAULT_LOWER_BOUND = -1;
    34         /// <summary>
    35         /// Default upper bound for scaling (1).
    36         /// </summary>
    37         public const int DEFAULT_UPPER_BOUND = 1;
    38 
    39         /// <summary>
    40         /// Determines the Range transform for the provided problem.  Uses the default lower and upper bounds.
    41         /// </summary>
    42         /// <param name="prob">The Problem to analyze</param>
    43         /// <returns>The Range transform for the problem</returns>
    44         public static RangeTransform DetermineRange(Problem prob)
    45         {
    46             return DetermineRangeTransform(prob, DEFAULT_LOWER_BOUND, DEFAULT_UPPER_BOUND);
    47         }
    48         /// <summary>
    49         /// Determines the Range transform for the provided problem.
    50         /// </summary>
    51         /// <param name="prob">The Problem to analyze</param>
    52         /// <param name="lowerBound">The lower bound for scaling</param>
    53         /// <param name="upperBound">The upper bound for scaling</param>
    54         /// <returns>The Range transform for the problem</returns>
    55         public static RangeTransform DetermineRangeTransform(Problem prob, double lowerBound, double upperBound)
    56         {
    57             double[] minVals = new double[prob.MaxIndex];
    58             double[] maxVals = new double[prob.MaxIndex];
    59             for (int i = 0; i < prob.MaxIndex; i++)
    60             {
    61                 minVals[i] = double.MaxValue;
    62                 maxVals[i] = double.MinValue;
    63             }
    64             for (int i = 0; i < prob.Count; i++)
    65             {
    66                 for (int j = 0; j < prob.X[i].Length; j++)
    67                 {
    68                     int index = prob.X[i][j].Index-1;
    69                     double value = prob.X[i][j].Value;
    70                     minVals[index] = Math.Min(minVals[index], value);
    71                     maxVals[index] = Math.Max(maxVals[index], value);
    72                 }
    73             }
    74             for (int i = 0; i < prob.MaxIndex; i++)
    75             {
    76                 if (minVals[i] == double.MaxValue || maxVals[i] == double.MinValue)
    77                 {
    78                     minVals[i] = 0;
    79                     maxVals[i] = 0;
    80                 }
    81             }
    82             return new RangeTransform(minVals, maxVals, lowerBound, upperBound);
    83         }
    8430        /// <summary>
    8531        /// Scales a problem using the provided range.  This will not affect the parameter.
     
    8834        /// <param name="range">The Range transform to use in scaling</param>
    8935        /// <returns>The Scaled problem</returns>
    90         public static Problem Scale(Problem prob, IRangeTransform range)
     36        public static Problem Scale(this IRangeTransform range, Problem prob)
    9137        {
    9238            Problem scaledProblem = new Problem(prob.Count, new double[prob.Count], new Node[prob.Count][], prob.MaxIndex);
  • 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}
  • trunk/sources/LibSVM/Training.cs

    r1819 r2415  
    2323namespace SVM
    2424{
    25     /// <remarks>
     25    /// <summary>
    2626    /// Class containing the routines to train SVM models.
    27     /// </remarks>
     27    /// </summary>
    2828    public static class Training
    2929    {
     30        /// <summary>
     31        /// Whether the system will output information to the console during the training process.
     32        /// </summary>
     33        public static bool IsVerbose
     34        {
     35            get
     36            {
     37                return Procedures.IsVerbose;
     38            }
     39            set
     40            {
     41                Procedures.IsVerbose = value;
     42            }
     43        }
     44
    3045        private static double doCrossValidation(Problem problem, Parameter parameters, int nr_fold)
    3146        {
    3247            int i;
    3348            double[] target = new double[problem.Count];
    34             Dictionary<int, double>[] confidence = new Dictionary<int, double>[problem.Count];
    35             Procedures.svm_cross_validation(problem, parameters, nr_fold, target, confidence);
    36             if (parameters.Probability)
    37             {
    38                 List<RankPair> ranks = new List<RankPair>();
    39                 for (i = 0; i < target.Length; i++)
    40                     ranks.Add(new RankPair(confidence[i][1], problem.Y[i]));
    41                 PerformanceEvaluator eval = new PerformanceEvaluator(ranks);
    42                 return eval.AuC*eval.AP;
     49            Procedures.svm_cross_validation(problem, parameters, nr_fold, target);
     50            int total_correct = 0;
     51            double total_error = 0;
     52            double sumv = 0, sumy = 0, sumvv = 0, sumyy = 0, sumvy = 0;
     53            if (parameters.SvmType == SvmType.EPSILON_SVR || parameters.SvmType == SvmType.NU_SVR)
     54            {
     55                for (i = 0; i < problem.Count; i++)
     56                {
     57                    double y = problem.Y[i];
     58                    double v = target[i];
     59                    total_error += (v - y) * (v - y);
     60                    sumv += v;
     61                    sumy += y;
     62                    sumvv += v * v;
     63                    sumyy += y * y;
     64                    sumvy += v * y;
     65                }
     66                return(problem.Count * sumvy - sumv * sumy) / (Math.Sqrt(problem.Count * sumvv - sumv * sumv) * Math.Sqrt(problem.Count * sumyy - sumy * sumy));
    4367            }
    4468            else
    45             {
    46                 int total_correct = 0;
    47                 double total_error = 0;
    48                 double sumv = 0, sumy = 0, sumvv = 0, sumyy = 0, sumvy = 0;
    49                 if (parameters.SvmType == SvmType.EPSILON_SVR || parameters.SvmType == SvmType.NU_SVR)
    50                 {
    51                     for (i = 0; i < problem.Count; i++)
    52                     {
    53                         double y = problem.Y[i];
    54                         double v = target[i];
    55                         total_error += (v - y) * (v - y);
    56                         sumv += v;
    57                         sumy += y;
    58                         sumvv += v * v;
    59                         sumyy += y * y;
    60                         sumvy += v * y;
    61                     }
    62                 }
    63                 else
    64                     for (i = 0; i < problem.Count; i++)
    65                         if (target[i] == problem.Y[i])
    66                             ++total_correct;
    67                 return (double)total_correct / problem.Count;
    68             }
    69 
     69                for (i = 0; i < problem.Count; i++)
     70                    if (target[i] == problem.Y[i])
     71                        ++total_correct;
     72            return (double)total_correct / problem.Count;
    7073        }
    7174        /// <summary>
     
    9699        public static double PerformCrossValidation(Problem problem, Parameter parameters, int nrfold)
    97100        {
    98             Procedures.svm_check_parameter(problem, parameters);
    99             return doCrossValidation(problem, parameters, nrfold);
     101            string error = Procedures.svm_check_parameter(problem, parameters);
     102            if (error == null)
     103                return doCrossValidation(problem, parameters, nrfold);
     104            else throw new Exception(error);
    100105        }
    101106
     
    108113        public static Model Train(Problem problem, Parameter parameters)
    109114        {
    110             Procedures.svm_check_parameter(problem, parameters);
    111 
    112             return Procedures.svm_train(problem, parameters);
     115            string error = Procedures.svm_check_parameter(problem, parameters);
     116
     117            if (error == null)
     118                return Procedures.svm_train(problem, parameters);
     119            else throw new Exception(error);
    113120        }
    114121
     
    190197
    191198                    case 'w':
    192                         ++parameters.WeightCount;
    193                         {
    194                             int[] old = parameters.WeightLabels;
    195                             parameters.WeightLabels = new int[parameters.WeightCount];
    196                             Array.Copy(old, 0, parameters.WeightLabels, 0, parameters.WeightCount - 1);
    197                         }
    198                         {
    199                             double[] old = parameters.Weights;
    200                             parameters.Weights = new double[parameters.WeightCount];
    201                             Array.Copy(old, 0, parameters.Weights, 0, parameters.WeightCount - 1);
    202                         }
    203 
    204                         parameters.WeightLabels[parameters.WeightCount - 1] = int.Parse(args[i - 1].Substring(2));
    205                         parameters.Weights[parameters.WeightCount - 1] = double.Parse(args[i]);
     199                        parameters.Weights[int.Parse(args[i - 1].Substring(2))] = double.Parse(args[1]);
    206200                        break;
    207201
Note: See TracChangeset for help on using the changeset viewer.