Problem Solving with Algorithms

728x90
반응형

[AI 인공지능 머신러닝 딥러닝/Python | PyTorch] - 인스톨! 파이토치 강의 소개

 

인스톨! 파이토치 강의 소개

혁펜하임 PyTorch 강의 오리엔테이션 요약혁펜하임 채널의 '[PyTorch] 0강. 오리엔테이션' 영상은 채널 5주년 기념으로 '인스톨! 파이토치' 강의를 소개하는 내용입니다. 강의자는 최근 출간한 '이론

inner-game.tistory.com

 

 

파이토치에서 신경망을 구축할 때 가장 먼저 만나게 되는 것이 바로 선형 레이어(Linear Layer)입니다. nn.Linear()는 단순해 보이지만 모든 딥러닝 모델의 기초가 되는 핵심 구성 요소로, 이를 제대로 이해해야 복잡한 신경망 구조도 자유롭게 설계할 수 있습니다. 3강에서는 선형 레이어의 작동 원리부터 실제 학습 루프 구현까지, 파이토치로 신경망을 만드는 전체 워크플로우를 완벽히 마스터할 수 있습니다.

 

 

인스톨! 파이토치

 

3-1강. nn.Linear()는 이 영상 하나만 보시면 됩니다

nn.Linear의 정의와 수학적 원리

nn.Linear()는 입력 데이터에 선형 변환(linear transformation)을 적용하는 모듈로, 수학적으로는 다음 식을 계산합니다:[^1]

y = xA^T + b

여기서 x는 입력 텐서, A는 가중치 행렬(weight matrix), b는 편향 벡터(bias vector)입니다. 이는 중학교에서 배운 일차 함수 y = mx + b를 다차원으로 확장한 것으로 생각할 수 있습니다. 선형 레이어는 입력 특성을 다른 차원 공간으로 변환하며, 이후 활성화 함수(activation function)를 거쳐 비선형성을 도입하는 것이 신경망의 기본 구조입니다.[^1]

입력과 출력의 차원

nn.Linear()를 생성할 때는 두 개의 필수 인자를 전달합니다:[^3]

import torch
import torch.nn as nn

# nn.Linear(in_features, out_features, bias=True)
linear_layer = nn.Linear(in_features=3, out_features=1)

위 코드는 3차원 입력을 1차원 출력으로 변환하는 선형 레이어를 생성합니다. 예를 들어, 768차원의 임베딩 벡터를 64차원으로 줄이고 싶다면 nn.Linear(768, 64)로 작성하면 됩니다. 입력 차원(in_features)과 출력 차원(out_features)을 명확히 지정해야 하며, 잘못된 차원을 전달하면 런타임 에러가 발생합니다.[^2][^4][^3]

순전파(forward pass) 시에는 간단히 입력 텐서를 전달하면 됩니다:[^3]

input_tensor = torch.tensor([1., 2., 3.])
output = linear_layer(input_tensor)
print(output)  # 1차원 텐서 출력

가중치(Weight)와 편향(Bias)의 역할

nn.Linear()를 생성하면 파이토치가 자동으로 가중치와 편향을 초기화합니다. 가중치의 형태는 (out_features, in_features)이고, 편향의 형태는 (out_features,)입니다.[^3][^1]

linear_layer = nn.Linear(in_features=3, out_features=2)

# 가중치 확인
print(f"Weight shape: {linear_layer.weight.shape}")  # torch.Size([2, 3])
print(f"Weight:\n{linear_layer.weight}")

# 편향 확인
print(f"Bias shape: {linear_layer.bias.shape}")  # torch.Size([^2])
print(f"Bias: {linear_layer.bias}")

가중치(weight)는 입력의 각 특성이 출력에 얼마나 영향을 주는지를 결정하는 학습 가능한 매개변수입니다. 편향(bias)은 선형 변환에 더해지는 상수로, 모델의 유연성을 높여줍니다. 예를 들어, bias가 없으면 모든 직선이 원점을 지나야 하지만, bias가 있으면 절편을 자유롭게 조정할 수 있습니다.[^1]

편향이 필요 없는 경우 bias=False로 설정할 수 있습니다:[^5]

linear_no_bias = nn.Linear(3, 2, bias=False)

가중치 접근 및 커스텀 초기화

학습된 가중치와 편향을 확인하거나 수정할 수 있습니다:[^6]

# state_dict를 통한 접근
layer_params = linear_layer.state_dict()
print(layer_params['weight'])
print(layer_params['bias'])

# 직접 접근
print(linear_layer.weight.data)
print(linear_layer.bias.data)

특정 값으로 가중치를 초기화하고 싶다면 직접 할당할 수 있습니다:[^7]

# 커스텀 가중치 설정
my_weights = torch.tensor([[1., 2., 3.], 
                           [4., 5., 6.]])
linear_layer.weight.data = my_weights

# Xavier 초기화 예시
def init_weights(m):
    if isinstance(m, nn.Linear):
        torch.nn.init.xavier_uniform_(m.weight)
        m.bias.data.fill_(0.01)

linear_layer.apply(init_weights)

Xavier(Glorot) 초기화는 신경망의 층별 활성화 분산을 일정하게 유지하여 학습을 안정화시키는 대표적인 초기화 방법입니다.[^1]

배치 처리와 다차원 입력

실제 딥러닝에서는 단일 샘플이 아닌 배치(batch) 단위로 데이터를 처리합니다. nn.Linear()는 배치 차원을 자동으로 처리합니다:[^4]

linear_layer = nn.Linear(5, 3)

# 단일 샘플: (5,)
single_input = torch.randn(5)
output = linear_layer(single_input)  # output shape: (3,)

# 배치 처리: (batch_size, 5)
batch_input = torch.randn(32, 5)  # 32개 샘플
output = linear_layer(batch_input)  # output shape: (32, 3)

# 3차원 입력도 가능: (batch, sequence, features)
sequence_input = torch.randn(32, 10, 5)  # 32개 샘플, 각 10개 시퀀스
output = linear_layer(sequence_input)  # output shape: (32, 10, 3)

마지막 차원만 in_features와 일치하면, 그 앞의 모든 차원은 배치 차원으로 처리됩니다. 이 특성은 RNN, Transformer 등 시퀀스 모델에서 매우 유용합니다.

 

 

 

 

3-2강. 인공 신경망 학습 예제 코드 10분 완성! | 파이토치 선형 회귀 실습

선형 회귀 모델 개요

선형 회귀(Linear Regression)는 종속 변수(y)와 하나 이상의 독립 변수(x) 간의 선형 관계를 모델링하는 가장 기본적인 머신러닝 기법입니다. 데이터의 상관관계가 직선 형태로 나타나기 때문에 '선형'이라 부르며, y = wx + b 형태의 간단한 수식으로 표현됩니다.[^8]

선형 회귀는 네 가지 가정에 기반합니다: (1) 선형성 - 종속 변수와 독립 변수의 관계가 선형적, (2) 독립성 - 데이터가 무작위로 분포, (3) 등분산성 - 오차의 분산이 일정, (4) 정규성 - 오차가 정규 분포를 따름.[^8]

1단계: 데이터 준비

가장 먼저 학습에 사용할 데이터를 준비합니다:[^9][^10]

import torch
import torch.nn as nn
import torch.optim as optim

# 재현성을 위한 시드 고정
torch.manual_seed(1)

# 데이터 생성 (y = 2x 관계)
x_train = torch.FloatTensor([[^1], [^2], [^3]])
y_train = torch.FloatTensor([[^2], [^4], [^6]])

위 예제는 y = 2x 관계를 가진 단순한 데이터로, 모델이 이 관계를 학습하도록 만들 것입니다.[^9]

2단계: 모델 정의

파이토치에서는 nn.Module을 상속받아 모델 클래스를 정의하는 것이 표준입니다:[^10][^8]

class LinearRegression(nn.Module):
    def __init__(self, input_dim, output_dim):
        super(LinearRegression, self).__init__()  # 부모 클래스 초기화
        self.linear = nn.Linear(input_dim, output_dim)  # 선형 레이어 정의

    def forward(self, x):
        # 순전파 연산 정의
        y = self.linear(x)
        return y

# 모델 인스턴스 생성 (입력 1차원, 출력 1차원)
model = LinearRegression(1, 1)

__init__() 메서드에서는 모델의 구조(레이어 구성)를 정의하고, forward() 메서드에서는 입력이 모델을 통과하는 순전파 로직을 정의합니다. 파이토치는 forward()만 정의하면 역전파는 autograd가 자동으로 처리합니다.[^11][^8][^9]

3단계: 손실 함수(Loss Function) 설정

손실 함수는 모델의 예측값과 실제 정답 사이의 차이를 수치화합니다. 선형 회귀에서는 일반적으로 평균 제곱 오차(MSE, Mean Squared Error)를 사용합니다:[^12][^8]

# 손실 함수 정의
criterion = nn.MSELoss()

MSE는 예측값과 실제값의 차이를 제곱한 뒤 평균을 계산하여, 큰 오차에 더 큰 페널티를 부여합니다.[^8]

4단계: 최적화(Optimizer) 설정

옵티마이저(Optimizer)는 손실 함수를 최소화하기 위해 모델의 매개변수를 업데이트하는 알고리즘입니다. 가장 기본적인 옵티마이저는 확률적 경사 하강법(SGD, Stochastic Gradient Descent)입니다:[^13][^8]

# 옵티마이저 정의 (학습률 0.01)
optimizer = optim.SGD(model.parameters(), lr=0.01)

model.parameters()는 학습 가능한 모든 매개변수(가중치와 편향)를 반환하며, lr은 학습률(learning rate)로 매개변수 업데이트 폭을 조절합니다.[^14][^13]

5단계: 학습 루프 작성

이제 실제 학습을 수행하는 루프를 작성합니다:[^10][^8]

epochs = 1000  # 전체 데이터를 1000번 반복 학습

for epoch in range(epochs):
    # 1. 순전파: 예측값 계산
    y_pred = model(x_train)

    # 2. 손실 계산
    loss = criterion(y_pred, y_train)

    # 3. 기울기 초기화 (이전 반복의 기울기 제거)
    optimizer.zero_grad()

    # 4. 역전파: 기울기 계산
    loss.backward()

    # 5. 매개변수 업데이트
    optimizer.step()

    # 100번마다 진행 상황 출력
    if (epoch + 1) % 100 == 0:
        print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}')

학습 루프의 핵심은 순전파 → 손실 계산 → 기울기 초기화 → 역전파 → 매개변수 업데이트의 5단계입니다. 이 과정을 반복하면서 모델이 점차 정답에 가까워집니다.[^15]

6단계: 학습 결과 확인

학습이 완료되면 모델의 매개변수와 예측 성능을 확인할 수 있습니다:[^10]

# 학습된 가중치와 편향 확인
print(f'\n학습된 가중치: {model.linear.weight.item():.4f}')
print(f'학습된 편향: {model.linear.bias.item():.4f}')

# 새로운 데이터로 예측
with torch.no_grad():
    x_test = torch.FloatTensor([[^4]])
    y_test = model(x_test)
    print(f'\nx=4일 때 예측값: {y_test.item():.4f}')

y = 2x 관계를 가진 데이터로 학습했다면, 가중치는 2에 가깝게, 편향은 0에 가깝게 수렴할 것입니다.[^9]

하이퍼파라미터 조정

모델 성능은 하이퍼파라미터(hyperparameter) 선택에 크게 영향을 받습니다. 주요 하이퍼파라미터는 다음과 같습니다:[^14]

  1. 학습률(Learning Rate): 너무 크면 발산하고, 너무 작으면 학습이 느립니다[^14]
  2. 에폭 수(Epochs): 학습 반복 횟수. 너무 많으면 과적합 위험[^14]
  3. 배치 크기(Batch Size): 한 번에 처리하는 샘플 수[^14]

학습률 스케줄러를 사용하면 학습 진행에 따라 학습률을 동적으로 조정할 수 있습니다:[^12]

# 특정 에폭에서 학습률을 0.1배로 감소
milestones = [500, 800]
scheduler = optim.lr_scheduler.MultiStepLR(optimizer, milestones, gamma=0.1)

for epoch in range(epochs):
    # ... 학습 루프 ...
    scheduler.step()  # 학습률 업데이트

전체 워크플로우 정리

파이토치로 신경망을 학습시키는 전체 과정은 다음과 같이 요약됩니다:[^13][^11]

  1. 데이터 준비: 텐서 형태로 데이터 로드
  2. 모델 설계: nn.Module 상속하여 클래스 정의
  3. 손실 함수와 옵티마이저 설정: 학습 목표와 최적화 알고리즘 선택
  4. 학습 루프: 순전파 → 손실 계산 → 역전파 → 업데이트 반복
  5. 평가 및 예측: 학습된 모델로 새로운 데이터 예측
    # 10분 완성 전체 코드 요약
    import torch
    import torch.nn as nn
    import torch.optim as optim
    

1. 데이터

x_train = torch.FloatTensor([[^1], [^2], [^3]])
y_train = torch.FloatTensor([[^2], [^4], [^6]])

2. 모델

model = nn.Linear(1, 1)

3. 손실 함수 & 옵티마이저

criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)

4. 학습 루프

for epoch in range(1000):
y_pred = model(x_train)
loss = criterion(y_pred, y_train)

optimizer.zero_grad()
loss.backward()
optimizer.step()

if (epoch + 1) % 100 == 0:
    print(f'Epoch {epoch+1}, Loss: {loss.item():.4f}')

5. 결과 확인

print(f'가중치: {model.weight.item():.4f}')
print(f'편향: {model.bias.item():.4f}')



### 고급 활용: 레이어별 학습률 설정

복잡한 모델에서는 레이어마다 다른 학습률을 적용할 수 있습니다:[^12]

```python
model = nn.Sequential(
    nn.Linear(2, 4),
    nn.Linear(4, 4),
    nn.Linear(4, 1)
)

# 첫 번째 레이어만 다른 학습률로 학습
params_first = [p for n, p in model.named_parameters() if '0' in n]
params_rest = [p for n, p in model.named_parameters() if '0' not in n]

optimizer = optim.SGD([
    {'params': params_first, 'lr': 0.01},
    {'params': params_rest, 'lr': 0.001}
])

특정 레이어를 고정(freeze)하려면 requires_grad=False로 설정합니다:[^12]

# 첫 번째 레이어 고정
model[^0].requires_grad_(False)

핵심 정리: nn.Linear()는 신경망의 가장 기본적인 빌딩 블록으로, 입력을 선형 변환하여 출력을 생성합니다. 가중치와 편향의 개념을 정확히 이해하고, 데이터 준비 → 모델 정의 → 손실 함수 → 옵티마이저 → 학습 루프의 5단계 워크플로우를 익히면, 더 복잡한 CNN, RNN, Transformer 등의 고급 모델도 동일한 패턴으로 구현할 수 있습니다.

 

 

다음 글

[AI 인공지능 머신러닝 딥러닝/Python | PyTorch] - 인스톨! 파이토치 4강 | 실전 분류 모델 구축부터 최적화까지: 이진 분류와 하이퍼파라미터 튜닝 (4강)

 

인스톨! 파이토치 4강 | 실전 분류 모델 구축부터 최적화까지: 이진 분류와 하이퍼파라미터 튜닝

[AI 인공지능 머신러닝 딥러닝/Python | PyTorch] - 인스톨! 파이토치 강의 소개 인스톨! 파이토치 강의 소개혁펜하임 PyTorch 강의 오리엔테이션 요약혁펜하임 채널의 '[PyTorch] 0강. 오리엔테이션' 영상

inner-game.tistory.com

 

 

 

728x90
반응형
반응형

공유하기

facebook twitter kakaoTalk kakaostory naver band
250x250