# GPT 배치 생성 함수 완벽 가이드 ## 배치(Batch) 생성이란? ### 배치의 개념 - **배치**: 여러 개의 데이터를 묶어서 한 번에 처리하는 단위 - 한 개씩 처리하는 것보다 **효율적**이고 **빠름** - GPU의 병렬 처리 능력을 최대한 활용 ### 왜 배치 처리를 하는가? 1. **계산 효율성**: GPU는 행렬 연산에 최적화되어 있음 2. **학습 안정성**: 여러 샘플의 평균 그래디언트로 업데이트 3. **메모리 효율성**: 적절한 크기로 데이터를 나누어 처리 ## 코드 상세 분석 ### 1. 초기 설정 ```python torch.manual_seed(1234) # 재현 가능한 랜덤 결과를 위한 시드 설정 batch_size = 4 # 한 번에 처리할 샘플 수 block_size = 8 # 각 샘플의 시퀀스 길이 ``` ### 2. batch_function 함수 분석 ```python def batch_function(mode): dataset = train_dataset if mode == "train" else test_dataset idx = torch.randint(len(dataset) - block_size, (batch_size,)) x = torch.stack([dataset[index:index+block_size] for index in idx]) y = torch.stack([dataset[index+1:index+block_size+1] for index in idx]) return x, y ``` #### 2.1 데이터셋 선택 ```python dataset = train_dataset if mode == "train" else test_dataset ``` - `mode`가 "train"이면 훈련 데이터, 아니면 테스트 데이터 사용 #### 2.2 랜덤 인덱스 생성 ```python idx = torch.randint(len(dataset) - block_size, (batch_size,)) ``` - `torch.randint()`: 랜덤 정수 생성 - 범위: 0 ~ (데이터셋 길이 - block_size - 1) - 개수: batch_size개 (여기서는 4개) **예시:** ```python # dataset 길이가 1000, block_size가 8일 때 idx = torch.randint(992, (4,)) # 0~991 사이에서 4개 랜덤 선택 # 결과: tensor([234, 567, 123, 890]) ``` #### 2.3 입력 데이터(x) 생성 ```python x = torch.stack([dataset[index:index+block_size] for index in idx]) ``` - 각 랜덤 위치에서 block_size만큼 슬라이싱 - `torch.stack()`: 여러 텐서를 새로운 차원으로 쌓기 **예시:** ```python # idx = [234, 567, 123, 890]일 때 x = torch.stack([ dataset[234:242], # 8개 요소 dataset[567:575], # 8개 요소 dataset[123:131], # 8개 요소 dataset[890:898] # 8개 요소 ]) # 결과: (4, 8) 크기의 2차원 텐서 ``` #### 2.4 타겟 데이터(y) 생성 ```python y = torch.stack([dataset[index+1:index+block_size+1] for index in idx]) ``` - x보다 한 칸씩 밀린 데이터 - 각 위치의 다음 토큰이 정답 **예시:** ```python # 같은 idx에서 y = torch.stack([ dataset[235:243], # x보다 1칸 밀림 dataset[568:576], dataset[124:132], dataset[891:899] ]) ``` ### 3. 출력 결과 분석 ```python inputs : torch.Size([4, 8]) # 4개 배치, 각 8개 토큰 targets : torch.Size([4, 8]) # 동일한 크기 example_x의 실제 값: tensor([[1764, 2555, 0, 1236, 2248, 0, 2017, 1976], [ 0, 1966, 2157, 0, 1951, 2062, 0, 2548], [ 0, 1304, 1485, 1586, 0, 1907, 2450, 0], [ 3, 2, 6, 5, 1, 0, 5, 3]]) example_y의 실제 값: tensor([[2555, 0, 1236, 2248, 0, 2017, 1976, 2546], [1966, 2157, 0, 1951, 2062, 0, 2548, 2289], [1304, 1485, 1586, 0, 1907, 2450, 0, 2480], [ 2, 6, 5, 1, 0, 5, 3, 5]]) ``` ### 4. 배치 내 모든 입력-타겟 쌍 확인 ```python for size in range(batch_size): # 각 배치 샘플에 대해 for t in range(block_size): # 각 시간 스텝에 대해 context = example_x[size, :t+1] target = example_y[size, t] print(f"input : {context}, target : {target}") ``` #### 첫 번째 배치 샘플 (size=0) 예시: ``` t=0: input=[1764], target=2555 t=1: input=[1764,2555], target=0 t=2: input=[1764,2555,0], target=1236 ... ``` ## torch.stack vs torch.cat 비교 ### torch.stack - **새로운 차원 추가** - 입력: 여러 개의 (8,) 텐서 - 출력: (4, 8) 텐서 ```python a = torch.tensor([1, 2, 3]) b = torch.tensor([4, 5, 6]) torch.stack([a, b]) # [[1,2,3], [4,5,6]] - (2,3) 크기 ``` ### torch.cat - **기존 차원에서 연결** - 입력: 여러 개의 (8,) 텐서 - 출력: (32,) 텐서 ```python torch.cat([a, b]) # [1,2,3,4,5,6] - (6,) 크기 ``` ## 배치 처리의 장점 1. **병렬 처리**: GPU가 4개 샘플을 동시에 처리 2. **안정적 학습**: 4개 샘플의 평균 그래디언트 사용 3. **효율적 메모리 사용**: 전체 데이터를 한 번에 로드하지 않음 ## 실제 학습에서의 활용 ```python # 학습 루프에서 for step in range(training_steps): x_batch, y_batch = batch_function("train") # 모델에 배치 입력 logits, loss = model(x_batch, y_batch) # 역전파 및 가중치 업데이트 optimizer.zero_grad() loss.backward() optimizer.step() ``` ## 핵심 포인트 1. **랜덤 샘플링**: 매번 다른 위치에서 데이터 추출 2. **배치 구성**: 여러 시퀀스를 2D 텐서로 구성 3. **입력-타겟 정렬**: y는 x보다 한 칸 밀려서 다음 토큰 예측 4. **효율성**: 한 번에 여러 샘플 처리로 학습 속도 향상 ## 관련 참고 자료 - [[02일차_2장 to 2.4_GPT 기초]] - [[GPT 언어모델 입력-타겟 쌍 생성 원리]] - [[PyTorch 텐서와 torch.tensor() 완전 가이드]]