외부 데이터에서 텐서 생성
실제 데이터는 텐서가 아니다
섹션 제목: “실제 데이터는 텐서가 아니다”실무에서 다루는 데이터는 CSV 파일, PNG 이미지, NumPy 배열, pandas DataFrame 등 다양한 형태로 존재합니다. 이 데이터들을 PyTorch 모델에 입력하려면 모두 텐서로 변환해야 합니다. 각 소스별 변환 방법을 정리합니다.
NumPy 배열에서 텐서로
섹션 제목: “NumPy 배열에서 텐서로”NumPy는 데이터 과학 생태계에서 가장 널리 쓰이는 배열 라이브러리입니다. PyTorch와의 변환은 두 가지 방식으로 가능합니다.
import numpy as npimport torch
np_array = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]], dtype=np.float32)
# 방법 1: torch.from_numpy() — 메모리 공유 (빠르지만 주의 필요)tensor_shared = torch.from_numpy(np_array)
# 방법 2: torch.tensor() — 독립 복사본 (안전)tensor_copy = torch.tensor(np_array)
print(tensor_shared.shape) # torch.Size([2, 3])print(tensor_shared.dtype) # torch.float32메모리 공유 확인
섹션 제목: “메모리 공유 확인”# from_numpy()는 메모리를 공유함np_array[0, 0] = 999.0print(tensor_shared[0, 0]) # tensor(999.) ← 함께 변경됨print(tensor_copy[0, 0]) # tensor(1.) ← 변경 없음
# 독립 복사본이 필요하면 .clone() 사용tensor_safe = torch.from_numpy(np_array).clone()np_array[0, 0] = 0.0print(tensor_safe[0, 0]) # tensor(999.) ← clone은 독립적dtype 불일치 처리
섹션 제목: “dtype 불일치 처리”# numpy float64 → torch float32로 변환np_f64 = np.array([1.0, 2.0, 3.0], dtype=np.float64)
# from_numpy는 dtype을 그대로 유지t_f64 = torch.from_numpy(np_f64)print(t_f64.dtype) # torch.float64
# float32로 변환하려면 .float() 또는 .to() 사용t_f32 = t_f64.float() # float32로 변환t_f32 = t_f64.to(dtype=torch.float32) # 동일한 결과print(t_f32.dtype) # torch.float32이미지에서 텐서로 (torchvision)
섹션 제목: “이미지에서 텐서로 (torchvision)”이미지 파일(PNG, JPEG 등)을 텐서로 변환할 때는 torchvision.transforms를 사용합니다.
from PIL import Imageimport torchvision.transforms as T
# 기본 변환 파이프라인transform = T.Compose([ T.Resize((224, 224)), # 크기 조정 T.ToTensor(), # PIL Image → 텐서 (C, H, W), 값 범위 [0, 1] T.Normalize( mean=[0.485, 0.456, 0.406], # ImageNet 평균 std=[0.229, 0.224, 0.225] # ImageNet 표준편차 )])
# 이미지 로드 및 변환image = Image.open("photo.jpg").convert("RGB")tensor = transform(image)
print(tensor.shape) # torch.Size([3, 224, 224]) ← (C, H, W)print(tensor.dtype) # torch.float32print(tensor.min()) # 정규화 후 음수 가능print(tensor.max()) # 정규화 후 1 초과 가능ToTensor()가 하는 일
섹션 제목: “ToTensor()가 하는 일”# ToTensor()는 세 가지를 한꺼번에 수행# 1. PIL Image (H, W, C) → Tensor (C, H, W) ← 축 순서 변환# 2. uint8 [0, 255] → float32 [0.0, 1.0] ← 값 범위 정규화# 3. numpy array도 동일하게 변환
# 수동으로 같은 결과를 얻으려면import numpy as nppil_img = Image.open("photo.jpg").convert("RGB")np_img = np.array(pil_img) # (H, W, C), uint8tensor_manual = torch.from_numpy(np_img) # (H, W, C), uint8tensor_manual = tensor_manual.permute(2, 0, 1) # (C, H, W)tensor_manual = tensor_manual.float() / 255.0 # [0, 1]torchvision.io로 직접 로드
섹션 제목: “torchvision.io로 직접 로드”import torchvision.io as tvio
# 이미지를 바로 텐서로 로드tensor = tvio.read_image("photo.jpg") # (C, H, W), uint8print(tensor.shape) # torch.Size([3, 480, 640])print(tensor.dtype) # torch.uint8
# float32로 변환tensor_f = tensor.float() / 255.0CSV / pandas DataFrame에서 텐서로
섹션 제목: “CSV / pandas DataFrame에서 텐서로”테이블 형태의 정형 데이터는 pandas를 거쳐 텐서로 변환하는 것이 일반적입니다.
import pandas as pdimport torch
# CSV 파일 로드df = pd.read_csv("data.csv")
# 예시 DataFramedf = pd.DataFrame({ "age": [25, 30, 35, 28, 42], "salary": [5000, 7000, 9000, 6000, 11000], "score": [0.82, 0.91, 0.78, 0.95, 0.88], "label": [0, 1, 0, 1, 1]})
# 특성(X)과 레이블(y) 분리X = df[["age", "salary", "score"]].values # numpy arrayy = df["label"].values
# 텐서로 변환X_tensor = torch.tensor(X, dtype=torch.float32)y_tensor = torch.tensor(y, dtype=torch.long)
print(X_tensor.shape) # torch.Size([5, 3])print(y_tensor.shape) # torch.Size([5])print(X_tensor.dtype) # torch.float32print(y_tensor.dtype) # torch.int64전처리 포함 파이프라인
섹션 제목: “전처리 포함 파이프라인”from sklearn.preprocessing import StandardScaler
# 스케일링 후 텐서 변환scaler = StandardScaler()X_scaled = scaler.fit_transform(df[["age", "salary", "score"]].values)
X_tensor = torch.tensor(X_scaled, dtype=torch.float32)print(X_tensor.mean(dim=0)) # ≈ [0., 0., 0.] ← 정규화 확인print(X_tensor.std(dim=0)) # ≈ [1., 1., 1.]파일 저장과 로드: torch.save() / torch.load()
섹션 제목: “파일 저장과 로드: torch.save() / torch.load()”학습된 가중치, 전처리된 텐서, 체크포인트를 파일로 저장하고 불러올 수 있습니다.
단일 텐서 저장/로드
섹션 제목: “단일 텐서 저장/로드”# 텐서 저장data = torch.randn(100, 10)torch.save(data, "data.pt")
# 텐서 로드loaded = torch.load("data.pt")print(loaded.shape) # torch.Size([100, 10])print(torch.allclose(data, loaded)) # True딕셔너리로 여러 텐서 저장
섹션 제목: “딕셔너리로 여러 텐서 저장”# 여러 텐서를 딕셔너리로 한 번에 저장checkpoint = { "epoch": 50, "model_state": {"weight": torch.randn(10, 5), "bias": torch.zeros(5)}, "optimizer_state": {"lr": 0.001}, "train_loss": torch.tensor(0.234),}
torch.save(checkpoint, "checkpoint.pt")
# 로드ckpt = torch.load("checkpoint.pt", weights_only=False)print(ckpt["epoch"]) # 50print(ckpt["train_loss"]) # tensor(0.2340)실전 체크포인트 패턴
섹션 제목: “실전 체크포인트 패턴”import torchimport torch.nn as nn
model = nn.Linear(10, 5)optimizer = torch.optim.Adam(model.parameters())
# 저장def save_checkpoint(model, optimizer, epoch, loss, path): torch.save({ "epoch": epoch, "model_state_dict": model.state_dict(), "optimizer_state_dict": optimizer.state_dict(), "loss": loss, }, path)
# 로드def load_checkpoint(model, optimizer, path): ckpt = torch.load(path, weights_only=False) model.load_state_dict(ckpt["model_state_dict"]) optimizer.load_state_dict(ckpt["optimizer_state_dict"]) return ckpt["epoch"], ckpt["loss"]
# 사용 예save_checkpoint(model, optimizer, epoch=10, loss=0.15, path="ckpt.pt")epoch, loss = load_checkpoint(model, optimizer, "ckpt.pt")print(f"재개 지점: epoch {epoch}, loss {loss:.4f}")소스별 변환 방법 요약
섹션 제목: “소스별 변환 방법 요약”| 데이터 소스 | 변환 방법 | 핵심 주의사항 |
|---|---|---|
| NumPy array | torch.from_numpy() 또는 torch.tensor() | from_numpy는 메모리 공유 |
| PIL Image | T.ToTensor() | (H,W,C) → (C,H,W), [0,255] → [0,1] |
| torchvision.io | tvio.read_image() | uint8 반환, /255 필요 |
| pandas DataFrame | .values → torch.tensor() | dtype 명시 권장 |
| 파일 (저장) | torch.save(obj, path) | 딕셔너리로 묶어 저장 |
| 파일 (로드) | torch.load(path) | weights_only 설정 확인 |
핵심 요약
섹션 제목: “핵심 요약”- NumPy → 텐서:
from_numpy()(공유) vstorch.tensor()(복사) - 이미지 → 텐서:
T.ToTensor()로 (C,H,W) float32 [0,1] 변환 - pandas → 텐서:
.values로 numpy 추출 후torch.tensor() - 저장:
torch.save(), 로드:torch.load(weights_only=False) - 체크포인트는 딕셔너리로 여러 상태를 묶어 한 파일에 저장
퀴즈를 불러오는 중...