베이지안 딥러닝

Study/Deep Learning|2023. 4. 3. 09:44
728x90
반응형

 

베이지안 딥러닝은 딥러닝과 베이지안 추론을 결합한 방법입니다. 베이지안 추론은 데이터와 모델에 대한 불확실성을 수학적으로 정량화하고 추론 과정에 포함시키는 것을 목표로 합니다. 베이지안 딥러닝은 신경망의 가중치에 대한 확률 분포를 추정하여, 모델의 예측 불확실성을 계산하는 데 사용합니다.

베이지안 딥러닝의 핵심 개념은 다음과 같습니다:

 

1. 사전 분포 (Prior Distribution): 가중치에 대한 사전 지식을 표현하는 확률 분포입니다. 사전 분포는 통상적으로 정규 분포와 같은 균형 잡힌 분포로 설정됩니다.

 

2. 가능도 함수 (Likelihood Function): 관측된 데이터와 가중치 사이의 관계를 나타내는 함수입니다. 딥러닝에서 가능도 함수는 일반적으로 손실 함수의 역수로 생각할 수 있습니다.

 

3. 사후 분포 (Posterior Distribution): 사전 분포와 가능도 함수를 결합하여 계산한 가중치에 대한 확률 분포입니다. 이 분포는 베이즈 정리를 통해 구할 수 있습니다.

 

베이즈 정리는 다음과 같이 표현됩니다:

 

P(θ|D) = P(D|θ) * P(θ) / P(D)

 

여기서 θ는 모델 가중치, D는 데이터, P(θ)는 사전 분포, P(D|θ)는 가능도 함수, P(θ|D)는 사후 분포입니다.

변분 추론 (Variational Inference): 사후 분포를 근사하는 확률 분포를 선택하고, 그 사이의 차이를 최소화하는 방식입니다. 이 방법에서는 Kullback-Leibler 발산(KL divergence)을 사용하여 두 분포 간의 차이를 측정합니다.

 

Markov Chain Monte Carlo (MCMC): 사후 분포를 근사하는 샘플을 생성하는 데 사용되는 확률론적 알고리즘입니다. 대표적인 MCMC 방법인 해밀턴 몬테카를로(Hamiltonian Monte Carlo, HMC)는 해밀턴 방정식을 사용하여 효율적으로 사후 분포를 탐색합니다.

 

베이지안 딥러닝은 다음과 같은 장점을 가지고 있습니다:

 

1. 불확실성 추정: 모델의 가중치에 대한 확률 분포를 추정함으로써, 예측 결과의 불확실성을 계산할 수 있습니다. 이를 통해 모델이 확신하지 못하는 영역에 대한 예측에 대한 신뢰도를 낮출 수 있습니다.

 

2. 오버피팅 방지: 가중치에 대한 사후 분포를 사용하면, 데이터에 너무 맞추지 않고 일반화를 유지할 수 있습니다. 이를 통해 오버피팅을 방지할 수 있습니다.

 

3. 데이터 효율성 향상: 베이지안 딥러닝은 불확실성을 고려하기 때문에, 데이터가 적은 상황에서도 상대적으로 안정적인 결과를 얻을 수 있습니다.

 

4. 베이지안 딥러닝을 파이토치로 구현하는 예시는 다음과 같습니다. 이 예시에서는 변분 오토인코더(Variational Autoencoder, VAE)를 사용합니다.

 

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

#인코더 정의
class Encoder(nn.Module):
    def __init__(self, input_dim, hidden_dim, latent_dim):
        super(Encoder, self).__init__()
        # 입력층과 은닉층 연결
        self.fc1 = nn.Linear(input_dim, hidden_dim)
        # 은닉층과 잠재변수 평균 연결
        self.fc21 = nn.Linear(hidden_dim, latent_dim)
        # 은닉층과 잠재변수 로그 분산 연결
        self.fc22 = nn.Linear(hidden_dim, latent_dim)

    def forward(self, x):
    	# 활성화 함수로 ReLU를 사용하여 은닉층 계산
        h1 = torch.relu(self.fc1(x))
        # 잠재변수의 평균과 로그 분산 반환
        return self.fc21(h1), self.fc22(h1)

# 디코더 정의
class Decoder(nn.Module):
    def __init__(self, latent_dim, hidden_dim, output_dim):
        super(Decoder, self).__init__()
        # 잠재변수와 은닉층 연결
        self.fc3 = nn.Linear(latent_dim, hidden_dim)
        # 은닉층과 출력층 연결
        self.fc4 = nn.Linear(hidden_dim, output_dim)

    def forward(self, z):
    	# 활성화 함수로 ReLU를 사용하여 은닉층 계산
        h3 = torch.relu(self.fc3(z))
        # 활성화 함수로 시그모이드를 사용하여 출력층 계산
        return torch.sigmoid(self.fc4(h3))

# VAE 전체 정의
class VAE(nn.Module):
    def __init__(self, input_dim, hidden_dim, latent_dim):
        super(VAE, self).__init__()
        # 인코더와 디코더 객체 생성
        self.encoder = Encoder(input_dim, hidden_dim, latent_dim)
        self.decoder = Decoder(latent_dim, hidden_dim, input_dim)

	#재매개변수화 기법을 사용하여 샘플링
    def reparameterize(self, mu, logvar):
        std = torch.exp(0.5 * logvar)
        eps = torch.randn_like(std)
        return mu + eps * std

    def forward(self, x):
    	# 인코더를 통해 입력 데이터의 잠재변수 평균과 로그 분산 계산
        mu, logvar = self.encoder(x)
        # 재매개변수화 기법을 사용하여 샘플링
        z = self.reparameterize(mu, logvar)
        # 디코더를 통해 재구성된 출력 계산
        return self.decoder(z), mu, logvar

 

이 예시에서는 변분 오토인코더를 구현하였습니다. 이제 학습과 손실 함수를 정의하고 VAE를 학습시킬 수 있습니다.

 
def vae_loss(recon_x, x, mu, logvar):
	# 재구성 손실: 원본데이터와 재구성된 데이터 간의 차이를 계산(이진 크로스 엔트로피 사용)
    recon_loss = nn.BCELoss(reduction='sum')(recon_x, x)
    #KL 발산: 잠재 변수의 사전 분포와 근사된 사후 분포 간의 차이를 계산
    kl_divergence = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())
    # 전체 손실은 재구성 손실과 KL 발산의 합
    return recon_loss + kl_divergence

# 하이퍼파라미터 설정
input_dim = 784
hidden_dim = 400
latent_dim = 20
learning_rate = 0.001
epochs = 20

#VAE 모델 생성
vae = VAE(input_dim, hidden_dim, latent_dim)
#옵티마이저 설정(Adam 사용)
optimizer = optim.Adam(vae.parameters(), lr=learning_rate)

#학습 루프
for epoch in range(epochs):
    for batch_idx, (data, _) in enumerate(train_loader):
    	#기울기 초기화
        optimizer.zero_grad()
        # 모델에 데이터를 전달하고 재구성된 데이터, 잠재 변수의 평균, 로그 분산 계산
        recon_batch, mu, logvar = vae(data)
        # 손실 함수 계산
        loss = vae_loss(recon_batch, data, mu, logvar)
        # 역전파를 통해 기울기 계산
        loss.backward()
        # 옵티마이저를 통해 가중치 업데이트
        optimizer.step()

변분 오토인코더는 베이지안 딥러닝의 한 예입니다. 비슷한 방식으로 다른 딥러닝 모델에 베이지안 추론을 적용할 수도 있습니다. 예를 들어, torch.nn.Module의 서브클래스로 베이지안 신경망을 정의하고 변분 추론을 사용하여 가중치의 사후 분포를 근사할 수 있습니다. 이를 통해 예측의 불확실성을 계산하고 모델을 안정적으로 학습시킬 수 있습니다.

베이지안 딥러닝은 불확실성 추정과 일반화 성능 향상을 위해 많은 연구가 진행되고 있는 분야입니다. 다양한 베이지안 딥러닝 모델과 근사 추론 방법이 연구되고 있으며, 이를 통해 딥러닝의 한계를 극복하려는 시도가 이루어지고 있습니다.

 
 
728x90
반응형

댓글()