https://product.kyobobook.co.kr/detail/S000214934825
한 권으로 끝내는 실전 LLM 파인튜닝 | 강다솔 - 교보문고
한 권으로 끝내는 실전 LLM 파인튜닝 | 실무 현장에서 꼭 필요한 파인튜닝, PEFT, vLLM 서빙 기술을 직접 실습하면서 배워 보자!AI 기술의 최전선에서 배우는 LLM 파인튜닝의 모든 것! 이론적 토대부터
product.kyobobook.co.kr
"한 권으로 끝내는 실전 LLM 파인튜닝" 교재를 활용해 3주(주말 제외) 동안 진행 되는 온라인 스터디
1. 언어 모델의 기본 개념
언어 모델은 주어진 텍스트 데이터를 입력받아 다음 단어, 문장 또는 구를 예측하는 확률 기반 시스템(모델)이다. 이를 위해 모델은 텍스트 데이터를 연속적인 시퀀스로 분할(ex.단어, 연속된 글자의 수)로 분할하고, 각 시퀀스의 패턴을 학습합니다.
1.1 학습 과정
- 입력: 텍스트 데이터 (예: "나는 학교에 간다.")
- 출력: 주어진 텍스트 시퀀스의 다음 단어 예측 (예: "간" 다음에 "다.")
1.2 데이터 전처리
- Block Size : 모델이 한번에 처리할 수 있는 텍스트 시퀀스의 길이
- block_size를 x로 설정하면 모델은 데이터의 연속된 x개 글자를 하나의 학습 단위로 이용
- 텍스트 데이터를 고정된 크기의 block으로 나누는 것은 모델이 다양한 문맥에서 언어를 이해하고 생성하는 능력을 키울 수 있다
- 무작위 샘플링을 통해 모델이 데이터의 특정 부분에 과적합되는 것을 방지
- 전체 데이터를 고르게 학습할 수 있어, 모델의 학습 효율을 높이는데 중요
- ex) 텍스트 : "나는 학교에 간다." , block_size = 5
- ['는 학교에'] ['나는 학교'] [' 학교에 '] ['학교에 간'] ['교에 간다']
- 중요.
- block_size가 너무 작으면, 모델이 문맥을 충분히 학습을 하지 못하는 문제 발생
- block_size가 너무 크면, 학습 효율이 떨어짐
- Batch Function :
데이터를 작은 묶음으로 나누어 모델이 한 번에 학습할 수 있도록 하는 역할
학습 속도를 개선하고, 메모리 사용량을 최적화할 수 있다- 여러 샘플을 동시에 처리하여 병렬화 효율을 극대화
- 데이터 샘플의 크기와 시퀀스 길이에 따라 배치를 구성(메모리 생각할 것)
- ex) 텍스트 : "나는 학교에 간다." , block_size = 5, batch_size = 2
- [['교에 간다', '학교에 간'],
['나는 학교', ' 학교에 '],
['는 학교에']]
- [['교에 간다', '학교에 간'],
1.3 언어 모델의 기본 구조 실습(Hands-on)
import torch
from torch.utils.data import DataLoader, Dataset
class TextDataset(Dataset):
def __init__(self, text, block_size):
self.text = text
self.block_size = block_size
self.data = [text[i:i+block_size] for i in range(0, len(text) - block_size)]
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
return self.data[idx]
# 데이터 준비
text = "나는 학교에 간다."
block_size = 5
batch_size = 2
dataset = TextDataset(text, block_size)
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)
# 배치 출력
for batch in dataloader:
print(batch)
# 출력 결과
"""
['교에 간다', '학교에 간']
['나는 학교', ' 학교에 ']
['는 학교에']
"""
2. 기본 언어 모델 구현: semiGPT
semiGPT는 텍스트를 처리하고 다음 단어를 예측하는 간단한 언어 모델
2.1 semiGPT 모델 기본 구조
- 임베딩 테이블: 텍스트를 숫자형 벡터로 변환.
- 전방 전달(forward): 입력 데이터를 모델에 전달하고 예측값을 생성.
- 손실 함수: 예측값과 실제값 간의 차이를 계산하여 모델 학습의 기준으로 사용.
import torch
import torch.nn as nn
from torch.nn import functional as F
class semiGPT(nn.Module):
def __init__(self, vocab_length):
super().__init__()
self.embedding_token_table = nn.Embedding(vocab_length, vocab_length)
def forward(self, inputs, targets=None):
logits = self.embedding_token_table(inputs)
if targets is None:
loss = None
else:
batch, seq_length, vocab_length = logits.shape
logits = logits.view(batch * seq_length, vocab_length)
targets = targets.view(batch * seq_length)
loss = F.cross_entropy(logits, targets)
return logits, loss
def generate(self, inputs, max_new_tokens):
for _ in range(max_new_tokens):
logits, _ = self.forward(inputs)
logits = logits[:, -1, :]
probs = F.softmax(logits, dim=-1)
next_inputs = torch.multinomial(probs, num_samples=1)
inputs = torch.cat((inputs, next_inputs), dim=1)
return inputs
model = semiGPT(ko_vocab_size).to(device)
2.2 모델 학습
- 입력 데이터 준비: batch_function을 사용하여 학습용 배치 생성
- 손실 계산: 예측값과 실제값의 차이를 계산하여 학습 방향 설정
- 가중치 업데이트: 역전파를 통해 모델 파라미터를 조정
optimizer = torch.optim.AdamW(model.parameters(), lr=learning_rate)
for step in range(max_iteration):
if step % eval_interval == 0:
losses = compute_loss_metrics()
print(f'step: {step}, train loss: {losses["train"]:.4f}, val loss: {losses["eval"]:.4f}')
example_x, example_y = batch_function("train")
logits, loss = model(example_x, example_y)
optimizer.zero_grad(set_to_none=True)
loss.backward()
optimizer.step()
inputs = torch.zeros((1, 1), dtype=torch.long, device=device)
print(token_decode(model.generate(inputs, max_new_tokens=100)[0].tolist()))
2.5 기본 언어 모델의 한계와 Transformer등장 및 파생 모델
트랜스포머(Transformer) 아키텍처는 딥러닝에서 자연어 처리(NLP)와 시퀀스 데이터를 처리하기 위해 설계된 모델로, 2017년에 "Attention is All You Need" 논문에서 처음 제안되었다.
트랜스포머는 기존의 순환신경망(RNN)이나 LSTM처럼 시퀀스를 순차적으로 처리하지 않고, 자기 주의 메커니즘(Self-Attention)을 사용하여 병렬 처리가 가능하다는 점에서 차별화된다. 이로 인해 학습 속도와 효율성이 크게 향상되었으며, 이후 다양한 파생 모델이 등장하게 되다.
- BERT (Bidirectional Encoder Representations from Transformers)
- 특징: 트랜스포머의 인코더 부분만 사용하며, 입력 시퀀스를 양방향으로 학습합니다
- 사용 사례: 문장 분류, 질의 응답, 텍스트 추출 등
- 핵심 혁신: 사전학습(pretraining)과 미세조정(finetuning) 기법의 대중화
- GPT (Generative Pre-trained Transformer)
- 특징: 트랜스포머의 디코더 부분을 기반으로 설계된 언어 생성 모델
- 사용 사례: 텍스트 생성, 요약, 창작 등
- 핵심 혁신: 시퀀스 생성 태스크에서 뛰어난 성능을 보여줌
- T5 (Text-to-Text Transfer Transformer)
- 특징: 모든 NLP 태스크를 텍스트 입력과 텍스트 출력 문제로 변환
- 사용 사례: 번역, 요약, 질문 답변 등
- 핵심 혁신: 문제의 범용적 처리 가능
- Vision Transformer (ViT)
- 특징: 트랜스포머를 컴퓨터 비전 분야에 도입하여 이미지 분류와 같은 태스크를 수행
- 사용 사례: 이미지 분류, 객체 탐지 등
- 핵심 혁신: CNN 없이 트랜스포머만으로 비전 태스크 수행
- Longformer
- 특징: 긴 시퀀스를 효율적으로 처리할 수 있도록 Sparse Attention 메커니즘 도입
- 사용 사례: 긴 문서 요약, QA 등
- 핵심 혁신: 긴 문장이나 문서 처리 최적화
어텐션 메커니즘 추가적인 내용 이전 글 참고(https://minhyuk0914.tistory.com/6)
Attention Mechanism
https://arxiv.org/abs/1409.0473 Neural Machine Translation by Jointly Learning to Align and TranslateNeural machine translation is a recently proposed approach to machine translation. Unlike the traditional statistical machine translation, the neural mach
minhyuk0914.tistory.com
3. 셀프 어텐션(Self-Attention) 추가하기
3.1 셀프 어텐션(Self-Attention) 기본 개념
셀프 어텐션(Self-Attention)은 시퀀스 내 각 토큰이 다른 모든 토큰과의 관계를 학습하도록 도와주는 메커니즘이다. 이를 통해 모델은 문맥 정보를 더 풍부하게 이해할 수 있다.
- Query, Key, Value 계산: 입력 데이터를 기반으로 관계를 나타내는 행렬 생성.
- 가중치 계산: Query와 Key 간의 유사성을 점수로 환산.
- 문맥 정보 집계: 계산된 가중치를 Value에 곱해 최종 출력 생성.
3.2 구현 코드
class Head(nn.Module):
def __init__(self, head_size):
super().__init__()
self.key = nn.Linear(n_embed, head_size, bias=False)
self.query = nn.Linear(n_embed, head_size, bias=False)
self.value = nn.Linear(n_embed, head_size, bias=False)
self.register_buffer("tril", torch.tril(torch.ones(block_size, block_size)))
def forward(self, inputs):
batch_size, sequence_length, embedding_dim = inputs.shape
keys = self.key(inputs)
queries = self.query(inputs)
weights = queries @ keys.transpose(-2, -1) * (embedding_dim ** -0.5)
weights = weights.masked_fill(
self.tril[:sequence_length, :sequence_length] == 0, float("-inf")
)
weights = F.softmax(weights, dim=-1)
values = self.value(inputs)
output = weights @ values
return output
class semiGPT(nn.Module):
def __init__(self, vocab_length):
super().__init__()
self.token_embedding_table = nn.Embedding(vocab_length, n_embed)
self.position_embedding_table = nn.Embedding(block_size, n_embed)
self.attention_head = Head(n_embed)
self.lm_head = nn.Linear(n_embed, vocab_length)
def forward(self, inputs, targets=None):
batch, sequence = inputs.shape
token_embed = self.token_embedding_table(inputs)
pos_embed = self.position_embedding_table(
torch.arange(sequence, device=device)
)
x = token_embed + pos_embed
x = self.attention_head(x)
logits = self.lm_head(x)
if targets is None:
loss = None
else:
batch, sequence, embed_size = logits.shape
logits = logits.view(batch * sequence, embed_size)
targets = targets.view(batch * sequence)
loss = F.cross_entropy(logits, targets)
return logits, loss
def generate(self, inputs, max_new_tokens):
for _ in range(max_new_tokens):
inputs_cond = inputs[:, -block_size:]
logits, _ = self(inputs_cond)
logits = logits[:, -1, :]
probs = F.softmax(logits, dim=-1)
next_inputs = torch.multinomial(probs, num_samples=1)
inputs = torch.cat((inputs, next_inputs), dim=1)
return inputs
'DL > LLM&RAG' 카테고리의 다른 글
한 권으로 LLM 온라인 스터디 1기 Day_5 - GPT, Gemma, Llama3 : 대규모 언어 모델의 진화와 비교 (0) | 2025.01.05 |
---|---|
한 권으로 LLM 온라인 스터디 1기 Day_4 - 파인튜닝의 모든 것 : PEFT와 태스크 적용 사례 (0) | 2025.01.05 |
한 권으로 LLM 온라인 스터디 1기 Day_3 - 멀티헤드 어텐션 & 피드포워드, Blocks (0) | 2025.01.05 |
한 권으로 LLM 온라인 스터디 1기 Day_1 - 런팟"RunPod" 소개 및 활용 (2) | 2024.12.31 |
Vector DB (1) (0) | 2024.09.10 |