딥러닝 모델은 우리가 흔히 쓰는 엑셀 파일(CSV)이나 SQL 테이블을 바로 이해하지 못합니다. 숫자로 이루어진 다차원 배열인 '텐서(Tensor)'로 변환해줘야 비로소 학습할 수 있죠.
의료 현장에서 마주칠 데이터들이 어떻게 텐서로 변환되는지 살펴봅시다.
1. 텐서(Tensor)의 차원별 이해
PyTorch 텐서는 NumPy의 ndarray와 매우 유사하지만, GPU를 사용할 수 있다는 결정적인 차이가 있습니다.
의료 데이터를 예시로 각 차원(Rank)을 직관적으로 이해해볼까요?
① 0D Tensor (Scalar): 환자의 체온
하나의 숫자만 존재하는 상태입니다.
- 예시: 환자 A의 체온 36.5도
import torch
# 스칼라 (0차원)
temp = torch.tensor(36.5)
print(f"체온: {temp}, 차원: {temp.dim()}")

② 1D Tensor (Vector): 한 환자의 바이탈 사인
숫자가 일렬로 늘어선 형태입니다. 파이썬의 리스트나 1차원 배열과 같습니다.
- 예시: 환자 A의 [수축기혈압, 이완기혈압, 맥박] = [120, 80, 75]
# 벡터 (1차원)
# FloatTensor를 사용하면 실수형으로 생성됩니다
vital_signs = torch.FloatTensor([120, 80, 75])
print(f"바이탈 데이터: {vital_signs}")
print(f"모양(Shape): {vital_signs.shape}") # torch.Size([3]) -> 데이터가 3개 있다는 뜻

③ 2D Tensor (Matrix): 환자 리스트 (엑셀 시트)
행(Row)과 열(Column)이 있는 형태입니다. SQL 테이블이나 Pandas DataFrame이 여기에 해당합니다.
- 예시: 환자 3명의 바이탈 사인 데이터셋
# 행렬 (2차원)
# 3명의 환자(행) x 3개의 바이탈 정보(열)
patients_data = torch.FloatTensor([
[120, 80, 75], # 환자 A
[110, 70, 80], # 환자 B
[130, 90, 65] # 환자 C
])
print(f"환자 데이터셋 차원: {patients_data.dim()}D")
print(f"데이터 모양: {patients_data.shape}") # torch.Size([3, 3])

④ 3D Tensor: MRI 이미지 (핵심!)
의료 영상 분석에서 가장 많이 보게 될 형태입니다. 2D 이미지가 여러 장 겹쳐 있는 구조죠.
- 예시: MRI 영상 (높이 x 너비 x 슬라이스 수)
# 3D 텐서 (3차원)
# (슬라이스 개수, 높이, 너비) 순서라고 가정
# 노트북에서는 밖에서 안쪽으로 차원을 선언한다고 설명합니다
mri_scan = torch.FloatTensor(10, 256, 256)
print(f"MRI 텐서 모양: {mri_scan.shape}")
# 결과: torch.Size([10, 256, 256]) -> 256x256 이미지가 10장 겹쳐 있음

2. 텐서 모양 변경하기 (view) - 중요!
딥러닝 모델(특히 완전연결계층, Linear Layer)에 이미지를 넣을 때는 2차원이나 3차원 데이터를 1줄로 쫙 펴주는(Flatten) 작업이 필요할 때가 많습니다. 이때 reshape도 쓰지만, PyTorch에서는 view를 더 많이 씁니다.
상황: 256x256 픽셀의 X-ray 사진 1장을 AI 모델에 넣기 위해 1줄로 펴야 한다면?
import torch
# 가상의 X-ray 이미지 (높이 4, 너비 4 라고 가정)
xray_image = torch.rand(4, 4) # 0~1 사이의 랜덤 값 생성
print("원본 형태:", xray_image.shape)
# view를 사용하여 1줄로 펴기 (-1은 '나머지 알아서 계산해'라는 뜻)
flattened_xray = xray_image.view(-1)
print("변경된 형태:", flattened_xray.shape)
# 결과: torch.Size([16]) -> 4x4=16개의 픽셀이 한 줄로 펴짐

Tip: view는 원본 데이터의 메모리를 공유하므로 매우 효율적입니다. 모양만 바꿀 뿐 실제 데이터 순서는 유지됩니다.
3. 차원 압축과 확장 (squeeze, unsqueeze)
이건 나중에 CNN(합성곱 신경망)을 할 때 배치(Batch) 개념 때문에 무조건 마주치게 되는 오류의 주범입니다. 미리 알아두면 좋습니다.
- squeeze(): 차원이 '1'인 것을 쥐어짜서(squeeze) 없앱니다.
- unsqueeze(dim): 특정 위치에 차원 '1'을 추가합니다.
상황: 모델은 (환자 수, 데이터) 형태를 원하는데, 데이터가 (데이터) 형태라서 에러가 날 때.
# 환자 1명의 데이터 (1차원)
single_patient = torch.FloatTensor([120, 80])
print(f"원본: {single_patient.shape}") # [2]
# 모델에 넣기 위해 '1명'이라는 배치 차원 추가 (Batch Size 추가)
# unsqueeze(0) -> 0번째 인덱스에 차원 추가
input_data = single_patient.unsqueeze(0)
print(f"모델 입력용 변환: {input_data.shape}") # [1, 2] -> 1명의 환자, 2개의 특징

시각화: 텐서가 어떻게 생겼나요?
말로만 하면 복잡하니, 우리가 만든 가상의 '미니 MRI' 텐서가 파이썬 내부에서 어떻게 보이는지 시각화 코드로 확인해 봅시다.
import torch
import matplotlib.pyplot as plt
import seaborn as sns
# 가상의 뇌 스캔 데이터 생성 (높이 10 x 너비 10)
# randn: 표준 정규 분포를 따르는 랜덤 값
brain_slice = torch.randn(10, 10)
plt.figure(figsize=(6, 5))
# 텐서를 시각화하려면 numpy()로 바꿔줘야 matplotlib이 이해합니다
sns.heatmap(brain_slice.numpy(), cmap='bone', annot=True, fmt=".1f", cbar=True)
plt.title("Visualizing a Tensor (Fake MRI Slice)")
plt.show()



각 격자의 숫자가 텐서의 원소값, 즉 픽셀의 밝기를 의미합니다.
요약 및 공부 포인트
- Tensor 생성: torch.FloatTensor로 실수형 텐서를 만듭니다. (최신 버전은 초기화 시 0으로 채워질 수 있음 주의)
- 모양 확인: .shape는 항상 확인하는 습관을 들이세요. (딥러닝 에러의 90%는 shape 불일치입니다.)
- 구조 변경: view()로 차원을 자유자재로 바꿀 줄 알아야 합니다. (이미지 펴기 등)
- NumPy 호환: tensor.numpy()와 torch.from_numpy()로 언제든 변환 가능합니다.
'Study Note > Deep Learning' 카테고리의 다른 글
| 딥러닝을 위한 필수 라이브러리, 의료 데이터로 정복하기 (0) | 2026.01.02 |
|---|---|
| [PyTorch] 의료 데이터를 위한 텐서(Tensor) 완전 정복 (1) | 2025.12.31 |
| 딥러닝의 그릇 '텐서(Tensor)'와 도구 '파이토치' (0) | 2025.12.30 |
| 수학으로 한 방에 풀까, 조금씩 찾아갈까? (최소제곱법 vs 경사하강법) (0) | 2025.12.30 |
| AI는 어떻게 '최적의 선'을 찾을까? (선형회귀와 경사하강법) (0) | 2025.12.30 |