본문 바로가기

딥러닝/딥러닝 실습 (PyTouch)

NumPy / Pandas 기초

들어가며

딥러닝 코드를 보다 보면 NumPy와 Pandas가 항상 등장한다. 파이썬은 쓸 수 있지만 이 두 라이브러리는 딥러닝에 특화된 방식으로 쓰이기 때문에 따로 정리해둘 필요가 있다. 특히 데이터 전처리 단계에서 NumPy와 Pandas 없이는 거의 불가능하다.


NumPy 핵심

배열 생성

import numpy as np

a = np.array([1, 2, 3, 4, 5])
b = np.array([[1, 2, 3], [4, 5, 6]])

print(a.shape)   # (5,)
print(b.shape)   # (2, 3)
print(b.ndim)    # 2

# 특수 배열
zeros   = np.zeros((3, 4))
ones    = np.ones((3, 4))
eye     = np.eye(4)                          # 단위 행렬
rand    = np.random.randn(3, 4)              # 정규분포 난수
arange  = np.arange(0, 10, 2)               # [0, 2, 4, 6, 8]
linspace = np.linspace(0, 1, 5)             # [0, 0.25, 0.5, 0.75, 1.0]

인덱싱과 슬라이싱

a = np.array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])

print(a[0])       # [1, 2, 3]
print(a[0, 1])    # 2
print(a[:2])      # [[1,2,3],[4,5,6]]
print(a[:, 1])    # [2, 5, 8] (1번 열 전체)

# 불리언 인덱싱
print(a[a > 5])   # [6, 7, 8, 9]

# 팬시 인덱싱
print(a[[0, 2]])  # [[1,2,3],[7,8,9]]

Shape 변환

a = np.arange(24)

b = a.reshape(4, 6)     # (24,) → (4, 6)
c = a.reshape(2, 3, 4)  # (24,) → (2, 3, 4)
d = a.reshape(4, -1)    # -1은 자동 계산
flat = b.flatten()      # 1차원으로 펼치기

# 차원 추가/제거
x = np.array([1, 2, 3])  # (3,)
x1 = x[np.newaxis, :]    # (1, 3)
x2 = x[:, np.newaxis]    # (3, 1)

# 딥러닝에서 자주 쓰는 패턴
image = np.random.randn(3, 224, 224)   # (C, H, W)
batch = np.expand_dims(image, axis=0)  # (1, C, H, W)

수학 연산

a = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])

print(a + b)       # [11, 22, 33, 44]
print(a * b)       # [10, 40, 90, 160]
print(a ** 2)      # [1, 4, 9, 16]
print(np.sqrt(a))  # [1, 1.41, 1.73, 2.0]

# 행렬 곱
A = np.random.randn(3, 4)
B = np.random.randn(4, 5)
C = A @ B   # (3, 5)

# 집계 함수
x = np.array([[1, 2, 3], [4, 5, 6]])
print(x.sum())           # 21
print(x.sum(axis=0))     # [5, 7, 9] (열 방향)
print(x.sum(axis=1))     # [6, 15] (행 방향)
print(x.argmax(axis=1))  # [2, 2] (각 행의 최댓값 인덱스)

브로드캐스팅

# 배치 정규화에서 자주 쓰임
X = np.random.randn(32, 10)  # 32개 샘플, 10개 특성

mean = X.mean(axis=0)        # (10,)
std  = X.std(axis=0)         # (10,)

X_norm = (X - mean) / (std + 1e-8)  # 자동 브로드캐스팅
print(X_norm.mean(axis=0).round(4)) # ≈ 0
print(X_norm.std(axis=0).round(4))  # ≈ 1

유용한 함수들

# 조건 함수
a = np.array([-2, -1, 0, 1, 2])
print(np.where(a > 0, a, 0))  # [0, 0, 0, 1, 2] → ReLU!
print(np.clip(a, -1, 1))      # [-1, -1, 0, 1, 1]

# 쌓기
x = np.array([1, 2, 3])
y = np.array([4, 5, 6])
print(np.stack([x, y]))        # [[1,2,3],[4,5,6]] (2, 3)
print(np.concatenate([x, y]))  # [1,2,3,4,5,6] (6,)

# 정렬
a = np.array([3, 1, 4, 1, 5])
print(np.sort(a))              # [1, 1, 3, 4, 5]
print(np.argsort(a))           # 정렬된 인덱스

Pandas 핵심

DataFrame 생성

import pandas as pd

df = pd.DataFrame({
    'name':   ['Alice', 'Bob', 'Charlie', 'David'],
    'age':    [25, 30, 35, 28],
    'score':  [85.5, 92.0, 78.3, 88.1],
    'passed': [True, True, False, True]
})

print(df.shape)     # (4, 4)
print(df.dtypes)    # 각 컬럼 데이터 타입
print(df.describe()) # 수치형 통계

# CSV 로드/저장
df = pd.read_csv('data.csv')
df.to_csv('output.csv', index=False)

데이터 탐색

print(df.head(3))   # 처음 3행
print(df.tail(3))   # 마지막 3행

# 컬럼 선택
print(df['name'])              # Series
print(df[['name', 'score']])   # DataFrame

# 행/열 선택
print(df.loc[0])               # 인덱스 기반
print(df.iloc[0:2, 0:2])       # 위치 기반

# 조건 필터링
print(df[df['age'] > 28])
print(df[(df['age'] > 25) & (df['passed'] == True)])
print(df[df['name'].isin(['Alice', 'Bob'])])

결측값 처리

df = pd.DataFrame({
    'A': [1, 2, np.nan, 4],
    'B': [np.nan, 2, 3, np.nan],
})

print(df.isnull().sum())     # 컬럼별 결측값 수

df_mean  = df.fillna(df.mean())        # 평균으로 채움
df_zero  = df.fillna(0)               # 0으로 채움
df_drop  = df.dropna()                # 결측값 행 삭제
df_ffill = df.fillna(method='ffill')  # 앞 값으로 채움

데이터 변환

df = pd.DataFrame({
    'name':  ['Alice', 'Bob', 'Charlie'],
    'score': [85.5, 92.0, 78.3],
    'grade': ['A', 'A', 'B']
})

# 새 컬럼 추가
df['score_norm'] = (df['score'] - df['score'].mean()) / df['score'].std()

# apply: 함수 적용
df['name_len']   = df['name'].apply(len)
df['score_level'] = df['score'].apply(lambda x: 'high' if x >= 85 else 'low')

# map: 값 변환
grade_map = {'A': 4.0, 'B': 3.0, 'C': 2.0}
df['gpa'] = df['grade'].map(grade_map)

그룹화와 집계

df = pd.DataFrame({
    'department': ['개발', '개발', '디자인', '디자인'],
    'salary':     [5000, 6000, 4500, 5500],
    'score':      [85, 92, 78, 88]
})

print(df.groupby('department')['salary'].mean())
print(df.groupby('department').agg({
    'salary': ['mean', 'sum'],
    'score':  'mean'
}))

딥러닝 전처리 실전

import pandas as pd
import numpy as np
from sklearn.preprocessing import LabelEncoder, StandardScaler
from sklearn.model_selection import train_test_split
import torch

df = pd.read_csv('titanic.csv')

# 1. 불필요한 컬럼 제거
df = df.drop(['PassengerId', 'Name', 'Ticket', 'Cabin'], axis=1)

# 2. 결측값 처리
df['Age']      = df['Age'].fillna(df['Age'].median())
df['Embarked'] = df['Embarked'].fillna(df['Embarked'].mode()[0])

# 3. 범주형 변수 인코딩
le = LabelEncoder()
df['Sex'] = le.fit_transform(df['Sex'])         # male=1, female=0
df = pd.get_dummies(df, columns=['Embarked'], drop_first=True)

# 4. 특성/타겟 분리
X = df.drop('Survived', axis=1).values  # NumPy 배열로 변환
y = df['Survived'].values

# 5. 학습/검증 분리
X_train, X_val, y_train, y_val = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

# 6. 정규화 (반드시 train 기준으로 fit)
scaler  = StandardScaler()
X_train = scaler.fit_transform(X_train)  # fit + transform
X_val   = scaler.transform(X_val)        # transform만!

# 7. PyTorch 텐서 변환
X_train_t = torch.tensor(X_train, dtype=torch.float32)
y_train_t = torch.tensor(y_train, dtype=torch.long)
X_val_t   = torch.tensor(X_val,   dtype=torch.float32)
y_val_t   = torch.tensor(y_val,   dtype=torch.long)

print(f"학습: {X_train_t.shape}, 검증: {X_val_t.shape}")

NumPy ↔ Pandas ↔ PyTorch 변환

import numpy as np
import pandas as pd
import torch

# NumPy → Pandas
arr = np.random.randn(5, 3)
df  = pd.DataFrame(arr, columns=['A', 'B', 'C'])

# Pandas → NumPy
arr_back = df.values   # 또는 df.to_numpy()

# NumPy → PyTorch
tensor = torch.from_numpy(arr)   # 메모리 공유 (효율적)

# PyTorch → NumPy
arr_from = tensor.detach().numpy()

# GPU 텐서는 먼저 cpu()로 이동
# gpu_tensor.cpu().numpy()

실무에서 자주 쓰는 패턴

# EDA 템플릿
def eda(df):
    print(f"Shape: {df.shape}")
    print(f"\n결측값:\n{df.isnull().sum()}")
    print(f"\n수치형 통계:\n{df.describe()}")
    for col in df.select_dtypes(include='object').columns:
        print(f"\n{col}: {df[col].value_counts().to_dict()}")

# 클래스 불균형 확인
def check_balance(y):
    unique, counts = np.unique(y, return_counts=True)
    for cls, cnt in zip(unique, counts):
        print(f"클래스 {cls}: {cnt}개 ({100*cnt/len(y):.1f}%)")

# 배치 생성기
def create_batches(X, y, batch_size=32, shuffle=True):
    n = len(X)
    indices = np.random.permutation(n) if shuffle else np.arange(n)
    for start in range(0, n, batch_size):
        idx = indices[start:start+batch_size]
        yield X[idx], y[idx]

정리

항목 NumPy Pandas
주요 자료구조 ndarray DataFrame, Series
사용 목적 수치 연산, 행렬 계산 테이블 데이터 처리
인덱싱 위치/불리언 기반 loc(레이블), iloc(위치)
결측값 nan isnull(), fillna()
딥러닝 활용 텐서 변환 직전 전처리, EDA

'딥러닝 > 딥러닝 실습 (PyTouch)' 카테고리의 다른 글

PyTorch 기초  (0) 2026.05.19