Line data Source code
1 : #pragma once 2 : 3 : #include <string> 4 : #include <vector> 5 : #include <memory> 6 : #include <ostream> 7 : #include <iomanip> 8 : 9 : #include "elsaDefines.h" 10 : #include "VolumeDescriptor.h" 11 : #include "Common.h" 12 : #include "State.h" 13 : #include "DataContainer.h" 14 : 15 : namespace elsa::ml 16 : { 17 : /// Base class for all layers in a network 18 : /// 19 : /// @author David Tellenbach 20 : template <typename data_t = real_t> 21 : class Layer 22 : { 23 : public: 24 : Layer() = default; 25 : 26 : /** 27 : * Construct a layer 28 : * 29 : * @param layerType the type of the layer 30 : * @param requiredNumberOfDimensions the required number of 31 : * dimensions any input to this layer has. This can be set 32 : * to Layer::AnyNumberOfInputDimensions to indicate that the 33 : * number of input dimensions is not restricted. 34 : * @param allowedNumberOfInputs the allowed number of inputs to 35 : * this layer. This can be set to Layer::AnyNumberOfInputs 36 : * to indicate that the layer accepts an arbitrary number of 37 : * inputs. 38 : */ 39 : Layer(LayerType layerType, const std::string& name, 40 : int requiredNumberOfDimensions = Layer::AnyNumberOfInputDimensions, 41 : int allowedNumberOfInputs = Layer::AnyNumberOfInputs, bool isTrainable = false); 42 : 43 : /// Copy constructor 44 : Layer(const Layer&); 45 : 46 : /// Move constructor 47 : Layer(Layer&&) = default; 48 : 49 : /// Copy-assignment operator 50 : Layer& operator=(const Layer&); 51 : 52 : /// Move assignment operator 53 : Layer& operator=(Layer&&) = default; 54 : 55 : /// Destructor 56 9 : virtual ~Layer() = default; 57 : 58 : /// @returns this layer's layer-type 59 : LayerType getLayerType() const; 60 : 61 : /// @returns this layer's name 62 : std::string getName() const; 63 : 64 : /// set the layer's input descriptor at a given index 65 : void setInputDescriptor(const VolumeDescriptor&); 66 : 67 : /// @returns this layer's input descriptor at a given index 68 : VolumeDescriptor getInputDescriptor(index_t index = 0) const; 69 : 70 : /// @returns the number of inputs of this layer 71 : index_t getNumberOfInputs() const; 72 : 73 : /// @returns the layer's output descriptor 74 : VolumeDescriptor getOutputDescriptor() const; 75 : 76 : /// @returns the layer's unique global index 77 : index_t getGlobalIndex() const; 78 : 79 : /// Set this layer's input. 80 : void setInput(Layer* layer); 81 : 82 : /// Set his layer's input. 83 : void setInput(std::initializer_list<Layer*>); 84 : 85 : /// Compute this layer's output descriptor. 86 : virtual void computeOutputDescriptor(); 87 : 88 : /// @returns true of a layer is trainable and false otherwise 89 : bool isTrainable() const; 90 : 91 : /// @returns true of a layer can merge multiple inputs and false otherwise 92 : virtual bool canMerge() const; 93 : 94 : /// @returns the number of trainable parameters 95 : index_t getNumberOfTrainableParameters() const; 96 : 97 : template <typename T> 98 : friend std::ostream& operator<<(std::ostream& os, const Layer<T>& layer); 99 : 100 : protected: 101 : /// check if the number of dimensions of the layer's input descriptor matches the 102 : /// required number of dimensions 103 : void checkNumberOfInputDimensions(const VolumeDescriptor&) const; 104 : 105 : static constexpr int AnyNumberOfInputDimensions = -1; 106 : static constexpr int AnyNumberOfInputs = -1; 107 : 108 : int requiredNumberOfDimensions_; 109 : int allowedNumberOfInputs_; 110 : 111 : index_t globalIndex_; 112 : LayerType layerType_; 113 : 114 : std::string name_; 115 : 116 : index_t numberOfTrainableParameters_; 117 : 118 : // A layer can have more than one input (e.g. any merging layer) but has 119 : // always a single well-defined output descriptor that in general depend 120 : // on the input descriptors 121 : std::vector<std::unique_ptr<DataDescriptor>> inputDescriptors_; 122 : std::unique_ptr<DataDescriptor> outputDescriptor_; 123 : 124 : bool isTrainable_; 125 : 126 : private: 127 : static index_t staticGlobalIndex_; 128 : }; 129 : 130 : template <typename data_t> 131 : index_t Layer<data_t>::staticGlobalIndex_{0}; 132 : 133 : template <typename T> 134 : std::ostream& operator<<(std::ostream& os, const Layer<T>& layer) 135 : { 136 : std::stringstream ss; 137 : 138 : // Name and layer-type 139 : std::string description = 140 : layer.getName() + " (" + detail::getEnumMemberAsString(layer.getLayerType()) + ")"; 141 : os << std::left << std::setw(35) << description; 142 : 143 : // output-shape 144 : Eigen::IOFormat fmt(Eigen::StreamPrecision, 0, ", ", ", ", "", "", "(", ")"); 145 : ss << layer.getOutputDescriptor().getNumberOfCoefficientsPerDimension().format(fmt); 146 : std::string outputShape = ss.str(); 147 : os << std::left << std::setw(20) << outputShape; 148 : 149 : // number of parameters 150 : os << std::left << std::setw(10) << layer.getNumberOfTrainableParameters(); 151 : 152 : return os; 153 : } 154 : 155 : } // namespace elsa::ml