Windows PyCharm에서 streamlit app debug하기

streamlit app에서 발생한 에러의 원인을 찾기 어려워서 debug를 하려고 하는데, IDE 없이 그냥 하려니 너무 막막하고, 범세계 툴인 PyCharm에서는 어떻게 하는지 찾기가 어려웠다.

사용 환경

  • Windows 환경의 PyCharm 이용
  • conda 사용하지 않고, PyCharm의 venv 활용

현재 Interpreter 위치 확인

“Settings > Project: {project_name} > Python Interpreter” 에서 Interpreter path 확인 및 복사

Debug 설정 변경

아래 순서로 디버그 시 실행할 스크립트를 지정한다. script 위치 지정 시, Copy & Paste 하지말고, python.exe만 streamlit.exe로 변경하도록 한다.

내용은 같지만, Copy & Paste 하니까 “Invalid or missing encoding declaration …” 에러를 해결하지 못하고 한참을 헤매었다. 안전하게 변경하도록 하자.

oobabooga/text-generation-webui 실행 시, undefined symbol 문제

최애 git 프로젝트인 oobabooga/text-generation-webui를 실행한 다음, huggingface에서 다운로드 받은 모델을 로드하면 undefined symbol 에러가 나는 문제를 정리한다.

$ python
>>> import torch
>>> print(torch.cuda.is_available())
True
>>> torch.__version__
'2.2.0+cu121'

CUDA, Pytorch까지 잘 설치된 것 같은데, 모델만 로딩하면 아래와 같은 에러가 발생한다.

ImportError: /home/idjung/miniconda3/envs/textgen/lib/python3.11/site-packages/flash_attn_2_cuda.cpython-311-x86_64-linux-gnu.so: undefined symbol: _ZN2at4_ops9_pad_enum4callERKNS_6TensorEN3c108ArrayRefINS5_6SymIntEEElNS5_8optionalIdEE

CUDA 버전에 문제가 있는 것인지, GPU Driver에 문제가 있는 것인지, 버전이 맞지 않는 문제인지 싶어서, 라이브러리를 다시 설치해 보고, 버전 별로 다시 설치해 보았는데도 해결이 되지 않았다.

에러 메시지에 집중하고, 다시 천천히 구글링해 보다가 아래와 같이 답을 얻었다. 이전에 보지 못한 메시지에 당황하지 말고, 아래와 같이 패키지를 다시 빌드해 보도록 한다. 빌드 시간이 길기 때문에 인내심을 가지고 기다리도록 한다. (AMD Ryzen 9 3900X에서 1시간 정도 걸린 거 같다.)

$ pip uninstall flash-attn
$ FLASH_ATTENTION_FORCE_BUILD=TRUE pip install flash-attn

ubuntu 22.04 LTS에 RTX-3090 설치하여, LLM 실행하기

컴퓨터에 Linux 설치하고, RTX-3090 을 인식시키는 걸 반복하고 있다. 순서를 정리해 두려고 한다.

1. UBUNTU 22.04 LTS server 설치

간단한 서비스를 개발하기 위해 UBUNTU 서버용을 설치한다.

2. GUI 설치

개발 환경을 간단하게 꾸미기 위해, GUI를 설치한다. 상황에 따라 불필요할 것 같기도 하다. 처음에는 이 환경으로 사용했지만, 나중에는 이 단계를 패스하고 있다.

$ apt install ubuntu-desktop

3. NVIDIA Driver 설치

드라이버를 설치하기 위해 시스템 정보를 수집한다.

$ lspci | grep -i nvidia
07:00.0 VGA compatible controller: NVIDIA Corporation GA102 [GeForce RTX 3090] (rev a1)
07:00.1 Audio device: NVIDIA Corporation GA102 High Definition Audio Controller (rev a1)

$ sudo apt install ubuntu-drivers-common
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
ubuntu-drivers-common is already the newest version (1:0.9.6.2~0.22.04.6).
ubuntu-drivers-common set to manually installed.
0 upgraded, 0 newly installed, 0 to remove and 6 not upgraded.

$ sudo ubuntu-drivers devices
== /sys/devices/pci0000:00/0000:00:03.1/0000:07:00.0 ==
modalias : pci:v000010DEd00002204sv00001043sd000087AFbc03sc00i00
vendor   : NVIDIA Corporation
model    : GA102 [GeForce RTX 3090]
driver   : nvidia-driver-535-server - distro non-free
driver   : nvidia-driver-535-server-open - distro non-free
driver   : nvidia-driver-535-open - distro non-free
driver   : nvidia-driver-525-server - distro non-free
driver   : nvidia-driver-470 - distro non-free
driver   : nvidia-driver-525-open - distro non-free
driver   : nvidia-driver-470-server - distro non-free
driver   : nvidia-driver-525 - distro non-free
driver   : nvidia-driver-535 - distro non-free recommended
driver   : xserver-xorg-video-nouveau - distro free builtin

드라이버를 설치하는 방법은 2가지가 있는데, 편한 걸 선택하길 바란다. 필자는 버전을 콕 집어서 설치하는 것을 선호한다.

#1) Option 1
$ sudo apt install nvidia-driver-535

#2) Option 2
$ sudo add-apt-repository ppa:graphics-drivers/ppa
$ sudo apt-get update
$ sudo ubuntu-drivers autoinstall

$ sudo reboot now

# 확인
$ nvidia-smi
Thu Jan 18 08:18:08 2024       
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.146.02             Driver Version: 535.146.02   CUDA Version: 12.2     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA GeForce RTX 3090        Off | 00000000:07:00.0  On |                  N/A |
|  0%   33C    P8              31W / 390W |    544MiB / 24576MiB |      0%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+
                                                                                         
+---------------------------------------------------------------------------------------+
| Processes:                                                                            |
|  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
|        ID   ID                                                             Usage      |
|=======================================================================================|
|    0   N/A  N/A      2002      G   /usr/lib/xorg/Xorg                          116MiB |
|    0   N/A  N/A      2135      G   /usr/bin/gnome-shell                        118MiB |
|    0   N/A  N/A      2584      G   ...irefox/3626/usr/lib/firefox/firefox      296MiB |
+---------------------------------------------------------------------------------------+

4. CUDA 설치

CUDA 12.1 설치 과정이다. 필요한 경우, NVIDIA 홈페이지(https://developer.nvidia.com/cuda-downloads) 참고한다.

$ sudo apt install nvidia-cuda-toolkit

$ wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-ubuntu2204.pin
$ sudo mv cuda-ubuntu2204.pin /etc/apt/preferences.d/cuda-repository-pin-600
$ wget https://developer.download.nvidia.com/compute/cuda/12.1.1/local_installers/cuda-repo-ubuntu2204-12-1-local_12.1.1-530.30.02-1_amd64.deb
$ sudo dpkg -i cuda-repo-ubuntu2204-12-1-local_12.1.1-530.30.02-1_amd64.deb
$ sudo cp /var/cuda-repo-ubuntu2204-12-1-local/cuda-*-keyring.gpg /usr/share/keyrings/
$ sudo apt-get update
$ sudo apt-get -y install cuda

5. miniconda 설치

여러 버전의 파이썬 환경을 구축하고 테스트하려면, conda가 꼭 필요하다.

https://docs.conda.io/projects/miniconda/en/latest/ 에서 파일을 받아서 설치한다.

6. LLM 환경 설치(Python 및 Pytorch 포함)

Oobabooga 설치해서 Pytorch까지 테스트한다.

$ /home/idjung/miniconda3/bin/conda init

$ conda create -n textgen python=3.10.10

$ git clone https://github.com/oobabooga/text-generation-webui.git

$ cd text-generation-webui/

$ pip install -r requirements.txt

$ python 

>>> import torch
>>> print(torch.cuda.is_available())
True

7. Huggingface에서 Model 다운로드

필요한 모델을 다운로드 한다.

$ python download-model.py ~~

8. Oobabooga 실행

잘 동작한다! 만세!

Custom Domain Data를 이용한 BERT 파인튜닝(번역)

원문: Training BERT from Scratch on Your Custom Domain Data: A Step-by-Step Guide with Amazon SageMaker

※ 한글을 최대한 쓰지만, 단어가 헷갈릴 수 있는 경우에는 영문을 그대로 사용한다.

Background

LLM(Large Language Model)은 일반적으로 언어 내 통계 패턴과 관계를 학습하기 위해 책, 아티클 및 기타 자료 등 대량 텍스트 데이터에 대해 훈련되는 기계 학습(ML) 모델의 한 형태이다. LLM은 다양한 NLP(Natural Language Processing) 작업에 사용할 수 있으며 다양한 벤치마크에서 인상적인 성능을 보여주었다. 기존의 NLP 및 NLU(Natural Language Understanding) 시스템은 원하는 성능을 달성하기 위해 상당한 양의 Labeled 훈련 데이터와 세심한 feature engineering이 필요하다. 그러나 BERT 및 기타 트랜스포머 기반 모델은 Labeled 데이터가 없거나 최소한으로 여러 언어 작업을 실행하는 방법을 배울 수 있으며 상대적으로 적은 노력으로 특정 task에 파인튜닝할 수 있다. 이를 통해 NLP 및 NLU 시스템의 개발 및 배포가 용이해졌고 새로운 세대의 정교한 언어 인식 응용 프로그램을 만들 수 있다.

전이 학습(Transfer learning)은 비교적 적은 양의 Labeled 훈련 데이터를 사용하여 특정 작업 또는 도메인에 대한 LLM을 파인튜닝할 수 있는 방법론이다. 이는 방대한 양의 범용 텍스트 데이터에 대해 이미 훈련된 LLM으로 시작한 다음 특정 task 또는 도메인에 대한 성능을 높이기 위해 새로운 훈련 데이터를 기반으로 모델의 매개 변수를 조정하여 학습을 완료한다. 전이 학습은 특정 작업에 대한 LLM 훈련에 필요한 Labeled 훈련 데이터 및 계산 리소스의 양을 크게 줄일 수 있으며 해당 작업에 대한 모델의 성능을 향상시킬 수 있다.

이 글의 목적은 BERT와 같은 LLM을 A부터 Z까지 따라해보는 것이다. custom closed-domain 산업별 데이터를 사용하여 맞춤형 BERT 모델을 사전 교육하기 위해 수행해야 하는 개별 단계를 중심으로 알아본다.

Intermediate Training

LLM이 일반적인 대규모 코퍼스를 사용하여 훈련되는 경우 이를 “pre-training”이라고 한다. pre-train 후 동일한 LLM이 특정 다운스트림 작업에 적용되는 경우 이를 “fine-tuning”이라고 한다. pre-training 및 fine-tune 단계 모두에서 모델 가중치에 대한 업데이트가 일어난다. 데이터가 특정 도메인(예: 법률, 재무, 생명과학 등)에 특화되어 있고 LLM을 훈련하는 데 사용된 “표준” 오픈 도메인 corpus와 상당히 다르다면, 이 custom 지식을 LLM에 통합하는 데 두 가지 옵션이 있다.

  1. Intermediate pre-training을 통해, 처음(scratch)부터 사용자 고유의 맞춤형 LLM 만들기
  2. 공개적으로 사용 가능한 도메인 특화 LLM 활용

도메인별 LLM의 몇 가지 예시로는 입법, 사건 및 계약으로 학습한 LEGAL-BERT, 금융 서비스 corpus로 학습한 FinBERT, 그리고 생명과학 문헌으로 학습한 BioBERT 등이 있다. 이러한 모델은 모두 HuggingFace 허브에서 무료로 공개되어 있다.

“Intermediate Training”이란 원래 pre-train된 BERT 모델을 새로운 중간 데이터셋으로 계속 훈련시켜 모델을 특정 도메인에서의 성능을 향상시키는 과정을 말한다. 이것은 일반적으로 모델을 큰 범용 오픈 도메인 데이터셋(Wikipedia, book corpus 등)으로 초기 훈련 후, 모델을 작은 작업 특화 데이터셋에서 마지막으로 파인튜닝하기 전에 수행된다. 이 추가적인 사전 훈련은 모델이 사용될 특정 도메인에 대해 더 많이 학습할 수 있도록 한다.

custom domain 데이터에 대한 BERT의 intermediate training은 동일한 데이터에 대한 BERT 파인 튜닝보다 일반적으로 성능이 우수하다. 그 이유 중 하나는 custom 데이터에서 모델을 처음부터 훈련시키면 데이터 내의 특정 패턴과 관계를 더 철저하게 학습할 수 있기 때문이다. 이는 보다 정확하고 효과적인 모델로 이어질 수 있으며 특정 작업 또는 도메인에 더 적합하게 될 것이다. intermediate training은 “continued pre-training“, “further pre-training“, 그리고 “domain adaptation“이라고 문헌에서 자주 언급된다. 보통 대규모 closed-domain corpus에 액세스하고 주로 GPU 형태의 충분한 컴퓨팅 자원이 있는 경우 처음부터 사전 훈련을 권장합니다.

[그림 1] 전이 학습의 훈련 타입 (출처: 원문의 그림)

Intermediate pre-training은 데이터셋이 레이블이 없어도 되는 초기 사전 훈련 작업과 유사한 비지도 학습 작업이다. 일반적으로 Intermediate training은 레이블이 지정된 데이터를 활용하는 하향 작업의 스탠다드 파인튜닝을 따르고, 이는 supervised learning task이다. 언어 모델은 아래의 두 가지 모델링 전략을 사용하여 개발할 수 있다.

  1. Masked Language Modeling (MLM)
  2. Causal Language Modeling (CLM)

MLM과 CLM 간의 차이는 MLM이 BERT와 같은 트랜스포머 기반 언어 모델을 훈련시키기 위해 사용되는 사전 훈련의 한 유형인 반면, CLM은 GPT (Generative Pre-trained Transformer)와 같은 자기 회귀 언어 모델을 훈련시키기 위해 사용되는 사전 훈련의 유형이다. MLM은 입력 텍스트의 일부를 마스킹한 다음 주변 단어의 맥락을 기반으로 마스킹된 단어를 예측하는 모델을 훈련시키는 것을 포함하며, CLM은 이전 단어에 기초하여 시퀀스에서 다음 단어를 예측하는 모델을 훈련시키는 것을 포함한다.

Intermediate pre-training에 대해서는 BERT를 사용하는 예제를 만들 것이다. BERT는 트랜스포머 기반 모델이며, MLM을 독립적으로 사용하거나 MLM을 Next Sentence Prediction (NSP)과 결합하여 custom corpus에 대한 지식을 모델에 통합할 수 있다. NSP는 BERT에 특화된 작업으로, 주어진 문장이 이전 문장을 따르는지 여부를 예측함으로써 BERT가 문장 간의 관계를 학습하는 데 도움을 준다. Intermediate pre-training을 시작할 때 고려해야 할 또 다른 중요한 사항은 프로세스의 시작점이다. 프로세스를 무작위로 초기화된 가중치로 시작하거나 초기 사전 훈련 단계의 끝 가중치로 시작할 수 있다. 전자의 방법을 선택하면 BERT의 모델 매개변수가 무작위로 초기화되므로 BERT가 일반 언어 이해를 습득한 이전 학습을 모두 재설정한다.

이 초기 사전 훈련이 Wikipedia 및 book corpus와 같은 방대한 양의 일반 목적 closed-domain 지식을 기반으로 하고 있다는 점을 감안할 때, 모델은 이제 일반 언어의 패턴과 관계를 처음부터 학습해야 하며 초기 사전 훈련 단계에 사용된 원래의 오픈 도메인 데이터 양과 동등한 사용자 지정 데이터 양이 필요할 수 있다. 또한 이는 최적의 성능을 달성하기 위해 상당한 계산 자원(GPU)이 필요하다는 것을 의미한다. 반면에 이미 사전 훈련된 BERT 모델의 가중치로 초기화된 사용자 지정 데이터에서 BERT를 계속 사전 훈련할 때, 공통 언어 이해의 원래 학습을 보존한다. 모델은 custom 데이터 내의 특정 패턴과 관계를 학습하는 데 집중할 수 있다. 이는 custom 언어 모델을 사전 훈련하기 위해 필요한 데이터 양과 계산 자원을 상당히 줄이고 사용자 지정 도메인 지식과 관련된 작업 및 쿼리에서 더 나은 성능을 보이게 하는 경우가 많다.

Intermediate pre-training을 통해 처음부터 custom LLM을 다음과 같은 과정으로 만들 것이다.

I. custom domain과 관련된 데이터셋을 확보한다. 이 데이터셋은 가능한 한 포괄적이고 다양해야 하며, custom domain에 고유한 언어와 개념의 예시가 포함되어야 한다.

II. 데이터셋을 Intermediate pre-training에 맞게 준비하기 위한 전처리 작업을 한다. 이는 custom 어휘를 추출하고 사용자 정의 토크나이저를 생성한다. 토크나이저가 설정되면 텍스트를 토큰화하고 BERT MLM에 적합한 입력 형식으로 변환다.

III. BERT MLM의 Intermediate pre-training 프로세스를 시작한다. pre-train 모델의 끝 가중치를 시작점으로 사용한다.

IV. custom 언어 모델이 사전 훈련되면 원래의 사전 훈련된 BERT와 비교 평가한다. 또한 custom BERT를 원래 BERT와 비교 평가할 것인데, 이 때 fine-tuning은 원래 BERT의 기본 어휘와 토크나이저를 사용하며 custom 데이터에 맞게 조정된 상태다.

V. 특정 NLP 하향 작업과 관련된 레이블이 지정된 작은 데이터셋에서 사용자 정의 BERT를 fine-tuning할 것이다. 이 경우 텍스트 분류가 해당 NLP 하향 작업입니다. 이 fine-tuning된 사용자 정의 BERT의 성능을 원래 BERT 모델과 비교 평가한다.

예를 들어, 앞서 언급한 단계를 적용하여 “CovidBERT”라는 사용자 정의 BERT를 생성할 것이다. 이 모델은 전 세계적 대유행 중 수집된 코로나바이러스와 관련된 뉴스 기사 데이터셋(Kaggle 데이터셋)에 대해 훈련될 것이다. 원래 BERT 모델은 2019년 초에 만들어졌기 때문에 코로나바이러스 연구에 대한 훈련이 이루어지지 않았으며 “coronavirus”, “COVID-19”, “COVID”와 같은 우리 응용 프로그램에 필요한 핵심 용어에 대한 어휘 항목조차 포함되어 있지 않다.

요약하면, 사용자 정의 BERT 모델을 처음부터 훈련하는 과정은 특정 관심 영역과 관련된 적절한 텍스트 데이터 corpus를 획득하는 것이 필요하다. 이 데이터는 중간 단계의 BERT 모델 사전 훈련에 사용되기 전에 전처리되어야 하며, custom 어휘 추출과 특별한 토크나이저 생성을 포함한다. 그 후 custom BERT 모델의 성능은 평가되고 필요한 경우 세밀하게 finetune되어야 한다.

Acquiring the dataset

이 글에서는 2020년 초 바이러스가 발생한 시점부터 2022년 봄까지의 기간 동안 수집된 COVID-19 대유행과 관련된 뉴스 기사의 Kaggle 데이터셋을 활용할 것이다. 이 데이터셋은 대략 50만 건의 기사로 구성되어 있으며, title 열은 뉴스 기사의 헤드라인을 나타내며, content 열은 텍스트 내용에 관련되어 있으며, category 열은 다섯 가지 범주(비즈니스, 환경, 사회 및 지배구조 (ESG), 일반, 과학 및 기술)로 뉴스 기사의 전반적인 맥락을 나타낸다.

데이터셋을 BERT 중간 사전 훈련 및 하위 작업의 최종 미세 조정 모두에 준비되어 있어야 합니다. intermediate pre-training을 위해 모든 뉴스 기사를 하나의 텍스트 파일로 결합하여 ‘covid_articles.txt’라는 이름으로 저장되어 있다. 이 파일에서 각 줄은 하나의 기사를 나타내며, 비지도 학습 작업이이므로 데이터셋에는 레이블이 없다. 하위 텍스트 분류 작업에 필요한 데이터셋을 유도하기 위해 데이터셋에서 ‘title’ 및 ‘category’ 열을 선택하고, ‘virus’, ‘COVID’, ‘pandemic’, ‘variant’와 같은 키워드와 일치하는 헤드라인만을 필터링하여 이를 압축하고 COVID-19 대유행의 custom 도메인에 더 특정하게 만들 수 있다. category 열은 하위 텍스트 분류 작업의 대상 변수로 기능할 수 있다.

Customizing vocabulary

제약업에서 일하고 있고 Covid-19 관련 뉴스 콘텐츠를 이해하고 분류하는 NLP 애플리케이션을 개발하려고 한다고 가정해 보자. 가장 확실한 방법은 HuggingFace 허브에서 제공되는 원본 BERT를 활용하고 이전 단계에서 분류를 위해 추출한 데이터셋을 직접 fine-tune하는 것이다. 그러나 원본 BERT는 Covid-19 대유행이 발생하기 전인 2019년에 만들어졌기 때문에 Covid-19에 특화된 기술 용어를 부적절하게 이해할 수 있다.

NLP 애플리케이션의 능력을 향상시키기 위해 두 가지 옵션이 있다. i) BERT를 기본 어휘와 토크나이저를 사용하여 도메인별 데이터로 계속 사전 훈련하거나 ii) 도메인별 데이터를 사용하여 BERT를 계속 사전 훈련하고 고유한 사용자 정의 어휘와 토크나이저를 생성할 수 있다. BERT 모델을 처음부터 훈련할 때는 종종 모델이 훈련되는 도메인에 적응된 사용자 정의 어휘를 사용하는 것이 필요하다. 이는 원래 사전 훈련된 BERT 모델이 Wikipedia와 책 corpus와 같은 일반 텍스트 데이터를 기반으로 한 어휘를 사용하고 있으며 이 어휘가 특정 도메인에 적합하지 않을 수 있기 때문이다. 따라서 도메인에 더 적합한 사용자 정의 어휘를 사용하는 것이 중요하다. 이 경우 Covid-19 관련 뉴스 기사 데이터셋으로 BERT 모델을 훈련할 예정이므로 추출한 사용자 정의 어휘에는 원래 모델의 어휘에 포함되지 않은 용어와 전문 용어가 포함될 것이다.

BERT 중간 훈련에 사용자 정의 어휘를 사용하는 것은 여러 이점이 있다. 첫째, 모델이 특정 도메인에서 훈련되는 동안 데이터 내의 패턴과 관계를 더 잘 포착하고 보다 정확한 예측을 생성함으로써 모델의 성능을 향상시킨다. 둘째, 사용자 정의 어휘를 사용하면 모델의 크기를 최소화하여 계산 및 메모리가 필요한 양을 줄여 훈련 및 배포 프로세스를 단순화할 수 있다. 어휘 사전 크기를 줄이지 않고 원래의 값인 30522개를 유지하며 훈련해 볼 예정이다.

[그림 2] custom 어휘 추출 (출처: 원문의 그림)

위의 그림은 SageMaker Processing 작업을 사용하여 사용자 지정 어휘를 추출하는 과정을 보여준다. SageMaker Processing은 ML에서 사용할 수 있는 다양한 기능을 제공하지만, 이 글에서 사용하지 않는다. 어휘 사전을 손대면 일이 커지니, 되도록이면 기존 어휘 사전을 사용하려고 한다.

Tokenizing datasets

토큰화는 BERT나 다른 LLMs를 사용할 때 필수적인 전처리 단계이다. BERT는 텍스트를 토큰의 형태로 처리하며, 이 토큰은 단어, 구두점 또는 [CLS] 및 [SEP]와 같은 특수 토큰과 같은 입력 텍스트의 개별 요소이다. 토큰화는 입력 텍스트를 이러한 개별 토큰으로 나누는 과정을 포함하며, 이는 BERT 모델이 방대한 양의 텍스트 데이터로 훈련되기 때문에 데이터를 모델에 입력하기 전에 개별 토큰으로 나눠야 하는 필수적인 작업이다. 이렇게 하면 모델이 텍스트를 효율적으로 처리하고 학습할 수 있다. 또한 토큰화는 모델이 입력 텍스트의 구조를 이해하는 데 도움이 되며, 문장 경계와 단어 간의 관계와 같은 많은 자연어 처리 작업에 중요하다.

BERT 모델의 훈련에서 토큰화 단계를 분리하는 이점 중 하나는 동일한 토크나이저를 여러 다른 훈련 실행에 사용할 수 있게 해준다는 것이다. 이것은 서로 다른 하이퍼파라미터나 다른 데이터셋에 대해 여러 BERT 모델을 훈련하려는 경우에 유용할 수 있다. 데이터를 처리하고 토큰을 생성하여 훈련 전에 각 훈련 실행마다 토큰화 단계를 반복하지 않고도 동일한 토큰화 체계를 사용할 수 있다. 이로써 시간과 계산 리소스를 절약할 수 있다.

[그림 3] 토큰화 (출처: 원문의 그림)

이전 단계에서 이미 사용자 지정 어휘를 추출했으므로 이 어휘를 covid_articles.txt 파일과 함께 또 다른 SageMaker Processing 작업의 입력으로 사용할 수 있다. 이 작업은 477,537개의 뉴스 기사를 중간 훈련을 위해 준비된 데이터 분할로 취합, 분할, 토큰화, 연결 및 청크 처리하는 작업을 수행한다.

이 작업의 일부로 추출된 사용자 지정 어휘를 사용하여 BERT 토크나이저가 다시 생성된다. 어휘 사전의 크기는 30522로 설정되고 model_max_len 매개변수는 512로 설정됩니다. 입력 데이터는 읽혀져 마스크 언어 모델링을 위한 뉴스 기사의 총합에 대한 mini-batch를 생성하기 위해 취합된다. 취합된 데이터 집합은 9:1의 비율로 학습용과 검증용으로 분할된다. 데이터 집합이 분할되면 다시 생성된 사용자 정의 토크나이저를 사용하여 토큰화된다. 토큰화된 데이터 집합에는 input_ids, token_type_ids, attention_mask 및 word_ids와 같은 사전 훈련 단계에 필요한 모든 구성 요소가 포함되어 있다. 마지막 단계로 토큰화된 데이터 집합은 고정된 길이로 연결되고 청크 처리된다. 이 프로세스 후 학습 세트는 3,918,934가 되고, 검증 세트는 441,959가 된다. 위 예시 역시 Amazon에서 실행하도록 원문에서는 정리하고 있는데, 본 글에서는 해당 사항이 없으므로 절차만 참고한다.

Tailoring BERT for Your Domain

대부분의 현대의 NLP 시스템은 “먼저 사전 훈련하고 미세 조정”이라고 알려진 다양한 용도를 위한 새로운 모델을 훈련하는 데 표준적인 접근 방식을 사용한다. 사전 훈련의 목표는 미세 조정을 위해 언어 이해의 일반적인 모델을 구축하기 위해 대량의 라벨 없는 텍스트를 활용하는 것이며, 이를 위해 텍스트 분류, 요약, 기계 번역 등과 같은 특정 NLP 작업을 위해 모델을 특정하게 만드는 것이다. 이 표준 프로세스의 확장은 중간 사전 훈련이며, 모델이 closed-domain 데이터셋에서 더 많은 사전 훈련을 수행함으로써 해당 도메인에 특화된 개념을 이해하도록 하는 것이다. 중간 사전 훈련 단계는 대규모의 독점 데이터가 있어 확장된 사전 훈련 단계가 필요한 공업용 AI에서 흔히 사용되는 실천입니다.

중간 사전 훈련을 위해 우리는 HuggingFace의 transformers 라이브러리에서 제공되는 BertForMaskedLM을 기반으로 시작할 수 있다. 이는 BERT 모델에 위에 마스크 언어 모델링 헤드가 추가된 변형이며, 이것은 사전 훈련 절차를 계속할 수 있게 하고 CovidBERT를 생성할 수 있게 하는 BERT 모델이다. 그러나 이 모델 클래스에는 다음 문장 예측(NSP) 작업이 포함되어 있지 않다. NSP 헤드와 MLM 헤드를 모두 포함하는 BertForPreTraining 클래스에서 이 작업을 찾을 수 있다.

[그림 4] Intermediate Training (출처: 원문의 그림)

이 예제의 단계에서는 SageMaker Training을 활용하여 딥 러닝 모델 및 훈련 데이터셋을 자동으로 여러 AWS GPU 인스턴스로 분할하는 파티셔닝한다.

  • 데이터 병렬화
  • 모델 병렬화

모델 병렬화는 모델을 작은 부분으로 나누어 여러 GPU에 분산하여 훈련하는 방식이며, 데이터 병렬화는 대규모 데이터셋을 동시에 훈련하기 위해 분할하는 것이다.

혼란도(Perplexity)는 통계 언어 모델과 같은 확률 모델이 샘플을 얼마나 잘 예측할 수 있는지를 측정하는 지표이다. 이는 언어 모델의 성능을 평가하는 데 사용되며, 낮은 혼란도 값은 모델이 샘플과 유사한 텍스트를 생성하는 데 더 능숙하다는 것을 나타낸다.

Catastrophic forgetting(치명적 망각)

Catastrophic forgetting은 한 데이터셋에서 훈련된 모델이 새로운 데이터셋에 대해 훈련받을 때 그동안 학습한 패턴과 관계를 잊어버리는 현상을 말한다.

이는 여러 다른 분포의 데이터셋에서 모델을 훈련하거나 원본 데이터셋과 다른 새로운 데이터셋에서 사전 훈련된 모델을 세밀하게 조정하는 것이 어려워지거나 불가능하게 할 수 있다. Catastrophic forgetting은 새로운 훈련 데이터가 모델의 매개변수를 변경하여 이전에 학습한 패턴과 관계를 덮어쓸 때 발생한다. 예를 들어, 예방 조치를 취하지 않고 고양이 사진의 새 데이터셋에 모델을 훈련시키면, 개를 정확하게 인식하는 능력을 잊어버릴 수 있지만, 고양이를 인식하는 능력은 향상될 수 있다.

중간 훈련은 모델이 새 데이터셋에 대한 학습을 할 때 이전 데이터셋에서 학습한 패턴과 관계를 잊지 않도록 허용하여 Catastrophic forgetting을 방지할 수 있다. 이는 전이 학습의 특성 때문에 가능한데, 모델은 이미 크고 일반적인 목적의 데이터셋에서 훈련된 일련의 매개변수로 시작하고, 그런 다음 중간 데이터셋에서 매개변수를 세밀하게 조정한다. 이를 통해 모델은 중간 데이터셋에서 학습하면서 이전 데이터셋에서 학습한 내용을 잊지 않게 되며, 최종 세밀 조정 단계에서 더 나은 성능을 얻을 수 있다. 예를 들어 중간 훈련은 모델이 Covid와 관련된 개념 및 용어를 학습하면서 원래 BERT의 개방형 도메인 학습을 잊지 않게 하며, 두 작업 모두에서 더 나은 성능을 얻을 수 있도록 할 것이다.

Comparison of CovidBERT and Original BERT on Masked Language Modeling Task

이전에 훈련한 CovidBERT의 성능을 평가하기 위해, 표준 기본 BERT 모델과 COVID 관련 뉴스 기사 데이터셋에서 세밀한 조정이 이루어진 BERT 모델과 비교할 것이다. 이 비교를 수행하기 위해 언어 모델의 성능을 평가하기에 적합한 벤치마크로서 마스크 채우기 작업을 선택하였다.

COVID 관련 뉴스 기사 데이터셋에서의 세밀한 조정을 통해 BERT 모델을 CovidBERT보다 적은 에포크 동안 세밀하게 조정할 것이다. 이것은 모델 간 성능 차이를 관찰하고 모델 성능을 향상시키는 수단으로 세밀한 조정의 효율성을 보여주기 위한 것이다. 이는 세밀한 조정이 모델이 처음부터 훈련하는 대신 사전 훈련된 가중치를 약간 조정하도록 허용하여 모델이 빠르게 수렴하도록 하는 효과가 있다.

마스크 언어 모델링에서 마스크 채우기는 문장이나 텍스트에서 누락되거나 마스크 처리된 토큰을 예측하는 과정을 나타낸다. 이 작업에서 입력 텍스트의 일부는 일반적으로 “[MASK]”와 같은 특별한 토큰으로 대체되며, 모델은 대체된 원래 토큰을 예측하도록 훈련된다. MLM은 모델이 문장에서 단어의 맥락을 학습하고 단어 간의 관계를 이해하는 데 도움이 되므로 중요하다. 마스크 처리된 토큰을 사용하여 텍스트의 맥락을 기반으로 누락된 토큰을 예측하도록 모델을 훈련함으로써 모델은 텍스트의 의미를 이해하고 텍스트 분류, 기계 번역, 질문 응답과 같은 자연어 처리 작업을 수행하는 능력이 향상된다. 게다가 MLM은 모델이 관례적인 표현과 비유 등을 이해하는 능력을 향상시키는 데에도 도움이 될 수 있으며, 이는 종종 전통적인 지도 학습 방법으로는 학습하기 어려운 부분이다.

[그림 5] 마스크 채우기 태스크에 대한 CovidBERT와 BERT 비교 (출처: 원문의 그림)

우리의 평가 결과(위에 설명된 것과 같음)에서 CovidBERT가 원본 BERT 및 세밀하게 조정된 BERT에 비해 제약 회사 이름을 예측하고 이를 COVID와 관련된 맥락에서 인식하는 데 있어서 탁월한 성능을 보인다는 걸을 알 수 있다. 이는 CovidBERT가 제약 회사 이름을 정확하게 예측하는 능력은 “Pfizer and [MASK] are both testing new formulations of their vaccine tailored to the omicron variant.”에서 확인할 수 있다. 마찬가지로 CovidBERT가 COVID와 관련된 맥락에서 약 이름을 인식하는 능력이 강조되는데, 입력 “A drug called [MASK] appears to actually work against the coronavirus that causes COVID-19″에서 예측된 약물 이름의 대부분이 COVID-19과 관련이 있었다. 우리의 분석은 모델에 도메인 특정 지식을 전달하고 사용자 정의 어휘를 추출하고 활용하는 Intermediate Pretrain의 중요성과 가치를 강조한다. 더 나아가 CovidBERT는 Catastrophic forgetting에 견고하며, 원본 BERT에서 상속된 더 오래된 실제 세계 정보를 보존한다는 것을 보여준다. 이는 결과 표를 자세히 살펴보면 볼 수 있는데, 굵게 표시된 단어는 세 모델에서 모두 예측된 고유한 단어이다. CovidBERT는 코로나 시대에 더 적절한 공통 지식을 향상시키는 것으로 보이며, 정밀도를 가지고 잠금, 대유행, 원격 의료, 바이러스 이름의 변종과 같은 용어를 예측할 수 있어 이 모델을 우수한 것으로 검증하였다.

Original BERT vs CovidBERT for Text Classification

다운스트림 작업을 위한 세밀한 조정은 BERT를 사용하여 분류 모델을 구축하는 일반적인 방법으로, 해당 특정 작업에 맞게 생성된 제한된 레이블 데이터셋을 활용한다. 그러나 많은 경우 응용 프로그램(분류기)은 BERT 또는 해당 변형에서 사용된 훈련 말뭉치에 반영되지 않은 특정 도메인의 키워드, 용어 및 개념이 필요하여 해당 응용 프로그램에 적합하지 않은 모델이 생성된다. 이에도 불구하고 BERT와 같은 사전 훈련된 모델을 세밀하게 조정하는 데는 상대적으로 적은 수의 epoch가 필요하며, BERT의 저자들은 2에서 4 에포크를 권장합니다.

[그림 6] 텍스트 분류 태스크에 대한 BERT (출처: 원문의 그림)

CovidBERT의 성능을 COVID 관련 뉴스 기사에 대한 세밀한 조정된 원본 BERT 모델과 비교하기 위해 우리는 F-Score macro를 사용하기로 결정하였다. 이 방법은 각 클래스에 대한 정밀도와 재현율의 평균을 취하고 각 클래스를 동등하게 중요하게 취급하여 모델의 성능을 정확하게 나타낸다. 뉴스 기사를 다섯 가지 다른 범주로 할당하는 분류 작업이기 때문에(비즈니스, 환경, 사회 및 거버넌스(ESG), 일반, 과학 및 기술), F-Score macro는 적절한 메트릭이며, 이를 통해 두 모델의 각 클래스에서의 성능을 비교하고 어떤 모델이 더 우수한 성과를 내는지 알 수 있다.

[그림 7] 텍스트 분류 태스크에 대한 CovidBERT와 BERT 비교 (출처: 원문의 그림)

Final Remarks

요약하자면, 우리 실험에서는 CovidBERT라고 불리는 모델이 COVID-19 관련 작업에 대한 언어 모델로 우수하게 적합함을 보여주고 있다. 이는 특히 도메인 특화 데이터가 많이 있는 경우 산업 전용 응용 프로그램에서 계속되는 사전 훈련이나 도메인 특정 세밀한 조정의 중요성을 추가로 확인하였다. 중간 사전 훈련 접근 방식은 모델이 COVID-19 도메인에 특정한 새로운 개념과 용어를 학습할 수 있도록 하는 동시에 원래 BERT 모델로부터 얻은 일반적인 언어 이해 능력에 영향을 미치지 않는다. 이는 텍스트에서 누락된 토큰을 예측하는 작업에서 모델이 더 나은 성능을 발휘하고 궁극적으로 다른 자연어 처리 작업에서의 성능을 향상시킬 수 있도록 한다.

자세한 내용은 원문을 참고하기 바란다.

LLaMa-2, Cannot access gated repo for url 조치 방법

문제

HuggingFace 라이브러리를 이용해서, LLaMa-2를 테스트하려고 한다. 아래와 같이 HuggingFace의 LLaMa-2 저장소에 접근할 권한이 없다는 에러가 발생한다.

Traceback (most recent call last):
File "/home/idjung/miniconda3/envs/crawl/lib/python3.10/site-packages/huggingface_hub/utils/_errors.py", line 261, in hf_raise_for_status
response.raise_for_status()
File "/home/idjung/miniconda3/envs/crawl/lib/python3.10/site-packages/requests/models.py", line 1021, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url: https://huggingface.co/meta-llama/Llama-2-7b-hf/resolve/main/config.json

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "/home/idjung/miniconda3/envs/crawl/lib/python3.10/site-packages/transformers/utils/hub.py", line 430, in cached_file
resolved_file = hf_hub_download(
File "/home/idjung/miniconda3/envs/crawl/lib/python3.10/site-packages/huggingface_hub/utils/_validators.py", line 118, in _inner_fn
return fn(*args, **kwargs)
File "/home/idjung/miniconda3/envs/crawl/lib/python3.10/site-packages/huggingface_hub/file_download.py", line 1431, in hf_hub_download
http_get(
File "/home/idjung/miniconda3/envs/crawl/lib/python3.10/site-packages/huggingface_hub/file_download.py", line 524, in http_get
hf_raise_for_status(r)
File "/home/idjung/miniconda3/envs/crawl/lib/python3.10/site-packages/huggingface_hub/utils/_errors.py", line 277, in hf_raise_for_status
raise GatedRepoError(message, response) from e
huggingface_hub.utils._errors.GatedRepoError: 401 Client Error. (Request ID: Root=1-123456de-1234fef1234ddf1234affdde5;123456a-e123-2223-bde2-1ec23c415675f)

Cannot access gated repo for url https://huggingface.co/meta-llama/llama-2-7b-hf/resolve/main/config.json.
Repo model meta-llama/llama-2-7b-hf is gated. You must be authenticated to access it.

시도 (웹에서 검색한 결과 가능한 시도 방법)

  1. $HOME/.bashrc 파일에 HF_TOKEN 변수 추가
  2. model 초기화 시 token 변수 넘기기
self.model_4bit = AutoModelForCausalLM.from_pretrained(
              self.model,
              device_map="auto",
              quantization_config=self.quant_config,
              token=_hf_token )

구체적인 방법은 웹에 자료가 많이 있으므로 생략한다.

결론 =Capitalizing

저장소를 칭하는 Llama-2-7b-hf 라고 소문자를 대문자로 변경하니 문제가 해결되었다. 이름은 괜히 타이프하지 말고, Huggingface 사이트의 복사 버튼을 이용하자.