PyTorch
1PyTorch¶
torch numpy + 자동 미분(역전파) +
import torch# x = np.array([1, 2, 3])
x = np.arange(10)
print(type(x), x.dtype, x.shape, x.ndim, x.size)
x = x.reshape(2, 5)
print(x.shape)
assert np.all(x - x == 0)
x = x.astype('float32')
print(x.dtype)
# x = torch.tensor([1, 2, 3])
x = torch.arange(10)
print(type(x), x.dtype, x.shape, x.ndim, x.numel())
x = x.reshape(2, 5)
print(x.shape)
assert torch.all(x - x == 0)
# 약간의 차이
assert x.shape == x.size()
x = x.float()
print(x.dtype)
x = x.numpy() # 텐서를 넘파이 배열로 변환
print(type(x))
x = torch.tensor(x) # 넘파이 배열을 텐서로 변환
print(type(x))Xs = np.random.randn(32, 64) # 32개의 표본, 64개의 특성
w = np.random.randn(64, 10) # 64개의 입력, 10개의 출력
b = np.random.randn(10) # 10개의 출력에 대한 편향
z = Xs @ w + b # 행렬 곱과 편향 더하기
print(z.shape) # (32, 10)
Xs = torch.randn(32, 64) # 32개의 표본, 64개의 특성
w = torch.randn(64, 10) # 64개의 입력, 10개의
b = torch.randn(10) # 10개의 출력에 대한 편향
z = Xs @ w + b # 행렬 곱과 편향 더하기
print(z.shape) # (32, 10)import torch
import matplotlib.pyplot as plt
# 1. 데이터 생성
xs = torch.linspace(-5, 5, 100) # 100개의 x 값
noise = torch.randn(len(xs)) # 노이즈 생성
ys = xs + noise # 타깃 값 (노이즈가 섞인 직선)
# 2. 상수항 추가 (X를 [1, xs] 형태로 변환)
X = torch.stack([torch.ones(len(xs)), xs], dim=1) # 100x2 행렬 (1열은 상수항, 2열은 특징 xs)
# 3. 정규 방정식 적용 (θ = (X^T X)^(-1) X^T y)
theta = torch.inverse(X.T @ X) @ X.T @ ys
# 4. 결과 출력
print(f'최적의 파라미터 (θ): {theta}')
# 5. 예측값 계산
ys_pred = X @ theta # 예측 값
# 6. 실제 값과 예측 값 시각화
plt.scatter(xs, ys, label='Actual data') # 실제 데이터
plt.plot(xs, ys_pred, color='red', label='Fitted line') # 예측된 직선
plt.legend()
plt.title("Linear Regression using Normal Equation")
plt.show()최적의 파라미터 (θ): tensor([0.1327, 1.0192])

1.1자동 미분¶
사과가격 = torch.tensor(100.0, requires_grad=True) # 사과 단가 텐서 (미분 계산 필요)
사과수량 = torch.tensor(2.0, requires_grad=True) # 사과 수량 텐서 (미분 계산 필요)
귤가격 = torch.tensor(150.0, requires_grad=True) # 귤 단가 텐서 (미분 계산 필요)
귤수량 = torch.tensor(3.0, requires_grad=True) # 귤 수량 텐서 (미분 계산 필요)
부가세 = torch.tensor(0.1) # 부가세율 텐서 (미분 계산 불필요)
print('# 순전파')
세전가격 = 사과가격 * 사과수량 + 귤가격 * 귤수량
가격 = 세전가격 * (1 + 부가세)
print(f'가격={가격:.1f}') # 최종 출력
print('# 역전파')
가격.backward(torch.tensor(1.0)) # 가격에 대한 미분 계산
# 전파는 계산그래프를 따라 자동으로 이루어집니다. 즉, 최종 출력에서만 역전파를 호출
pd.DataFrame({
'사과단가': [사과가격.item(), 사과가격.grad.item()],
'사과수량': [사과수량.item(), 사과수량.grad.item()],
'귤단가': [귤가격.item(), 귤가격.grad.item()],
'귤수량': [귤수량.item(), 귤수량.grad.item()],
'부가세': [1 + 부가세.item(), 부가세.grad] # 부가세는 미분 계산 불필요
}, index=['값', 'd가격/d값'])x = torch.tensor(0.0, requires_grad=True)
y = 1 / (1 + torch.exp(-x)) # 시그모이드 함수
y.backward() # y에 대한 미분 계산
print(f'x={x.item()}, y={y.item():.2f}, dy/dx={x.grad.item():.2f}')1.2GPU 연산¶
x = torch.linspace(0, 1, 5)
print(f'연산장치: {x.device}, x={x}')
assert torch.all(x - x == 0)
print('GPU (CUDA) 사용 가능 여부:', torch.cuda.is_available())
if torch.cuda.is_available():
x2 = x.to('cuda') # GPU로 텐서 이동
print(f'연산장치: {x2.device}, x2={x2}')
assert torch.all(x2 - x2 == 0)
try:
x - x2
except RuntimeError as e:
print(e)1.3torch.nn¶
import torch.nn as nn # neuralnet 관련 모듈
# nn.Linear = XW + b "(다중)퍼셉트론"
layer1 = nn.Linear(in_features=4, out_features=3)
print(f'W={layer1.weight.shape}, b={layer1.bias.shape}')
# 학습할 매개변수들은 미분 계산이 설정되어 있음
assert layer1.weight.requires_grad and layer1.bias.requires_grad
Xs = torch.randn(5, 4)
z1 = layer1(Xs)
assert torch.all(Xs @ layer1.weight.T + layer1.bias == z1)model = nn.Sequential( # 순전파 (feed forward; sequential)
nn.Linear(784, 50), nn.Sigmoid(), # 1층
nn.Linear(50, 100), nn.Sigmoid(), # 2층
nn.Linear(100, 10) # 3층 (출력층)
)
print(model)
for layer in model:
# hasattr: "has attribute?" 객체가 특정 속성이 있나?
# sigmoid도 일종의 계층이지만, 학습할 매개변수는 없음
if hasattr(layer, 'weight'):
print(layer)
print('# 매개변수')
for param in model.parameters():
print(param.device, param.shape)