기간 : 10/27 ~ 10/31
Transformer와 LLM 시작. 진짜 자연어 처리를 배우기 시작했다.
이번 주에 배운 내용은 크게 3가지다.
1. Attention을 활용한 Transformer 아키텍처
- RNN 및 Seq2Seq 기반 구조의 문제점(장기 의존성, 정보 손실 등)을 해결하기 위해 각 단어의 관계성에 주목하는 기법
- 문장 내 단어의 위치와 의미적 유사성을 병렬적으로 N번 학습하여(Multi-Head) 문맥을 파악
- Seq2Seq 구조를 탈피하고 Attention만을 활용한 Transformer 구조
2. Hugging Face에서 모델 가져오기
- GitHub와 비슷하게 개발자들이 학습된 모델을 레포지토리에 올리고 공유하는 곳
- 필요한 Task에 따라 적절한 모델을 찾아 로드
3. OpenAI와 Ollama를 활용한 LLM 프롬프팅
🔨Transformer 구현
https://github.com/WindyAle/Transformer
GitHub - WindyAle/Transformer: 공부하면서 구현해본 Transformer 구조
공부하면서 구현해본 Transformer 구조. Contribute to WindyAle/Transformer development by creating an account on GitHub.
github.com
글로 보면 언뜻 알것 같으면서도 내가 이해한 내용이 코드로 연결이 잘 안되는 것 같아서
그냥 직접 구현해보면서 부딪혀봤다.
Transformer/
├── main.ipynb # main 파일 (테스트용)
└── modules/
├── MyTransformer.py # 인코더-디코더
└── common.py # 여러 번 재사용되는 구조들
## attention, Embedding, MultiHeadAttention, FeedForward
수업에서 실습으로 진행한 코드를 기반으로 함수끼리 좀 더 직관적으로 서로 연결되도록 노력해봤는데 잘 됐는지는 모르겠다.
- common
핵심 메커니즘인 attention 함수 그리고 임베딩, 멀티헤드, 피드포워드는 트랜스포머 내부에서 여러 번 재사용되고 여기저기서 호출되는 도구들 - MyTransformer
common의 도구들을 사용해 인코더와 디코더 그리고 그 둘을 연결하는 메인 클래스 - (최상위) main
import를 테스트하는 파일. 초기값 설정하고 입력값만 넣으면 끝이다.
class Config:
def __init__(self, vocab_size, pad_token_id=0):
self.vocab_size = vocab_size # 단어사전 크기
self.hidden_size = 768 # 은닉층 차원수 (attention_eads의 배수)
self.max_position_embeddings = 768 # 최대 시퀀스 길이
self.num_attention_heads = 12 # 어텐션 헤드 개수
self.num_hidden_layers = 12 # 레이어 개수
self.intermediate_size = 2048 # FeedForward 레이어의 중간 차원
self.hidden_dropout_prob = 0.1 # dropout 비율
self.layer_norm_eps = 1e-12 # epsilon
self.pad_token_id = pad_token_id # 패딩 토큰
테스트를 위한 Config 객체
대부분의 숫자는 자유롭게 주면 되지만 hidden_size는 num_attention heads의 배수여야 한다.
멀티 헤드 어텐션 시 임베딩 차원을 헤드 수만큼 나눠야 하기 때문.
source_ids = torch.tensor([
[101, 2054, 2064, 2106, 102, 0, 0, 0, 0, 0, 0, 0],
[101, 3000, 4000, 102, 2000, 102, 0, 0, 0, 0, 0, 0]
], dtype=torch.long)
target_ids = torch.tensor([
[201, 3054, 3064, 3106, 202, 0, 0, 0, 0, 0],
[201, 4000, 5000, 202, 6000, 202, 0, 0, 0, 0]
], dtype=torch.long)
테스트를 위해 더미로 만든 데이터
원시 텍스트에서 벡터화까지 진행되었다 가정하고 아무 숫자를 넣었다.
import torch
from modules.MyTransformer import Transformer
model = Transformer(config_enc, config_dec)
model.eval() # 평가 모드
# ... (생략)
logits = model(source_ids, target_ids)
print(f"Output Logits shape: {logits.shape}")
# 예상 출력 (VOCAB_SIZE == 15000)
# [2, 10, 15000]

다행히도 예상과 동일한 결과가 나온다.
batch_size(2)개의 문장이 만들어졌고
각 문장은 seq_len(10)개의 단어로 이루어져 있으며
단어사전에 있는 vocab_size(15000)개의 단어들이 각 위치에 올 수 있는 확률이다.
- [2, 10, 768]로 계산된 아웃풋이
- 디코더에서 Linear(hidden_size, vocab_size)를 거쳐
- 단어사전에 매핑된 각 단어들에 대한 확률분포로 최종값이 나온다.
💥Trouble Shooting
🚨 RuntimeError: view size is not compatible with input tensor's size and stride
상황
- transpose를 적용한 텐서에 view를 사용할 때
원인
expand, narrow, transpose 등 배열의 형태를 바꾸는 메서드를 적용하면 메모리의 stride가 바뀐다.
배열의 저장 형태가 non-unit stride일 경우 view가 읽어오지 못한다.
해결
context = context.transpose(1, 2).contiguous()
context = context.view(batch_size, -1, self.embed_dim)
contiguous()를 추가로 적용
Q. 동일한 동작을 하는 reshape와의 차이점
- view는 얕은 복사. 원본 배열을 특정한 모양으로 조회하는 메커니즘이다. unit stride를 만족해야 한다.
- reshape는 기본적으로는 view와 동일, view를 못하는 상황에는 그냥 새로운 배열을 만드는 스마트한 버전.
Q. 근본적인 의문으로, view는 왜 stride를 체크하는가?
→ view에 dtype 파라미터가 있는게 힌트였다. 데이터타입 레벨에서 값을 읽어오려면 원본 배열을 바이트 단위로 읽어야 하기 때문
🚨 AttributeError: 'Embedding' object has no attribute 'self.position_ids'
상황
- 포지션 임베딩 중 Embedding 클래스가 호출될 때
원인
Embedding의 클래스 속성으로 self.position_ids을 정의했는데 이것을 forward 메서드가 참조하지 못한다.
파라미터에 device 속성을 적용한게 원인이었다.
다른 파라미터들은 GPU로 이동했는데 텐서만 여전히 CPU에 남아있어서 서로 connected 되지 못했다.
→ torch.tensor()는 model.to()가 적용되지 않는다.
해결
self.register_buffer("position_ids", torch.arange(...))
torch.tensor는 GPU로 이동하기 위해 별도의 명시가 필요하다.
register_buffer()라는 메서드를 새로 알았다.
Q. position_ids를 forward에서 선언하면 되지 않을까?
→ 이 경우 메서드가 호출될 때마다 새로운 position_ids가 매번 생성되고, 불필요한 오버헤드가 반복되어 별로다.
Q. 왜 텐서만 특수하게 취급할까?
→ 모델의 속성이지만 학습 대상은 아닌 파라미터를 다루기 위한 PyTorch의 규칙이라고 한다. 단순 계산 or 임시저장용 텐서는 모델 state에 저장될 필요가 없으므로 이런 경우를 구분하기 위함인듯.
'SKN 19기' 카테고리의 다른 글
| [플레이데이터 SK네트웍스 Family AI 캠프 19기] 17주차 회고 (0) | 2026.01.03 |
|---|---|
| [플레이데이터 SK네트웍스 Family AI 캠프 19기] 11주차 회고 (0) | 2025.11.09 |
| [플레이데이터 SK네트웍스 Family AI 캠프 19기] 9주차 회고 (0) | 2025.10.26 |
| [플레이데이터 SK네트웍스 Family AI 캠프 19기] 8주차 회고 (0) | 2025.10.18 |
| [플레이데이터 SK네트웍스 Family AI 캠프 19기] 7주차 미니 프로젝트 회고 (2) | 2025.10.06 |