다수의 신호를 입력 받아 하나의 신호를 출력하는 것
를 (편향, bias)로 치환 시,
신호의 총 합이 를 넘을 때만 1 출력 (: 임계값)
뉴런이 활성화 한다.
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
이를 만족하는 매개변수()가 무수히 많다.
0.5 0.5 0.7 0.5 0.5 1 ... ... ...
AND 게이트 매개변수 반전
-0.5 | -0.5 | -0.7 |
-0.5 | -0.5 | -1 |
... | ... | ... |
0.5 | 0.5 | 0.4 |
... | ... | ... |
배타적 논리합, 어느 한쪽만 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 출력
torch.nn.linear(x)
torch.nn.sigmoid(x)
torch.nn.tanh(x)
torch.nn.relu(x)
torch.nn.leaky_relu(x, 0.01)
지수함수가 매우 쉽게 커지기 때문에 오버플로 문제 발생
C를 대입하여 개선(C는 의 최대값)시그모이드 함수 일반화한 형태
훈련데이터로부터 매개변수의 최적값을 자동으로 획득
자동으로 학습할 때 손실함수(Loss)를 지표로 사용!
손실함수를 최소화하는 매개변수를 찾는다.
미분, 기울기 이용
속도와 최소값의 수렴을 고려하여 미니배치 경사하강법 채택
각 미니배치별 손실함수 = 각 데이터의 손실함수 평균
정확도를 손실함수로 사용하지 않는 이유
기울기를 잘 이용해 함수의 최소값을 찾아가는 방법
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
밑바닥부터 시작하는 딥러닝 <사이토 고키>
파이썬 딥러닝 파이토치 (이경택, 방성수, 안상준)