SHOGUN
3.2.1
Main Page
Related Pages
Modules
Classes
Files
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Friends
Macros
Groups
Pages
src
shogun
statistics
MMDKernelSelectionComb.cpp
Go to the documentation of this file.
1
/*
2
* This program is free software; you can redistribute it and/or modify
3
* it under the terms of the GNU General Public License as published by
4
* the Free Software Foundation; either version 3 of the License, or
5
* (at your option) any later version.
6
*
7
* Written (W) 2012-2013 Heiko Strathmann
8
*/
9
10
#include <
shogun/statistics/MMDKernelSelectionComb.h
>
11
#include <
shogun/statistics/KernelTwoSampleTest.h
>
12
#include <
shogun/kernel/CombinedKernel.h
>
13
14
using namespace
shogun;
15
16
CMMDKernelSelectionComb::CMMDKernelSelectionComb
() :
17
CMMDKernelSelection
()
18
{
19
init();
20
}
21
22
CMMDKernelSelectionComb::CMMDKernelSelectionComb
(
23
CKernelTwoSampleTest
* mmd) :
CMMDKernelSelection
(mmd)
24
{
25
init();
26
}
27
28
CMMDKernelSelectionComb::~CMMDKernelSelectionComb
()
29
{
30
}
31
32
void
CMMDKernelSelectionComb::init()
33
{
34
#ifdef HAVE_LAPACK
35
SG_ADD
(&
m_opt_max_iterations
,
"opt_max_iterations"
,
"Maximum number of "
36
"iterations for qp solver"
,
MS_NOT_AVAILABLE
);
37
SG_ADD
(&
m_opt_epsilon
,
"opt_epsilon"
,
"Stopping criterion for qp solver"
,
38
MS_NOT_AVAILABLE
);
39
SG_ADD
(&
m_opt_low_cut
,
"opt_low_cut"
,
"Low cut value for optimization "
40
"kernel weights"
,
MS_NOT_AVAILABLE
);
41
42
/* sensible values for optimization */
43
m_opt_max_iterations
=10000;
44
m_opt_epsilon
=10E-15;
45
m_opt_low_cut
=10E-7;
46
#endif
47
}
48
49
#ifdef HAVE_LAPACK
50
/* no reference counting, use the static context constructor of SGMatrix */
51
SGMatrix<float64_t>
CMMDKernelSelectionComb::m_Q
=
SGMatrix<float64_t>
(
false
);
52
53
const
float64_t
*
CMMDKernelSelectionComb::get_Q_col
(uint32_t i)
54
{
55
return
&
m_Q
[
m_Q
.
num_rows
*i];
56
}
57
59
void
CMMDKernelSelectionComb::print_state
(libqp_state_T state)
60
{
61
SG_SDEBUG
(
"CMMDKernelSelectionComb::print_state: libqp state:"
62
" primal=%f\n"
, state.QP);
63
}
64
65
CKernel
*
CMMDKernelSelectionComb::select_kernel
()
66
{
67
/* cast is safe due to assertion in constructor */
68
CCombinedKernel
* combined=(
CCombinedKernel
*)
m_mmd
->
get_kernel
();
69
70
/* optimise for kernel weights and set them */
71
SGVector<float64_t>
weights=
compute_measures
();
72
combined->
set_subkernel_weights
(weights);
73
74
/* note that kernel is SG_REF'ed from getter above */
75
return
combined;
76
}
77
78
SGVector<float64_t>
CMMDKernelSelectionComb::solve_optimization
(
79
SGVector<float64_t>
mmds)
80
{
81
/* readability */
82
index_t
num_kernels=mmds.
vlen
;
83
84
/* compute sum of mmds to generate feasible point for convex program */
85
float64_t
sum_mmds=0;
86
for
(
index_t
i=0; i<mmds.
vlen
; ++i)
87
sum_mmds+=mmds[i];
88
89
/* QP: 0.5*x'*Q*x + f'*x
90
* subject to
91
* mmds'*x = b
92
* LB[i] <= x[i] <= UB[i] for all i=1..n */
93
SGVector<float64_t>
Q_diag(num_kernels);
94
SGVector<float64_t>
f(num_kernels);
95
SGVector<float64_t>
lb(num_kernels);
96
SGVector<float64_t>
ub(num_kernels);
97
SGVector<float64_t>
weights(num_kernels);
98
99
/* init everything, there are two cases possible: i) at least one mmd is
100
* is positive, ii) all mmds are negative */
101
bool
one_pos=
false
;
102
for
(
index_t
i=0; i<mmds.
vlen
; ++i)
103
{
104
if
(mmds[i]>0)
105
{
106
SG_DEBUG
(
"found at least one positive MMD\n"
)
107
one_pos=
true
;
108
break
;
109
}
110
}
111
112
if
(!one_pos)
113
{
114
SG_WARNING
(
"CMMDKernelSelectionComb::solve_optimization(): all mmd "
115
"estimates are negative. This is techically possible, although "
116
"extremely rare. Consider using different kernels. "
117
"This combination will lead to a bad two-sample test. Since any"
118
"combination is bad, will now just return equally distributed "
119
"kernel weights\n"
);
120
121
/* if no element is positive, we can choose arbritary weights since
122
* the results will be bad anyway */
123
weights.
set_const
(1.0/num_kernels);
124
}
125
else
126
{
127
SG_DEBUG
(
"one MMD entry is positive, performing optimisation\n"
)
128
/* do optimisation, init vectors */
129
for
(
index_t
i=0; i<num_kernels; ++i)
130
{
131
Q_diag[i]=
m_Q
(i,i);
132
f[i]=0;
133
lb[i]=0;
134
ub[i]=
CMath::INFTY
;
135
136
/* initial point has to be feasible, i.e. mmds'*x = b */
137
weights[i]=1.0/sum_mmds;
138
}
139
140
/* start libqp solver with desired parameters */
141
SG_DEBUG
(
"starting libqp optimization\n"
)
142
libqp_state_T qp_exitflag=libqp_gsmo_solver(&
get_Q_col
, Q_diag.
vector
,
143
f.
vector
, mmds.
vector
,
144
one_pos ? 1 : -1,
145
lb.
vector
, ub.
vector
,
146
weights.
vector
, num_kernels,
m_opt_max_iterations
,
147
m_opt_epsilon
, &(
CMMDKernelSelectionComb::print_state
));
148
149
SG_DEBUG
(
"libqp returns: nIts=%d, exit_flag: %d\n"
, qp_exitflag.nIter,
150
qp_exitflag.exitflag);
151
152
/* set really small entries to zero and sum up for normalization */
153
float64_t
sum_weights=0;
154
for
(
index_t
i=0; i<weights.
vlen
; ++i)
155
{
156
if
(weights[i]<
m_opt_low_cut
)
157
{
158
SG_DEBUG
(
"lowcut: weight[%i]=%f<%f setting to zero\n"
, i, weights[i],
159
m_opt_low_cut
);
160
weights[i]=0;
161
}
162
163
sum_weights+=weights[i];
164
}
165
166
/* normalize (allowed since problem is scale invariant) */
167
for
(
index_t
i=0; i<weights.
vlen
; ++i)
168
weights[i]/=sum_weights;
169
}
170
171
return
weights;
172
}
173
#else
174
CKernel
*
CMMDKernelSelectionComb::select_kernel
()
175
{
176
SG_ERROR
(
"CMMDKernelSelectionComb::select_kernel(): LAPACK needs to be "
177
"installed in order to use weight optimisation for combined "
178
"kernels!\n"
);
179
return
NULL;
180
}
181
182
SGVector<float64_t>
CMMDKernelSelectionComb::compute_measures
()
183
{
184
SG_ERROR
(
"CMMDKernelSelectionComb::select_kernel(): LAPACK needs to be "
185
"installed in order to use weight optimisation for combined "
186
"kernels!\n"
);
187
return
SGVector<float64_t>
();
188
}
189
190
SGVector<float64_t>
CMMDKernelSelectionComb::solve_optimization
(
191
SGVector<float64_t>
mmds)
192
{
193
SG_ERROR
(
"CMMDKernelSelectionComb::solve_optimization(): LAPACK needs to be "
194
"installed in order to use weight optimisation for combined "
195
"kernels!\n"
);
196
return
SGVector<float64_t>
();
197
}
198
#endif
SHOGUN
Machine Learning Toolbox - Documentation