public static (double[] scale, double bias) QuantizeWeights(bool isConv2d, Tensor <float> weights, K210ConvLayerConfig config, int weightsBits) { #if CHANNEL_WISE var kernels = weights.ToDenseTensor().Buffer.Span; var channels = weights.Dimensions[isConv2d ? 0 : 1]; var channelSize = weights.Dimensions.GetSize() / channels; var totalRange = Quantizer.GetRange(kernels); var scales = new double[channels]; for (int i = 0; i < channels; i++) { double s; var buffer = kernels.Slice(i * channelSize, channelSize); var range = Quantizer.GetRange(buffer); var s1 = totalRange.Max / range.Max; var s2 = totalRange.Min / range.Min; s = (s1 < 0 || s2 < 0) ? Math.Max(s1, s2) : Math.Min(s1, s2); Debug.Assert(s > 0); for (int j = 0; j < buffer.Length; j++) { buffer[j] = (float)(buffer[j] * s); } scales[i] = s; } (var scale, var bias) = Quantizer.GetRange(kernels).GetScaleBias(weightsBits); (var mul, var shift) = Quantizer.ExtractValueAndShift(bias, 24, 15); config.Weights = Quantizer.Quantize(kernels, scale, bias, weightsBits); config.ArgX = (int)Math.Round(mul); config.ShiftX = shift; for (int i = 0; i < scales.Length; i++) { scales[i] *= scale; } return(scales, bias); #else var buffer = weights.ToDenseTensor().Buffer.Span; (var scale, var bias) = GetRange(buffer).GetScaleBias(); (var mul, var shift) = ExtractValueAndShift(bias, 24, 15); config.Weights = Quantize(buffer, scale, bias); config.ArgX = (int)Math.Round(mul); config.ShiftX = shift; return(Enumerable.Repeat(scale, weights.Dimensions[0]).ToArray(), bias); #endif }