Normalizer.h
Go to the documentation of this file.
1 /*!
2  *
3  *
4  * \brief Model for scaling and translation of data vectors.
5  *
6  *
7  *
8  * \author T. Glasmachers
9  * \date 2013
10  *
11  *
12  * \par Copyright 1995-2015 Shark Development Team
13  *
14  * <BR><HR>
15  * This file is part of Shark.
16  * <http://image.diku.dk/shark/>
17  *
18  * Shark is free software: you can redistribute it and/or modify
19  * it under the terms of the GNU Lesser General Public License as published
20  * by the Free Software Foundation, either version 3 of the License, or
21  * (at your option) any later version.
22  *
23  * Shark is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26  * GNU Lesser General Public License for more details.
27  *
28  * You should have received a copy of the GNU Lesser General Public License
29  * along with Shark. If not, see <http://www.gnu.org/licenses/>.
30  *
31  */
32 #ifndef SHARK_MODELS_NORMALIZER_H
33 #define SHARK_MODELS_NORMALIZER_H
34 
36 #include <shark/LinAlg/Base.h>
37 
38 
39 namespace shark {
40 
41 
42 ///
43 /// \brief "Diagonal" linear model for data normalization.
44 ///
45 /// \par
46 /// The Normalizer is a restricted and often more efficient variant of
47 /// the LinearModel class. It restricts the linear model in two respects:
48 /// (1) input and output dimension must agree,
49 /// (2) computations are independent for each component.
50 /// This is useful mostly for data normalization (therefore the name).
51 /// The model's operation is of the form \f$ x \mapsto A x + b \f$ where
52 /// A is a diagonal matrix. This reduces memory requirements to linear,
53 /// which is why there is no sparse version of this model (as opposed to
54 /// the more general linear model). Also, the addition of b is optional.
55 ///
56 template <class DataType = RealVector>
57 class Normalizer : public AbstractModel<DataType, DataType>
58 {
59 public:
62 
65 
66  /// Constructor of an invalid model; use setStructure later
68  { }
69 
70  /// copy constructor
71  Normalizer(const self_type& model)
72  : m_A(model.m_A)
73  , m_b(model.m_b)
74  , m_hasOffset(model.m_hasOffset)
75  { }
76 
77  /// Construction from dimension
78  Normalizer(std::size_t dimension, bool hasOffset = false)
79  : m_A(dimension, dimension)
80  , m_b(dimension)
82  { }
83 
84  /// Construction from matrix
85  Normalizer(RealVector diagonal)
86  : m_A(diagonal)
87  , m_hasOffset(false)
88  { }
89 
90  /// Construction from matrix and vector
91  Normalizer(RealVector diagonal, RealVector vector)
92  : m_A(diagonal)
93  , m_b(vector)
94  , m_hasOffset(true)
95  { }
96 
97 
98  /// \brief From INameable: return the class name.
99  std::string name() const
100  { return "Normalizer"; }
101 
102  /// assignment operator
103  const self_type operator = (const self_type& model)
104  {
105  m_A = model.m_A;
106  m_b = model.m_b;
107  m_hasOffset = model.m_hasOffset;
108  }
109 
110  /// derivative storage object (empty for this model)
111  boost::shared_ptr<State> createState() const
112  {
113  return boost::shared_ptr<State>(new EmptyState());
114  }
115 
116 
117  /// check if the model is properly initialized
118  bool isValid() const
119  {
120  return (m_A.size() != 0);
121  }
122 
123  /// check for the presence of an offset term
124  bool hasOffset() const
125  {
126  return m_hasOffset;
127  }
128 
129  /// return the diagonal of the matrix
130  RealVector const& diagonal() const
131  {
132  SHARK_CHECK(isValid(), "[Normalizer::matrix] model is not initialized");
133  return m_A;
134  }
135 
136  /// return the offset vector
137  RealVector const& offset() const
138  {
139  SHARK_CHECK(isValid(), "[Normalizer::vector] model is not initialized");
140  return m_b;
141  }
142 
143  /// obtain the input dimension
144  std::size_t inputSize() const
145  {
146  SHARK_CHECK(isValid(), "[Normalizer::inputSize] model is not initialized");
147  return m_A.size();
148  }
149 
150  /// obtain the output dimension
151  std::size_t outputSize() const
152  {
153  SHARK_CHECK(isValid(), "[Normalizer::outputSize] model is not initialized");
154  return m_A.size();
155  }
156 
157  /// obtain the parameter vector
158  RealVector parameterVector() const
159  {
160  SHARK_CHECK(isValid(), "[Normalizer::parameterVector] model is not initialized");
161  std::size_t dim = m_A.size();
162  if (hasOffset())
163  {
164  RealVector param(2 * dim);
165  init(param)<<m_A,m_b;
166  return param;
167  }
168  else
169  {
170  RealVector param(dim);
171  init(param)<<m_A;
172  return param;
173  }
174  }
175 
176  /// overwrite the parameter vector
177  void setParameterVector(RealVector const& newParameters)
178  {
179  SHARK_CHECK(isValid(), "[Normalizer::setParameterVector] model is not initialized");
180  std::size_t dim = m_A.size();
181  if (hasOffset())
182  {
183  SIZE_CHECK(newParameters.size() == 2 * dim);
184  init(newParameters)>>m_A,m_b;
185  }
186  else
187  {
188  SIZE_CHECK(newParameters.size() == dim);
189  init(newParameters)>>m_A;
190  }
191  }
192 
193  /// return the number of parameter
194  std::size_t numberOfParameters() const
195  {
196  SHARK_CHECK(isValid(), "[Normalizer::numberOfParameters] model is not initialized");
197  return (m_hasOffset) ? m_A.size() + m_b.size() : m_A.size();
198  }
199 
200  /// overwrite structure and parameters
201  void setStructure(RealVector const& diagonal)
202  {
203  m_A = diagonal;
204  m_hasOffset = false;
205  }
206 
207  /// overwrite structure and parameters
208  void setStructure(std::size_t dimension, bool hasOffset = false)
209  {
210  m_A.resize(dimension);
212  if (hasOffset) m_b.resize(dimension);
213  }
214 
215  /// overwrite structure and parameters
216  void setStructure(RealVector const& diagonal, RealVector const& offset)
217  {
218  SHARK_CHECK(diagonal.size() == offset.size(), "[Normalizer::setStructure] dimension conflict");
219  m_A = diagonal;
220  m_b = offset;
221  m_hasOffset = true;
222  }
223 
224  using base_type::eval;
225 
226  /// \brief Evaluate the model: output = matrix * input + offset.
227  void eval(BatchInputType const& input, BatchOutputType& output) const
228  {
229  SHARK_CHECK(isValid(), "[Normalizer::eval] model is not initialized");
230  output.resize(input.size1(), input.size2());
231  noalias(output) = input * repeat(m_A,input.size1());
232  if (hasOffset())
233  {
234  noalias(output) += repeat(m_b,input.size1());
235  }
236  }
237 
238  /// \brief Evaluate the model: output = matrix * input + offset.
239  void eval(BatchInputType const& input, BatchOutputType& output, State& state) const
240  {
241  eval(input, output);
242  }
243 
244  /// from ISerializable
245  void read(InArchive& archive)
246  {
247  archive & m_A;
248  archive & m_b;
249  archive & m_hasOffset;
250  }
251 
252  /// from ISerializable
253  void write(OutArchive& archive) const
254  {
255  archive & m_A;
256  archive & m_b;
257  archive & m_hasOffset;
258  }
259 
260 protected:
261  RealVector m_A; ///< matrix A (see class documentation)
262  RealVector m_b; ///< vector b (see class documentation)
263  bool m_hasOffset; ///< if true: add offset therm b; if false: don't.
264 };
265 
266 
267 }
268 #endif