Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/LibSVM/Kernel.cs @ 2476

Last change on this file since 2476 was 2415, checked in by gkronber, 15 years ago

Updated LibSVM project to latest version. #774

File size: 6.8 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5
6namespace SVM
7{
8    internal interface IQMatrix
9    {
10        float[] GetQ(int column, int len);
11        float[] GetQD();
12        void SwapIndex(int i, int j);
13    }
14
15    internal abstract class Kernel : IQMatrix
16    {
17        private Node[][] _x;
18        private double[] _xSquare;
19
20        private KernelType _kernelType;
21        private int _degree;
22        private double _gamma;
23        private double _coef0;
24
25        public abstract float[] GetQ(int column, int len);
26        public abstract float[] GetQD();
27
28        public virtual void SwapIndex(int i, int j)
29        {
30            _x.SwapIndex(i, j);
31
32            if (_xSquare != null)
33            {
34                _xSquare.SwapIndex(i, j);
35            }
36        }
37
38        private static double powi(double value, int times)
39        {
40            double tmp = value, ret = 1.0;
41
42            for (int t = times; t > 0; t /= 2)
43            {
44                if (t % 2 == 1) ret *= tmp;
45                tmp = tmp * tmp;
46            }
47            return ret;
48        }
49
50        public double KernelFunction(int i, int j)
51        {
52            switch (_kernelType)
53            {
54                case KernelType.LINEAR:
55                    return dot(_x[i], _x[j]);
56                case KernelType.POLY:
57                    return powi(_gamma * dot(_x[i], _x[j]) + _coef0, _degree);
58                case KernelType.RBF:
59                    return Math.Exp(-_gamma * (_xSquare[i] + _xSquare[j] - 2 * dot(_x[i], _x[j])));
60                case KernelType.SIGMOID:
61                    return Math.Tanh(_gamma * dot(_x[i], _x[j]) + _coef0);
62                case KernelType.PRECOMPUTED:
63                    return _x[i][(int)(_x[j][0].Value)].Value;
64                default:
65                    return 0;
66            }
67        }
68
69        public Kernel(int l, Node[][] x_, Parameter param)
70        {
71            _kernelType = param.KernelType;
72            _degree = param.Degree;
73            _gamma = param.Gamma;
74            _coef0 = param.Coefficient0;
75
76            _x = (Node[][])x_.Clone();
77
78            if (_kernelType == KernelType.RBF)
79            {
80                _xSquare = new double[l];
81                for (int i = 0; i < l; i++)
82                    _xSquare[i] = dot(_x[i], _x[i]);
83            }
84            else _xSquare = null;
85        }
86
87        private static double dot(Node[] xNodes, Node[] yNodes)
88        {
89            double sum = 0;
90            int xlen = xNodes.Length;
91            int ylen = yNodes.Length;
92            int i = 0;
93            int j = 0;
94            Node x = xNodes[0];
95            Node y = yNodes[0];
96            while (true)
97            {
98                if (x._index == y._index)
99                {
100                    sum += x._value * y._value;
101                    i++;
102                    j++;
103                    if (i < xlen && j < ylen)
104                    {
105                        x = xNodes[i];
106                        y = yNodes[j];
107                    }
108                    else if (i < xlen)
109                    {
110                        x = xNodes[i];
111                        break;
112                    }
113                    else if (j < ylen)
114                    {
115                        y = yNodes[j];
116                        break;
117                    }
118                    else break;
119                }
120                else
121                {
122                    if (x._index > y._index)
123                    {
124                        ++j;
125                        if (j < ylen)
126                            y = yNodes[j];
127                        else break;
128                    }
129                    else
130                    {
131                        ++i;
132                        if (i < xlen)
133                            x = xNodes[i];
134                        else break;
135                    }
136                }
137            }
138            return sum;
139        }
140
141        private static double computeSquaredDistance(Node[] xNodes, Node[] yNodes)
142        {
143            Node x = xNodes[0];
144            Node y = yNodes[0];
145            int xLength = xNodes.Length;
146            int yLength = yNodes.Length;
147            int xIndex = 0;
148            int yIndex = 0;
149            double sum = 0;
150
151            while (true)
152            {
153                if (x._index == y._index)
154                {
155                    double d = x._value - y._value;
156                    sum += d * d;
157                    xIndex++;
158                    yIndex++;
159                    if (xIndex < xLength && yIndex < yLength)
160                    {
161                        x = xNodes[xIndex];
162                        y = yNodes[yIndex];
163                    }
164                    else if(xIndex < xLength){
165                        x = xNodes[xIndex];
166                        break;
167                    }
168                    else if(yIndex < yLength){
169                        y = yNodes[yIndex];
170                        break;
171                    }else break;
172                }
173                else if (x._index > y._index)
174                {
175                    sum += y._value * y._value;
176                    if (++yIndex < yLength)
177                        y = yNodes[yIndex];
178                    else break;
179                }
180                else
181                {
182                    sum += x._value * x._value;
183                    if (++xIndex < xLength)
184                        x = xNodes[xIndex];
185                    else break;
186                }
187            }
188
189            for (; xIndex < xLength; xIndex++)
190            {
191                double d = xNodes[xIndex]._value;
192                sum += d * d;
193            }
194
195            for (; yIndex < yLength; yIndex++)
196            {
197                double d = yNodes[yIndex]._value;
198                sum += d * d;
199            }
200
201            return sum;
202        }
203
204        public static double KernelFunction(Node[] x, Node[] y, Parameter param)
205        {
206            switch (param.KernelType)
207            {
208                case KernelType.LINEAR:
209                    return dot(x, y);
210                case KernelType.POLY:
211                    return powi(param.Degree * dot(x, y) + param.Coefficient0, param.Degree);
212                case KernelType.RBF:
213                    {
214                        double sum = computeSquaredDistance(x, y);
215                        return Math.Exp(-param.Gamma * sum);
216                    }
217                case KernelType.SIGMOID:
218                    return Math.Tanh(param.Gamma * dot(x, y) + param.Coefficient0);
219                case KernelType.PRECOMPUTED:
220                    return x[(int)(y[0].Value)].Value;
221                default:
222                    return 0;
223            }
224        }
225    }
226}
Note: See TracBrowser for help on using the repository browser.