인공신경망(Artificial Neural Networks) 기반 머신러닝
중요한 패턴 : 작업 수행에 큰 영향을 주는 요소 - 가장 잘 동작하는 특징
importimport torch # 핵심 라이브러리
import torch.nn as nn # neural networks 신경망 구성
import torch.optim as optim # 최적화(함수를 최소 또는 최대로 맞추는 변수를 찾는 것)
import torchvision # 이미지 처리
import torchvision.transforms as transforms # 이미지 처리 전처리
# 데이터셋 전처리
transform = transforms.Compose([
transforms.ToTensor(),
# 이미지를 Tensor(파이토치 자료구조)로 전환
transforms.Normalize((0.5,), (0.5,))
# 이미지 정규화(평균, 표준편차)
])
# MNIST 데이터셋 로드
trainset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform)
# 경로 # train(학습용) 데이터셋 여부 # 다운로드 여부 #transform 전달-전처리한 상태로
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
# 토치.유틸.데이터 기능.데이터 로더(데이터 셋, batch_size(쪼갠단위로 학습), suffle(섞어서 쪼갬))
testset = torchvision.datasets.MNIST(root='./data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=64, shuffle=False)
class SimpleANN(nn.Module): # 상속으로 기능 가져오기
# init 설정
def __init__(self):
# 부모 클래스의 init 가져오기
super(SimpleANN, self).__init__()
# fc : fully connected module ; 서로가 서로에게 연결된 레이어
self.fc1 = nn.Linear(28 * 28, 128) # 입력층에서 은닉층으로
# nn.Linear: ANN모델 생성 함수
# 입출력 지정
# 28 * 28 데이터셋의 크기 / 10 0~9 10개로 출력
self.fc2 = nn.Linear(128, 64) # 은닉층에서 은닉층으로
self.fc3 = nn.Linear(64, 10) # 은닉층에서 출력층으로
def forward(self, x): # 레이어간 전달
x = x.view(-1, 28 * 28) # 입력 이미지를 1차원 벡터로 변환
# view 함수 -1
# 전체 요소 개수에서 28*28 을 제외한 성분의 수
# 예시) 전체 16 (-1, 4) # (4,4)로 생성
x = torch.relu(self.fc1(x))
x = torch.relu(self.fc2(x))
x = self.fc3(x) # 최종출력 레이어는 relu 처리가 필요 없음
return x # 결과는 (64개 데이터 * 10차원)
# 모델 초기화
model = SimpleANN()
correct = 0
total = 0
with torch.no_grad():
# 평가 단계에서는 기울기 계산 필요가 없음, 생략
for data in testloader:
images, labels = data
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
# 10개의 레이브은 각각의 가능성, 각 레이블에서 가능성이 가장 큰것만 추출
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f'Accuracy of the network on the 10000 test images: {100 * correct / total:.2f}%')
# 학습 전 = 9.35%
criterion = nn.CrossEntropyLoss() # 분류모델 손실함수 계산
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
# 최적화, lr- 학습률(적당히 작은값), momentum - 치후 설명
# 모델 학습
for epoch in range(10): # 10 에포크 동안 학습
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
# i = index,
inputs, labels = data
# 기울기 초기화 - 연쇄법칙 수행으로 남아있는 로그 제거
optimizer.zero_grad()
# 순전파 + 역전파 + 최적화
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
# 업데이트를 진행할 방향, 기울기를 찾는 과정
optimizer.step()
# 기울기를 바탕으로 가중치를 업데이트
# 손실 출력
running_loss += loss.item()
if i % 100 == 99: # 매 100 미니배치마다 출력
print(f'[Epoch {epoch + 1}, Batch {i + 1}] loss: {running_loss / 100:.3f}')
running_loss = 0.0
print('Finished Training')
correct = 0
total = 0
with torch.no_grad():
# 평가 단계에서는 기울기 계산 필요가 없음, 생략
for data in testloader:
images, labels = data
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
# 10개의 레이브은 각각의 가능성, 각 레이블에서 가능성이 가장 큰것만 추출
total += labels.size(0)
# 배치 크기
correct += (predicted == labels).sum().item()
# 에측값과 실제 값이 일치하는 샘플의 수를 계산
print(f'Accuracy of the network on the 10000 test images: {100 * correct / total:.2f}%')
# 97.61%