[TFLite] 9(3). 양자화 인식 학습
양자화 인식 학습
양자화 인식 학습은 모델을 학습하는 과정에서 양자화를 적용하는 기법으로, 모델의 크기를 줄이려는 목적이 아니라 양자화를 적용한 후 정확도가 더 높은 모델을 얻기 위해 사용합니다.
양자화 인식 학습은 학습 단계에서 적용하는 양자화 기법이므로 학습 후 양자화와 달리 학습 데이터가 필요합니다. 여기서는 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
결과를 보면 양자화를 적용했음에도 불구하고 정확도가 원본 모델과 거의 유사합니다.
이처럼 양자화 인식 학습은 양자화를 적용하더라도 원본 모델 수준으로 정확도를 최대한 유지할 수 있게 해줍니다.
Leave a comment