본문 바로가기
Artificial Intelligence/21. PyTorch

[PYTORCH] NumPy 배열을 텐서로 변환하는 3가지 핵심 방법과 메모리 공유 문제 해결 및 7개 실무 예제

by Papa Martino V 2026. 4. 5.
728x90

NumPy 배열
NumPy 배열

 

현대 데이터 과학과 딥러닝 워크플로우에서 NumPyPyTorch 간의 상호 운용성은 필수적입니다. 단순히 데이터를 옮기는 것을 넘어, 메모리 효율성을 극대화하고 연산 병목 현상을 해결하는 구체적인 테크닉이 필요합니다. 본 가이드에서는 from_numpy를 포함한 다양한 변환 방식의 결정적 차이를 분석하고, 실무에서 즉시 활용 가능한 최적화 전략을 제시합니다.


1. NumPy와 PyTorch의 연결고리: 데이터 브릿지 이해하기

데이터 전처리는 보통 NumPy나 Pandas에서 이루어지지만, 모델 학습은 GPU 가속을 지원하는 PyTorch에서 진행됩니다. 이때 가장 중요한 키워드는 "Memory Copy vs Memory Sharing"입니다. 데이터의 크기가 기가바이트(GB) 단위로 커질 경우, 단순 복사는 심각한 RAM 부족 현상을 야기할 수 있습니다. PyTorch는 이를 해결하기 위해 torch.from_numpy()라는 강력한 기능을 제공합니다. 이 함수는 메모리를 새로 할당하지 않고 기존 NumPy 배열의 버퍼를 참조(View)하여 텐서를 생성합니다. 반면 torch.tensor()는 항상 데이터를 복사하여 독립적인 객체를 만듭니다. 이 미묘한 차이가 대규모 파이프라인의 성패를 가릅니다.

2. 변환 방식별 특성 비교 분석

개발자가 상황에 맞는 최적의 함수를 선택할 수 있도록 주요 변환 방식 3가지를 비교하였습니다.

비교 항목 torch.from_numpy() torch.tensor() torch.as_tensor()
메모리 메커니즘 메모리 공유 (Zero-copy) 항상 데이터 복사 (Deep Copy) 가능한 경우 공유, 필요시 복사
원본 수정 시 영향 텐서 값도 동시 변경됨 영향 없음 (독립적) NumPy 배열인 경우 변경됨
장치 이동 (GPU) 불가 (CPU 메모리 전용) 생성 시 장치 지정 가능 장치 지정 가능
추천 용도 CPU 내 고속 데이터 로딩 안전한 데이터 독립성 보장 범용적인 최적화 변환

3. 실무 직결: 해결 방법과 7가지 개발 예제

실제 프로젝트에서 발생할 수 있는 데이터 타입 불일치, 메모리 오염 문제를 해결하는 실전 코드입니다.

Example 1: from_numpy를 활용한 제로-카피(Zero-copy) 구현

가장 기본적인 방법으로, 대용량 배열을 변환할 때 메모리 사용량을 0에 가깝게 유지합니다.


import numpy as np
import torch

np_array = np.array([1, 2, 3], dtype=np.float32)
tensor = torch.from_numpy(np_array)

# 메모리 공유 확인
np_array[0] = 100
print(tensor[0])  # 출력: tensor(100.)
        

Example 2: 데이터 독립성이 필요한 경우의 복사 방법

원본 NumPy 데이터가 휘발성이거나 루프 내에서 값이 계속 바뀔 때 안전하게 값을 보존합니다.


# 복사를 통해 독립적인 텐서 생성
safe_tensor = torch.tensor(np_array)
np_array[1] = 999
print(safe_tensor[1])  # 출력: 2.0 (원본 수정에 영향받지 않음)
        

Example 3: 데이터 타입(Dtype) 불일치 해결 방법

NumPy의 기본 float64와 PyTorch 모델의 float32 충돌을 방지하는 최적의 패턴입니다.


# NumPy는 64비트가 기본인 경우가 많으므로 명시적 캐스팅 필수
np_data = np.random.rand(10, 10)
tensor_f32 = torch.from_numpy(np_data).float() # 또는 .to(torch.float32)
        

Example 4: Pandas DataFrame에서 텐서로의 원스톱 변환

데이터 분석 프로젝트에서 테이블 데이터를 모델 입력값으로 전환하는 실무 기법입니다.


import pandas as pd

df = pd.DataFrame({'a': [1, 2], 'b': [3, 4]})
# .values는 numpy 배열을 반환하므로 이를 활용
tensor_df = torch.from_numpy(df.values).to(torch.float32)
        

Example 5: GPU로 즉시 전송하는 가속 방법

NumPy 배열을 생성함과 동시에 가속기(CUDA) 메모리로 올리는 효율적인 방법입니다.


device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# as_tensor를 사용하면 불필요한 복사를 줄이면서 장치 이동 가능
gpu_tensor = torch.as_tensor(np_array, device=device)
        

Example 6: 비연속적(Non-contiguous) 배열 문제 해결

슬라이싱된 NumPy 배열을 변환할 때 발생하는 레이아웃 에러를 방지합니다.


# 슬라이싱된 배열은 메모리 상에서 연속적이지 않을 수 있음
np_sub = np_array[::2]
# .copy()를 통해 연속적인 메모리 레이아웃 확보 후 변환
clean_tensor = torch.from_numpy(np_sub.copy())
        

Example 7: 이미지 데이터(HWC to CHW) 전처리 통합

OpenCV(NumPy 기반) 이미지 데이터를 PyTorch 채널 순서로 변경하며 변환합니다.


# (Height, Width, Channel) -> (Channel, Height, Width)
img_np = np.random.randint(0, 255, (224, 224, 3), dtype=np.uint8)
img_tensor = torch.from_numpy(img_np.transpose(2, 0, 1)).float() / 255.0
        

4. 독창적 인사이트: 왜 as_tensor가 대세인가?

최근 오픈소스 라이브러리들(HuggingFace, TIMM 등)은 from_numpy보다 as_tensor를 선호하는 경향이 있습니다. 그 이유는 다형성(Polymorphism)에 있습니다. from_numpy는 오직 NumPy 배열만 인자로 받을 수 있지만, as_tensor는 리스트, 튜플, 다른 텐서까지 모두 수용하며 최적의 메모리 전략을 스스로 결정하기 때문입니다. 코드의 유연성을 높이고 싶다면 as_tensor 사용을 적극 권장합니다.

5. 참고 문헌 및 출처

  • PyTorch Documentation: torch.from_numpy reference (https://pytorch.org/docs/stable/generated/torch.from_numpy.html)
  • NumPy Documentation: Interoperability with Array Protocols
  • Effective PyTorch: Best Practices for High Performance (GitHub Technical Blog)
  • Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow (Aurélien Géron)
728x90