파이썬을 처음부터 다시 배우는 기분이다. 이걸로 당장 모델을 구현해야 한다니,,, 숨을 쉴 수가 없다 ㅠㅠ
학습시간 09:00~01:00(당일16H/누적343H)
A. Tensor
.cuda())# 0차원 텐서 (스칼라)
np.array(3)
# 1차원 텐서 (벡터)
np.array([1, 2])
# 2차원 텐서 (행렬)
np.array([[1, 2], [3, 4]])
# 3차원 텐서
np.array([[[1, 2], [3, 4]],
[[5, 6], [7, 8]]])
B. Autograd
C. nn.Module
D. Optim
E. DataLoader / Dataset
A. 모델 정의
nn.Module 상속 후 forward() 함수 정의B. 손실 함수 정의
nn.CrossEntropyLoss, nn.MSELoss 등 사용C. 옵티마이저 정의
torch.optim 내 최적화 도구 설정D. 학습 루프 구성
E. 모델 저장/불러오기
torch.save(model.state_dict(), path)model.load_state_dict(torch.load(path))| 항목 | 설명 |
|---|---|
| 프레임워크 유형 | 동적 그래프 기반 딥러닝 프레임워크 |
| 주요 구성 | Tensor, Autograd, nn.Module, Optim, DataLoader |
| 핵심 특징 | Pythonic, GPU 연산, 유연한 디버깅 |
| 학습 구조 | 모델 정의 → 손실 계산 → 역전파 → 파라미터 업데이트 |
| 확장 도구 | TorchScript, ONNX, torchvision 등 |
[5, 1] 텐서 + [5, 3] 텐서 → [5, 3]으로 연산 가능규칙 적용 순서
| 단계 | 규칙 내용 |
|---|---|
| 1 | 오른쪽부터 각 차원 비교 시작 |
| 2 | 차원이 동일하거나 한 쪽이 1이면 가능 |
| 3 | 둘 중 하나가 더 짧으면 앞쪽에 1을 붙여 맞춤 |
| 4 | 가능한 경우, 1인 차원을 자동으로 복제하여 연산 진행 |
| 5 | 두 차원이 서로 다르고 1도 아니면 오류 발생 |
규칙 적용 결과
| 텐서 A shape | 텐서 B shape | 브로드캐스팅 결과 | 설명 |
|---|---|---|---|
(3, 1) | (3, 5) | (3, 5) | 두 번째 차원만 복제 |
(1, 5) | (3, 5) | (3, 5) | 첫 번째 차원 복제 |
(1, 1) | (3, 5) | (3, 5) | 두 차원 모두 복제 |
(3, 4) | (2, 4) | 오류 | 첫 번째 차원 불일치 (3 ≠ 2) |
(4,) | (3, 4) | (3, 4) | 앞에 1 자동 추가 → (1,4)로 간주 후 복제 |
import torch
a = torch.tensor([[1], [2], [3]]) # shape: (3, 1)
b = torch.tensor([[10, 20, 30]]) # shape: (1, 3)
result = a * b # shape: (3, 3)
print(result)
# 출력값 예시
tensor([[10, 20, 30],
[20, 40, 60],
[30, 60, 90]])
a는 (3,1), b는 (1,3) → 둘 다 2차원이니까 자동으로 (3,3)으로 브로드캐스팅됨!| 연산 종류 | 함수명 | 동일한 연산자 | 설명 |
|---|---|---|---|
| 덧셈 | torch.add(a, b) | a + b | 요소별 덧셈 |
| 뺄셈 | torch.sub(a, b) | a - b | 요소별 뺄셈 |
| 곱셈 (원소곱) | torch.mul(a, b) | a * b | 요소별 곱셈 |
| 나눗셈 | torch.div(a, b) | a / b | 요소별 나눗셈 |
| 행렬곱 | torch.matmul(a, b) | a @ b | 행렬 내적 곱 |
| 지수 연산 | torch.pow(a, x) | 없음 | 각 요소를 x제곱 |
| 제곱근 | torch.sqrt(a) | 없음 | 각 요소의 제곱근 |
| 절댓값 | torch.abs(a) | 없음 | 각 요소의 절댓값 |
| 최대값 | torch.max(a, b) | 없음 | 두 텐서 중 요소별 최대값 |
| 최소값 | torch.min(a, b) | 없음 | 두 텐서 중 요소별 최소값 |
| 비교-같음 | torch.eq(a, b) | a == b | 요소별 동등 비교 |
| 비교-큼 | torch.gt(a, b) | a > b | 요소별 크기 비교 (a가 b보다 큰가) |
| 비교-작음 | torch.lt(a, b) | a < b | 요소별 작음 비교 |
| 비교-크거나 같음 | torch.ge(a, b) | a >= b | 요소별 크거나 같음 |
| 비교-작거나 같음 | torch.le(a, b) | a <= b | 요소별 작거나 같음 |
| 변환 목적 | 함수 / 속성 | 설명 |
|---|---|---|
| 자료형 변환 | tensor.float() | float32로 변환 |
tensor.double() | float64로 변환 | |
tensor.int() | int32로 변환 | |
tensor.long() | int64로 변환 | |
tensor.bool() | True/False 논리형으로 변환 | |
tensor.type(torch.자료형) | 원하는 자료형 직접 지정 | |
| 자료형 확인 | tensor.dtype | 현재 자료형 확인 |
| 장치(CPU/GPU) 이동 | tensor.to("cuda") | GPU로 이동 |
tensor.to("cpu") | CPU로 이동 | |
tensor.to(device) | device 객체 활용한 일반화 이동 | |
| NumPy 변환 | tensor.numpy() | 텐서 → 넘파이 배열 (CPU 전용) |
torch.from_numpy(array) | 넘파이 배열 → 텐서 | |
| 복사 | tensor.clone() | 원본 텐서와 독립적인 복사본 생성 |
| 메모리 공유 여부 | tensor.share_memory_() | 텐서 간 메모리 공유 설정 (고급) |
| 함수명 | 설명 |
|---|---|
tensor.contiguous() | 비연속 텐서를 메모리상 연속 구조로 재정렬함. .view() 사용 전 필요 |
tensor.permute(dims) | 차원 순서 변경 (ex: (0, 2, 1)) → 메모리 순서도 변경됨 |
tensor.transpose(dim0, dim1) | 두 차원의 위치만 서로 교환 |
tensor.clone() | 메모리까지 복사된 완전한 사본 생성 (원본과 독립) |
tensor.detach() | 텐서를 계산 그래프에서 분리 (역전파 제외용) |
tensor.share_memory_() | 다른 프로세스와 텐서 메모리 공유 설정 (멀티프로세싱 용도) |
tensor.storage() | 텐서가 실제로 저장되는 메모리 영역 확인 (고급용) |
| 함수명 | 설명 |
|---|---|
torch.cat(tensors, dim) | 여러 텐서를 지정한 차원에서 이어붙임 |
torch.stack(tensors, dim) | 여러 텐서를 새 차원으로 쌓음 |
torch.split(tensor, size) | 텐서를 지정된 크기로 분할 |
torch.chunk(tensor, n) | 텐서를 n개로 균등하게 나눔 |
tensor.view(shape) | 텐서 형태 변경 (메모리 연속 필요) |
tensor.reshape(shape) | 텐서 형태 변경 (더 유연, 메모리 복사 발생 가능) |
tensor.squeeze(dim) | 크기 1인 차원 제거 |
tensor.unsqueeze(dim) | 새로운 차원 추가 |
tensor.expand(size) | 브로드캐스팅 없이 차원 확장 |
tensor.repeat(*sizes) | 텐서 복제 (반복)하여 크기 확장 |
(강의 내용 아님)
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
# 1. 데이터셋 로딩 및 전처리
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])
trainset = torchvision.datasets.FashionMNIST(
root='./data', train=True, download=True, transform=transform
)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
testset = torchvision.datasets.FashionMNIST(
root='./data', train=False, download=True, transform=transform
)
testloader = torch.utils.data.DataLoader(testset, batch_size=64, shuffle=False)
# 2. 모델 정의
class SimpleNet(nn.Module):
def __init__(self):
super(SimpleNet, self).__init__()
self.fc1 = nn.Linear(28*28, 128)
self.relu = nn.ReLU()
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = x.view(-1, 28*28) # Flatten
x = self.relu(self.fc1(x))
x = self.fc2(x)
return x
model = SimpleNet()
# 3. 손실 함수 및 옵티마이저 설정
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 4. 학습 루프
for epoch in range(5): # 총 5 에폭
running_loss = 0.0
for images, labels in trainloader:
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
print(f"Epoch {epoch+1}, Loss: {running_loss:.4f}")
# 5. 평가 (정확도 계산)
correct = 0
total = 0
with torch.no_grad():
for images, labels in testloader:
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f"Test Accuracy: {100 * correct / total:.2f}%")