/* * SVM.NET Library * Copyright (C) 2008 Matthew Johnson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ using System; using System.IO; namespace SVM { /// /// Encapsulates an SVM Model. /// [Serializable] public class Model { private Parameter _parameter; private int _numberOfClasses; private int _supportVectorCount; private Node[][] _supportVectors; private double[][] _supportVectorCoefficients; private double[] _rho; private double[] _pairwiseProbabilityA; private double[] _pairwiseProbabilityB; private int[] _classLabels; private int[] _numberOfSVPerClass; internal Model() { } /// /// Parameter object. /// public Parameter Parameter { get { return _parameter; } set { _parameter = value; } } /// /// Number of classes in the model. /// public int NumberOfClasses { get { return _numberOfClasses; } set { _numberOfClasses = value; } } /// /// Total number of support vectors. /// public int SupportVectorCount { get { return _supportVectorCount; } set { _supportVectorCount = value; } } /// /// The support vectors. /// public Node[][] SupportVectors { get { return _supportVectors; } set { _supportVectors = value; } } /// /// The coefficients for the support vectors. /// public double[][] SupportVectorCoefficients { get { return _supportVectorCoefficients; } set { _supportVectorCoefficients = value; } } /// /// Rho values. /// public double[] Rho { get { return _rho; } set { _rho = value; } } /// /// First pairwise probability. /// public double[] PairwiseProbabilityA { get { return _pairwiseProbabilityA; } set { _pairwiseProbabilityA = value; } } /// /// Second pairwise probability. /// public double[] PairwiseProbabilityB { get { return _pairwiseProbabilityB; } set { _pairwiseProbabilityB = value; } } // for classification only /// /// Class labels. /// public int[] ClassLabels { get { return _classLabels; } set { _classLabels = value; } } /// /// Number of support vectors per class. /// public int[] NumberOfSVPerClass { get { return _numberOfSVPerClass; } set { _numberOfSVPerClass = value; } } /// /// Reads a Model from the provided file. /// /// The name of the file containing the Model /// the Model public static Model Read(string filename) { FileStream input = File.OpenRead(filename); try { return Read(input); } finally { input.Close(); } } /// /// Reads a Model from the provided stream. /// /// The stream from which to read the Model. /// the Model public static Model Read(Stream stream) { StreamReader input = new StreamReader(stream); // read parameters Model model = new Model(); Parameter param = new Parameter(); model.Parameter = param; model.Rho = null; model.PairwiseProbabilityA = null; model.PairwiseProbabilityB = null; model.ClassLabels = null; model.NumberOfSVPerClass = null; bool headerFinished = false; while (!headerFinished) { string line = input.ReadLine(); string cmd, arg; int splitIndex = line.IndexOf(' '); if (splitIndex >= 0) { cmd = line.Substring(0, splitIndex); arg = line.Substring(splitIndex + 1); } else { cmd = line; arg = ""; } arg = arg.ToLower(); int i,n; switch(cmd){ case "svm_type": param.SvmType = (SvmType)Enum.Parse(typeof(SvmType), arg.ToUpper()); break; case "kernel_type": param.KernelType = (KernelType)Enum.Parse(typeof(KernelType), arg.ToUpper()); break; case "degree": param.Degree = int.Parse(arg); break; case "gamma": param.Gamma = double.Parse(arg); break; case "coef0": param.Coefficient0 = double.Parse(arg); break; case "nr_class": model.NumberOfClasses = int.Parse(arg); break; case "total_sv": model.SupportVectorCount = int.Parse(arg); break; case "rho": n = model.NumberOfClasses * (model.NumberOfClasses - 1) / 2; model.Rho = new double[n]; string[] rhoParts = arg.Split(); for(i=0; i /// Writes a model to the provided filename. This will overwrite any previous data in the file. /// /// The desired file /// The Model to write public static void Write(string filename, Model model) { FileStream stream = File.Open(filename, FileMode.Create); try { Write(stream, model); } finally { stream.Close(); } } /// /// Writes a model to the provided stream. /// /// The output stream /// The model to write public static void Write(Stream stream, Model model) { StreamWriter output = new StreamWriter(stream); Parameter param = model.Parameter; output.Write("svm_type " + param.SvmType + "\n"); output.Write("kernel_type " + param.KernelType + "\n"); if (param.KernelType == KernelType.POLY) output.Write("degree " + param.Degree + "\n"); if (param.KernelType == KernelType.POLY || param.KernelType == KernelType.RBF || param.KernelType == KernelType.SIGMOID) output.Write("gamma " + param.Gamma + "\n"); if (param.KernelType == KernelType.POLY || param.KernelType == KernelType.SIGMOID) output.Write("coef0 " + param.Coefficient0 + "\n"); int nr_class = model.NumberOfClasses; int l = model.SupportVectorCount; output.Write("nr_class " + nr_class + "\n"); output.Write("total_sv " + l + "\n"); { output.Write("rho"); for (int i = 0; i < nr_class * (nr_class - 1) / 2; i++) output.Write(" " + model.Rho[i]); output.Write("\n"); } if (model.ClassLabels != null) { output.Write("label"); for (int i = 0; i < nr_class; i++) output.Write(" " + model.ClassLabels[i]); output.Write("\n"); } if (model.PairwiseProbabilityA != null) // regression has probA only { output.Write("probA"); for (int i = 0; i < nr_class * (nr_class - 1) / 2; i++) output.Write(" " + model.PairwiseProbabilityA[i]); output.Write("\n"); } if (model.PairwiseProbabilityB != null) { output.Write("probB"); for (int i = 0; i < nr_class * (nr_class - 1) / 2; i++) output.Write(" " + model.PairwiseProbabilityB[i]); output.Write("\n"); } if (model.NumberOfSVPerClass != null) { output.Write("nr_sv"); for (int i = 0; i < nr_class; i++) output.Write(" " + model.NumberOfSVPerClass[i]); output.Write("\n"); } output.Write("SV\n"); double[][] sv_coef = model.SupportVectorCoefficients; Node[][] SV = model.SupportVectors; for (int i = 0; i < l; i++) { for (int j = 0; j < nr_class - 1; j++) output.Write(sv_coef[j][i] + " "); Node[] p = SV[i]; if (p.Length == 0) { output.WriteLine(); continue; } if (param.KernelType == KernelType.PRECOMPUTED) output.Write("0:{0}", (int)p[0].Value); else { output.Write("{0}:{1}", p[0].Index, p[0].Value); for (int j = 1; j < p.Length; j++) output.Write(" {0}:{1}", p[j].Index, p[j].Value); } output.WriteLine(); } output.Flush(); } } }