| 77 | } |
| 78 | |
| 79 | void Revert::writeExtraDescribeTensor(float* scale, float* offset) { |
| 80 | int opCounts = static_cast<int32_t>(mMNNNet->oplists.size()); |
| 81 | for (int opIndex = 0; opIndex < opCounts; ++opIndex) { |
| 82 | std::unique_ptr<MNN::TensorDescribeT> describe(new MNN::TensorDescribeT); |
| 83 | describe->index = opIndex; |
| 84 | describe->quantInfo.reset(new MNN::TensorQuantInfoT); |
| 85 | describe->quantInfo->scale = *scale; |
| 86 | describe->quantInfo->zero = *offset; |
| 87 | describe->quantInfo->min = -127; |
| 88 | describe->quantInfo->max = 127; |
| 89 | describe->quantInfo->type = MNN::DataType_DT_INT8; |
| 90 | mMNNNet->extraTensorDescribe.emplace_back(std::move(describe)); |
| 91 | } |
| 92 | for (const auto& op: mMNNNet->oplists) { |
| 93 | const auto opType = op->type; |
| 94 | if (opType != MNN::OpType_Convolution && opType != MNN::OpType_ConvolutionDepthwise && opType != MNN::OpType_Deconvolution) { |
| 95 | continue; |
| 96 | } |
| 97 | // Conv/ConvDepthwise/Deconv weight quant. |
| 98 | const float inputScale = *scale; |
| 99 | const float outputScale = *scale; |
| 100 | const int outputChannel = static_cast<int32_t>(op->outputIndexes.size()); |
| 101 | |
| 102 | auto param = op->main.AsConvolution2D(); |
| 103 | float* originWeight = param->weight.data(); |
| 104 | const int channels = param->common->outputCount; |
| 105 | param->symmetricQuan.reset(new MNN::QuantizedFloatParamT); |
| 106 | param->symmetricQuan->nbits = 8; |
| 107 | const int weightSize = static_cast<int32_t>(param->weight.size()); |
| 108 | param->common->inputCount = weightSize / (channels * param->common->kernelX * param->common->kernelY); |
| 109 | std::vector<int8_t> quantizedWeight(weightSize); |
| 110 | std::vector<float> quantizedWeightScale(channels); |
| 111 | |
| 112 | if (originWeight[0] == 0.f && originWeight[1] == 0.f) { // Process weight is null. |
| 113 | // Initialize originWeight |
| 114 | std::uniform_real_distribution<double> u(-200, 200); |
| 115 | std::default_random_engine e(time(NULL)); |
| 116 | for (int i = 0; i < weightSize; ++i) { |
| 117 | originWeight[i] = u(e); |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | SymmetricQuantizeWeight(originWeight, weightSize, quantizedWeight.data(), quantizedWeightScale.data(), channels, 127.0f); |
| 122 | param->quanParameter = IDSTEncoder::encode(param->weight.data(), quantizedWeightScale, weightSize/channels, channels, false, quantizedWeight.data(), -127.0f); |
| 123 | param->quanParameter->scaleIn = *scale; |
| 124 | param->quanParameter->scaleOut = *scale; |
| 125 | if (param->common->relu6) { |
| 126 | param->common->relu = true; |
| 127 | param->common->relu6 = false; |
| 128 | } |
| 129 | param->weight.clear(); |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | void Revert::packMNNNet() { |
| 134 | flatbuffers::FlatBufferBuilder builder(1024); |
nothing calls this directly
no test coverage detected