tesseract  4.00.00dev
plumbing.cpp
Go to the documentation of this file.
1 // File: plumbing.cpp
3 // Description: Base class for networks that organize other networks
4 // eg series or parallel.
5 // Author: Ray Smith
6 // Created: Mon May 12 08:17:34 PST 2014
7 //
8 // (C) Copyright 2014, Google Inc.
9 // Licensed under the Apache License, Version 2.0 (the "License");
10 // you may not use this file except in compliance with the License.
11 // You may obtain a copy of the License at
12 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 
20 #include "plumbing.h"
21 
22 namespace tesseract {
23 
24 // ni_ and no_ will be set by AddToStack.
26  : Network(NT_PARALLEL, name, 0, 0) {
27 }
28 
30 }
31 
32 // Suspends/Enables training by setting the training_ flag. Serialize and
33 // DeSerialize only operate on the run-time data if state is false.
36  for (int i = 0; i < stack_.size(); ++i)
37  stack_[i]->SetEnableTraining(state);
38 }
39 
40 // Sets flags that control the action of the network. See NetworkFlags enum
41 // for bit values.
44  for (int i = 0; i < stack_.size(); ++i)
45  stack_[i]->SetNetworkFlags(flags);
46 }
47 
48 // Sets up the network for training. Initializes weights using weights of
49 // scale `range` picked according to the random number generator `randomizer`.
50 // Note that randomizer is a borrowed pointer that should outlive the network
51 // and should not be deleted by any of the networks.
52 // Returns the number of weights initialized.
53 int Plumbing::InitWeights(float range, TRand* randomizer) {
54  num_weights_ = 0;
55  for (int i = 0; i < stack_.size(); ++i)
56  num_weights_ += stack_[i]->InitWeights(range, randomizer);
57  return num_weights_;
58 }
59 
60 // Converts a float network to an int network.
62  for (int i = 0; i < stack_.size(); ++i)
63  stack_[i]->ConvertToInt();
64 }
65 
66 // Provides a pointer to a TRand for any networks that care to use it.
67 // Note that randomizer is a borrowed pointer that should outlive the network
68 // and should not be deleted by any of the networks.
69 void Plumbing::SetRandomizer(TRand* randomizer) {
70  for (int i = 0; i < stack_.size(); ++i)
71  stack_[i]->SetRandomizer(randomizer);
72 }
73 
74 // Adds the given network to the stack.
75 void Plumbing::AddToStack(Network* network) {
76  if (stack_.empty()) {
77  ni_ = network->NumInputs();
78  no_ = network->NumOutputs();
79  } else if (type_ == NT_SERIES) {
80  // ni is input of first, no output of last, others match output to input.
81  ASSERT_HOST(no_ == network->NumInputs());
82  no_ = network->NumOutputs();
83  } else {
84  // All parallel types. Output is sum of outputs, inputs all match.
85  ASSERT_HOST(ni_ == network->NumInputs());
86  no_ += network->NumOutputs();
87  }
88  stack_.push_back(network);
89 }
90 
91 // Sets needs_to_backprop_ to needs_backprop and calls on sub-network
92 // according to needs_backprop || any weights in this network.
93 bool Plumbing::SetupNeedsBackprop(bool needs_backprop) {
94  if (IsTraining()) {
95  needs_to_backprop_ = needs_backprop;
96  bool retval = needs_backprop;
97  for (int i = 0; i < stack_.size(); ++i) {
98  if (stack_[i]->SetupNeedsBackprop(needs_backprop)) retval = true;
99  }
100  return retval;
101  }
102  // Frozen networks don't do backprop.
103  needs_to_backprop_ = false;
104  return false;
105 }
106 
107 // Returns an integer reduction factor that the network applies to the
108 // time sequence. Assumes that any 2-d is already eliminated. Used for
109 // scaling bounding boxes of truth data.
110 // WARNING: if GlobalMinimax is used to vary the scale, this will return
111 // the last used scale factor. Call it before any forward, and it will return
112 // the minimum scale factor of the paths through the GlobalMinimax.
114  return stack_[0]->XScaleFactor();
115 }
116 
117 // Provides the (minimum) x scale factor to the network (of interest only to
118 // input units) so they can determine how to scale bounding boxes.
119 void Plumbing::CacheXScaleFactor(int factor) {
120  for (int i = 0; i < stack_.size(); ++i) {
121  stack_[i]->CacheXScaleFactor(factor);
122  }
123 }
124 
125 // Provides debug output on the weights.
127  for (int i = 0; i < stack_.size(); ++i)
128  stack_[i]->DebugWeights();
129 }
130 
131 // Returns a set of strings representing the layer-ids of all layers below.
133  GenericVector<STRING>* layers) const {
134  for (int i = 0; i < stack_.size(); ++i) {
135  STRING layer_name;
136  if (prefix) layer_name = *prefix;
137  layer_name.add_str_int(":", i);
138  if (stack_[i]->IsPlumbingType()) {
139  Plumbing* plumbing = static_cast<Plumbing*>(stack_[i]);
140  plumbing->EnumerateLayers(&layer_name, layers);
141  } else {
142  layers->push_back(layer_name);
143  }
144  }
145 }
146 
147 // Returns a pointer to the network layer corresponding to the given id.
148 Network* Plumbing::GetLayer(const char* id) const {
149  char* next_id;
150  int index = strtol(id, &next_id, 10);
151  if (index < 0 || index >= stack_.size()) return NULL;
152  if (stack_[index]->IsPlumbingType()) {
153  Plumbing* plumbing = static_cast<Plumbing*>(stack_[index]);
154  ASSERT_HOST(*next_id == ':');
155  return plumbing->GetLayer(next_id + 1);
156  }
157  return stack_[index];
158 }
159 
160 // Returns a pointer to the learning rate for the given layer id.
161 float* Plumbing::LayerLearningRatePtr(const char* id) const {
162  char* next_id;
163  int index = strtol(id, &next_id, 10);
164  if (index < 0 || index >= stack_.size()) return NULL;
165  if (stack_[index]->IsPlumbingType()) {
166  Plumbing* plumbing = static_cast<Plumbing*>(stack_[index]);
167  ASSERT_HOST(*next_id == ':');
168  return plumbing->LayerLearningRatePtr(next_id + 1);
169  }
170  if (index < 0 || index >= learning_rates_.size()) return NULL;
171  return &learning_rates_[index];
172 }
173 
174 // Writes to the given file. Returns false in case of error.
175 bool Plumbing::Serialize(TFile* fp) const {
176  if (!Network::Serialize(fp)) return false;
177  inT32 size = stack_.size();
178  // Can't use PointerVector::Serialize here as we need a special DeSerialize.
179  if (fp->FWrite(&size, sizeof(size), 1) != 1) return false;
180  for (int i = 0; i < size; ++i)
181  if (!stack_[i]->Serialize(fp)) return false;
183  !learning_rates_.Serialize(fp)) {
184  return false;
185  }
186  return true;
187 }
188 
189 // Reads from the given file. Returns false in case of error.
191  stack_.truncate(0);
192  no_ = 0; // We will be modifying this as we AddToStack.
193  inT32 size;
194  if (fp->FReadEndian(&size, sizeof(size), 1) != 1) return false;
195  for (int i = 0; i < size; ++i) {
196  Network* network = CreateFromFile(fp);
197  if (network == NULL) return false;
198  AddToStack(network);
199  }
202  return false;
203  }
204  return true;
205 }
206 
207 // Updates the weights using the given learning rate and momentum.
208 // num_samples is the quotient to be used in the adagrad computation iff
209 // use_ada_grad_ is true.
210 void Plumbing::Update(float learning_rate, float momentum, int num_samples) {
211  for (int i = 0; i < stack_.size(); ++i) {
213  if (i < learning_rates_.size())
214  learning_rate = learning_rates_[i];
215  else
216  learning_rates_.push_back(learning_rate);
217  }
218  if (stack_[i]->IsTraining()) {
219  stack_[i]->Update(learning_rate, momentum, num_samples);
220  }
221  }
222 }
223 
224 // Sums the products of weight updates in *this and other, splitting into
225 // positive (same direction) in *same and negative (different direction) in
226 // *changed.
227 void Plumbing::CountAlternators(const Network& other, double* same,
228  double* changed) const {
229  ASSERT_HOST(other.type() == type_);
230  const Plumbing* plumbing = static_cast<const Plumbing*>(&other);
231  ASSERT_HOST(plumbing->stack_.size() == stack_.size());
232  for (int i = 0; i < stack_.size(); ++i)
233  stack_[i]->CountAlternators(*plumbing->stack_[i], same, changed);
234 }
235 
236 } // namespace tesseract.
237 
bool DeSerialize(bool swap, FILE *fp)
void add_str_int(const char *str, int number)
Definition: strngs.cpp:381
bool needs_to_backprop_
Definition: network.h:287
float * LayerLearningRatePtr(const char *id) const
Definition: plumbing.cpp:161
int32_t inT32
Definition: host.h:38
virtual void Update(float learning_rate, float momentum, int num_samples)
Definition: plumbing.cpp:210
voidpf void uLong size
Definition: ioapi.h:39
Plumbing(const STRING &name)
Definition: plumbing.cpp:25
virtual int InitWeights(float range, TRand *randomizer)
Definition: plumbing.cpp:53
NetworkType type() const
Definition: network.h:112
int push_back(T object)
Network * GetLayer(const char *id) const
Definition: plumbing.cpp:148
static Network * CreateFromFile(TFile *fp)
Definition: network.cpp:203
virtual void SetNetworkFlags(uinT32 flags)
Definition: plumbing.cpp:42
virtual void CacheXScaleFactor(int factor)
Definition: plumbing.cpp:119
bool IsTraining() const
Definition: network.h:115
int FReadEndian(void *buffer, int size, int count)
Definition: serialis.cpp:97
int size() const
Definition: genericvector.h:72
TrainingState
Definition: network.h:92
virtual bool DeSerialize(TFile *fp)
Definition: plumbing.cpp:190
#define ASSERT_HOST(x)
Definition: errcode.h:84
virtual void SetNetworkFlags(uinT32 flags)
Definition: network.cpp:126
virtual void SetEnableTraining(TrainingState state)
Definition: plumbing.cpp:34
inT32 network_flags_
Definition: network.h:288
virtual bool SetupNeedsBackprop(bool needs_backprop)
Definition: plumbing.cpp:93
uint32_t uinT32
Definition: host.h:39
PointerVector< Network > stack_
Definition: plumbing.h:133
Definition: strngs.h:45
virtual int XScaleFactor() const
Definition: plumbing.cpp:113
virtual void SetRandomizer(TRand *randomizer)
Definition: plumbing.cpp:69
virtual void ConvertToInt()
Definition: plumbing.cpp:61
virtual bool IsPlumbingType() const
Definition: plumbing.h:44
int FWrite(const void *buffer, int size, int count)
Definition: serialis.cpp:148
NetworkType type_
Definition: network.h:285
virtual void DebugWeights()
Definition: plumbing.cpp:126
int NumInputs() const
Definition: network.h:120
bool Serialize(FILE *fp) const
GenericVector< float > learning_rates_
Definition: plumbing.h:136
int NumOutputs() const
Definition: network.h:123
virtual bool Serialize(TFile *fp) const
Definition: network.cpp:153
void EnumerateLayers(const STRING *prefix, GenericVector< STRING > *layers) const
Definition: plumbing.cpp:132
inT32 num_weights_
Definition: network.h:291
virtual void CountAlternators(const Network &other, double *same, double *changed) const
Definition: plumbing.cpp:227
virtual ~Plumbing()
Definition: plumbing.cpp:29
virtual void SetEnableTraining(TrainingState state)
Definition: network.cpp:112
virtual void AddToStack(Network *network)
Definition: plumbing.cpp:75
virtual bool Serialize(TFile *fp) const
Definition: plumbing.cpp:175