EvalSkipMissingFeatures.h
Go to the documentation of this file.
1 //===========================================================================
2 /*!
3  *
4  *
5  * \brief Do special kernel evaluation by skipping missing features
6  *
7  *
8  *
9  * \author B. Li
10  * \date 2012
11  *
12  *
13  * \par Copyright 1995-2015 Shark Development Team
14  *
15  * <BR><HR>
16  * This file is part of Shark.
17  * <http://image.diku.dk/shark/>
18  *
19  * Shark is free software: you can redistribute it and/or modify
20  * it under the terms of the GNU Lesser General Public License as published
21  * by the Free Software Foundation, either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * Shark is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU Lesser General Public License for more details.
28  *
29  * You should have received a copy of the GNU Lesser General Public License
30  * along with Shark. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
33 //===========================================================================
34 #ifndef SHARK_MODELS_KERNELS_EVAL_SKIP_MISSING_FEATURES_H
35 #define SHARK_MODELS_KERNELS_EVAL_SKIP_MISSING_FEATURES_H
36 
37 #include "shark/Core/Exception.h"
38 #include "shark/LinAlg/Base.h"
43 
44 #include <boost/optional.hpp>
45 #include <boost/math/special_functions/fpclassify.hpp>
46 #include <vector>
47 
48 namespace shark {
49 
50 /// Does a kernel function evaluation with Missing features in the inputs
51 /// @param kernelFunction The kernel function used to do evaluation
52 /// @param inputA a input
53 /// @param inputB another input
54 ///
55 /// The kernel k(x,y) is evaluated taking missing features into account. For this it is checked whether a feature
56 /// of x or y is nan and in this case the corresponding features in @a inputA and @a inputB won't be considered.
57 template <typename InputType,typename InputTypeT1,typename InputTypeT2>
59  const AbstractKernelFunction<InputType>& kernelFunction,
60  const InputTypeT1& inputA,
61  const InputTypeT2& inputB)
62 {
63  SIZE_CHECK(inputA.size() == inputB.size());
64  // Do kernel type check
65  if (!kernelFunction.supportsVariableInputSize())
66  throw SHARKEXCEPTION("[evalSkipMissingFeatures] Kernel must support variable input size.");
67 
68  // Work out features that are valid for both dataset i and j, and also should not be filtered out by missingness
69  // Because we won't exact length of valid features beforehand, so we choose to construct two vectors and then
70  // construct another two InputTypes with them.
71  typedef typename InputType::value_type InputValueType;
72  std::vector<InputValueType> tempInputA;
73  std::vector<InputValueType> tempInputB;
74  tempInputA.reserve(inputA.size());
75  tempInputB.reserve(inputB.size());
76  for (std::size_t index = 0; index < inputA.size(); ++index)
77  {
78  //using namespace boost::math;
79  if (!boost::math::isnan(inputA(index)) && !boost::math::isnan(inputB(index)))
80  {
81  tempInputA.push_back(inputA(index));
82  tempInputB.push_back(inputB(index));
83  }
84  }
85 
86  SIZE_CHECK(tempInputA.size() == tempInputB.size());
87  SIZE_CHECK(tempInputA.size() > 0);
88  InputType validInputA(tempInputA.size());
89  InputType validInputB(tempInputA.size());
90  std::copy(tempInputA.begin(),tempInputA.end(),validInputA.begin());
91  std::copy(tempInputB.begin(),tempInputB.end(),validInputB.begin());
92 
93  // And then pass them to the kernel for calculation
94  return kernelFunction.eval(validInputA, validInputB);
95 }
96 
97 /// Do kernel function evaluation while Missing features in the inputs
98 /// @param kernelFunction The kernel function used to do evaluation
99 /// @param inputA a input
100 /// @param inputB another input
101 /// @param missingness
102 /// used to decide which features in the inputs to take into consideration for the purpose of evaluation.
103 /// If a feature is NaN, then the corresponding features in @a inputA and @a inputB won't be considered.
104 template <typename InputType,typename InputTypeT1,typename InputTypeT2,typename InputTypeT3>
106  const AbstractKernelFunction<InputType>& kernelFunction,
107  const InputTypeT1& inputA,
108  const InputTypeT2& inputB,
109  InputTypeT3 const& missingness)
110 {
111  SIZE_CHECK(inputA.size() == inputB.size());
112  //SIZE_CHECK(inputA.size() == missingness.size());
113  // Do kernel type check
114  if (!kernelFunction.supportsVariableInputSize())
115  throw SHARKEXCEPTION("[evalSkipMissingFeatures] Kernel must support variable input size.");
116 
117 
118 
119  // Work out features that are valid for both dataset i and j, and also should not be filtered out by missingness
120  // Because we won't exact length of valid features beforehand, so we choose to construct two vectors and then
121  // construct another two InputTypes with them.
122  typedef typename InputType::value_type InputValueType;
123  std::vector<InputValueType> tempInputA;
124  std::vector<InputValueType> tempInputB;
125  tempInputA.resize(inputA.size());
126  tempInputB.resize(inputB.size());
127  for (std::size_t index = 0; index < inputA.size(); ++index)
128  {
129  if (!boost::math::isnan(inputA(index)) && !boost::math::isnan(inputB(index)) && !boost::math::isnan(missingness(index)))
130  {
131  tempInputA.push_back(inputA(index));
132  tempInputB.push_back(inputB(index));
133  }
134  }
135 
136  SIZE_CHECK(tempInputA.size() == tempInputB.size());
137  SIZE_CHECK(tempInputA.size() > 0);
138  InputType validInputA(tempInputA.size());
139  InputType validInputB(tempInputA.size());
140  for (std::size_t i = 0; i < tempInputA.size(); ++i)
141  {
142  validInputA(i) = tempInputA[i];
143  validInputB(i) = tempInputB[i];
144  }
145 
146  // And then pass them to the kernel for calculation
147  return kernelFunction.eval(validInputA, validInputB);
148 }
149 
150 } // namespace shark {
151 
152 #endif // SHARK_MODELS_KERNELS_EVAL_SKIP_MISSING_FEATURES_H