Скалярное квантование заданного c слоя в кератах & python - PullRequest
0 голосов
/ 20 марта 2020

Я делаю эксперимент, в котором мне нужно квантовать определенный c слой сверточной модели. Однако даже при использовании большого количества битов (например, 12 бит с SQNR ~ 60 дБ), когда я устанавливаю в модель квантованные веса и смещение, точность снижается с ~ 99% до ~ 10%.

Я выполняю квантование с использованием этой функции:

def scalar_quantization(signal, bits):
   print('bits used: ', bits)
   min_val =  np.min(signal)
   max_val = np.max(signal)
   codebook = np.linspace(min_val, max_val, 2**bits)
   quantized_signal = np.zeros(len(signal))
   for i in range(0, len(signal)):
    quantized_signal[i] = closest(codebook, signal[i])

   noise = signal- quantized_signal
   snr = 10*math.log10(np.var(signal)/np.var(noise))    
   return quantized_signal, snr    

#Auxiliar function
def closest(lst, K):       
  return lst[min(range(len(lst)), key = lambda i: abs(lst[i]-K))] 

Я установил вес, используя следующий код (я пытаюсь квантовать первый слой):

quantized_layer = []
layer_names_it = 1
quantized_layer.append(np.array(np.reshape(quantized_weights, layer_shape),dtype=np.float32))
quantized_layer.append(np.array(np.reshape(quantized_bias, bias_shape), dtype=np.float32))
model.layers[layer_names_it].set_weights(quantized_layer)

Затем, когда я снова тестирую модель, я получаю точность 10%. Без квантования точность составляла ~ 99%.

Поэтому, что я делаю не так?

PS: Ниже представлен весь код, используемый для воспроизведения

import math
import keras
import numpy as np
import math
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K


def create_and_train_model():
    model = Sequential()
    model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))
    model.add(Flatten())
    model.add(Dense(128, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(num_classes, activation='softmax'))
    model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])

    return model


def scalar_quantization(signal, bits):
    min_val =  np.min(signal)
    max_val = np.max(signal)
    codebook = np.linspace(min_val, max_val, 2**bits)
    quantized_signal = np.zeros(len(signal))
    for i in range(0, len(signal)):
        quantized_signal[i] = closest(codebook, signal[i])

    noise = signal- quantized_signal
    snr = 10*math.log10(np.var(signal)/np.var(noise))    
    return quantized_signal, snr    


def closest(lst, K):       
    return lst[min(range(len(lst)), key = lambda i: abs(lst[i]-K))] 


batch_size = 128
num_classes = 10
epochs = 12

# input image dimensions
img_rows, img_cols = 28, 28

# the data, split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()


if K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)


x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)


model = create_and_train_model()

model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss without quantization:', score[0])
print('Test accuracy without quantization:', score[1])

layer_names=[layer.name for layer in model.layers] #Get the names of all layers

layer_names_it = 1 #In this example, I'm only quantizing the first layer

layer = model.get_layer(layer_names[layer_names_it]) #Get the desired layer
layer_shape = np.shape(layer.get_weights()[0])
bias_shape = np.shape(layer.get_weights()[1])

weights = np.reshape(layer.get_weights()[0].tolist(),-1,1) #Convert it to a vector of one dimension to quantize it
bias = np.reshape(layer.get_weights()[1].tolist(),-1,1)#Convert it to a vector of one dimension to quantize it

print('quantization step...')
quantized_weights, snr = scalar_quantization(weights,  bits = 12)
noise_weights = weights - quantized_weights
snr_weights = 10*math.log10(np.var(weights) / np.var(noise_weights))
print('SNR quantized weights: ', snr_weights)


quantized_bias, snr = scalar_quantization(bias,  bits = 12)
noise_bias =  bias - quantized_bias
snr_bias = 10*math.log10(np.var(bias) / np.var(noise_bias))
print('SNR quantized bias: ', snr_bias)



quantized_layer = []

quantized_layer.append(np.array(np.reshape(quantized_weights, layer_shape), dtype = np.float32))
quantized_layer.append(np.array(np.reshape(quantized_bias, bias_shape),  dtype = np.float32))

model.layers[layer_names_it].set_weights(quantized_layer)
score = model.evaluate(x_test, y_test, verbose=1)
print('Test loss with quantization:', score[0])
print('Test accuracy with quantization:', score[1]) ```


...