in nn-samples/sequence/src/main/cpp/sequence_model.cpp [147:355]
bool SimpleSequenceModel::CreateModel() {
int32_t status;
// Create the ANeuralNetworksModel handle.
status = ANeuralNetworksModel_create(&model_);
if (status != ANEURALNETWORKS_NO_ERROR) {
__android_log_print(ANDROID_LOG_ERROR,
LOG_TAG,
"ANeuralNetworksModel_create failed");
return false;
}
uint32_t dimensions[] = {dimLength_, dimLength_};
ANeuralNetworksOperandType float32TensorType{
.type = ANEURALNETWORKS_TENSOR_FLOAT32,
.dimensionCount = sizeof(dimensions) / sizeof(dimensions[0]),
.dimensions = dimensions,
.scale = 0.0f,
.zeroPoint = 0,
};
ANeuralNetworksOperandType scalarInt32Type{
.type = ANEURALNETWORKS_INT32,
.dimensionCount = 0,
.dimensions = nullptr,
.scale = 0.0f,
.zeroPoint = 0,
};
/**
* Add operands and operations to construct the model.
*
* Operands are implicitly identified by the order in which they are added to the model,
* starting from 0.
*
* These indexes are not returned by the model_addOperand call. The application must
* manage these values. Here, we use opIdx to do the bookkeeping.
*/
uint32_t opIdx = 0;
// We first add the operand for the NONE activation function, and set its
// value to ANEURALNETWORKS_FUSED_NONE.
// This constant scalar operand will be used for both ADD and MUL.
status = ANeuralNetworksModel_addOperand(model_, &scalarInt32Type);
uint32_t fusedActivationFuncNone = opIdx++;
if (status != ANEURALNETWORKS_NO_ERROR) {
__android_log_print(ANDROID_LOG_ERROR,
LOG_TAG,
"ANeuralNetworksModel_addOperand failed for operand (%d)",
fusedActivationFuncNone);
return false;
}
FuseCode fusedActivationCodeValue = ANEURALNETWORKS_FUSED_NONE;
status = ANeuralNetworksModel_setOperandValue(model_, fusedActivationFuncNone,
&fusedActivationCodeValue,
sizeof(fusedActivationCodeValue));
if (status != ANEURALNETWORKS_NO_ERROR) {
__android_log_print(ANDROID_LOG_ERROR,
LOG_TAG,
"ANeuralNetworksModel_setOperandValue failed for operand (%d)",
fusedActivationFuncNone);
return false;
}
// sumIn is one of the user provided input tensors to the trained model.
// Its value is determined pre-execution.
status = ANeuralNetworksModel_addOperand(model_, &float32TensorType);
uint32_t sumIn = opIdx++;
if (status != ANEURALNETWORKS_NO_ERROR) {
__android_log_print(ANDROID_LOG_ERROR,
LOG_TAG,
"ANeuralNetworksModel_addOperand failed for operand (%d)",
sumIn);
return false;
}
// stateIn is one of the user provided input tensors to the trained model.
// Its value is determined pre-execution.
status = ANeuralNetworksModel_addOperand(model_, &float32TensorType);
uint32_t stateIn = opIdx++;
if (status != ANEURALNETWORKS_NO_ERROR) {
__android_log_print(ANDROID_LOG_ERROR,
LOG_TAG,
"ANeuralNetworksModel_addOperand failed for operand (%d)",
stateIn);
return false;
}
// ratio is a constant tensor that was established during training.
// We read these values from the corresponding ANeuralNetworksMemory object.
status = ANeuralNetworksModel_addOperand(model_, &float32TensorType);
uint32_t ratio = opIdx++;
if (status != ANEURALNETWORKS_NO_ERROR) {
__android_log_print(ANDROID_LOG_ERROR,
LOG_TAG,
"ANeuralNetworksModel_addOperand failed for operand (%d)",
ratio);
return false;
}
status = ANeuralNetworksModel_setOperandValueFromMemory(model_,
ratio,
memoryRatio_,
0,
tensorSize_
* sizeof(float));
if (status != ANEURALNETWORKS_NO_ERROR) {
__android_log_print(
ANDROID_LOG_ERROR,
LOG_TAG,
"ANeuralNetworksModel_setOperandValueFromMemory failed for operand (%d)",
ratio);
return false;
}
// sumOut is the output of the ADD operation.
// Its value will be computed during execution.
status = ANeuralNetworksModel_addOperand(model_, &float32TensorType);
uint32_t sumOut = opIdx++;
if (status != ANEURALNETWORKS_NO_ERROR) {
__android_log_print(ANDROID_LOG_ERROR,
LOG_TAG,
"ANeuralNetworksModel_addOperand failed for operand (%d)",
sumOut);
return false;
}
// stateOut is the output of the MUL operation.
// Its value will be computed during execution.
status = ANeuralNetworksModel_addOperand(model_, &float32TensorType);
uint32_t stateOut = opIdx++;
if (status != ANEURALNETWORKS_NO_ERROR) {
__android_log_print(ANDROID_LOG_ERROR,
LOG_TAG,
"ANeuralNetworksModel_addOperand failed for operand (%d)",
stateOut);
return false;
}
// Add the ADD operation.
std::vector<uint32_t> addInputOperands = {
sumIn,
stateIn,
fusedActivationFuncNone,
};
status = ANeuralNetworksModel_addOperation(model_,
ANEURALNETWORKS_ADD,
addInputOperands.size(),
addInputOperands.data(),
1,
&sumOut);
if (status != ANEURALNETWORKS_NO_ERROR) {
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
"ANeuralNetworksModel_addOperation failed for ADD");
return false;
}
// Add the MUL operation.
std::vector<uint32_t> mulInputOperands = {
stateIn,
ratio,
fusedActivationFuncNone,
};
status = ANeuralNetworksModel_addOperation(model_,
ANEURALNETWORKS_MUL,
mulInputOperands.size(),
mulInputOperands.data(),
1,
&stateOut);
if (status != ANEURALNETWORKS_NO_ERROR) {
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
"ANeuralNetworksModel_addOperation failed for MUL");
return false;
}
// Identify the input and output tensors to the model.
// Inputs: {sumIn, stateIn}
// Outputs: {sumOut, stateOut}
std::vector<uint32_t> modelInputs = {
sumIn,
stateIn,
};
std::vector<uint32_t> modelOutputs = {
sumOut,
stateOut,
};
status =
ANeuralNetworksModel_identifyInputsAndOutputs(model_,
modelInputs.size(),
modelInputs.data(),
modelOutputs.size(),
modelOutputs.data());
if (status != ANEURALNETWORKS_NO_ERROR) {
__android_log_print(ANDROID_LOG_ERROR,
LOG_TAG,
"ANeuralNetworksModel_identifyInputsAndOutputs failed");
return false;
}
// Finish constructing the model.
// The values of constant operands cannot be altered after
// the finish function is called.
status = ANeuralNetworksModel_finish(model_);
if (status != ANEURALNETWORKS_NO_ERROR) {
__android_log_print(ANDROID_LOG_ERROR,
LOG_TAG,
"ANeuralNetworksModel_finish failed");
return false;
}
return true;
}