ProjectBudgetMaintenanceStrategy.h
Go to the documentation of this file.
1//===========================================================================
2/*!
3 *
4 *
5 * \brief Project budget maintenance strategy
6 *
7 * \par
8 * This is an budget strategy that simply project one of the
9 * budget vectors onto the others. To save time, the smallest
10 * vector (measured in 2-norm of the alpha-coefficients) will
11 * be selected for projection.
12 *
13 *
14 *
15 *
16 * \author Aydin Demircioglu
17 * \date 2014
18 *
19 *
20 * \par Copyright 1995-2017 Shark Development Team
21 *
22 * <BR><HR>
23 * This file is part of Shark.
24 * <https://shark-ml.github.io/Shark/>
25 *
26 * Shark is free software: you can redistribute it and/or modify
27 * it under the terms of the GNU Lesser General Public License as published
28 * by the Free Software Foundation, either version 3 of the License, or
29 * (at your option) any later version.
30 *
31 * Shark is distributed in the hope that it will be useful,
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 * GNU Lesser General Public License for more details.
35 *
36 * You should have received a copy of the GNU Lesser General Public License
37 * along with Shark. If not, see <http://www.gnu.org/licenses/>.
38 *
39 */
40//===========================================================================
41
42
43#ifndef SHARK_MODELS_PROJECTBUDGETMAINTENANCESTRATEGY_H
44#define SHARK_MODELS_PROJECTBUDGETMAINTENANCESTRATEGY_H
45
47#include <shark/ObjectiveFunctions/KernelBasisDistance.h>
48#include <shark/Data/Dataset.h>
49#include <shark/Data/DataView.h>
50
51
52namespace shark {
53
54 ///
55 /// \brief Budget maintenance strategy that projects a vector
56 ///
57 /// This is an budget strategy that simply projects one of the
58 /// budget vectors onto the others. The resulting coefficients are
59 /// then added to the other vectors and the projected vector is
60 /// removed from the budget.
61 ///
62 template<class InputType>
66 typedef typename DataType::element_type ElementType;
67
68 public:
69
70 /// constructor.
73
74
75 /// add to model.
76 /// this is just a fake here, as it is unclear in general how to merge two objects,
77 /// one needs to specialize this template.
78 ///
79 /// @param[in,out] model the model the strategy will work with
80 /// @param[in] alpha alphas for the new budget vector
81 /// @param[in] supportVector the vector to add to the model by applying the maintenance strategy
82 ///
83 virtual void addToModel (ModelType& model, InputType const& alpha, ElementType const& supportVector) {
84 // to project we simply utilize the kernel basis distance
85 }
86
87
88 /// class name
89 std::string name() const
90 { return "ProjectBudgetMaintenanceStrategy"; }
91
92 protected:
93
94 };
95
96 ///
97 /// \brief Budget maintenance strategy that projects a vector
98 ///
99 /// \par This is an specialization of the project budget maintenance strategy
100 /// that handles simple real-valued vectors. This is a nearly 1:1 adoption of
101 /// the strategy presented in Wang, Cramer and Vucetic.
102 ///
103 template<>
105 typedef RealVector InputType;
108 typedef typename DataType::element_type ElementType;
109
110 public:
111
112 /// constructor.
115
116
117
118 /// add a vector to the model.
119 /// this will add the given vector to the model and merge the budget so that afterwards
120 /// the budget size is kept the same. If the budget has a free entry anyway, no merging
121 /// will be performed, but instead the given vector is simply added to the budget.
122 ///
123 /// @param[in,out] model the model the strategy will work with
124 /// @param[in] alpha alphas for the new budget vector
125 /// @param[in] supportVector the vector to add to the model by applying the maintenance strategy
126 ///
127 virtual void addToModel (ModelType& model, InputType const& alpha, ElementType const& supportVector) {
128
129 // projecting should try out every budget vector
130 // but as this would yield $O(B^3)$ runtime, the vector
131 // with the smallest alpha is taken instead.
132
133 // first put the new vector into place
134 size_t maxIndex = model.basis().numberOfElements();
135 model.basis().element(maxIndex - 1) = supportVector.input;
136 row (model.alpha(), maxIndex - 1) = alpha;
137
138
139 size_t firstIndex = 0;
140 double firstAlpha = 0;
141 findSmallestVector (model, firstIndex, firstAlpha);
142
143 // if the smallest vector has zero alpha,
144 // the budget is not yet filled so we can skip projecting.
145 if (firstAlpha == 0.0f)
146 {
147 // as we need the last vector to be zero, we put the new
148 // vector to that place and undo our putting-the-vector-to-back-position
149 model.basis().element(firstIndex) = supportVector.input;
150 row (model.alpha(), firstIndex) = alpha;
151
152 // enough to zero out the alpha
153 row (model.alpha(), maxIndex - 1).clear();
154
155 // ready.
156 return;
157 }
158
159 // now solve the projection equation
160
161 // we need to project the one vector we have chosen down
162 // to all others. so we need a model with just thet one vector
163 // and then we try to approximate alphas from the rest of thet
164 // vectors, such that the difference is small as possible.
165
166 // create a KernelExpansion just with the one selected vector.
167 std::vector<RealVector> singlePointVector (1,model.basis().element(firstIndex));
168 std::vector<unsigned int> singlePointLabel (1, 0);
169 ClassificationDataset singlePointData = createLabeledDataFromRange(singlePointVector, singlePointLabel);
170 KernelExpansion<RealVector> singlePointExpansion(model.kernel(), singlePointData.inputs(), false, model.alpha().size2());
171 row (singlePointExpansion.alpha(), 0) = row (model.alpha(), firstIndex);
172 KernelBasisDistance distance(&singlePointExpansion, maxIndex - 1);
173
174 // now create a whole new 'point' with all the other vectors.
175 // then our approximation will give us one coefficient to approximate
176 // the basis, which consits only of the one selected vector.
177 // thus, we approximate the one vector with the rest of them.
178 size_t inputDimension = model.basis().element(0).size();
179 RealVector point(inputDimension * (maxIndex - 1));
180
181 // copy all other budget vectors into one big vector
182 size_t linearIndex = 0;
183 for(std::size_t t = 0; t < maxIndex; t++){
184 // do not copy the first index.
185 if (t == firstIndex)
186 continue;
187 noalias(subrange(point, linearIndex*inputDimension, (linearIndex+1)*inputDimension)) = (model.basis().element(t));
188 linearIndex++;
189 }
190
191 //calculate solution found by the function and check that it is close
192 RealMatrix projectedAlphas = distance.findOptimalBeta(point);
193
194 // stupid sanity check
195 SHARK_ASSERT (projectedAlphas.size2() == model.alpha().size2());
196
197 // add the projected values to the budget
198 linearIndex = 0;
199 for (std::size_t j = 0; j < maxIndex; j++)
200 {
201 if (j == firstIndex)
202 continue;
203
204 // for each class we add the alpha contribution to the true alphas.
205 for (std::size_t c = 0; c < model.alpha().size2(); c++)
206 model.alpha(j, c) += projectedAlphas(linearIndex, c);
207
208 linearIndex++;
209 }
210
211 // overwrite the projected vector with the last vector
212 model.basis().element(firstIndex) = supportVector.input;
213 row (model.alpha(), firstIndex) = alpha;
214
215 // zero out buffer, enough to zero out the alpha
216 row (model.alpha(), maxIndex - 1).clear();
217 }
218
219
220 /// class name
221 std::string name() const
222 { return "ProjectBudgetMaintenanceStrategy"; }
223
224 protected:
225
226 };
227
228
229}
230#endif