[안드로이드 앱 생성]PyTorch 모델을 TensorFlow Lite모델로 변환

2024. 6. 3. 14:08컴퓨터과학

반응형

[작업 개요]

텍스트 분류 기능을 파이썬으로 코딩하여 PyTorch모델을 만들었다.

  • pytorch_model.bin [679MB
  • BERT 자연어처리 분류모델로 작성
  • 안드로이드 앱에서 해당 모델 기능 사용하기 위해 파일 형식 변환이 필요
  • 변환 후에 사이즈 경량화가 필요한 경우 추가작업이 필요

 

 

[ 모델 파일 변환 계획 ]

  1. 모델파일 형식 변경(경량화는 아직 안함)
  2. (필요시)변경된 파일에 추가 경량화
  3. 경량화된 모델파일 생성하고 경량화 추가작업 수행

 

 


ㆍ 계획 ① 모델파일 형식 변경

  • PyTorch 모델인 pytorch_model.bin 파일은 안드로이드에서 직접 구동되지 않는 파일 형식입니다. 따라서, 이 모델을 TensorFlow Lite 포맷인 tflite 파일로 변환하는 작업은 안드로이드에서 구동 가능한 모델로 만들기 위한 변환 작업입니다.
    1. 모델 포맷 변환: PyTorch 모델을 안드로이드 환경에서 사용할 수 있는 TensorFlow Lite 모델로 변환.
    2. 경량화: 변환 과정에서 모델을 경량화하여 안드로이드 디바이스에서 효율적으로 실행될 수 있도록 함.
    이를 위해 여러 경량화 기법이 적용되었습니다 (아래 코드설명 중간에 따로 설명 있으니 스킵하셔도 되는 내용) :
    1. ONNX 변환: PyTorch 모델을 ONNX 포맷으로 변환하여 다양한 프레임워크와 호환성을 높임.(model.onnx)
    2. TensorFlow 변환: ONNX 모델을 TensorFlow 포맷으로 변환하여 TensorFlow Lite로 변환할 준비를 함. (saved_model.pb)
    3. TensorFlow Lite 변환: TensorFlow 모델을 TensorFlow Lite 포맷으로 변환하여 모바일 환경에서 실행 가능하게 함. (bert_model.tflite)  

 


  • 작업 환경 : 구글 Colab 
연결된 런타임:
Python 3 Google Compute Engine 백엔드 (GPU)
RAM: 10.09 GB/12.67 GB
디스크: 31.70 GB/78.19 GB

[모델 변환]

▶변환을 왜해?

1. Android 호환성: 
TensorFlow Lite는 Android 및 iOS와 같은 모바일 및 임베디드 장치에서 기계 학습 모델을 실행하기 위해 설계되었습니다. PyTorch 모델(pytorch_model.bin)은 직접적으로 Android에서 실행할 수 없기 때문에 TensorFlow Lite 형식으로 변환해야 합니다.

2. 성능 최적화: 
TensorFlow Lite는 모델을 모바일 장치에서 효율적으로 실행할 수 있도록 최적화된 인터프리터를 제공합니다. 이는 메모리 사용량을 줄이고, 추론 시간을 단축시킵니다.

3. 경량화: 
TensorFlow Lite 모델은 경량화되어 모바일 장치에서 빠르고 효율적으로 실행할 수 있습니다. 이는 배터리 소모와 같은 자원 소비를 줄여줍니다.

4. 에코시스템 통합: 
TensorFlow Lite는 TensorFlow 에코시스템의 일부로, Android에서 쉽게 통합할 수 있는 다양한 도구와 라이브러리를 제공합니다.

▶변환 파이썬 코드

ㆍPyTorch to ONNX

    *PyTorch가 뭔데

더보기

1. PyTorch 모델 (pytorch_model.bin)

  • 구조: PyTorch 모델은 .bin 형식으로 저장됩니다. 이는 PyTorch 프레임워크에서 모델의 가중치와 구조를 포함하는 바이너리 파일입니다.
  • 유연성: PyTorch는 동적 연산 그래프를 사용하여 유연한 모델 정의와 디버깅을 지원합니다.
  • 학습 및 추론: 주로 학습(Training)과 추론(Inference)에 사용되며, 연구 및 프로토타입 개발에 적합합니다.
  • 호환성 문제: PyTorch 모델은 Android와 같은 모바일 장치에서 직접 실행하기 어렵습니다.

     * ONNX가 뭔데

더보기

2. ONNX 모델 (bert_model.onnx)

  • 구조: ONNX(Open Neural Network Exchange) 모델은 다양한 딥러닝 프레임워크 간의 상호 운용성을 제공하기 위해 설계된 오픈 형식입니다.
  • 변환: PyTorch 모델을 ONNX 형식으로 변환하여 다른 프레임워크(TensorFlow 등)에서 사용할 수 있습니다.
  • 유연성: 다양한 딥러닝 프레임워크에서 모델을 사용할 수 있도록 지원합니다.
  • 중간 형식: ONNX는 주로 모델 변환의 중간 형식으로 사용됩니다.

     *변환 코드

더보기
# 1.PyTorch 모델을 조각으로 나누어 ONNX로 변환:

import torch
import torch.onnx
import onnx
from transformers import BertForSequenceClassification, BertConfig, BertTokenizer

# 모델 경로 및 설정
model_dir = '/content/gdrive/MyDrive/Uplus/bert/module/model240423_ver6.6.5_현장등록용_epoch5'
model_path = f'{model_dir}/pytorch_model.bin'
onnx_model_path = '/content/gdrive/MyDrive/Uplus/AndroidStudio/lite_model1/model.onnx'

# Bert 모델 구성 로드
config = BertConfig.from_pretrained(model_dir)
tokenizer = BertTokenizer.from_pretrained(model_dir)

# PyTorch 모델 로드
state_dict = torch.load(model_path, map_location=torch.device('cpu'))

# BertForSequenceClassification 인스턴스 생성 및 state_dict 로드
pytorch_model = BertForSequenceClassification(config)
pytorch_model.load_state_dict(state_dict)

# 사용자 정의 래퍼 함수
class CustomModel(torch.nn.Module):
    def __init__(self, model):
        super(CustomModel, self).__init__()
        self.model = model

    def forward(self, input_ids):
        outputs = self.model(input_ids)
        return outputs.logits

wrapped_model = CustomModel(pytorch_model)

# PyTorch 모델을 ONNX로 변환
dummy_input = torch.randint(0, config.vocab_size, (1, 128)).to('cpu')  # 모델에 맞는 입력 크기로 설정 (BertModel은 일반적으로 1, 128)
torch.onnx.export(wrapped_model, dummy_input, onnx_model_path, 
                  input_names=["input_ids"], output_names=["logits"], opset_version=14)

print("ONNX model conversion completed successfully.")

ㆍONNX to TensorFlow

 

     * TensorFlow가 뭔데

더보기

3. TensorFlow 모델 (bert_model.pb)

  • 구조: TensorFlow 모델은 .pb 형식(Protocol Buffers)으로 저장됩니다. 이는 모델의 그래프 구조와 가중치를 포함합니다.
  • 광범위한 사용: 연구, 프로덕션, 모바일 등 다양한 환경에서 사용됩니다.
  • 성능 최적화: TensorFlow는 모델 최적화 및 배포를 위한 다양한 도구와 라이브러리를 제공합니다.
  • 변환 용이성: TensorFlow 모델은 TensorFlow Lite 모델로 쉽게 변환할 수 있습니다.

     *변환 코드

더보기

 

# 2.ONNX 모델을 조각으로 나누어 TensorFlow로 변환:
import onnx
import tensorflow as tf
from onnx_tf.backend import prepare

# ONNX 모델 로드
onnx_model_path = '/content/gdrive/MyDrive/Uplus/AndroidStudio/lite_model1/model.onnx'
onnx_model = onnx.load(onnx_model_path)

# ONNX 모델을 TensorFlow 모델로 변환
tf_rep = prepare(onnx_model)
tf_model_dir = '/content/gdrive/MyDrive/Uplus/AndroidStudio/lite_model1/model_tf'
tf_rep.export_graph(tf_model_dir)

print("TensorFlow model conversion completed successfully.")

ㆍTensorFlow to TensorFlow Lite

 

     *TensorFlow Lite가 뭔데

더보기

4. TensorFlow Lite 모델 (bert_model.tflite)

  • 구조: TensorFlow Lite 모델은 .tflite 형식으로 저장됩니다. 이는 경량화되고 최적화된 모델 형식입니다.
  • 모바일 최적화: 모바일 및 임베디드 장치에서의 빠르고 효율적인 추론을 위해 최적화되었습니다.
  • 성능: 메모리 사용량이 적고, 빠른 추론 시간을 제공합니다.
  • 경량화: 모델의 크기가 작아 배포 및 실행 시 자원 소모를 최소화합니다.
  • 에코시스템 통합: TensorFlow Lite는 Android 및 iOS와 같은 플랫폼에서 쉽게 통합하고 사용할 수 있는 도구와 라이브러리를 제공합니다.

     *변환 코드

더보기

 

# 3.TensorFlow 모델을 조각으로 나누어 TensorFlow Lite로 변환:
import tensorflow as tf

# TensorFlow 모델을 TFLite로 변환
converter = tf.lite.TFLiteConverter.from_saved_model(tf_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS,  # Enable default ops.
                                       tf.lite.OpsSet.SELECT_TF_OPS]  # Enable TensorFlow ops.
tflite_model = converter.convert()

# TFLite 모델 저장
tflite_model_path = '/content/gdrive/MyDrive/Uplus/AndroidStudio/lite_model1/bert_model.tflite'
with open(tflite_model_path, "wb") as f:
    f.write(tflite_model)

print("TFLite model conversion completed successfully.")

 


 


ㆍ 계획 ② (필요시)변경된 파일에 추가 경량화

  • tflite파일 사이즈가 커서(100MB보다 작아야 한다고 함) 앱에서 구동이 안됨. 추가 경량화가 필요함.
  • 모델 경량화 방안은 여러가지임. 
    ▽ 간략히 비교글 ▽
더보기

모델 경량화 방안 정리 각 단계와 사용된 방법, 생성된 파일, 그리고 해당 방식의 특징

  1. Quantize 방식
    입력 파일: saved_model.pb
    출력 파일: quantized_model.tflite
    특징: 모델의 파라미터 값을 32비트에서 8비트로 줄여 모델 크기를 줄이고 속도 향상.
  2. Prune 방식
    입력 파일: saved_model.pb
    출력 파일: pruned_model.tflite
    특징: 모델의 불필요한 파라미터를 제거하여 경량화. 
  3. Simplified 방식
    입력 파일: model.onnx
    출력 파일: model_simplified.onnx
    특징: 모델의 불필요한 연산을 제거하여 경량화.
  4. Sliced 방식
    입력 파일: model.onnx
    출력 파일: model_sliced.onnx
    특징: 모델의 일부 레이어를 제거하여 경량화. 
  5. Hybrid 방식
    입력 파일: model.onnx
    출력 파일: hybrid_model.tflite
    특징: Prune와 Quantize 방식 등을 혼합하여 경량화를 시도. 

 



- 프루닝작업 수행

더보기
# [추가] 프루닝(Pruning): 가중치의 일부를 제거하여 모델 크기를 줄이는 방법
# !pip install tensorflow_model_optimization
import tensorflow as tf
import numpy as np
from transformers import TFBertForSequenceClassification, BertConfig
import tensorflow_model_optimization as tfmot

# 모델 디렉토리 및 경로
model_dir = '/content/gdrive/MyDrive/Uplus/bert/module/model240423_ver6.6.5_현장등록용_epoch5'
model_path = f'{model_dir}/pytorch_model.bin'
saved_model_dir = '/content/gdrive/MyDrive/Uplus/AndroidStudio/lite_model1/model_tf'
tflite_model_path = '/content/gdrive/MyDrive/Uplus/AndroidStudio/lite_model1/bert_model_pruned.tflite'

# Bert 모델 구성 로드
config = BertConfig.from_pretrained(model_dir)
model = TFBertForSequenceClassification.from_pretrained(model_dir, from_pt=True)

# 프루닝 적용 함수 정의
prune_low_magnitude = tfmot.sparsity.keras.prune_low_magnitude

pruning_params = {
    'pruning_schedule': tfmot.sparsity.keras.PolynomialDecay(initial_sparsity=0.50,
                                                             final_sparsity=0.80,
                                                             begin_step=0,
                                                             end_step=1000)
}

# 프루닝 적용 가능 여부를 확인하는 함수
def is_prunable(layer):
    return isinstance(layer, tf.keras.layers.Dense) or isinstance(layer, tf.keras.layers.Conv2D)

# 모델의 프루닝을 적용한 레이어를 반환하는 함수
def apply_pruning_to_layers(model):
    for i, layer in enumerate(model.layers):
        if is_prunable(layer):
            model.layers[i] = prune_low_magnitude(layer, **pruning_params)
        if hasattr(layer, 'layers'):
            model.layers[i] = apply_pruning_to_layers(layer)
    return model

# 프루닝 적용된 모델 생성
model = apply_pruning_to_layers(model)

# 모델 컴파일
model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

# 프루닝 동안 모델 훈련
logdir = "/content/gdrive/MyDrive/Uplus/AndroidStudio/logs"
callbacks = [
    tfmot.sparsity.keras.UpdatePruningStep(),
    tfmot.sparsity.keras.PruningSummaries(log_dir=logdir),
]

# 여기서는 예제 데이터셋을 사용했으나 실제 데이터셋으로 대체해야 함
# 데이터 타입을 int32로 설정
input_ids = np.random.randint(0, config.vocab_size, (32, 128), dtype=np.int32)
labels = np.random.randint(0, 2, (32,), dtype=np.int32)  # 레이블 데이터가 None이 아닌지 확인

train_data = tf.data.Dataset.from_tensor_slices((input_ids, labels))
train_data = train_data.batch(8)

model.fit(train_data, epochs=2, callbacks=callbacks)

# 프루닝 스트립 함수
def strip_pruning_from_layers(model):
    for layer in model.layers:
        if isinstance(layer, tfmot.sparsity.keras.PruneLowMagnitude):
            model = tfmot.sparsity.keras.strip_pruning(layer)
        if hasattr(layer, 'layers'):
            strip_pruning_from_layers(layer)
    return model

# 프루닝 스트립 및 저장
model = tf.keras.models.clone_model(model)
model.save(saved_model_dir, save_format='tf')

# TFLite 변환자 생성 (양자화 적용)
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]

# TFLite 모델 변환
tflite_model = converter.convert()

# TFLite 모델 저장
with open(tflite_model_path, 'wb') as f:
    f.write(tflite_model)

print("Pruned TFLite model conversion completed successfully.")

결과 : 170M로 경량화됨

 

 


 

 

 

 


ㆍ 계획 (번외) ③ 경량화된 모델파일 생성하고 경량화 추가작업 수행

  • tflite파일 사이즈가 커서(100MB보다 작아야 한다고 함) 앱에서 구동이 안됨. 추가 경량화가 필요함.
  • 채택 방식 : 기존의 BERT모델을 아예 다시만든다. 처음부터 경량화BERT를 만들고 그 다음에 경량화작업을 또 한다.
  • 모델 자체를 작게하는 방법을 수행한 뒤 경량화를 진행하는 것임. 

 

ㆍ경량화BERT..? 그게 뭔데

더보기

BERT 모델과 DistilBERT의 차이 및 선택 이유

BERT와 DistilBERT의 차이

  • BERT (Bidirectional Encoder Representations from Transformers):
    • BERT는 Google에서 개발한 대규모 사전 학습 언어 모델로, 자연어 처리(NLP) 작업에서 뛰어난 성능을 보입니다.
    • 많은 매개변수(약 110M~340M 파라미터)를 가지고 있으며, 여러 NLP 태스크에서 우수한 성능을 보여줍니다.
    • 그러나 대규모 모델이므로 훈련 및 추론 시 많은 계산 자원과 시간이 필요합니다.
  • DistilBERT:
    • DistilBERT는 BERT의 경량화 버전으로, Hugging Face에서 개발하였습니다.
    • BERT의 약 60%의 파라미터와 계산량을 가지면서도 성능의 약 97%를 유지합니다.

모델 크기가 작아 추론 속도가 빠르고, 계산 자원이 적게 들기 때문에 모바일 및 임베디드 시스템에 적합합니다.

 

ㆍ파일 용량 변화 비교

  1. BERT 모델 변환 과정
    • BERT 모델 (700MB) -> TensorFlow Lite 모델 (170MB)
  2. DistilBERT 모델 변환 과정
    • DistilBERT 모델 (517MB) -> TensorFlow Lite 모델 (65.5M)

 

 

 

 

 


 

 

끝.

반응형