Tenncor
conv.hpp
Go to the documentation of this file.
1 
9 #include "eteq/generated/api.hpp"
10 
11 #include "layr/layer.hpp"
12 
13 #ifndef LAYR_CONV_HPP
14 #define LAYR_CONV_HPP
15 
16 namespace layr
17 {
18 
20 const std::string conv_weight_key = "weight";
21 
23 const std::string conv_bias_key = "bias";
24 
26 struct ConvBuilder final : public iLayerBuilder
27 {
28  ConvBuilder (std::string label) : label_(label) {}
29 
31  void set_tensor (teq::TensptrT tens, std::string target) override
32  {
33  if (target == conv_weight_key)
34  {
36  return;
37  }
38  else if (target == conv_bias_key)
39  {
41  return;
42  }
43  logs::warnf("attempt to create convolution layer "
44  "with unknown tensor `%s` of label `%s`",
45  tens->to_string().c_str(), target.c_str());
46  }
47 
49  void set_sublayer (LayerptrT layer) override {} // dense has no sublayer
50 
52  LayerptrT build (void) const override;
53 
54 private:
55  NodeptrT weight_ = nullptr;
56 
57  NodeptrT bias_ = nullptr;
58 
59  std::string label_;
60 };
61 
63 const std::string conv_layer_key =
65 [](std::string label) -> LBuilderptrT
66 {
67  return std::make_shared<ConvBuilder>(label);
68 });
69 
71 struct Conv final : public iLayer
72 {
73  Conv (std::pair<teq::DimT,teq::DimT> filter_hw,
74  teq::DimT in_ncol, teq::DimT out_ncol,
75  const std::string& label) :
76  label_(label)
77  {
78  teq::Shape kernelshape({out_ncol, in_ncol,
79  filter_hw.second, filter_hw.first});
80  size_t ndata = kernelshape.n_elems();
81 
82  size_t input_size = filter_hw.first * filter_hw.second * in_ncol;
83  PybindT bound = 1. / std::sqrt(input_size);
84  std::uniform_real_distribution<PybindT> dist(-bound, bound);
85  auto gen = [&dist]()
86  {
87  return dist(eteq::get_engine());
88  };
89  std::vector<PybindT> data(ndata);
90  std::generate(data.begin(), data.end(), gen);
91 
92  weight_ = eteq::make_variable<PybindT>(
93  data.data(), kernelshape, conv_weight_key);
94  bias_ = eteq::make_variable_scalar<PybindT>(
95  0., teq::Shape({out_ncol}), conv_bias_key);
96  tag(weight_->get_tensor(), LayerId(conv_weight_key));
97  tag(bias_->get_tensor(), LayerId(conv_bias_key));
98  }
99 
100  Conv (NodeptrT weight, NodeptrT bias, std::string label) :
101  label_(label),
102  weight_(weight),
103  bias_(bias)
104  {
105  tag(weight_->get_tensor(), LayerId(conv_weight_key));
106  if (bias)
107  {
108  tag(bias_->get_tensor(), LayerId(conv_bias_key));
109  }
110  }
111 
112  Conv (const Conv& other,
113  std::string label_prefix = "")
114  {
115  copy_helper(other, label_prefix);
116  }
117 
118  Conv& operator = (const Conv& other)
119  {
120  if (this != &other)
121  {
122  copy_helper(other);
123  }
124  return *this;
125  }
126 
127  Conv (Conv&& other) = default;
128 
129  Conv& operator = (Conv&& other) = default;
130 
132  Conv* clone (std::string label_prefix = "") const
133  {
134  return static_cast<Conv*>(this->clone_impl(label_prefix));
135  }
136 
138  size_t get_ninput (void) const override
139  {
140  return weight_->shape().at(1);
141  }
142 
144  size_t get_noutput (void) const override
145  {
146  return weight_->shape().at(0);
147  }
148 
150  std::string get_ltype (void) const override
151  {
152  return conv_layer_key;
153  }
154 
156  std::string get_label (void) const override
157  {
158  return label_;
159  }
160 
162  teq::TensptrsT get_contents (void) const override
163  {
164  return {
165  weight_->get_tensor(),
166  nullptr == bias_ ? nullptr : bias_->get_tensor(),
167  };
168  }
169 
171  NodeptrT connect (NodeptrT input) const override
172  {
173  auto out = tenncor::nn::conv2d(input, weight_);
174  teq::TensSetT leaves = {
175  input->get_tensor().get(),
176  weight_->get_tensor().get(),
177  };
178  if (bias_)
179  {
180  teq::Shape outshape = out->shape();
181  out = out + tenncor::extend(bias_, 1, {
182  outshape.at(1), outshape.at(2), outshape.at(3)});
183  leaves.emplace(bias_->get_tensor().get());
184  }
185  recursive_tag(out->get_tensor(), leaves, LayerId());
186  return out;
187  }
188 
189 private:
190  iLayer* clone_impl (const std::string& label_prefix) const override
191  {
192  return new Conv(*this, label_prefix);
193  }
194 
195  void copy_helper (const Conv& other, std::string label_prefix = "")
196  {
197  label_ = label_prefix + other.label_;
198  weight_ = NodeptrT(other.weight_->clone());
199  tag(weight_->get_tensor(), LayerId(conv_weight_key));
200  if (other.bias_)
201  {
202  bias_ = NodeptrT(other.bias_->clone());
203  tag(bias_->get_tensor(), LayerId(conv_bias_key));
204  }
205  }
206 
207  std::string label_;
208 
210 
211  NodeptrT bias_ = nullptr;
212 };
213 
215 using ConvptrT = std::shared_ptr<Conv>;
216 
217 }
218 
219 #endif // LAYR_CONV_HPP
std::unordered_set< teq::iTensor * > TensSetT
Hash set of raw tensor pointers.
Definition: itensor.hpp:63
Conv(std::pair< teq::DimT, teq::DimT > filter_hw, teq::DimT in_ncol, teq::DimT out_ncol, const std::string &label)
Definition: conv.hpp:73
std::string label_
Definition: conv.hpp:207
Layer implementation to apply conv2d functions to weight and optional bias.
Definition: conv.hpp:71
LayerRegistry & get_layer_reg(void)
Return global layer registry reference.
CoordptrT extend(teq::RankT rank, std::vector< teq::DimT > ext)
Return CoordMap wrapper of extension parameters.
const std::string conv_bias_key
Convolutional bias label.
Definition: conv.hpp:23
iLayer * clone_impl(const std::string &label_prefix) const override
Definition: conv.hpp:190
static NodeptrT< T > to_node(teq::TensptrT tens)
Return node associated with tensor type.
Definition: inode.hpp:81
EigenptrT< T > sqrt(teq::Shape &outshape, const OpArg< T > &in)
Definition: operator.hpp:427
ConvBuilder(std::string label)
Definition: conv.hpp:28
std::string register_tagr(std::string key, LayerBuildF builder)
Definition: layer.hpp:198
Definition: shape.hpp:62
NodeptrT connect(NodeptrT input) const override
Implementation of iLayer.
Definition: conv.hpp:171
void recursive_tag(teq::TensptrT root, teq::TensSetT ignores, LayerId subs) const
Definition: conv.hpp:16
Conv * clone(std::string label_prefix="") const
Return deep copy of this layer with prefixed label.
Definition: conv.hpp:132
std::shared_ptr< iLayerBuilder > LBuilderptrT
Layer builder smart pointer.
Definition: layer.hpp:179
void set_sublayer(LayerptrT layer) override
Implementation of iLayerBuilder.
Definition: conv.hpp:49
std::string get_label(void) const override
Implementation of iLayer.
Definition: conv.hpp:156
Builder implementation for convolution layer.
Definition: conv.hpp:26
NodeptrT bias_
Definition: conv.hpp:57
size_t get_noutput(void) const override
Implementation of iLayer.
Definition: conv.hpp:144
std::shared_ptr< Conv > ConvptrT
Smart pointer of convolutional layer.
Definition: conv.hpp:215
NodeptrT bias_
Definition: conv.hpp:211
NodeptrT weight_
Definition: conv.hpp:55
const std::string layers_key_prefix
String prefixed to every layer key.
Definition: layer.hpp:25
Definition: layer.hpp:164
const std::string conv_layer_key
Identifier for convolutional layer.
Definition: conv.hpp:63
teq::TensptrsT get_contents(void) const override
Implementation of iLayer.
Definition: conv.hpp:162
NodeptrT weight_
Definition: conv.hpp:209
const std::string conv_weight_key
Convolutional weight label.
Definition: conv.hpp:20
LayerptrT build(void) const override
Implementation of iLayerBuilder.
Definition: conv.cpp:8
void copy_helper(const Conv &other, std::string label_prefix="")
Definition: conv.hpp:195
void tag(teq::TensptrT tensor, LayerId subs) const
std::shared_ptr< iTensor > TensptrT
Tensor smart pointer.
Definition: itensor.hpp:51
std::vector< TensptrT > TensptrsT
Vector of tensor smart pointers.
Definition: itensor.hpp:60
Sublayer type, label, and index encapsulation.
Definition: layer.hpp:35
size_t get_ninput(void) const override
Implementation of iLayer.
Definition: conv.hpp:138
uint16_t DimT
Type used for shape dimension.
Definition: shape.hpp:31
std::string label_
Definition: conv.hpp:59
Conv(const Conv &other, std::string label_prefix="")
Definition: conv.hpp:112
Conv(NodeptrT weight, NodeptrT bias, std::string label)
Definition: conv.hpp:100
std::shared_ptr< iNode< T > > NodeptrT
Smart pointer of node.
Definition: inode.hpp:63
void set_tensor(teq::TensptrT tens, std::string target) override
Implementation of iLayerBuilder.
Definition: conv.hpp:31
std::string get_ltype(void) const override
Implementation of iLayer.
Definition: conv.hpp:150
DimT at(RankT idx) const
Return DimT element at idx for any index in range [0:rank_cap)
Definition: shape.hpp:108
std::shared_ptr< iLayer > LayerptrT
Smart pointer of layer.
Definition: layer.hpp:159
EngineT & get_engine(void)
Return global random generator.
NElemT n_elems(void) const
Return the total number of elements represented by the shape.
Definition: shape.hpp:118
Definition: layer.hpp:121
Conv & operator=(const Conv &other)
Definition: conv.hpp:118