[TFLite] 9(3). 양자화 인식 학습

2 minute read

양자화 인식 학습

양자화 인식 학습은 모델을 학습하는 과정에서 양자화를 적용하는 기법으로, 모델의 크기를 줄이려는 목적이 아니라 양자화를 적용한 후 정확도가 더 높은 모델을 얻기 위해 사용합니다.

양자화 인식 학습은 학습 단계에서 적용하는 양자화 기법이므로 학습 후 양자화와 달리 학습 데이터가 필요합니다. 여기서는 MNIST 데이터셋을 사용하겠습니다.


텐서플로 모델 생성


단순한 형태의 합성곱 신경망 모델을 MNIST 데이터로 학습시킵니다.

import tensorflow as tf

mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()

x_train, x_test = x_train / 255.0, x_test / 255.0
x_train = x_train.reshape(-1,28,28,1)
x_test = x_test.reshape(-1,28,28,1)

cnn_model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(12, (3,3), activation='relu', input_shape=(28,28,1)),
    tf.keras.layers.MaxPooling2D((2,2)),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(10)
])

cnn_model.compile(optimizer='adam', 
                 loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                 metrics = ['accuracy'])

cnn_model.summary()
cnn_model.fit(x_train, y_train, epochs=1, validation_split=0.1)
cnn_model.evaluate(x_test, y_test)
Model: "sequential_3"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_3 (Conv2D)            (None, 26, 26, 12)        120       
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 13, 13, 12)        0         
_________________________________________________________________
flatten_3 (Flatten)          (None, 2028)              0         
_________________________________________________________________
dense_3 (Dense)              (None, 10)                20290     
=================================================================
Total params: 20,410
Trainable params: 20,410
Non-trainable params: 0
_________________________________________________________________
1688/1688 [==============================] - 14s 8ms/step - loss: 0.2944 - accuracy: 0.9157 - val_loss: 0.1156 - val_accuracy: 0.9698
313/313 [==============================] - 1s 3ms/step - loss: 0.1342 - accuracy: 0.9621





[0.13423223793506622, 0.9621000289916992]

총 20410개의 파라미터로 구성되어 있으며, 96.21%의 정확도를 보여줍니다.



양자화 적용 모델


앞에서 생성한 모델에 양자화 인식 학습을 적용할 수 있습니다.

먼저 최적화를 지원하기 위한 텐서플로 패키지인 tensorflow_model_optimization을 설치해야 합니다.

# conda activate tf2
# pip install tensorflow-model-optimization (아나콘다 커맨드 창)
# 또는 
# !pip install tensorflow-model-optimization (주피터 노트북)


패키지가 설치되면 모델에 양자화 인식 학습을 적용할 수 있습니다.

import tensorflow_model_optimization as tfmot

quantized_cnn_model = tfmot.quantization.keras.quantize_model(cnn_model) # 양자화 인식 학습 모델 

quantized_cnn_model.compile(optimizer='adam', 
                           loss='sparse_categorical_crossentropy', 
                           metrics=['accuracy'])

quantized_cnn_model.summary()
Model: "sequential_3"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
quantize_layer_3 (QuantizeLa (None, 28, 28, 1)         3         
_________________________________________________________________
quant_conv2d_3 (QuantizeWrap (None, 26, 26, 12)        147       
_________________________________________________________________
quant_max_pooling2d_3 (Quant (None, 13, 13, 12)        1         
_________________________________________________________________
quant_flatten_3 (QuantizeWra (None, 2028)              1         
_________________________________________________________________
quant_dense_3 (QuantizeWrapp (None, 10)                20295     
=================================================================
Total params: 20,447
Trainable params: 20,410
Non-trainable params: 37
_________________________________________________________________

입력 계층을 비롯해 모델을 구성하는 각 레이어가 양자화가 적용된 레이어로 변환되었습니다. 또한 매개변수가 다소 늘었지만 학습 가능한 매개변수의 수(Trainable params)는 원본 모델과 동일합니다.


아래 코드는 양자화된 모델에 학습 데이터의 일부를 사용하여 추가로 학습시킨 뒤 정확도를 확인하는 코드입니다.

train_image_subset = x_train[:1000]
train_labels_subset = y_train[:1000]

quantized_cnn_model.fit(train_image_subset, train_labels_subset, 
                       batch_size = 500, epochs=1, validation_split=0.1)
quantized_cnn_model.evaluate(x_test, y_test)
2/2 [==============================] - 1s 243ms/step - loss: 0.4517 - accuracy: 0.9622 - val_loss: 0.6555 - val_accuracy: 0.9500
313/313 [==============================] - 1s 4ms/step - loss: 0.3999 - accuracy: 0.9609



[0.39992278814315796, 0.9609000086784363]

정확도가 96.09%로 원본 모델과 거의 유사하며 오히려 좀 더 향상되었습니다.


아직은 케라스 모델이므로 tflite 파일로 변환된 후에도 모델의 정확도가 유지되는지 확인이 필요합니다. 원본 합성곱 신경망 모델과 양자화가 적용된 합성곱 신경망 모델을 tflite 파일로 저장합니다.

converter = tf.lite.TFLiteConverter.from_keras_model(cnn_model)
cnn_tflite_model = converter.convert()

with open("./cnn_model.tflite", "wb") as f:
    f.write(cnn_tflite_model)
converter = tf.lite.TFLiteConverter.from_keras_model(quantized_cnn_model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
quantized_cnn_tflite_model = converter.convert()

with open("./quantized_cnn_model.tflite", "wb") as f:
    f.write(quantized_cnn_tflite_model)


원본 모델은 추가적인 양자화없이 tflite 파일로 변환했고, 양자화를 적용한 모델은 학습 후 양자화(Dynamic Range) 를 같이 적용했습니다.



양자화 모델의 정확도 비교


변환된 tflite 파일을 이용하여 Interpreter를 생성하고 test 데이터로 추론하여 모델의 정확도를 확인해봅니다.

def run_tflite_model(path, x_test, y_test):
    interpreter = tf.lite.Interpreter(str(path))
    interpreter.allocate_tensors()
    
    input_details = interpreter.get_input_details()[0]
    output_details = interpreter.get_output_details()[0]
    
    y_pred = []
    for i, test_image in enumerate(x_test):
        test_image = np.expand_dims(test_image, axis=0).astype(np.float32)
        
        interpreter.set_tensor(input_details['index'], test_image)
        interpreter.invoke()
        output = interpreter.get_tensor(output_details['index'])
        
        y_pred.append(output.argmax())
        
    y_pred = np.array(y_pred)
    accuracy = (y_pred == y_test).mean()
    return accuracy


이제 원본 합성곱 모델과 양자화가 적용된 합성곱 신경망 모델의 tflite 파일을 전달하여 정확도를 비교합니다.

# 원본 합성곱 신경망
run_tflite_model("./cnn_model.tflite", x_test, y_test)
0.9621
# 양자화가 적용된 합성곱 신경망
run_tflite_model("./quantized_cnn_model.tflite", x_test, y_test)
0.9609


결과를 보면 양자화를 적용했음에도 불구하고 정확도가 원본 모델과 거의 유사합니다.

이처럼 양자화 인식 학습은 양자화를 적용하더라도 원본 모델 수준으로 정확도를 최대한 유지할 수 있게 해줍니다.

Categories:

Updated:

Leave a comment