| 27 | |
| 28 | |
| 29 | int main() |
| 30 | { |
| 31 | // The svm functions use column vectors to contain a lot of the data on |
| 32 | // which they operate. So the first thing we do here is declare a convenient |
| 33 | // typedef. |
| 34 | |
| 35 | // This typedef declares a matrix with 2 rows and 1 column. It will be the |
| 36 | // object that contains each of our 2 dimensional samples. (Note that if |
| 37 | // you wanted more than 2 features in this vector you can simply change the |
| 38 | // 2 to something else. Or if you don't know how many features you want |
| 39 | // until runtime then you can put a 0 here and use the matrix.set_size() |
| 40 | // member function) |
| 41 | typedef matrix<double, 2, 1> sample_type; |
| 42 | |
| 43 | // This is a typedef for the type of kernel we are going to use in this |
| 44 | // example. In this case I have selected the radial basis kernel that can |
| 45 | // operate on our 2D sample_type objects. You can use your own custom |
| 46 | // kernels with these tools as well, see custom_trainer_ex.cpp for an |
| 47 | // example. |
| 48 | typedef radial_basis_kernel<sample_type> kernel_type; |
| 49 | |
| 50 | |
| 51 | // Now we make objects to contain our samples and their respective labels. |
| 52 | std::vector<sample_type> samples; |
| 53 | std::vector<double> labels; |
| 54 | |
| 55 | // Now let's put some data into our samples and labels objects. We do this |
| 56 | // by looping over a bunch of points and labeling them according to their |
| 57 | // distance from the origin. |
| 58 | for (int r = -20; r <= 20; ++r) |
| 59 | { |
| 60 | for (int c = -20; c <= 20; ++c) |
| 61 | { |
| 62 | sample_type samp; |
| 63 | samp(0) = r; |
| 64 | samp(1) = c; |
| 65 | samples.push_back(samp); |
| 66 | |
| 67 | // if this point is less than 10 from the origin |
| 68 | if (sqrt((double)r*r + c*c) <= 10) |
| 69 | labels.push_back(+1); |
| 70 | else |
| 71 | labels.push_back(-1); |
| 72 | |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | |
| 77 | // Here we normalize all the samples by subtracting their mean and dividing |
| 78 | // by their standard deviation. This is generally a good idea since it |
| 79 | // often heads off numerical stability problems and also prevents one large |
| 80 | // feature from smothering others. Doing this doesn't matter much in this |
| 81 | // example so I'm just doing this here so you can see an easy way to |
| 82 | // accomplish it. |
| 83 | vector_normalizer<sample_type> normalizer; |
| 84 | // Let the normalizer learn the mean and standard deviation of the samples. |
| 85 | normalizer.train(samples); |
| 86 | // now normalize each sample |
nothing calls this directly
no test coverage detected