딥러닝 입문자를 위한 NumPy ndarray 기초: array, dtype, shape, reshape, astype

1. 왜 ndarray부터 시작할까?



딥러닝을 하다 보면 이런 코드들을 매번 보게 됩니다.

  • 입력 텐서의 shape를 확인하고
  • 배치를 위해 reshape을 쓰고
  • GPU 연산을 위해 float32로 바꾸고…

이 모든 것의 “원형”이 바로 NumPy의 ndarray 입니다.

  • PyTorch의 TensorNumPy ndarray를 거의 그대로 따라 만든 구조
  • 딥러닝 모델의 입력, 가중치, 출력은 전부 다차원 배열(= 텐서)

그래서 ndarray를 잘 이해하는 것 = 텐서 연산의 기본 문법을 익히는 것 이라고 볼 수 있습니다.


2. ndarray란 무엇인가?

ndarrayN-dimensional array, 즉 “N차원 배열”의 줄임말입니다.

  • 1차원: 벡터
  • 2차원: 행렬
  • 3차원 이상: 텐서 (이미지 배치, 시계열, 영상 등)

간단한 예:

import numpy as np

x = np.array([1, 2, 3])            # 1차원 (벡터)
M = np.array([[1, 2], [3, 4]])     # 2차원 (행렬)

print(type(x))          # <class 'numpy.ndarray'>
print(x.ndim, x.shape)  # 차원 수, 모양
print(M.ndim, M.shape)
  • ndim: 몇 차원인지
  • shape: 각 차원의 크기가 어떻게 되는지

3. PyTorch Tensor와 얼마나 비슷할까?



PyTorch 텐서도 결국 “다차원 배열”입니다.

import torch

x_np = np.array([[1, 2], [3, 4]])   # NumPy ndarray
x_torch = torch.tensor([[1, 2], [3, 4]])  # PyTorch Tensor

print(type(x_np))      # numpy.ndarray
print(type(x_torch))   # torch.Tensor

print(x_np.shape)      # (2, 2)
print(x_torch.shape)   # torch.Size([2, 2])

둘의 공통점:

  • 둘 다 “다차원 숫자 배열”
  • shape, reshape, dtype 개념이 거의 동일
  • 연산 방식도 비슷 (+, *, @ 등)

차이점 (딥러닝에서 중요한 부분):

  • NumPy: CPU, 자동 미분 없음
  • PyTorch 텐서: GPU 사용 가능, 자동 미분 지원

그래서 보통 이렇게 사용합니다.

  • 개념 연습 / 수식 실험 / 데이터 조작 → NumPy
  • 실제 모델 학습 → PyTorch

NumPy의 ndarray에 익숙해질수록, PyTorch 텐서 연산이 훨씬 자연스럽게 느껴집니다.


4. np.array: ndarray 만드는 기본 방법

ndarray의 가장 기본적인 생성 함수가 np.array입니다.

4.1 파이썬 리스트 → ndarray

import numpy as np

# 1차원 배열 (벡터)
x = np.array([1, 2, 3])
print(x)
print(x.ndim)   # 1
print(x.shape)  # (3,)

# 2차원 배열 (행렬)
M = np.array([[1, 2, 3],
              [4, 5, 6]])
print(M)
print(M.ndim)   # 2
print(M.shape)  # (2, 3)
  • 파이썬의 리스트/리스트의 리스트np.array에 넣으면 ndarray가 됩니다.
  • 딥러닝에서 자주 보는 batch_size x feature_dim 행렬도 결국 이런 형태입니다.

4.2 초기값을 빠르게 만들기

학습용 예제나 실험에서는 처음부터 난수나 0으로 채워진 배열을 만드는 경우가 많습니다.

zeros = np.zeros((2, 3))       # 2x3 행렬, 전부 0
ones = np.ones((2, 3))         # 2x3 행렬, 전부 1
randn = np.random.randn(2, 3)  # 정규분포 난수

print(zeros.shape)  # (2, 3)

이 패턴은 PyTorch에서도 거의 동일합니다.

import torch

zeros_t = torch.zeros((2, 3))
ones_t = torch.ones((2, 3))
randn_t = torch.randn((2, 3))

5. dtype: 숫자의 “자료형” 이해하기

dtypedata type, 즉 “이 배열 안에 들어 있는 숫자가 어떤 타입인지”를 뜻합니다.

자주 보게 되는 것들:

  • int32, int64: 정수형
  • float32, float64: 실수형 (부동소수점)

확인해볼까요?

x = np.array([1, 2, 3])
print(x.dtype)  # 보통 int64 혹은 int32

y = np.array([1.0, 2.0, 3.0])
print(y.dtype)  # 보통 float64

5.1 dtype을 지정해서 만들기

x = np.array([1, 2, 3], dtype=np.float32)
print(x.dtype)  # float32

딥러닝에서는 보통 float32(PyTorch의 torch.float32) 를 많이 사용합니다. GPU 연산에 적합하고 메모리 사용량도 적당하기 때문입니다.


6. shape: 데이터의 “모양” 읽기

shape는 배열의 모양(각 차원의 크기)을 나타내는 튜플입니다.

import numpy as np

x = np.array([1, 2, 3])
print(x.shape)  # (3,)

M = np.array([[1, 2, 3],
              [4, 5, 6]])
print(M.shape)  # (2, 3)

딥러닝에서 자주 등장하는 shape 예시:

  • 특성 벡터 하나: (feature_dim,) → 예: (3,)
  • 배치 데이터: (batch_size, feature_dim) → 예: (32, 3)
  • 이미지 배치 (PyTorch 기본): (batch_size, channels, height, width) 예: (32, 3, 224, 224)

NumPy로 이런 shape를 미리 만져보고 익숙해지면, PyTorch 텐서의 shape 에러를 만났을 때도 훨씬 쉽게 원인을 찾을 수 있습니다.


7. reshape: 모양 바꾸기

reshape배열 안에 있는 “원소 수”는 그대로 두고, 모양만 바꾸는 연산입니다.

import numpy as np

x = np.array([1, 2, 3, 4, 5, 6])
print(x.shape)  # (6,)

M = x.reshape(2, 3)
print(M)
print(M.shape)  # (2, 3)

중요한 점:

  • reshape 전후의 총 원소 개수는 같아야 합니다.
  • 위 예시에서 6개 원소 → (2 x 3) = 6개 → OK

7.1 -1을 사용해서 자동 계산하기

배치나 이미지 처리에서는 -1을 자주 사용합니다. -1은 “이 자리는 자동으로 계산해줘”라는 의미입니다.

x = np.array([[1, 2, 3],
              [4, 5, 6]])  # shape: (2, 3)

# 전체를 1차원으로 펼치기 (flatten)
flat = x.reshape(-1)        # shape: (6,)
print(flat)

# 다시 2행으로 만들되, 열은 자동 계산
M = flat.reshape(2, -1)     # shape: (2, 3)
print(M)

PyTorch에서도 아주 비슷하게 사용합니다.

import torch

x_t = torch.tensor([[1, 2, 3],
                    [4, 5, 6]])  # (2, 3)

flat_t = x_t.reshape(-1)        # (6,)
M_t = flat_t.reshape(2, -1)     # (2, 3)

reshape에 익숙해지면:

  • CNN에서 feature map을 flatten
  • RNN/LSTM 입력을 (batch, seq_len, feature) 형태로 정리
  • 배치 차원을 앞으로/뒤로 배치

하는 작업들이 훨씬 직관적으로 느껴집니다.


8. astype: dtype 바꾸기

astype은 배열의 자료형을 바꾸는 함수입니다.

import numpy as np

x = np.array([1, 2, 3])      # int형
print(x.dtype)               # int32 or int64

x_float = x.astype(np.float32)
print(x_float)
print(x_float.dtype)         # float32

딥러닝에서 자주 쓰이는 상황:

  • 정수형 라벨을 실수형으로 바꾸어 loss 계산
  • float64로 들어온 데이터를 float32로 통일
  • PyTorch에 넘기기 전에 타입 맞추기

예:

import torch
import numpy as np

x = np.array([1, 2, 3], dtype=np.int32)
x = x.astype(np.float32)              # float32로 변환
x_torch = torch.from_numpy(x)         # 텐서로 변환
print(x_torch.dtype)                  # torch.float32

만약 타입을 맞추지 않으면, PyTorch에서 연산 중에 “Expected Float but got Double” 같은 타입 에러가 나기도 합니다.


9. 정리: 오늘 다룬 ndarray 기본 문법

이번 글에서 다룬 내용:

  1. ndarray란?
  • 딥러닝에서 다루는 모든 데이터 구조의 기본이 되는 “다차원 배열” 2. PyTorch Tensor와의 관계

  • 개념적으로 거의 동일, 딥러닝 버전의 ndarray 3. np.array

  • 파이썬 리스트/리스트의 리스트 → ndarray 생성 4. dtype

  • 숫자 타입 (정수/실수, 32/64bit)을 표현 5. shape

  • 데이터의 모양, 딥러닝에서 가장 많이 보는 속성 6. reshape

  • 원소 개수는 유지하면서 모양만 바꾸기 (-1 자주 사용) 7. astype

  • 자료형 변환 (intfloat32 등)

이 네 가지(array, dtype, shape, reshape, astype)만 제대로 손에 익어도:

  • 텐서 shape 에러를 만났을 때 당황하지 않고
  • 논문 수식과 코드 사이를 오가는 연습이 쉬워지고
  • PyTorch 튜토리얼 예제를 훨씬 편하게 따라갈 수 있습니다.

image