svm_sparse_ex.cpp 4.12 KB
Newer Older
Davis King's avatar
Davis King committed
1
2
3
// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt
/*

Davis King's avatar
Davis King committed
4
5
    This is an example showing how to use sparse feature vectors with
    the dlib C++ library's machine learning tools.
Davis King's avatar
Davis King committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

    This example creates a simple binary classification problem and shows
    you how to train a support vector machine on that data.

    The data used in this example will be 100 dimensional data and will
    come from a simple linearly separable distribution.  
*/


#include <iostream>
#include <ctime>
#include <vector>
#include "dlib/svm.h"

using namespace std;
using namespace dlib;


int main()
{
    // In this example program we will be dealing with feature vectors that are sparse (i.e. most
    // of the values in each vector are zero).  So rather than using a dlib::matrix we can use
    // one of the containers from the STL to represent our sample vectors.  In particular, we 
    // can use the std::map to represent sparse vectors.  (Note that you don't have to use std::map.
    // Any STL container of std::pair objects that is sorted can be used.  So for example, you could 
Davis King's avatar
Davis King committed
31
32
    // use a std::vector<std::pair<unsigned long,double> > here so long as you took care to sort every vector)
    typedef std::map<unsigned long,double> sample_type;
Davis King's avatar
Davis King committed
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47


    // This is a typedef for the type of kernel we are going to use in this example.
    // Since our data is linearly separable I picked the linear kernel.  Note that if you
    // are using a sparse vector representation like std::map then you have to use a kernel
    // meant to be used with that kind of data type.  
    typedef sparse_linear_kernel<sample_type> kernel_type;


    // Here we create an instance of the pegasos svm trainer object we will be using.
    svm_pegasos<kernel_type> trainer;
    // Here we setup a parameter to this object.  See the dlib documentation for a 
    // description of what this parameter does. 
    trainer.set_lambda(0.00001);

Davis King's avatar
Davis King committed
48
49
50
51
    // Lets also use the svm trainer specially optimized for the linear_kernel and
    // sparse_linear_kernel.
    svm_c_linear_trainer<kernel_type> linear_trainer;

Davis King's avatar
Davis King committed
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
    std::vector<sample_type> samples;
    std::vector<double> labels;

    // make an instance of a sample vector so we can use it below
    sample_type sample;


    // Now lets go into a loop and randomly generate 10000 samples.
    srand(time(0));
    double label = +1;
    for (int i = 0; i < 10000; ++i)
    {
        // flip this flag
        label *= -1;

        sample.clear();

        // now make a random sparse sample with at most 10 non-zero elements
        for (int j = 0; j < 10; ++j)
        {
            int idx = std::rand()%100;
            double value = static_cast<double>(std::rand())/RAND_MAX;

            sample[idx] = label*value;
        }

Davis King's avatar
Davis King committed
78
        // let the svm_pegasos learn about this sample.  
Davis King's avatar
Davis King committed
79
        trainer.train(sample,label);
Davis King's avatar
Davis King committed
80
81
82
83
84

        // Also save the samples we are generating so we can let the svm_c_linear_trainer
        // learn from them below.  
        samples.push_back(sample);
        labels.push_back(label);
Davis King's avatar
Davis King committed
85
86
    }

Davis King's avatar
Davis King committed
87
88
89
90
91
92
93
    // In addition to the rule we learned with the pegasos trainer lets also use our linear_trainer
    // to learn a decision rule.
    decision_function<kernel_type> df = linear_trainer.train(samples, labels);

    // Now we have trained our SVMs.  Lets test them out a bit.  
    // Each of these statements prints the output of the SVMs given a particular sample.  
    // Each SVM outputs a number > 0 if a sample is predicted to be in the +1 class and < 0 
Davis King's avatar
Davis King committed
94
95
    // if a sample is predicted to be in the -1 class.

Davis King's avatar
Davis King committed
96

Davis King's avatar
Davis King committed
97
98
99
100
    sample.clear();
    sample[4] = 0.3;
    sample[10] = 0.9;
    cout << "This is a +1 example, its SVM output is: " << trainer(sample) << endl;
Davis King's avatar
Davis King committed
101
    cout << "df: " << df(sample) << endl;
Davis King's avatar
Davis King committed
102
103
104
105
106
107

    sample.clear();
    sample[83] = -0.3;
    sample[26] = -0.9;
    sample[58] = -0.7;
    cout << "This is a -1 example, its SVM output is: " << trainer(sample) << endl;
Davis King's avatar
Davis King committed
108
    cout << "df: " << df(sample) << endl;
Davis King's avatar
Davis King committed
109
110
111
112
113

    sample.clear();
    sample[0] = -0.2;
    sample[9] = -0.8;
    cout << "This is a -1 example, its SVM output is: " << trainer(sample) << endl;
Davis King's avatar
Davis King committed
114
115
    cout << "df: " << df(sample) << endl;

Davis King's avatar
Davis King committed
116
117
}