-
2장 토큰화와 Emdeding Python code 예LLM/LLM을 활용한 실전 AI 애플리케이션 개발 2025. 1. 18. 22:02
목차
github code & 사전준비
github :
사전 준비
01. python 설치 : mac 은 기 설치되어 있음
python --version python3 --version # Python 3.12.8
02. pycharm 설치 https://www.jetbrains.com/pycharm
03. pytorch 설치 https://pytorch.org/
pip3 install torch torchvision torchaudio
import torch print(torch.__version__)
04. numpy 설치
pip3 install numpy
pip3 show numpy # 2.2.2
예제 2.1 토큰화 코드
# 띄어쓰기 단위로 분리 input_text = "나는 최근 파리로 여행을 다녀왔다" input_text_list = input_text.split() print("input_text_list: ", input_text_list) # 토큰 -> 아이디 딕셔너리와 아이디 -> 토큰 딕셔너리 만들기 str2idx = {word:idx for idx, word in enumerate(input_text_list)} idx2str = {idx:word for idx, word in enumerate(input_text_list)} print("str2idx: ", str2idx) print("idx2str: ", idx2str) # 토큰을 토큰 아이디로 변환 input_ids = [str2idx[word] for word in input_text_list] print("input_ids: ", input_ids)
result
input_text_list: ['나는', '최근', '알프스와', '파리로', '여행을', '다녀왔다']
str2idx: {'나는': 0, '최근': 1, '알프스와': 2, '파리로': 3, '여행을': 4, '다녀왔다': 5}
idx2str: {0: '나는', 1: '최근', 2: '알프스와', 3: '파리로', 4: '여행을', 5: '다녀왔다'}
input_ids: [0, 1, 2, 3, 4, 5]딕셔너리 컴프리헨션 (Dictionary Comprehension)
이 코드는 파이썬의 강력한 기능 중 하나인 딕셔너리 컴프리헨션을 활용하여 딕셔너리를 생성하는 부분입니다. 딕셔너리 컴프리헨션은 간결한 문법으로 딕셔너리를 만들 수 있게 해주는 기능입니다.
{word:idx for idx, word in enumerate(input_text_list)}
코드 분석1
{word:idx for idx, word in enumerate(input_text_list)}
1-1) {key:value for item in iterable} 형태
key : word : 나는 최근 파리로 ...
value: idx 0,1,2,3,4
1-2) enumerate(input_text_list)는 리스트의 각 요소에 인덱스를 부여합니다:
# enumerate() 결과
# (0, "나는")
# (1, "최근")
# (2, "파리로")
# (3, "여행을")
# (4, "다녀왔다")1-3) for idx, word in enumerate(input_text_list)에서:- idx는 각 단어의 인덱스 (0, 1, 2, ...)
- word는 각 단어 ("나는", "최근", ...)
- enumerate로 반환된 각 (인덱스, 요소) 쌍을 idx와 word 변수로 각각 저장합니다.
- 즉, 반복 과정에서 첫 번째 값이 인덱스 idx로, 두 번째 값이 요소 word로 할당됩니다.
1-4) 최종적으로 생성되는 딕셔너리는:
str2idx = {
"나는": 0,
"최근": 1,
"파리로": 2,
"여행을": 3,
"다녀왔다": 4
}코드분석2
input_ids = [str2idx[word] for word in input_text_list]
결과
input_ids: [0, 1, 2, 3, 4]
설명
input_text_list: ['나는', '최근', '알프스와', '파리로', '여행을', '다녀왔다']
str2idx: {'나는': 0, '최근': 1, '알프스와': 2, '파리로': 3, '여행을': 4, '다녀왔다': 5}
input_text_list 에서 for 문을 돌며 글자를 가져와서, str2idx dictionary 의 value 인 index(0,1,2...) 를 가져온다
Embedding이란?
Embedding은 이산적인(discrete) 데이터를 연속적인(continuous) 벡터 공간으로 매핑하는 것입니다.
주로 자연어 처리에서 단어를 벡터로 변환할 때 사용됩니다.
torch.nn.Embedding의 기본 구조
pythonCopytorch.nn.Embedding(num_embeddings: int, embedding_dim: int)
주요 매개변수:
num_embeddings: 임베딩할 단어의 총 개수 (vocabulary size)
embedding_dim: 각 단어를 표현할 벡터의 차원embedding 예제코드1
import torch import torch.nn as nn # Embedding 레이어 생성 (단어 개수: 10, 임베딩 차원: 3) embedding = nn.Embedding(10, 3) # 입력 텐서 (단어 인덱스) input_ids = torch.LongTensor([1, 4, 3]) # 임베딩 실행 output = embedding(input_ids) output.shape # 결과 torch.Size([3, 3])
임베딩 레이어는 (10 × 3) 크기의 가중치 행렬을 생성
각 단어 인덱스는 이 행렬에서 해당하는 행의 벡터값으로 변환
output의 shape는 [3, 3]이 됨 (입력 길이 × 임베딩 차원)embedding 예제코드2
# 간단한 문장 처리 예시 vocab_size = 5000 # 단어 사전 크기 embedding_dim = 100 # 임베딩 차원 embedding_layer = nn.Embedding(vocab_size, embedding_dim) # 문장을 인덱스로 변환한 텐서 sentence = torch.LongTensor([[1, 2, 3], [4, 5, 6]]) # 임베딩 적용 embedded_sentence = embedding_layer(sentence) embedded_sentence.shape # 결과 torch.Size([2, 3, 100]) (배치 크기, 문장 길이, 임베딩 차원)
예제 2.2 토큰 아이디에서 벡터로 변환
import torch import torch.nn as nn input_text = "나는 최근 파리로 여행을 다녀왔다" input_text_list = input_text.split() str2idx = {word:idx for idx, word in enumerate(input_text_list)} input_ids = [str2idx[word] for word in input_text_list] # {0,1,2,3,4} embedding_dim = 16 embed_layer = nn.Embedding(len(str2idx), embedding_dim) input_embeddings = embed_layer(torch.tensor(input_ids)) # (5, 16) input_embeddings = input_embeddings.unsqueeze(0) # (1, 5, 16) input_embeddings.shape
result
torch.Size([1, 5, 16])
input_ids: [0, 1, 2, 3, 4] 이므로 len(str2idx) = 5 입니다.
embed_layer = nn.Embedding(len(str2idx), embedding_dim) 에서 (5,16) 의 임베딩 벡터 차원이 생성됩니다
input_embeddings = input_embeddings.unsqueeze(0) # (1, 5, 16) 에서
unsqueeze(0) 을 통해 첫번째에 1인 차원을 생성했으므로
(5,16) -> (1,5,16) 으로 임베딩 벡터 차원이 변경됩니다
Squeeze 함수
squeeze함수는 차원이 1인 차원을 제거해준다.
따로 차원을 설정하지 않으면 1인 차원을 모두 제거한다. 그리고 차원을 설정해주면 그 차원만 제거한다.
import torch x = torch.rand(3, 1, 20, 128) x = x.squeeze() #[3, 1, 20, 128] -> [3, 20, 128]
import torch x = torch.rand(1, 1, 20, 128) x = x.squeeze() # [1, 1, 20, 128] -> [20, 128] x2 = torch.rand(1, 1, 20, 128) x2 = x2.squeeze(dim=1) # [1, 1, 20, 128] -> [1, 20, 128]
unsqueeze함수
unsqueeze함수는 squeeze함수의 반대로 1인 차원을 생성하는 함수이다.
그래서 어느 차원에 1인 차원을 생성할 지 꼭 지정해주어야한다.
import torch x = torch.rand(3, 20, 128) x = x.unsqueeze(dim=1) #[3, 20, 128] -> [3, 1, 20, 128]
출처 : [PyTorch] squeeze, unsqueeze함수: 차원 삭제와 차원 삽입
https://sanghyu.tistory.com/86
torch.arrange 함수
torch.arange는 PyTorch에서 사용되는 함수로, 주어진 범위의 값을 포함하는 1차원 텐서를 생성합니다.
이 함수는 주로 데이터 생성 및 초기화에 유용합니다.
PyTorch 라이브러리의 함수로, 일정 간격을 가지고 숫자의 배열을 생성하는 데 사용됩니다.
이 함수는 NumPy의 arange 함수와 유사합니다. 주요 사용법은 다음과 같습니다:torch.arange(start=0, end, step=1, *, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
각 매개변수는 다음과 같은 의미를 가집니다:
start: 배열의 시작 값 (포함).
end: 배열의 끝 값 (포함되지 않음).
step: 숫자 간의 간격 (기본값은 1).
dtype: 생성할 배열의 데이터 타입 (선택 사항).
device: 배열이 할당될 장치 (선택 사항).예
import torch
tensor1 = torch.arange(5) # tensor([0, 1, 2, 3, 4])
tensor2 = torch.arange(1, 4) # tensor([1, 2, 3])
tensor3 = torch.arange(0, 10, 2) # tensor([0, 2, 4, 6, 8])예제 2.3 절대적 위치 인코딩
import torch import torch.nn as nn embedding_dim = 16 max_position = 12 # 토큰 임베딩 층 생성 embed_layer = nn.Embedding(len(str2idx), embedding_dim) # 위치 인코딩 층 생성 position_embed_layer = nn.Embedding(max_position, embedding_dim) position_ids = torch.arange(len(input_ids), dtype=torch.long).unsqueeze(0) position_encodings = position_embed_layer(position_ids) token_embeddings = embed_layer(torch.tensor(input_ids)) # (5, 16) token_embeddings = token_embeddings.unsqueeze(0) # (1, 5, 16) # 토큰 임베딩과 위치 인코딩을 더해 최종 입력 임베딩 생성 input_embeddings = token_embeddings + position_encodings input_embeddings.shape print("position_ids:", position_ids) print("input_embeddings.shape",input_embeddings.shape) # result # position_ids: tensor([[0, 1, 2, 3, 4]]) # input_embeddings.shape torch.Size([1, 5, 16])
str2idx: {'나는': 0, '최근': 1, '파리로': 2, '여행을': 3, '다녀왔다': 4}
input_ids: [0, 1, 2, 3, 4]
를 이용하여,
token_embeddings 과
position_enbedding 을 하는 코드 입니다
둘다 차원은 5,16 -> 1,5,16 입니다.
position_embed_layer = nn.Embedding(max_position, embedding_dim) print("position_embed_layer:", position_embed_layer) # position_embed_layer: Embedding(12, 16)
위 코드로 위치 인코딩 층을 12,16 으로 생성합니다
position_ids = torch.arange(len(input_ids), dtype=torch.long).unsqueeze(0) print("position_ids:", position_ids) # position_ids: tensor([[0, 1, 2, 3, 4]])
위 코드에서 torch.arrange 를 사용하여 position_ids 를 만듭니다.
position_encodings = position_embed_layer(position_ids) print("position_encodings:", position_encodings) # position_encodings: # tensor([[[ 1.2249, 0.6867, 1.7294, 0.3493, 0.0687, 1.5959, 1.9263, # 2.1862, -0.0935, -0.1626, 0.9718, 1.3019, 2.8211, -0.6323, # -1.2881, 0.1205], # [ 0.4762, 0.6097, -0.2412, 0.0338, -2.1402, -0.4766, 2.0567, # -1.1137, 0.8133, -0.2408, -0.7346, 0.1239, -1.3321, -0.3675, # -1.9920, 2.4420], # [ 0.2850, -1.9323, -1.4105, 0.8441, 1.2749, 0.5842, -0.0642, # 0.6701, 0.5678, 1.1704, -0.8503, 1.6145, 0.2567, 0.9667, # 1.2605, -0.4639], # [ 2.4829, 0.0128, 1.4214, 1.2140, 1.3723, -0.4188, -0.5099, # -0.9746, 1.2901, -0.1404, 0.9404, 1.9529, -0.0886, 1.9274, # -0.0831, 1.8268], # [-0.2267, 0.0037, -0.4448, 0.9218, -1.5701, 0.3842, -0.5214, # 1.6281, 0.5830, 2.2555, 0.1615, 0.2579, -0.6377, 0.3406, # -0.1599, -1.7529]]], grad_fn=<EmbeddingBackward0>)
positions_ids 를 생성해둔 poistion_embed_layer 층에 넣어서, position encoding 을 합니다.
token_embeddings = embed_layer(torch.tensor(input_ids)) # (5, 16) token_embeddings = token_embeddings.unsqueeze(0) # (1, 5, 16) print("token_embeddings", token_embeddings) #token_embeddings # tensor([[[ 1.2940, 0.5634, -0.9380, 2.0672, -0.7711, -0.5628, 1.5723, # -0.0757, 0.0325, 0.3588, 0.1069, 1.1663, -0.0736, 0.4490, # -0.5269, -0.3489], # [-0.7662, 0.0792, -0.2584, -1.4920, 1.6173, 1.3689, -1.0596, # -0.9092, 0.3055, -0.9085, 0.2122, 0.3238, 0.3050, -0.8115, # 0.5968, -1.5606], # [-1.0736, 2.1904, 0.4247, 1.1781, -1.3371, -1.0677, -0.6786, # 0.1351, -0.8071, -0.0088, 0.4296, 1.9977, -0.8690, 1.0972, # 0.1069, 0.3029], # [ 0.2464, 0.2058, 0.3025, 0.2863, -0.3435, -2.3024, -1.5169, # 0.9519, 1.2383, 0.3907, 0.9274, -0.7000, -2.3389, -1.5153, # -1.5764, -0.7036], # [ 0.7313, 0.0512, 0.6351, -0.4502, -0.3187, -0.3763, -1.0381, # -1.8719, 1.3853, -1.1969, 0.9985, 0.2518, 0.6452, 0.7640, # 0.5743, 0.5138]]], grad_fn=<UnsqueezeBackward0>)
token 도 유사한 방법으로 embeding 합니다
'LLM > LLM을 활용한 실전 AI 애플리케이션 개발' 카테고리의 다른 글
4.2 채점 모델로 코드 가독성 높이기 (0) 2025.01.27 4장 말 잘 듣는 모델 만들기 4.1 코딩 테스트 통과하기 (1) 2025.01.26 1.4 LLM의 미래: 인식과 행동의 확장 (0) 2025.01.12 1.3 LLM 애플리케이션의 시대가 열리다 (0) 2025.01.12 2.5 인코더 (0) 2025.01.10