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-2017 Shark Development Team
14 *
15 * <BR><HR>
16 * This file is part of Shark.
17 * <https://shark-ml.github.io/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
38#include "shark/LinAlg/Base.h"
43
44#include <boost/optional.hpp>
45#include <boost/math/special_functions/fpclassify.hpp>
46#include <vector>
47
48namespace 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/// \ingroup kernels
58template <typename InputType,typename InputTypeT1,typename InputTypeT2>
60 const AbstractKernelFunction<InputType>& kernelFunction,
61 const InputTypeT1& inputA,
62 const InputTypeT2& inputB)
63{
64 SIZE_CHECK(inputA.size() == inputB.size());
65 // Do kernel type check
66 SHARK_RUNTIME_CHECK(kernelFunction.supportsVariableInputSize(), "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/// \ingroup kernels
105template <typename InputType,typename InputTypeT1,typename InputTypeT2,typename InputTypeT3>
107 const AbstractKernelFunction<InputType>& kernelFunction,
108 const InputTypeT1& inputA,
109 const InputTypeT2& inputB,
110 InputTypeT3 const& missingness)
111{
112 SIZE_CHECK(inputA.size() == inputB.size());
113 //SIZE_CHECK(inputA.size() == missingness.size());
114 // Do kernel type check
115 SHARK_RUNTIME_CHECK(kernelFunction.supportsVariableInputSize(), "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