def test_grow(self, verbose):
        x_1 = torch.tensor([0, 255, 255, 255, 255, 255]).cuda()
        x_2 = torch.tensor([0, 255, 255, 255, 255, 256]).cuda()

        hist_calibrator = calib.HistogramCalibrator(8,
                                                    None,
                                                    False,
                                                    grow_method='stretch')
        hist_calibrator.collect(x_1)
        hist_calibrator.collect(x_2)

        amax = hist_calibrator.compute_amax(method='entropy')

        if verbose:
            print('amax={:.4f}'.format(amax.item()), end=' ')

        # amax should be closer to 256 because the last bin gets stretched to (~255, 257)
        assert (amax - 255.).abs() < (amax - 256.).abs()

        hist_calibrator = calib.HistogramCalibrator(8,
                                                    None,
                                                    False,
                                                    grow_method='append')
        hist_calibrator.collect(x_1)
        hist_calibrator.collect(x_2)

        amax = hist_calibrator.compute_amax(method='mse')

        if verbose:
            print('amax={:.4f}'.format(amax.item()), end=' ')

        # amax should be closer to 255
        assert (amax - 255.).abs() < 0.5
    def test_torch_hist(self):
        x_1 = torch.rand(1023, device="cuda")
        x_1[0] = 0
        x_2 = torch.rand(
            1023,
            device="cuda") + 1  # Make sure histogram bins need to be grown
        x_2[1] = 0

        calibrator_np = calib.HistogramCalibrator(8,
                                                  None,
                                                  False,
                                                  num_bins=19,
                                                  torch_hist=False)
        calibrator_torch = calib.HistogramCalibrator(8,
                                                     None,
                                                     False,
                                                     num_bins=19,
                                                     torch_hist=True)

        calibrator_np.collect(x_1)
        calibrator_torch.collect(x_1)
        assert calibrator_torch._calib_hist.numel(
        ) == calibrator_torch._calib_bin_edges.numel() - 1
        np.testing.assert_array_equal(
            calibrator_np._calib_hist,
            calibrator_torch._calib_hist.cpu().numpy())
        np.testing.assert_array_almost_equal(
            calibrator_np._calib_bin_edges,
            calibrator_torch._calib_bin_edges.cpu().numpy())

        # Test multiple collections with some of them needs to expand range
        for _ in range(3):
            calibrator_np.collect(x_2)
            calibrator_torch.collect(x_2)
            calibrator_np.collect(x_1)
            calibrator_torch.collect(x_1)

            # Test compute_amax function doesn't convert _calib_hist and _calib_bin_edges unnecessarily
            calibrator_np.compute_amax("percentile", percentile=99.99)
            calibrator_torch.compute_amax("percentile", percentile=99.99)

            np.testing.assert_array_equal(
                calibrator_np._calib_hist,
                calibrator_torch._calib_hist.cpu().numpy())
            np.testing.assert_array_almost_equal(
                calibrator_np._calib_bin_edges,
                calibrator_torch._calib_bin_edges.cpu().numpy())
            assert calibrator_torch._calib_hist.numel(
            ) == calibrator_torch._calib_bin_edges.numel() - 1
 def test_range(self):
     calibrator = calib.HistogramCalibrator(8, None, False)
     x_1 = torch.arange(100)
     calibrator.collect(x_1)
     with pytest.raises(ValueError, match="range"):
         calibrator.compute_amax("percentile", percentile=-10)
     with pytest.raises(ValueError, match="range"):
         calibrator.compute_amax("percentile", percentile=200)
Exemple #4
0
    def test_mse_with_axis(self):
        torch.manual_seed(12345)
        test_lenet = QuantLeNet()

        ref_calibrator = calib.HistogramCalibrator(8, None, False)

        calib.calibrate_weights(test_lenet, method="mse", perchannel=True)
        ref_calibrator.collect(test_lenet.conv2.weight[1])
        ref_amax = ref_calibrator.compute_amax("mse")
        test_utils.compare(ref_amax, test_lenet.conv2.weight_quantizer.amax[1], rtol=0, atol=0, ctol=0)
Exemple #5
0
    def test_percentile(self):
        torch.manual_seed(12345)
        test_lenet = QuantLeNet()
        test_percentile = 99.99

        ref_calibrator = calib.HistogramCalibrator(8, None, False)

        calib.calibrate_weights(test_lenet, method="percentile", perchannel=False, percentile=test_percentile)
        ref_calibrator.collect(test_lenet.conv1.weight)
        ref_amax = ref_calibrator.compute_amax("percentile", percentile=test_percentile)
        test_utils.compare(ref_amax, test_lenet.conv1.weight_quantizer.amax, rtol=0, atol=0, ctol=0)
    def test_unsigned_one_tensor(self, verbose):
        calibrator = calib.HistogramCalibrator(8, None, True)

        x_1 = torch.arange(100)
        calibrator.collect(x_1)

        amax = calibrator.compute_amax("percentile", percentile=80)

        if verbose:
            print('amax={:.4f}'.format(amax.item()), end=' ')

        # amax should be approximately 79
        assert (amax - 79.).abs() < 100 / 2048
Exemple #7
0
    def test_unsigned(self, verbose):
        hist_calibrator = calib.HistogramCalibrator(8, None, True, grow_method='stretch')

        x_2 = torch.rand(11, 7, 3, 3).cuda() # uniform in (0,1)
        x_2[1, 1, 1, 1] = 10. # create outlier
        hist_calibrator.collect(x_2)

        amax = hist_calibrator.compute_amax("entropy")

        if verbose:
            print('amax={:.4f}'.format(amax.item()), end=' ')

        assert amax < 1.1
    def test_unsigned_one_tensor(self, verbose):
        calibrator = calib.HistogramCalibrator(8, None, True)

        x_1 = torch.ones(11, 7, 3, 3).cuda() * 512.
        x_1[1, 1, 1, 1] = 513.  # create an outlier
        calibrator.collect(x_1)

        amax = calibrator.compute_amax("mse")

        if verbose:
            print('amax={:.4f}'.format(amax.item()), end=' ')

        # amax should be closer to 512
        assert (amax - 512.).abs() < (amax - 513.).abs()
Exemple #9
0
    def test_two_tensor(self, verbose):
        calibrator = calib.HistogramCalibrator(8, None, False)

        x_1 = torch.arange(100)
        calibrator.collect(x_1)
        x_2 = torch.arange(0, 50, 0.5)
        calibrator.collect(x_2)
        amax = calibrator.compute_amax("percentile", percentile=99)

        if verbose:
            print('amax={:.4f}'.format(amax.item()), end=' ')

        # amax should be approximately 97
        assert (amax - 97.).abs() < 100/1024
Exemple #10
0
    def test_one_tensor(self, verbose):
        hist_calibrator = calib.HistogramCalibrator(8, None, False, grow_method='stretch')

        x_2 = torch.rand(11, 7, 3, 3).cuda() # uniform in (0,1)
        x_2[1, 1, 1, 1] = 10. # create outlier
        hist_calibrator.collect(x_2)

        # Don't have a better test metric. One outlier 10 should be discared by KL-divergence
        amax = hist_calibrator.compute_amax("entropy")

        if verbose:
            print('amax={:.4f}'.format(amax.item()), end=' ')

        assert amax < 1.1
    def __init__(self,
                 quant_desc=QuantDescriptor(),
                 disabled=False,
                 if_quant=True,
                 if_clip=False,
                 if_calib=False):
        """Initialize quantizer and set up required variables"""
        super(TensorQuantizer, self).__init__()
        # Expand quant_desc. Use quant_desc.dict would be eaiser, but adding one-by-one explicitly gives more control
        self._num_bits = quant_desc.num_bits
        self._fake_quant = quant_desc.fake_quant
        self._axis = quant_desc.axis
        self._scale_amax = quant_desc.scale_amax
        self._learn_amax = quant_desc.learn_amax
        self._unsigned = quant_desc.unsigned
        self._narrow_range = quant_desc.narrow_range

        self._scale = None if not quant_desc.fake_quant else 1.
        self._disabled = disabled
        self._if_quant = if_quant
        self._if_clip = False
        self._if_calib = if_calib

        if quant_desc.amax is not None:
            self.register_buffer('_amax', torch.tensor(quant_desc.amax))

        # Clip module consumes a lot of memory, so only create it if learn_amax is True
        if self._learn_amax:
            init_amax = quant_desc.amax if quant_desc.amax is not None else 1.
            self.clip = Clip(-init_amax,
                             init_amax,
                             learn_min=True,
                             learn_max=True)
            # It makes more sense to enable clip stage (which learns amax) if learn_amax is true
            self.enable_clip()
        if if_clip:
            self.enable_clip()

        if quant_desc.calib_method == "histogram":
            logging.info("Creating histogram calibrator")
            self._calibrator = calib.HistogramCalibrator(
                num_bits=self._num_bits,
                axis=self._axis,
                unsigned=self._unsigned)
        elif quant_desc.calib_method == "max":
            logging.info("Creating Max calibrator")
            self._calibrator = calib.MaxCalibrator(num_bits=self._num_bits,
                                                   axis=self._axis,
                                                   unsigned=self._unsigned)
    def test_skip_zeros(self, verbose):
        x_1 = torch.tensor([0, 0, 0, 0, 0, 1, 2, 3, 4, 5])
        x_2 = torch.tensor([0, 0, 0, 0, 0, 6, 7, 8, 9, 10])

        calibrator = calib.HistogramCalibrator(8, None, False, skip_zeros=True)
        calibrator.collect(x_1)
        calibrator.collect(x_2)

        amax = calibrator.compute_amax("percentile", percentile=50)

        if verbose:
            print('amax={:.4f}'.format(amax.item()), end=' ')

        # amax should be close to 5
        assert (amax - 5.).abs() < 10 / 2048
Exemple #13
0
    def test_two_tensor(self, verbose):
        calibrator = calib.HistogramCalibrator(8, None, False)

        x_1 = torch.ones(11, 7, 3, 3).cuda() * 255.
        x_1[1, 1, 1, 1] = 256. # create an outlier
        calibrator.collect(x_1)
        x_2 = torch.ones(11, 7, 3, 3).cuda() * 255.
        calibrator.collect(x_2)

        amax = calibrator.compute_amax("mse")

        if verbose:
            print('amax={:.4f}'.format(amax.item()), end=' ')

        # amax should be closer to 255
        assert (amax - 255.).abs() < (amax - 256.).abs()
Exemple #14
0
 def test_print_calibrator(self):
     print(calib.MaxCalibrator(7, 1, False))
     hist_calibrator = calib.HistogramCalibrator(8, None, True)
     hist_calibrator.collect(torch.rand(10))
     print(hist_calibrator)
 def test_repr(self):
     calibrator = calib.HistogramCalibrator(8, None, False)
     repr(calibrator)
 def test_repr(self):
     hist_calibrator = calib.HistogramCalibrator(8, None, True)
     repr(hist_calibrator)