SHOGUN
v3.0.0
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/KernelTwoSampleTestStatistic.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
CKernelTwoSampleTestStatistic
* 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;
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
one_pos=
false
;
111
}
112
113
if
(!one_pos)
114
{
115
SG_WARNING
(
"CMMDKernelSelectionComb::solve_optimization(): all mmd "
116
"estimates are negative. This is techically possible, although "
117
"extremely rare. Consider using different kernels. "
118
"This combination will lead to a bad two-sample test. Since any"
119
"combination is bad, will now just return equally distributed "
120
"kernel weights\n"
);
121
122
/* if no element is positive, we can choose arbritary weights since
123
* the results will be bad anyway */
124
weights.
set_const
(1.0/num_kernels);
125
}
126
else
127
{
128
SG_DEBUG
(
"one MMD entry is positive, performing optimisation\n"
)
129
/* do optimisation, init vectors */
130
for
(
index_t
i=0; i<num_kernels; ++i)
131
{
132
Q_diag[i]=
m_Q
(i,i);
133
f[i]=0;
134
lb[i]=0;
135
ub[i]=
CMath::INFTY
;
136
137
/* initial point has to be feasible, i.e. mmds'*x = b */
138
weights[i]=1.0/sum_mmds;
139
}
140
141
/* start libqp solver with desired parameters */
142
SG_DEBUG
(
"starting libqp optimization\n"
)
143
libqp_state_T qp_exitflag=libqp_gsmo_solver(&
get_Q_col
, Q_diag.
vector
,
144
f.
vector
, mmds.
vector
,
145
one_pos ? 1 : -1,
146
lb.
vector
, ub.
vector
,
147
weights.
vector
, num_kernels,
m_opt_max_iterations
,
148
m_opt_epsilon
, &(
CMMDKernelSelectionComb::print_state
));
149
150
SG_DEBUG
(
"libqp returns: nIts=%d, exit_flag: %d\n"
, qp_exitflag.nIter,
151
qp_exitflag.exitflag);
152
153
/* set really small entries to zero and sum up for normalization */
154
float64_t
sum_weights=0;
155
for
(
index_t
i=0; i<weights.
vlen
; ++i)
156
{
157
if
(weights[i]<
m_opt_low_cut
)
158
{
159
SG_DEBUG
(
"lowcut: weight[%i]=%f<%f setting to zero\n"
, i, weights[i],
160
m_opt_low_cut
);
161
weights[i]=0;
162
}
163
164
sum_weights+=weights[i];
165
}
166
167
/* normalize (allowed since problem is scale invariant) */
168
for
(
index_t
i=0; i<weights.
vlen
; ++i)
169
weights[i]/=sum_weights;
170
}
171
172
return
weights;
173
}
174
#else
175
CKernel
*
CMMDKernelSelectionComb::select_kernel
()
176
{
177
SG_ERROR
(
"CMMDKernelSelectionComb::select_kernel(): LAPACK needs to be "
178
"installed in order to use weight optimisation for combined "
179
"kernels!\n"
);
180
return
NULL;
181
}
182
183
SGVector<float64_t>
CMMDKernelSelectionComb::compute_measures
()
184
{
185
SG_ERROR
(
"CMMDKernelSelectionComb::select_kernel(): LAPACK needs to be "
186
"installed in order to use weight optimisation for combined "
187
"kernels!\n"
);
188
return
SGVector<float64_t>
();
189
}
190
191
SGVector<float64_t>
CMMDKernelSelectionComb::solve_optimization
(
192
SGVector<float64_t>
mmds)
193
{
194
SG_ERROR
(
"CMMDKernelSelectionComb::solve_optimization(): LAPACK needs to be "
195
"installed in order to use weight optimisation for combined "
196
"kernels!\n"
);
197
return
SGVector<float64_t>
();
198
}
199
#endif
SHOGUN
Machine Learning Toolbox - Documentation