После квантизации в нейронной сети, нужно ли масштабировать выход с обратным масштабированием веса - PullRequest
0 голосов
/ 16 февраля 2019

В настоящее время я пишу сценарий для количественной оценки модели Keras до 8 бит.Я делаю довольно простое линейное масштабирование весов, предполагая нормальное распределение весов и смещений, а затем интерполирую все значения в пределах 2 стандартных отклонений от среднего значения до диапазона [-128, 127].Все это работает, и я провожу модель через умозаключение, но мой имидж безумно плох.Я знаю, что произойдет небольшое снижение производительности, но я вижу примерно 10-кратное снижение производительности.Мой вопрос, после этого масштабирования весов, нужно ли мне выполнять обратную операцию масштабирования для моего вывода?Кажется, ни одна из статей, которые я читал, не упоминает об этом, но я не уверен, почему иначе мои результаты были бы такими плохими.Он принимает изображение в формате RAW и предназначен для вывода изображения с очень низким уровнем шума и отсутствием артефактов демозаики.Моя модель с высокой точностью очень хорошая, с PSNR изображений около 40-43 дБ, но после квантования я получаю 4-8 дБ и невероятно плохо выглядящие изображения.

Код для тех, кто потрудился прочитать его1005 *

for i in layer_index:
    count = count+1
    layer = model.get_layer(index = i);
    weights = layer.get_weights();
    weights_act = weights[0];

    bias_act = weights[1];

    std = np.std(weights_act)
    if (std > max_std):
        max_std = std

    mean = np.mean(weights_act)
    mean_of_mean = mean_of_mean + mean


   mean_of_mean = mean_of_mean / count

max_bound = mean_of_mean + 2*max_std
min_bound = mean_of_mean - 2*max_std

print(max_bound, min_bound)


for i in layer_index:
    layer = model.get_layer(index = i);
    weights = layer.get_weights();
    weights_act = weights[0];
    bias_act = weights[1];
    weights_shape = weights_act.shape;
    bias_shape = bias_act.shape;
    new_weights = np.empty(weights_shape, dtype = np.int8)
    print(new_weights.dtype)
    new_biass = np.empty(bias_shape, dtype = np.int8)

    for a in range(weights_shape[0]):
        for b in range(weights_shape[1]):
            for c in range(weights_shape[2]):
                for d in range(weights_shape[3]):
                    new_weight = (((weights_act[a,b,c,d] - min_bound) * (127 - (-128)) / (max_bound - min_bound)) + (-128))
                    new_weights[a,b,c,d] = np.int8(new_weight)
                    #print(new_weights[a,b,c,d], weights_act[a,b,c,d])

    for e in range(bias_shape[0]):
        new_bias = (((bias_act[e] - min_bound) * (127 - (-128)) / (max_bound - min_bound)) + (-128))
        new_biass[e] = np.int8(new_bias)

    new_weight_layer = (new_weights, new_biass)
   layer.set_weights(new_weight_layer)

1 Ответ

0 голосов
/ 17 февраля 2019

Вы не делаете то, что, как вы думаете, вы делаете, я объясню.Если вы хотите взять предварительно обученную модель и квантовать ее, вы должны добавлять весы после каждой операции, которая включает весовые коэффициенты, давайте возьмем, например, операцию свертки.Поскольку мы знаем, что операция свертки является линейной в моем объяснении, я буду игнорировать смещение для простоты (добавить его относительно легко), Давайте предположим, что X - это наш вход, Y - это наш вывод, а W - это вес, свертка может быть записана как:

Y=W*X

где '*' представляет операцию свертки, то, что вы в основном делаете, - это взятие весов и умножение их на некоторый скаляр (давайте назовем его 'a') и смещение их на другой скаляр (давайтеназовите это 'b'), поэтому в вашей модели вы используете W ', где: W'= Wa+b

Итак, если мы вернемся к операции свертки, мы получим, что в вашей квантованной сети вы в основном выполните следующую операцию: Y' = W'*X = (Wa+b)*X

Поскольку свертка линейная, мы получаем: Y' = a(W*X) + b*X' Не забывайте, что в вашей сети вы хотите получать Y, а не Y 'на выходе свертки, поэтому вы должны выполнить сдвиг + повторное масштабирование, чтобы получить правильное значение.ответ.

Итак, после этого объяснения (которое, я надеюсь, было достаточно ясным), я надеюсь, вы сможете понять, в чем проблема в вашей сети, йоВы делаете это масштабирование и переходите ко всем весам, и вы никогда не компенсируете его, я думаю, что вы путаетесь в том, что вы читали статьи, которые обучали модели в квантованном режиме с самого начала и не брали предварительно обученную модель, квантовали ее.

Для вашей проблемы я думаю, что инструмент преобразования тензорного потока может помочь, взгляните на: https://github.com/tensorflow/tensorflow/blob/master/tensorflow/tools/graph_transforms/README.md

Если вы хотите узнать больше о квантовании предварительно обученной модели, вы можете найти более подробную информацию в (для получения дополнительной информации простоперейдите на scholar.google.com: https://www.tensorflow.org/lite/performance/post_training_quantization

...