[D&A 운영진 딥러닝 스터디] 1주차 2차시
퍼셉트론
다수의 신호를 입력 받아 하나의 신호를 출력하는 것
- 신호가 흐른다/안 흐른다(1/0)으로 나뉜다.
- 인간의 뇌에 있는 뉴런(neuron)을 본떠 만듦(신호 전달)
- linear classifier 수행
를 (편향, bias)로 치환 시,
신호의 총 합이 를 넘을 때만 1 출력 (: 임계값)
뉴런이 활성화 한다.
1. AND 게이트 구현
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
이를 만족하는 매개변수()가 무수히 많다.
0.5 0.5 0.7 0.5 0.5 1 ... ... ...
2. NAND 게이트 구현
AND 게이트 매개변수 반전
-0.5 | -0.5 | -0.7 |
-0.5 | -0.5 | -1 |
... | ... | ... |
3. OR 게이트 구현
0.5 | 0.5 | 0.4 |
... | ... | ... |
4. XOR 게이트 구현
배타적 논리합, 어느 한쪽만 1인 경우
- 단층 퍼센트론으로는 구현 불가 ( 선형으로 분류 불가)
- 다층 퍼셉트론(비선형)으로 구현 가능!
0 | 0 | 1 | 0 | 0 |
0 | 1 | 1 | 1 | 1 |
1 | 0 | 1 | 1 | 1 |
1 | 1 | 0 | 1 | 0 |
, 는 입력, 는 NAND의 출력, 는 OR의 출력
이와 같이 퍼셉트론의 층을 깊게 쌓아 매우 복잡한 것 구현 가능
다층 퍼셉트론은 복잡한 함수도 표현할 수 있지만, 가중치를 설정하는 작업을 사람이 수동으로 해야한다.
신경망이 자동으로 해결
# data
X = torch.FloatTensor([ [0,0], [0,1], [1,0], [1,1] ]).to(device)
Y = torch.FloatTensor([ [0], [1], [2], [3] ]).to(device)
# layers
linear1 = torch.nn.Linear(2, 2, bias=True) # input_size = 2, hidden_size = 2, 편향 존재
linear2 = torch.nn.Linear(2, 1, bias=True) # hidden_size=2, output_size = 1, 편향 존재
sigmoid = torch.nn.Sigmoid() # 활성화함수 - 시그모이드
model = torch.nn.Sequential(linear1, sigmoid, linear2, sigmoid).to(device) # 모델 연결
# loss & optimizer
criterion = torch.nn.BCELoss().to(device) # Binary CrossEntropy
optimizer = torch.optim.SGD(model.parameters(), lr=1) # SGD를 통해 model의 파라미터 학습(학습률=1)
# training
for step in range(10001):
optimizer.zero_grad() # 기울기 고정
hypothesis = model(X) # 예측값
cost = criterion(hypothesis, Y) # 실제값과 예측값을 통한 loss 계산
cost.backward() # 손실함수를 통해 오차역전파법 실행
optimizer.step() # 오차역전파법을 통해 얻는 기울기를 이용해 파라미터 갱신
if step%100 == 0: # 100 epochs마다
print(f'step: {step}\nloss: {cost.item()}') # step과 loss 출력
신경망(Neural Network)
- 한 층에서의 출력 과정1. 활성화 함수(activation function)
- 입력 신호의 총합을 출력 신호로 변환하는 함수
- 입력 신호의 총합이 활성화를 일으키는지 정함
- 위의 식에서 h를 의미
torch.nn.linear(x)
torch.nn.sigmoid(x)
torch.nn.tanh(x)
torch.nn.relu(x)
torch.nn.leaky_relu(x, 0.01)
- 계단 함수(Step Function)
- 임계값()을 경계로 출력이 변하는 함수
- 퍼셉트론에서 사용하는 활성화 함수
- 0과 1로 밖에 출력할 수 없다.(다중 출력 불가)
- 선형 함수(Linear Activation Function)
- 선형으로 이루어진 함수
- 다중 출력 가능
- 오차역전파법(BackPropagation) 불가
- 여려겹으로 쌓아도 출력 로 동일
- 시그모이드 함수(Sigmoid Function)
- 출력 값 범위가 0~1이다.
- 라장 많이 사용되는 활성화 함수
- Saturation(포화상태) 발생
- 오차역전파법 사용 시 미분 값을 사용해야 하는데, 미분 값이 이므로 최대값이 0.25이다.
- 그러므로 함수의 기울기가 0에 가까워져 Gradient Vanishing 문제 야기
- non-zero centered
- 쌍곡탄젠트 함수(Hyperbolic Tangent Function)
- 출력 값의 범위: -1 ~ 1
- zero-centered
- Gradient Vanishing 문제 야기
- 미분 시 이기 때문
- ReLU함수(Rectified Linear Unit)
- 양의 값에서는 Saturation 발생하지 않음(gradient가 0 or 1)
- 계산 효율이 뛰어남(빠름)
- 비선형함수
- non-zero centered
- Dying ReLU: 입력 값이 0 이하일 때, gradient가 0이 되어 학습을 하지 못함.
- Leaky ReLU
- ReLU와 유사하지만 0 이하의 범위에서 더이상 0이 아니다.
- PReLU(Parametric ReLU)
- 0 이하일 때, 기울기가 인 Leaky ReLU
- 는 Backpropagation으로 학습
- ELU(Exponential Linear Unit)
- zero-mean에 가까운 출력 값 보임
- ReLU의 모든 장점 및 Dying ReLU 문제 해결
- 지수함수를 사용해 연산비용 추가
- 큰 음수 값에 쉽게 포화
- Maxout Neuron
- ReLU와 LeakyReLU의 더 일반화 된 형태(두 개의 선형 함수를 취하기 때문)
- 선형이기 때문에 Saturation 발생하지 않는다.
- Dropout과 함께 사용하기 좋음
- neuron 당 parameter 수가 두 배가 됨(계산량 많고 복잡)
- 출력층 활성화함수
- 분류 문제
- 이진 분류: 시그모이드 함수
- 다지 분류: 소프트맥스 함수(softmax)
지수함수가 매우 쉽게 커지기 때문에 오버플로 문제 발생
C를 대입하여 개선(C는 의 최대값)시그모이드 함수 일반화한 형태
- 회귀문제
- 항등함수
- 항등함수
신경망 학습
훈련데이터로부터 매개변수의 최적값을 자동으로 획득
자동으로 학습할 때 손실함수(Loss)를 지표로 사용!
손실함수를 최소화하는 매개변수를 찾는다.
미분, 기울기 이용
손실함수
- 오차제곱합(SSE; Sum of Squared Error)
- 교차엔트로피(CEE; Cross-Entropy Error)
- 실제로 정답일 때의 예측값의 자연로그 계산()
- 정답일 때의 출력이 전체 값을 정함
- 이면 는 이므로 에 C를 더해줌
Gradient Update
- Batch Gradient Descent
모든 학습 데이터를 사용하여 Graident 계산 및 Update - Stochastic Gradient Descent
한 개의 학습 데이터를 사용하여 Gradient 계산 및 Update - Mini-batch Gradient Descent
모든 학습 데이터를 Mini-batch로 쪼개어 한 번의 Gradient 계산 및 Update에 한 개의 Mini-batch 사용
속도와 최소값의 수렴을 고려하여 미니배치 경사하강법 채택
-
각 미니배치별 손실함수 = 각 데이터의 손실함수 평균
-
정확도를 손실함수로 사용하지 않는 이유
- 매개변수의 미분값이 대부분의 장소에서 0이기 때문
- 정확도 개선 시 불연속적으로 개선
- 계단 함수를 활성화 함수로 사용하지 않는 이유 중 하나
- 시그모이드 함수는 어디에서도 기울기가 0이 아니기에 적합
- Gradient Vanishing 문제 보유하고 있긴 함
경사하강법
기울기를 잘 이용해 함수의 최소값을 찾아가는 방법
- 현 위치에서 기울기를 구해 기울어진 방향으로 일정 거리만큼 이동하기를 반복
- 기울기(경사): 모든 변수의 편미분을 벡터로 정리한 것(수치미분을 이용하여 계산)
- 기울기가 0이라고 최소값인 것은 아니다. ( 극소점, 안장점)
- 기울기는 수치미분을 통해 구하는 것은 단순하지만 시간이 오래걸린다.
- 이를 개선하여 오차역전파법 사용
MNIST 예제
1) 모두를 위한 딥러닝
if torch.cuda.is_available():
device = torch.device('cuda')
else:
device = torch.device('cpu')
# hyperparameter
learning_rate = 0.001
training_epochs = 15
batch_size = 100
# load data
import torchvision.datasets as dsets # 데이터 불러오는 패키지
from torchvision import transforms
mnist_train = dsets.MNIST(root='MNIST_data/', train=True,
transform=transforms.ToTensor())
mnist_test = dsets.MNIST(root='MNIST_data/', train=False,
transform=transforms.ToTensor())
# root: 데이터 저장 위치, train data 여부, transofrm: 변환 적용 종류
data_loader = torch.utils.DataLoader(DataLoader=mnist_train,
batch_size=batch_size, shuffle=True, drop_last=True) # 데이터 불러오기
# modeling
linear1 = torch.nn.Linear(28*28, 256, bias=True).to(device)
linear2 = torch.nn.Linear(256, 256, bias=True).to(device)
linear3 = torch.nn.Linear(256, 10, bias=True).to(device)
relu = torch.nn.ReLU()
torch.nn.init.normal_(linear1.weight) # 가중치를 정규분포로 초기화
torch.nn.init.normal_(linear2.weight)
torch.nn.init.normal_(linear3.weight)
model.nn.Sequential(linear1, relu, linear2, relu, linear3) # 마지막은 softmax로
criterion = torch.nn.CrossEntropyLoss().to(device) # 내부적으로 softmax 실행
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate) # Adam으로 파라미터 최적화
for epoch in range(training_epochs): # epochs만큼 반복 학습
avg_cost = 0 # 손실함수 초기화
total_batch = len(data_loader)
for X,Y in data_loader:
X = X.view(-1, 28*28).to(device) # flatten
optimizer.zero_grad() # gradient 초기화
hypothesis = model(X) # 모델 예측값
cost = criterion(hypothesis, Y) # 손실함수 계산
cost.backward() # 오차역전파법 수행
avg_cost += cost/total_batch
print(f'Epoch: {epoch+1}, cost: {avg_cost}')
2) 파이썬 딥러닝 파이토치
if torch.cuda.is_available():
device = torch.device('cuda')
else:
device = torch.device('cpu')
batch_size = 32
epochs = 10
# load data
from torchvision import transforms, datasets
train_dataset = datasets.MNIST(root = 'data/MNIST',
train = True, download = True,
transform = transforms.ToTensor())
# root: 데이터 저장 장소, train: 학습용 데이터 여부
# download: 다운로드 시행할 것인지 여부, transform: 기본적인 전처리
test_dataset = datasets.MNIST(root = 'data/MNIST',
train = False,
transform = transforms.ToTensor())
train_loader = torch.utils.data.DataLoader(dataset = train_dataset,
batch_size = batch_size,
shuffle = True)
# 다운로드한 데이터셋 mini-batch단위로 분리해 지정
# 순서를 암기할 수 있으므로 shuffle
test_loader = torch.utils.data.DataLoader(dataset = test_dataset,
batch_size = batch_size,
shuffle = False)
# 모델 구조 정의
class Net(torch.nn.Module):
# pytorch 내에 딥러닝 관련 기본 함수를 포함하는 nn.Module 클래스 상속
# nn.Module 클래스에서 이용할 수 있는 모든 함수 사용 가능
def __init__(self): # 인스턴스를 생성했을 시 지니게 되는 성질 정의
super(Net, self).__init__() # nn.Module 내에 있는 메소드 상속받아 이용
self.fc1 = torch.nn.Linear(28*28, 512)
self.fc2 = torch.nn.Linear(512, 256)
self.fc3 = torch.nn.Linear(256,10)
def forward(self, x):
x = x.view(-1, 28*28) # flatten
x = self.fc1(x)
x = torch.nn.functional.sigmoid(x)
x = self.fc2(x)
x = torch.nn.functional.sigmoid(x)
x = self.fc3(x)
return x
# model, optimizer, criterion
model = Net().to(device)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, mementum=0.5)
criterion = torch.nn.CrossEntropyLoss() # 내부적으로 softmax 실행
def train(model, train_loader, optimizer, log_interval):
model.train() # 모델을 학습상태로 지정
for batch_idx, (image, label) in train_loader:
image = image.to(device)
label = label.to(device)
optimizer.zero_grad() # gradient 초기화
output = model(image) # input으로 output 계산
loss = criterion(output, label)
loss.backward() # 오차역전파법 수행
optimizer.step() # 파라미터 업데이트
if batch_idx % log_interval == 0:
print("Train Epoch: {} [{}/{} ({:.0f}%)]\tTrain Loss: {:.6f}".format(
epoch, batch_idx * len(image),
len(train_loader.dataset), 100. * batch_idx / len(train_loader),
loss.item()))
def evaluate(model, test_loader):
model.eval() # 모델을 평가상태로 지정
test_loss = 0
correct = 0
with torch.no_grad(): # 평가 과정에서 gradient 업데이트를 하지 않기 위해
for image, label in test_loader:
image = image.to(device)
label = label.to(device)
output = model(image)
test_loss += criterion(output, label).item()
prediction = output.max(1, keepdim=True)[1] # 벡터 값 내 최대값으로 예측
correct += prediction.eq(label.view_as(prediction)).sum().item()
test_loss /= len(test_loader.dataset)
test_accuracy = 100 * correct /len(test_loader.dataset)
return test_loss, test_accuracy
# 반복 학습
for epoch in range(1, epoch+1):
train(model, train_loader, optimizer, 200)
test_loss, test_accuracy = evaluate(model, test_loader)
print("\n[EPOCH: {}], \tTest Loss: {:.4f}, \tTest Accuracy: {:.2f} % \n".format(
epoch, test_loss, test_accuracy))
참고
모두를 위한 딥러닝 시즌 2 Lab 8-1, 8-2, 9-1
밑바닥부터 시작하는 딥러닝 <사이토 고키>
파이썬 딥러닝 파이토치 (이경택, 방성수, 안상준)
Author And Source
이 문제에 관하여([D&A 운영진 딥러닝 스터디] 1주차 2차시), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@rnjsdb72/DA-운영진-딥러닝-스터디-1주차-2차시저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)