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