OnlineRNNet.h
Go to the documentation of this file.
1 //===========================================================================
2 /*!
3  *
4  *
5  * \brief Offers the functions to create and to work with a
6  * recurrent neural network.
7  *
8  *
9  *
10  * \author O. Krause
11  * \date 2010
12  *
13  *
14  * \par Copyright 1995-2017 Shark Development Team
15  *
16  * <BR><HR>
17  * This file is part of Shark.
18  * <http://shark-ml.org/>
19  *
20  * Shark is free software: you can redistribute it and/or modify
21  * it under the terms of the GNU Lesser General Public License as published
22  * by the Free Software Foundation, either version 3 of the License, or
23  * (at your option) any later version.
24  *
25  * Shark is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28  * GNU Lesser General Public License for more details.
29  *
30  * You should have received a copy of the GNU Lesser General Public License
31  * along with Shark. If not, see <http://www.gnu.org/licenses/>.
32  *
33  */
34 #ifndef SHARK_MODELS_ONLINERNNET_H
35 #define SHARK_MODELS_ONLINERNNET_H
36 
37 #include <shark/Core/DLLSupport.h>
40 namespace shark{
41 
42 //! \brief A recurrent neural network regression model optimized
43 //! for online learning.
44 //!
45 //! The OnlineRNNet can only process a single input at a time. Internally
46 //! it stores the last activation as well as the derivatives which get updated
47 //! over the course of the sequence. Instead of feeding in the whole sequence,
48 //! the inputs must be given one after another. However if the whole sequence is
49 //! available in advance, this implementation is not advisable, since it is a lot slower
50 //! than RNNet which is targeted to whole sequences.
51 //!
52 //! All network state is stored in the State structure which can be created by createState()
53 //! which has to be supplied to eval.
54 //! A new time sequence is started by generating a new state object.
55 //! When the network is created the user has to decide whether gradients
56 //! are needed. In this case additional ressources are allocated in the state object on creation
57 //! and eval makes sure that the gradient is properly updated between steps, this is costly.
58 //! It is possible to skip steps updating the parameters, e.g. when no reward signal is available.
59 //!
60 //! Note that eval can only work with batches of size one and eval without a state object can not
61 //! be called.
62 class OnlineRNNet:public AbstractModel<RealVector,RealVector>
63 {
64 private:
65  struct InternalState: public State{
66 
67  InternalState(RecurrentStructure const& structure)
68  : activation(structure.numberOfUnits(),0.0)
69  , lastActivation(structure.numberOfUnits(),0.0)
70  , unitGradient(structure.parameters(),structure.numberOfNeurons(),0.0){}
71  //!the activation of the network at time t (after evaluation)
72  RealVector activation;
73  //!the activation of the network at time t-1 (before evaluation)
74  RealVector lastActivation;
75 
76  //!\brief the gradient of the hidden units with respect to every weight
77  //!
78  //!The gradient \f$ \frac{\delta y_k(t)}{\delta w_{ij}} \f$ is stored in this
79  //!structure. Using this gradient, the derivative of the Network can be calculated as
80  //!\f[ \frac{\delta E(y(t))}{\delta w_{ij}}=\sum_{k=1}^n\frac{\delta E(y(t))}{\delta y_k} \frac{\delta y_k(t)}{\delta w_{ij}} \f]
81  //!where \f$ y_k(t) \f$ is the activation of neuron \f$ k \f$ at timestep \f$ t \f$
82  //!the gradient needs to be updated after every timestep using the formula
83  //!\f[ \frac{\delta y_k(t+1)}{\delta w_{ij}}= y'_k(t)= \left[\sum_{l=1}^n w_{il}\frac{\delta y_l(t)}{\delta w_{ij}} +\delta_{kl}y_l(t-1)\right]\f]
84  //!so if the gradient is needed, don't forget to call weightedParameterDerivative at every timestep!
85  RealMatrix unitGradient;
86  };
87 public:
88  //! creates a configured neural network
89  //!
90  //! \brief structure The structure of the OnlineRNNet
91  //! \brief computeGradient Whether the network will be used to compute gradients
92  SHARK_EXPORT_SYMBOL OnlineRNNet(RecurrentStructure* structure, bool computeGradient);
93 
94  /// \brief From INameable: return the class name.
95  std::string name() const
96  { return "OnlineRNNet"; }
97 
98  //! \brief Feeds a timestep of a time series to the model and
99  //! calculates it's output. The batches must have size 1.
100  //!
101  //! \param pattern Input patterns for the network.
102  //! \param output Used to store the outputs of the network.
103  //! \param state the current state of the RNN that is updated by eval
104  SHARK_EXPORT_SYMBOL void eval(RealMatrix const& pattern,RealMatrix& output, State& state)const;
105 
106 
107  /// \brief It is forbidding to call eval without a state object.
108  SHARK_EXPORT_SYMBOL void eval(RealMatrix const& pattern,RealMatrix& output)const{
109  throw SHARKEXCEPTION("[OnlineRNNet::eval] Eval can not be called without state object");
110  }
112 
113  /// obtain the input dimension
114  std::size_t inputSize() const{
115  return mpe_structure->inputs();
116  }
117 
118  /// obtain the output dimension
119  std::size_t outputSize() const{
120  return mpe_structure->outputs();
121  }
122 
123  //!\brief calculates the weighted sum of gradients w.r.t the parameters
124  //!
125  //!Uses an iterative update scheme to calculate the gradient at timestep t from the gradient
126  //!at timestep t-1 using forward propagation. This Methods requires O(n^3) Memory and O(n^4) computations,
127  //!where n is the number of neurons. So if the network is very large, RNNet should be used!
128  //!
129  //! \param pattern the pattern to evaluate
130  //! \param coefficients the oefficients which are used to calculate the weighted sum
131  //! \param gradient the calculated gradient
132  //! \param state the current state of the RNN
134  RealMatrix const& pattern, RealMatrix const& coefficients,
135  State const& state, RealVector& gradient
136  )const;
137 
138  //! get internal parameters of the model
139  RealVector parameterVector() const{
140  return mpe_structure->parameterVector();
141  }
142  //! set internal parameters of the model
143  void setParameterVector(RealVector const& newParameters){
144  mpe_structure->setParameterVector(newParameters);
145  }
146 
147  //!number of parameters of the network
148  std::size_t numberOfParameters() const{
149  return mpe_structure->parameters();
150  }
151 
152  boost::shared_ptr<State> createState()const{
153  return boost::shared_ptr<State>(new InternalState( *mpe_structure));
154  }
155 
156 
157  //! \brief This Method sets the activation of the output neurons
158  //!
159  //! This is usefull when teacher forcing is used. When the network
160  //! is trained to predict a timeseries and diverges from the sequence
161  //! at an early stage, the resulting gradient might not be very helpfull.
162  //! In this case, teacher forcing can be applied to prevent diverging.
163  //! However, the network might become unstable, when teacher-forcing is turned off
164  //! because there is no force which prevents it from diverging anymore.
165  //!
166  //! \param state The current state of the network
167  //! \param activation Input patterns for the network.
168  void setOutputActivation(State& state, RealVector const& activation){
169  InternalState& s = state.toState<InternalState>();
170  s.activation.resize(mpe_structure->numberOfUnits());
171  subrange(s.activation,mpe_structure->numberOfUnits()-outputSize(),mpe_structure->numberOfUnits()) = activation;
172  }
173 
174 
175 
176 protected:
177 
178  //! the topology of the network.
180 
181  //! stores whether the network should compute a gradient
183 
184 };
185 }
186 
187 #endif //RNNET_H
188 
189 
190 
191 
192 
193 
194 
195 
196