std::numeric_limits<float>::max()),
intRand(static_cast<int32_t>(OpCodes::opFirst),
static_cast<int32_t>(OpCodes::opLast)),
- operatorCounts{0},
- opCreators{
- [this](int input_tensor_id) { createLayerCONV_2D(input_tensor_id);},
- } {};
+ operatorCounts{0} {
+ opCreators[static_cast<int>(OpCodes::opConv2d)] =
+ [this](treebuilder::Tree* t, treebuilder::Operation* op) {
+ createLayerCONV_2D(t, op);
+ };
+ };
virtual ~RandomModelBuilder() = default;
- /**
- * @brief createLayerXXX are creator for operators.
- * @param input_tensor_id is id of input tensor.
- */
- virtual void createLayerCONV_2D(int input_tensor_id) = 0;
+ virtual void convertTreeToModel(treebuilder::Tree* t) = 0;
/**
- * @brief addInput does add input tensor to model.
- * @return status of adding.
- */
- virtual bool addInput() = 0;
- /**
- * @brief addLayer does add a new layer to model.
- * @return status of adding.
- */
- virtual bool addLayer() = 0;
- /**
* @brief getModelSaver does create unique_ptr to ModelSaver.
* @return unique_ptr to ModelSaver.
*/
/**
* @brief operatorCounts this array contains amount of used operators in generated model.
- * @details For example: operatorCounts[Op_CONV_2D] -- amount of used 2D convolution operators.
+ * @details For example: operatorCounts[OpCodes::opConv2d] -- amount of used 2D convolution operators.
*/
int operatorCounts[static_cast<int32_t>(OpCodes::opCount)];
/**
* @brief opCreators this array contains a lambda with call of method
* for building specified operator.
- * @details This array are used for convenient creation random operators,
- * like follow: opCreators[rand()%OpCodes::OpCnt]
- * For example: opCreators[Op_CONV_2D](0) -- will lead to call createLayerCONV_2D method.
+ * @details This array is used for convenient creation random operators,
+ * like follow: opCreators[OpCodes::opCount]
+ * For example: opCreators[OpCodes::opConv2d](0) -- will lead to call createLayerCONV_2D method.
*/
- std::function<void(int)> opCreators[static_cast<int32_t>(OpCodes::opCount)];
-};
+ std::function<void(treebuilder::Tree*, treebuilder::Operation*)>
+ opCreators[static_cast<int32_t>(OpCodes::opCount)];
+ /**
+ * @Brief createInput does add input tensor to model.
+ */
+ virtual void createInput(treebuilder::Tree* t) = 0;
+ /**
+ * @brief addOperator does add a new layer to model.
+ */
+ virtual void addOperator(treebuilder::Tree* t, treebuilder::Operation* op) = 0;
+
+ /**
+ * @brief createLayerXXX are creator for operators.
+ * @param input_tensor_id is id of input tensor.
+ */
+ virtual void createLayerCONV_2D(treebuilder::Tree*, treebuilder::Operation*) = 0;
+};
} // namespace modelgen
#endif // RANDOM_MODELBUILDER_H
std::fill_n(_mapOperatorCode, static_cast<long>(OpCodes::opCount), notInitialized);
}
-std::unique_ptr<TensorT>
- TFLiteRandomModelBuilder::createEmptyTensor(const std::vector<int32_t>& shape,
- const char* name) {
- auto tensor_ptr = std::unique_ptr<TensorT>(new TensorT);
+void TFLiteRandomModelBuilder::convertTreeToModel(treebuilder::Tree* t) {
+ createInput(t);
- tensor_ptr->type = tflite::TensorType_FLOAT32;
- tensor_ptr->name = name;
- tensor_ptr->shape = shape;
- tensor_ptr->buffer = static_cast<uint32_t>(_model->buffers.size());
- _model->buffers.push_back(std::unique_ptr<BufferT>(new BufferT));
+ for (auto& op : t->opList) {
+ addOperator(t, op.get());
+ }
+}
- return tensor_ptr;
+std::unique_ptr<ModelSaver> TFLiteRandomModelBuilder::createModelSaver() {
+ return std::unique_ptr<ModelSaver>(new TFLiteModelSaver(std::move(_model)));
}
-std::unique_ptr<TensorT>
- TFLiteRandomModelBuilder::createTensorWthBuffer(const std::vector<int32_t>& shape,
- const char* name) {
- auto tensor_ptr = createEmptyTensor(shape, name);
+/**
+ * @todo Add support several inputs.
+ */
+void TFLiteRandomModelBuilder::createInput(treebuilder::Tree* t) {
+ assert(_model->subgraphs.empty() && "Subgraph is already created");
- size_t buffer_size = 1;
- for (auto s : shape) {
- buffer_size *= s;
- }
- buffer_size *= sizeof(float);
+ std::unique_ptr<SubGraphT> subgraph(new SubGraphT);
+ subgraph->inputs.push_back(0);
+ subgraph->outputs.push_back(0);
- _model->buffers[tensor_ptr->buffer]->data.resize(buffer_size);
+ subgraph->tensors.push_back(createEmptyTensor(t->inputShapeTree, "input"));
+ _operandTree2tensor.push_back(0); // it is same as: push_pack(subgraph->tensors.size() - 1);
- for (size_t i = 0; i < buffer_size; i += sizeof(float)) {
- float val = floatRand(gen);
- memcpy(_model->buffers[tensor_ptr->buffer]->data.data() + i, &val, sizeof(float));
- }
- return tensor_ptr;
+ _model->subgraphs.push_back(std::move(subgraph));
+ _model->description = "Random tflite model";
+ _model->version = 3;
}
-std::unique_ptr<OperatorT> TFLiteRandomModelBuilder::createEmptyLayer(int opcode) {
- auto operator_ptr = std::unique_ptr<OperatorT>(new OperatorT);
- auto opcode_id = _mapOperatorCode[opcode];
- auto tflite_opcode = internalOpCode2TFLiteOpCode[opcode];
+void TFLiteRandomModelBuilder::addOperator(treebuilder::Tree* t, treebuilder::Operation* op) {
+ assert(!_model->subgraphs.empty() && "Subgraph is not created");
- if (opcode_id == notInitialized) {
- auto opCodePtr = std::unique_ptr<OperatorCodeT>(new OperatorCodeT);
- opCodePtr->builtin_code = tflite_opcode;
- opCodePtr->custom_code = tflite::EnumNamesBuiltinOperator()[tflite_opcode];
- opcode_id = _model->operator_codes.size();
- _model->operator_codes.push_back(std::move(opCodePtr));
- _mapOperatorCode[opcode] = opcode_id;
- }
- operator_ptr->opcode_index = opcode_id;
- operatorCounts[opcode]++;
-
- return operator_ptr;
+ std::cout << "Add operator [" << opNames[static_cast<int32_t>(op->opcode)] << "] on the level [ "
+ << op->levelOwner << " ]" << std::endl;
+ opCreators[static_cast<int32_t>(op->opcode)](t, op);
+ _model->subgraphs[0]->outputs[0] = (*_model->subgraphs[0]->operators.rbegin())->outputs[0];
}
-void TFLiteRandomModelBuilder::createLayerCONV_2D(int input_tensor_id) {
+void TFLiteRandomModelBuilder::createLayerCONV_2D(treebuilder::Tree* t,
+ treebuilder::Operation* op) {
std::string output_name(opNames[static_cast<int32_t>(OpCodes::opConv2d)]);
output_name += "_" + std::to_string(operatorCounts[static_cast<int32_t>(OpCodes::opConv2d)]);
- auto operator_ptr = createEmptyLayer(static_cast<int32_t>(OpCodes::opConv2d));
+ auto operator_ptr = createEmptyOperator(op);
- // @todo Random tensor's shape.
- auto out_tensor_ptr = createEmptyTensor(_model->subgraphs[0]->tensors[input_tensor_id]->shape,
- output_name.c_str());
- auto kernel_ptr = createTensorWthBuffer({3, 1, 1, 3}, "Kernel");
- auto bias_ptr = createTensorWthBuffer({3}, "bias");
+ auto out_tensor_ptr = createEmptyTensor(op->outputShape, output_name.c_str());
+ auto kernel_ptr = createTensorWthBuffer(op->kernelShape, "Kernel");
+ auto bias_ptr = createTensorWthBuffer({op->outputShape[3]}, "bias");
- operator_ptr->inputs.push_back(input_tensor_id);
+ auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0] :
+ _operandTree2tensor[t->inputCnt + op->inputs[0]];
+ operator_ptr->inputs.push_back(input_tensor_id);
operator_ptr->inputs.push_back(static_cast<int32_t>(_model->subgraphs[0]->tensors.size()));
_model->subgraphs[0]->tensors.push_back(std::move(kernel_ptr));
operator_ptr->inputs.push_back(static_cast<int32_t>(_model->subgraphs[0]->tensors.size()));
_model->subgraphs[0]->tensors.push_back(std::move(bias_ptr));
- operator_ptr->outputs.push_back(static_cast<int32_t>(_model->subgraphs[0]->tensors.size()));
+ auto output_tensor_id = static_cast<int32_t>(_model->subgraphs[0]->tensors.size());
+ _operandTree2tensor.push_back(output_tensor_id);
+ operator_ptr->outputs.push_back(output_tensor_id);
_model->subgraphs[0]->tensors.push_back(std::move(out_tensor_ptr));
- // @todo Random activation function.
operator_ptr->builtin_options.Set(tflite::Conv2DOptionsT());
auto conv2D_opt = operator_ptr->builtin_options.AsConv2DOptions();
conv2D_opt->stride_w = conv2D_opt->stride_h = 1;
_model->subgraphs[0]->operators.push_back(std::move(operator_ptr));
}
-bool TFLiteRandomModelBuilder::addInput() {
- if (!_model->subgraphs.empty()) {
- return false;
- }
-
- std::unique_ptr<SubGraphT> subgraph(new SubGraphT);
- subgraph->inputs.push_back(static_cast<int32_t>(subgraph->tensors.size()));
- subgraph->outputs.push_back(static_cast<int32_t>(subgraph->tensors.size()));
- subgraph->tensors.push_back(createEmptyTensor({1, 224, 224, 3}, "input"));
+std::unique_ptr<TensorT>
+TFLiteRandomModelBuilder::createEmptyTensor(const std::vector<int32_t>& shape,
+ const char* name) {
+ auto tensor_ptr = std::unique_ptr<TensorT>(new TensorT);
- _model->subgraphs.push_back(std::move(subgraph));
- _model->description = "Random tflite model";
- _model->version = 3;
+ tensor_ptr->type = tflite::TensorType_FLOAT32;
+ tensor_ptr->name = name;
+ tensor_ptr->shape = shape;
+ tensor_ptr->buffer = static_cast<uint32_t>(_model->buffers.size());
+ _model->buffers.push_back(std::unique_ptr<BufferT>(new BufferT));
- return true;
+ return tensor_ptr;
}
-bool TFLiteRandomModelBuilder::addLayer() {
+std::unique_ptr<TensorT>
+TFLiteRandomModelBuilder::createTensorWthBuffer(const std::vector<int32_t>& shape,
+ const char* name) {
+ auto tensor_ptr = createEmptyTensor(shape, name);
- if (_model->subgraphs.empty()) {
- return false;
+ size_t buffer_size = 1;
+ for (auto s : shape) {
+ buffer_size *= s;
}
+ buffer_size *= sizeof(float);
- auto input_id =
- _model->subgraphs[0]->operators.size() == 0 ? _model->subgraphs[0]->inputs[0] :
- _model->subgraphs[0]->operators[_model->subgraphs[0]->operators.size() - 1]->outputs[0];
+ _model->buffers[tensor_ptr->buffer]->data.resize(buffer_size);
+
+ for (size_t i = 0; i < buffer_size; i += sizeof(float)) {
+ float val = floatRand(gen);
+ memcpy(_model->buffers[tensor_ptr->buffer]->data.data() + i, &val, sizeof(float));
+ }
+ return tensor_ptr;
+}
- auto op_id = intRand(gen);
+std::unique_ptr<OperatorT>
+TFLiteRandomModelBuilder::createEmptyOperator(treebuilder::Operation* op) {
+ auto operator_ptr = std::unique_ptr<OperatorT>(new OperatorT);
+ auto opcode_id = _mapOperatorCode[static_cast<int32_t>(op->opcode)];
+ auto tflite_opcode = internalOpCode2TFLiteOpCode[static_cast<int32_t>(op->opcode)];
- std::cout << "Add layer: " << opNames[op_id] << std::endl;
- opCreators[op_id](input_id);
- _model->subgraphs[0]->outputs[0] = (*_model->subgraphs[0]->operators.rbegin())->outputs[0];
+ if (opcode_id == notInitialized) {
+ auto opcode_ptr = std::unique_ptr<OperatorCodeT>(new OperatorCodeT);
+ opcode_ptr->builtin_code = tflite_opcode;
+ opcode_ptr->custom_code = tflite::EnumNamesBuiltinOperator()[tflite_opcode];
+ opcode_id = static_cast<int32_t>(_model->operator_codes.size());
+ _model->operator_codes.push_back(std::move(opcode_ptr));
+ _mapOperatorCode[static_cast<int32_t>(op->opcode)] = opcode_id;
+ }
+ operator_ptr->opcode_index = static_cast<uint32_t>(opcode_id);
+ operatorCounts[static_cast<int32_t>(op->opcode)]++;
- return true;
+ return operator_ptr;
}
-std::unique_ptr<ModelSaver> TFLiteRandomModelBuilder::createModelSaver() {
- return std::unique_ptr<ModelSaver>(new TFLiteModelSaver(std::move(_model)));
-}
} // namespace modelgen
#include <vector>
#include <memory>
+#include "Tree.h"
#include "RandomModelBuilder.h"
#include "schema_generated.h"
TFLiteModelSaver() = default;
~TFLiteModelSaver() override = default;
- TFLiteModelSaver(std::unique_ptr<ModelT> &&m) : ModelSaver(), _model(std::move(m)) {}
+ TFLiteModelSaver(std::unique_ptr<ModelT>&& m) : ModelSaver(), _model(std::move(m)) {}
void saveModel() override;
-
private:
flatbuffers::FlatBufferBuilder _flatBufferBuilder;
std::unique_ptr<ModelT> _model;
TFLiteRandomModelBuilder();
~TFLiteRandomModelBuilder() override = default;
- void createLayerCONV_2D(int input_tensor_id) override;
-
- bool addInput() override;
- bool addLayer() override;
+ void convertTreeToModel(treebuilder::Tree* t) override;
std::unique_ptr<ModelSaver> createModelSaver() override;
-
+protected:
+ void createInput(treebuilder::Tree* t) override;
+ void addOperator(treebuilder::Tree* t, treebuilder::Operation* op) override;
+ /**
+ * Operations:
+ */
+ void createLayerCONV_2D(treebuilder::Tree* t, treebuilder::Operation* op) override;
private:
/**
* @brief createEmptyTensor does create tensor without buffer
std::unique_ptr<TensorT> createTensorWthBuffer(const std::vector<int32_t>& shape,
const char* name);
/**
- * @brief createEmptyLayer does create operator without tensors and
+ * @brief createEmptyOperator does create operator without tensors and
* add operator to operators array of SubGraphT
* @param opcode is operator's code.
* @return unique_ptr to created operator.
*/
- std::unique_ptr<OperatorT> createEmptyLayer(int opcode);
+ std::unique_ptr<OperatorT> createEmptyOperator(treebuilder::Operation* op);
std::unique_ptr<ModelT> _model;
+
+ /**
+ * @details This vector contains a index of tensor (in subgraph tflite vector)
+ * for output operand of tree's node `i`.
+ */
+ std::vector<int32_t> _operandTree2tensor;
+
/**
* @brief mapOperatorCode contains indexes to operator_codes array in ModelT.
*/
long _mapOperatorCode[static_cast<int32_t>(OpCodes::opCount)];
};
-} // namespace modegGen
+} // namespace modelgen
#endif // TFLITEBUILDER_H