데보션앱 소개페이지 바로가기
로그인 선택

신고하기

CLOSE
신고사유 (대표 사유 1개)
상세내용 (선택)
0/200
  • 신고한 게시글은 더 이상 보이지 않습니다.
  • 이용약관과 운영정책에 따라 신고사유에 해당하는지 검토 후 조치됩니다.
  • 허위 신고인 경우, 신고자의 서비스 이용이 제한될 수 있으니 유의하시어 신중하게 신고해 주세요.
(이 회원이 작성한 모든 댓글과 커뮤니티 게시물이 보이지 않고, 알림도 오지 않습니다.)

미리보기

커뮤니티

      1,234

      badge 23.06.15

      글 등록

      카테고리를 선택해주세요.

      DEVOTEE를 활성화 시키면
      지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.

      버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.

      임시저장함에 저장되었습니다. 저장일시 : 2022.5.17 14:29:08

      임시저장함

      제목을 선택하시면 이어서 작성이 가능하며,
      최대 20건까지 저장합니다.
      컨텐츠 유형, 제목, 저장일시, 삭제로 이뤄진 임시저장 목록
      컨텐츠 유형 제목 저장일 삭제

      데보션 블로그 게재 요청

      CLOSE
      • *
      • *

      본인인증

      효율적인 데보션 서비스 이용 및
      고객님의 소중한 개인정보보호를 위해
      본인인증을 진행해주세요. 본인인증 미 진행 시 로그인이 제한됩니다.
      본인인증 실패

      본인인증 로그인에 실패하였습니다.
      회원이 아니시거나 본인인증 등록이
      완료되지 않은 사용자입니다.

      회원정보 연결

      안드로이드에서 Gemma2 파인튜닝 모델 실행하기

      shkwak 24.11.11
      2,511 12 0
      DEVOTEE 요약
      본 블로그에서는 안드로이드에서 파인튜닝된 Gemma2 모델을 실행하는 방법을 설명합니다. 파인튜닝된 모델을 MediaPipe용 모델로 변환하여 안드로이드에서 실행하고, 결과를 비교하여 파인튜닝 전후의 모델 성능을 평가합니다. 자체적인 파인튜닝 모델을 활용할 수 있어 다양한 응용 분야에서 사용될 수 있습니다.
      DEVOTEE 추천 블로그

      지난 포스팅에서 "안드로이드에서 On-Device로 Gemma 1 & 2 실행하기"에 대한 주제를 살펴보았습니다.

      최근 MediaPipe 관련 라이브러리가 업데이트 된 후 파인튜닝 된 모델도 잘 동작하는 것을 확인하여 관련 내용을 다뤄보고자 합니다.

      파인튜닝은 이미 훈련된 모델을 특정 작업이나 목적에 맞게 새로운 데이터를 추가적으로 학습시키는 과정을 뜻합니다.

      일부 가중치만 추가적으로 학습시켜도 좋은 출력을 생성해 낼 수 있기 때문에 시간과 비용을 절약할 수 있습니다.


      안드로이드에서 파인튜닝된 모델을 실행하는 과정은 크게 아래와 같이 나눌 수 있습니다.

      • Gemma2 모델(.safetensors)을 파인튜닝 하기

      • 파인튜닝된 모델(.safetensors)을 MediaPipe 모델(.bin)로 변환

      • Android에서 MediaPipe 모델(.bin) 실행하기


      첫번째, .safetensors 파일을 파인튜닝 하는 법은 이미 많이 방법들이 소개되어 있고 여기선 기존 데보션에 소개되었던 방법을 사용합니다.

      네이버 기사 요약 데이터셋을 사용하여 한국어 요약 모델로 만드는 방법입니다.


      두번째, 안드로이드에서 바로 .safetensors 형식의 모델을 실행하기는 어렵기 때문에 MediaPipe용 모델(.bin)로 변환이 필요합니다.

      관련 Converter는 MediaPipe에서 제공해주고 있습니다.


      마지막으로, MediaPipe용 모델(.bin)을 안드로이드에서 불러오면 되는데

      해당 방법은 "안드로이드에서 On-Device로 Gemma 1 & 2 실행하기"의  MediaPipe를 통한 Gemma 모델 실행과 동일하게 진행됩니다.


      * 참고로 아래 코드는 Colab Pro의 L4 GPU에서 구동하였습니다. (무료로 제공하고 있는 T4 GPU에서는 현재 MediaPipe용 모델 변환과정에서 메모리 부족으로 세션이 다운됩니다.)


      1 - 한국어 요약 모델 파인튜닝

      Gemma2 모델의 파인튜닝은 기본적으로 alankim님이 작성하신 "Gemma 한국어 요약 모델 파인튜닝 빠르게 해보기"를 참고하시면 어렵지 않게 진행하실 수 있습니다.

      여기서는 꼭 필요한 부분만 간략히 설명하도록 하겠습니다.

      필수 라이브러리 설치하기

      아래 라이브러리를 최신 버전들로 설치해줍니다.

      !pip3 install --U transformers
      !pip3 install --U datasets
      !pip3 install --U bitsandbytes
      !pip3 install --U peft
      !pip3 install --U trl
      !pip3 install --U accelerate

      Import modules

      import torch
      from datasets import Dataset, load_dataset
      from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig, pipeline, TrainingArguments
      from peft import LoraConfig, PeftModel
      from trl import SFTTrainer

      Huggingface 로그인

      from huggingface_hub import notebook_login
      notebook_login()

      데이터셋 로드

      네이버 기사 요약 데이터셋을 불러 오도록 합니다.

      from datasets import load_dataset
      dataset = load_dataset("daekeun-ml/naver-news-summarization-ko")

      해당 데이터셋은 아래와 같은 내용을 담고 있습니다.

      {
       ...
       'document': '앵커 정부가 올해 하반기 우리 경제의 버팀목인 수출 확대를 위해 총력을 기울이기로 했습니다. 특히 수출 중소기업의 물류난 해소를 위해 무역금융 규모를 40조 원 이상 확대하고 물류비 지원과 임시선박 투입 등을 추진하기로 했습니다. 류환홍 기자가 보도합니다. 기자 수출은 최고의 실적을 보였지만 수입액이 급증하면서 올해 상반기 우리나라 무역수지는 역대 최악인 103억 달러 적자를 기록했습니다. 정부가 수출확대에 총력을 기울이기로 한 것은 원자재 가격 상승 등 대외 리스크가 가중되는 상황에서 수출 증가세 지속이야말로 한국경제의 회복을 위한 열쇠라고 본 것입니다. 추경호 경제부총리 겸 기획재정부 장관 정부는 우리 경제의 성장엔진인 수출이 높은 증가세를 지속할 수 있도록 총력을 다하겠습니다. 우선 물류 부담 증가 원자재 가격 상승 등 가중되고 있는 대외 리스크에 대해 적극 대응하겠습니다. 특히 중소기업과 중견기업 수출 지원을 위해 무역금융 규모를 연초 목표보다 40조 원 늘린 301조 원까지 확대하고 물류비 부담을 줄이기 위한 대책도 마련했습니다. 이창양 산업통상자원부 장관 국제 해상운임이 안정될 때까지 월 4척 이상의 임시선박을 지속 투입하는 한편 중소기업 전용 선복 적재 용량 도 현재보다 주당 50TEU 늘려 공급하겠습니다. 하반기에 우리 기업들의 수출 기회를 늘리기 위해 2 500여 개 수출기업을 대상으로 해외 전시회 참가를 지원하는 등 마케팅 지원도 벌이기로 했습니다. 정부는 또 이달 중으로 반도체를 비롯한 첨단 산업 육성 전략을 마련해 수출 증가세를 뒷받침하고 에너지 소비를 줄이기 위한 효율화 방안을 마련해 무역수지 개선에 나서기로 했습니다. YTN 류환홍입니다.',
       'summary': '올해 상반기 우리나라 무역수지는 역대 최악인 103억 달러 적자를 기록한 가운데, 정부가 하반기에 우리 경제의 버팀목인 수출 확대를 위해 총력을 기울이기로 결정한 가운데, 특히 수출 중소기업의 물류난 해소를 위해 무역금융 규모를 40조 원 이상 확대하고 물류비 지원과 임시선박 투입 등을 추진하기로 했다.'
      }

      모델 다운로드

      REPO_ID은 허깅페이스 Gemma2 모델에 맞춰서 google/gemma-2-2b-it 을 지정해줍니다.

      BASE_MODEL은 Gemma2 모델이 다운로드 될 위치를 지정해줍니다.

      from huggingface_hub import hf_hub_download
       
      REPO_ID = "google/gemma-2-2b-it"
      BASE_MODEL = "./gemma-2-2b-it"
       
      FILENAMES = ["tokenizer.json", "tokenizer_config.json", "model-00001-of-00002.safetensors", "model-00002-of-00002.safetensors", "config.json", "model.safetensors.index.json"]
      for filename in FILENAMES:
          hf_hub_download(repo_id=REPO_ID, filename=filename, local_dir=BASE_MODEL)

      학습용 프롬프트 및 훈련용 데이터셋

      def generate_prompt(example):
          prompt_list = []
          for i in range(len(example['document'])):
              prompt_list.append(r"""<bos><start_of_turn>user
      다음 글을 요약해주세요:
       
      {}<end_of_turn>
      <start_of_turn>model
      {}<end_of_turn><eos>""".format(example['document'][i], example['summary'][i]))
          return prompt_list
      train_data = dataset['train']

      QLoRA 설정

      LoraConfig에서 target_modules은 ["q_proj", "o_proj", "k_proj", "v_proj"]로 지정해주었습니다.

       ["gate_proj", "up_proj", "down_proj"] 레이어들도 포함해도 되지만 직접 테스트본 결과 학습량이 적어서인지 몰라도 ["q_proj", "o_proj", "k_proj", "v_proj"]만 지정했을 때 결과가 더 좋게 나왔습니다.

      lora_config = LoraConfig(
          r=6,
          lora_alpha = 8,
          lora_dropout = 0.05,
          target_modules=["q_proj", "o_proj", "k_proj", "v_proj"],
          task_type="CAUSAL_LM",
      )
       
      bnb_config = BitsAndBytesConfig(
          load_in_4bit=True,
          bnb_4bit_quant_type="nf4",
          bnb_4bit_compute_dtype=torch.float16
      )

      모델 로드

      model = AutoModelForCausalLM.from_pretrained(BASE_MODEL, device_map="auto", quantization_config=bnb_config)
      tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL)
      tokenizer.padding_side = 'right'

      Trainer 실행

      trainer = SFTTrainer(
          model=model,
          train_dataset=train_data,
          max_seq_length=512,
          tokenizer=tokenizer,
          args=TrainingArguments(
              output_dir="outputs",
      #        num_train_epochs = 1,
              max_steps=3000,
              per_device_train_batch_size=1,
              gradient_accumulation_steps=4,
              optim="paged_adamw_8bit",
              warmup_ratio=0.03,
              learning_rate=2e-4,
              fp16=True,
              logging_steps=100,
              push_to_hub=False,
              report_to='none',
          ),
          peft_config=lora_config,
          formatting_func=generate_prompt,
      )

      Finetuned Model 저장

      훈련을 시작합니다. L4 GPU로 3000 steps를 수행했을 때 1시간 20분 정도의 시간이 소요됩니다.

      trainer.train()

      우선, 학습된 adapter 모델을 저장합니다.

      ADAPTER_MODEL = "lora_adapter"
      trainer.model.save_pretrained(ADAPTER_MODEL)

      그 다음, base모델과 adapter모델을 합쳐서 하나의 모델로 만들어서 저장합니다.

      model = AutoModelForCausalLM.from_pretrained(BASE_MODEL, device_map='auto', torch_dtype=torch.float16)
      model = PeftModel.from_pretrained(model, ADAPTER_MODEL, device_map='auto', torch_dtype=torch.float16)
       
      FINETUNED_MODEL = "./gemma-2-2b-it-sum-ko"
      model = model.merge_and_unload()
      model.save_pretrained(FINETUNED_MODEL)


      2- MediaPipe용 모델로 변환하기

      Android에서 실행하기 위해서 MediaPipe용 모델로 변환이 필요합니다.

      구글에서 배포중인 LLM Conversion 스크립트를 참고하였는데 Gemma2에 맞춰서 몇 군데 추가적으로 수정을 하였습니다.


      mediapipe를 설치할 때 mediapipe-nightly 버전을 설치해서 최신 수정 사항들도 내려 받을 수 있도록 합니다.

      !pip install mediapipe-nightly
      !pip install torch
      !pip install huggingface_hub
      import os
      from mediapipe.tasks.python.genai import converter

      ConversionConfig를 생성할 때 model_type에 GEMMA_2B가 아니라 GEMMA2_2B를 지정합니다.

      def gemma_convert_config():
        input_ckpt = FINETUNED_MODEL
        vocab_model_file = BASE_MODEL
        output_dir = '/content/intermediate/gemma-2-2b-it/'
        output_tflite_file = f'/content/converted_models/gemma2_gpu.bin'
        return converter.ConversionConfig(input_ckpt=input_ckpt, ckpt_format='safetensors', model_type='GEMMA2_2B', backend='gpu', output_dir=output_dir, combine_file_only=False, vocab_model_file=vocab_model_file, output_tflite_file=output_tflite_file)

      변환 작업을 시작합니다.

      config = gemma_convert_config()
      converter.convert_checkpoint(config)

      output_tflite_file로 지정한 경로(/content/converted_models/gemma2_gpu.bin)에 변환된 모델이 생성된 것을 확인할 수 있습니다.


      3 - On-device로 파인튜닝 모델 실행하기

      위에서 생성한 파일을 다운로드 받아서 디바이스에 복사합니다.

      adb shell mkdir -p /data/local/tmp/llm/
      adb push gemma2_gpu.bin /data/local/tmp/llm/gemma2_gpu.bin

      MediaPipe LLM Inference Android Demo 소스(https://github.com/google-ai-edge/mediapipe-samples/tree/main/examples/llm_inference/android)를 받은 후 모델 경로를 적절히 수정 후 빌드하여 설치합니다.

      val options = LlmInferenceOptions.builder()
              .setModelPath("/data/local/tmp/llm/gemma2_gpu.bin")
              .setMaxTokens(1000)
              .setTopK(40)
              .setTemperature(0.8)
              .setRandomSeed(101)
              .setResultListener { partialResult, done ->
                  _partialResults.tryEmit(partialResult to done)
              }
              .build()
        
      llmInference = LlmInference.createFromOptions(context, options)


      4 - 파인튜닝 전후 결과 비교

      파인튜닝 전 (기본 Gemma2 모델)

      파인튜닝 후

      파인튜닝 후에 학습한대로 내용을 간략하게 요약해서 출력해주는 것을 확인할 수 있습니다.


      5 - 마무리

      Gemma2 모델을 파인튜닝 하고 MediaPipe용 모델로 변환 후 안드로이드에서 On-device로 실행하는 과정까지 살펴보았습니다.

      누구나 자신만의 파인튜닝 모델을 만들어서 실행할 수 있기 때문에 그 활용분야는 더욱 넓어질 것 같습니다.

      한가지 아쉬운 점은 긴 문장을 입력하였을 때 처리하지 못하고 로딩 상태를 유지하는 경우가 있습니다.

      관련 라이브러리들이 지속적으로 업데이트 되고 있으므로 이런 문제는 곧 해결될 것으로 기대합니다.


      Reference

      댓글 0

      DEVOTEE를 활성화 시키면
      지금 작성한 댓글에 AI가 댓글을 달아줍니다.

      shkwak 님의 최신 블로그

      더보기

      DEVOTEE 추천 블로그

      동영상 기고하기