ReLU의 대안, Leaky ReLU

ReLU의 대안, Leaky ReLU
Photo by Luca Bravo / Unsplash

사실 너무나도 오래된 Activatio Function이지만, 복기 차원에서 정리해보았음

Leaky ReLU is

  • Leaky ReLU(Leaky Rectified Linear Unit)는 ReLU(Rectified Linear Unit)의 변형으로, ReLU의 단점을 보완하기 위해 고안
    $$ \text{Leaky ReLU}(x) = \begin{cases} x & \text{if } x > 0 \ \alpha x & \text{if } x \leq 0 \end{cases} $$
  • 여기서 α는 작은 양수 값으로, 일반적으로 0.01로 설정
    • 입력 값이 음수일 때 작은 기울기를 제공하여 dead ReLU problem 완화

Pros

  • Dead ReLU Problem 완화: Leaky ReLU는 음수 입력에 대해 작은 기울기를 가지므로 뉴런이 활성화되지 않는 문제를 줄여줌.
  • 비선형성 유지: Leaky ReLU는 비선형성을 제공하여 신경망이 복잡한 패턴을 학습할 수 있음
  • 단순한 구현: ReLU와 유사한 형태로 구현이 간단함

Cons

  • 고정된 기울기: α 값이 고정되어 있어 최적의 기울기를 찾는 데 한계가 있을 수 있을 수 있음
  • 과적합 가능성: 작은 기울기가 모든 문제에 적합하지 않을 수 있으며, 일부 경우에는 과적합을 초래할 수 있음
    

Alternatives

  • ReLU: 입력 값이 양수일 때는 그대로 출력하고, 음수일 때는 0을 출력
  • Parametric ReLU (PReLU): α값을 학습 가능한 파라미터로 만들어 최적의 기울기를 찾음
  • Exponential Linear Unit (ELU): 음수 입력에 대해 지수 함수를 적용
  • Scaled Exponential Linear Unit (SELU) 자동으로 수렴을 보장하고 정규화된 출력을 제공하여 깊은 신경망에서 특히 유용

Sample Code

import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split

# 데이터 생성
X, y = make_moons(n_samples=1000, noise=0.2, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# PyTorch 텐서로 변환
X_train = torch.FloatTensor(X_train)
X_test = torch.FloatTensor(X_test)
y_train = torch.LongTensor(y_train)
y_test = torch.LongTensor(y_test)

# 모델 정의
class SimpleNN(nn.Module):
    def __init__(self, activation_fn):
        super(SimpleNN, self).__init__()
        self.layer1 = nn.Linear(2, 64)
        self.layer2 = nn.Linear(64, 64)
        self.layer3 = nn.Linear(64, 2)
        self.activation_fn = activation_fn

    def forward(self, x):
        x = self.activation_fn(self.layer1(x))
        x = self.activation_fn(self.layer2(x))
        x = self.layer3(x)
        return x

# 모델 생성 (ReLU와 Leaky ReLU 비교)
relu_model = SimpleNN(nn.ReLU())
leaky_relu_model = SimpleNN(nn.LeakyReLU(0.01))

# 손실 함수와 옵티마이저 정의
criterion = nn.CrossEntropyLoss()
relu_optimizer = optim.Adam(relu_model.parameters(), lr=0.01)
leaky_relu_optimizer = optim.Adam(leaky_relu_model.parameters(), lr=0.01)

# 모델 학습 함수
def train_model(model, optimizer, X_train, y_train, epochs=100):
    model.train()
    losses = []
    for epoch in range(epochs):
        optimizer.zero_grad()
        outputs = model(X_train)
        loss = criterion(outputs, y_train)
        loss.backward()
        optimizer.step()
        losses.append(loss.item())
    return losses

# 모델 평가 함수
def evaluate_model(model, X_test, y_test):
    model.eval()
    with torch.no_grad():
        outputs = model(X_test)
        _, predicted = torch.max(outputs, 1)
        accuracy = (predicted == y_test).float().mean().item()
    return accuracy

# 모델 학습
relu_losses = train_model(relu_model, relu_optimizer, X_train, y_train)
leaky_relu_losses = train_model(leaky_relu_model, leaky_relu_optimizer, X_train, y_train)

# 모델 평가
relu_accuracy = evaluate_model(relu_model, X_test, y_test)
leaky_relu_accuracy = evaluate_model(leaky_relu_model, X_test, y_test)

print(f'ReLU Test Accuracy: {relu_accuracy}')
print(f'Leaky ReLU Test Accuracy: {leaky_relu_accuracy}')

# 학습 곡선 시각화
plt.plot(relu_losses, label='ReLU Loss')
plt.plot(leaky_relu_losses, label='Leaky ReLU Loss')
plt.legend()
plt.title('ReLU vs Leaky ReLU Loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.show()

# 예측 결과 시각화
def plot_decision_boundary(model, X, y, ax):
    x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx, yy = torch.meshgrid(torch.arange(x_min, x_max, 0.01), torch.arange(y_min, y_max, 0.01))
    grid = torch.cat([xx.reshape(-1, 1), yy.reshape(-1, 1)], dim=1)
    with torch.no_grad():
        pred = model(grid).argmax(dim=1).reshape(xx.shape).numpy()
    ax.contourf(xx, yy, pred, alpha=0.5)
    ax.scatter(X[:, 0], X[:, 1], c=y, edgecolors='k')

fig, ax = plt.subplots(1, 2, figsize=(12, 6))
plot_decision_boundary(relu_model, X_test.numpy(), y_test.numpy(), ax[0])
ax[0].set_title('ReLU Decision Boundary')
plot_decision_boundary(leaky_relu_model, X_test.numpy(), y_test.numpy(), ax[1])
ax[1].set_title('Leaky ReLU Decision Boundary')
plt.show()

Read more

다중공선성은 잘못된 인과추론 결과를 만들어낼 수 있습니다.

다중공선성은 잘못된 인과추론 결과를 만들어낼 수 있습니다.

다중공선성(Multi Collinearity) * **Multi-Collinearity(다중공선성)**는 독립 변수들 간의 강한 상관관계가 존재할 때 발생합니다. 즉, 한 독립 변수가 다른 독립 변수에 의해 설명될 수 있을 정도로 상관관계가 높은 상황을 의미합니다. * 이 문제는 주로 회귀 분석에서 나타나며, 변수들 간의 관계를 해석하는 데 있어 큰 장애물이 될 수 있습니다. * 일반적인 회귀식을 $Y=

Bayesian P-Value는 불확실성을 감안하여 모델의 적합도를 평가합니다.

Bayesian P-Value는 불확실성을 감안하여 모델의 적합도를 평가합니다.

Bayesian P- Value * Bayesian P-Value는 **모델의 적합도(goodness-of-fit)**를 평가하는 데 사용됩니다. * 사후 분포(posterior distribution)를 이용하여 실제 데이터와 모델이 생성한 예상 데이터를 비교함으로써, 관측된 데이터가 모델에 의해 얼마나 잘 설명되는지를 평가합니다. * 빈도주의 p-값은 "관찰된 데이터보다 극단적인 데이터가 나올 확률"을 계산하지만, Bayesian P-Value는 "모델이 실제

Non-Identifiability는 Model Parameter를 고유하게 식별할 수 없는 현상입니다.

Non-Identifiability는 Model Parameter를 고유하게 식별할 수 없는 현상입니다.

Non Identifiability * Non-Identifiability는 주어진 데이터와 모델에 대해 특정 파라미터를 고유하게 식별할 수 없는 상황을 의미합니다. 즉, 여러 파라미터 값들이 동일한 데이터를 생성할 수 있으며, 이로 인해 특정 파라미터 값을 확정적으로 추정하기 어렵게 됩니다. * 베이지안 추론에서 Non-Identifiability는 사후 분포가 특정 파라미터 값에 대해 명확하게 수렴하지 않고, 여러 값들에 대해 비슷한 확률을

Rootgram은 큰 분산을 갖거나 비정규 형태의 데이터를 위한 히스토그램입니다.

Rootgram은 큰 분산을 갖거나 비정규 형태의 데이터를 위한 히스토그램입니다.

Rootgram * 히스토그램의 변형으로 데이터가 비정규적이거나 큰 분산을 가지는 경우, 정확한 분포를 파악하기 위해 사용됩니다. * 일반적으로 히스토그램은 데이터의 빈도를 직접적으로 나타내기 때문에, 큰 값이 빈번하게 발생하는 경우 상대적으로 작은 값을 잘 드러내지 못하는 경향이 있습니다. 반면, Rootgram은 빈도를 제곱근 형태로 변환하여, 데이터 분포의 차이를 더 잘 시각화할 수 있도록 돕습니다 * 여기서