카테고리 없음

파이토치 자연어처리(5) - 신경망 구성 요소(1) : 퍼셉트론, 활성화함수

SolartheNomad 2023. 2. 11. 18:12

1. 퍼셉트론 

 

 

1.1 퍼셉트론 유닛 

 

 

입력 : x 

출력 : y

가중치 : w

절편 : b 

활성화 함수 : f 

 

위의 그림에 대해서 다음과 같이 f를 서술하는 것이 가능함. 이 f가 퍼셉트론 유닛이다. 

단층 퍼셉트론 : 한개의 계층으로 이루어진 퍼셉트론. 보내는 값과 출력하는 단계, 딱 두 단계로 이루어짐. input layer / output layer 두 개의 층으로 이루어짐. 

 

wx + b : 선형 함수 

임의의 개수의 입력을 받아 아핀 변환을 수행하고 + 활성화 함수를 적용함 

 

** 아핀 변환 

 

#퍼센트론(활성화 함수f) 생성하기

import torch   #pytorch 임포트
import torch.nn as nn   ## torch.nn 패키지 임포트 

class Perceptron(nn.Module):
   """퍼셉트론은 하나의 선형 층이다."""  
   def __init__(self, input_dim):
   
   """
   매개변수 : 
        input_dim(int) : 입력 레이어의 차원/입력 기능 수  
   """
   
   super(Perceptron, self).__init__()   #super()은 위의 Perceptron class를 상속받고, __init__()으로 초기화 시켜줌 
   
   self.fc1 = nn.Linear(input_dim, 1)
   
   
   #퍼셉트론의 정방향 계산
   def forward(self, x_in) :
   
   return torch.sigmoid(self.fc1(x_in)).squeeze()
   
   # squeeze() : 차원 삭제 하기(차원 감소)

 

Linear() : torch.nn에서 제공하는 가중치와 절편에 필요한 부가 작업과 아핀 변환 수행함 

 

forward의 매개변수 x_in

= x_in(torch, Tensor) : 입력 데이터의 텐서

   x_inshape : (batch, num_features)이다. 

 

 2. 활성화 함수 종류 

 

2.1 시그모이드 

 

# 임의의 실숫값을 받아 0과 1사이의 범위로 압축해줌 

 

 

 

# 시그모이드 함수 구현하기 

 

import torch
import matplotlib.pyplot as lpt 

x = torch.range(-5, 5, 0.1)  #-5와 5사이의 0.1 간격으로 띄어서 배열로 표현한다.

x = torch.sigmoid(x)
plt.plot(x.numpy(), y.numpy())
plt.show()

#결과

 

 

 

** 그레디언트 폭주 문제(그레디언트 소실 문제)

시그모이드 함수는 극단적인 출력을 만들어낸다. = 그레디언트가 0이 되거나 아예 발산하여 오버플로가 되는 문제가 발생하는 것  

 

=> 시그모이드 활성화 함수는 주로 출력층에서만 사용하게 됨 (출력을 확률로 압축함)

 

 

2.2 하이퍼볼릭 탄젠트 

 

 

(음의 무한대, 양의 무한대) 범위의 실숫값을 [-1 ,+1]로 바꾼다. 

 

import torch
import matplotlib.pyplot as plt 

x = torch.range(-5 ,5 0.1)
y = torch.tanh(x)     # tanh() = 하이퍼볼릭 탄젠트 

plt.plot(x.numpy() , y.numpy())
plt.show()

 

 

2.3 렐루

 

# 음숫값을 0으로 자르는 일을 하는 함수 

 

import torch 
import matplotlib.pyplot as plt 

relu = torch.nn.ReLU()
x = torch.range(-5, 5, 0.1)
y = relu(x)

plt.plot(x.numpy() , y.numpy())
plt.show()

 

실행 결과 

 

 

 

문제점 : 음수르 제거하여 그레디언트 소실 문제에 도움이 되지만, 신경망의 출력이 0이 되면 다시 되돌아 오지 않는다. 

 

=> 리키렐루, PReLU 함수를 사용하여 문제 해결이 가능한데, 가장 많이 사용되는 PReLU 함수를 통해 표현해보자 

 

#PReLU 함수 

 

 

import torch 
import matplotlib.pyplot as plt 

prelu = torch.nn.PReLU(num_parameters =1)
x = torch.range(-5 ,5 ,0.1)
y = prelu(x)

plt.plot(x.numpy(), y.numpy())
plt.show()

 

2.4소프트맥스 

 

신경망 유닛의 출력을 0과 1 사이로 압축함(시그모이드, 하이퍼블릭 탄젠트와 비슷함)

모든 출력의 합으로 각 출력을 나누어 k 개의 클래스에 대한 이산 확률 분포를 만듦 

 

 

#소프트맥스 함수 구현 

import torch.nn as nn 
import torch

softmax = nn.Softmax(dim=1)
x_input = torch.randn(1,3)
y_output = softmax(x_input)

print(x_input)
print(y_output)