= 특징점 찾는 알고리즘
T라는 과업에서 P의 향상을 위해 E를 학습했다.
훈련하는 알고리즘이 학습 과정에서 데이터(E)의 중요한 특징을 스스로 파악한다는 것
사람은 낱말카드나 사물을 인식할 때 낱말카드, 사물카드에 대한 답은 이거다. 라고 답을 맞췄다.
Representation learning은 데이터에서 중요한 특징을 알고리즘이 감지하는 것
결국 AI라는 광범위한 분야 중 머신러닝 이면서 동시에 데이터에서 핵심을 잘 선별해내는 기술
이 분야에서 매우 유능한 알고리즘 하나가 등장하는데, 인공신경망 이다.
ANN > DNN > CNN
각 노트의 입력치 n개와 가중치 n을 곱한 값을 모두 합한 것
합한 것을 활성함수로 판단해 True, False로 출력한다.
활성함수에는 CrossEntropy, sigmoid 등 다양하다.
가중치의 크기는 일반적으로 입력값의 중요도를 나타낸다.
앞에서 input, output 사이에 hidden layer가 있었는데 단층은 hidden layer가 없다.
단층과 다층을 구분할 때는 은닉층이 있는지 여부에 따라 구분한다.
단층 : 데이터 입력층과 출력층만 존재
다층 : 입력층과 출력층 사이에 하나 이상의 은닉층 존재
복잡한 문제를 해결하려면 다층 퍼셉트론 내 은닉층 개수가 많아진다 -> 심층 신경망 (DNN)
여러개 은닉층으로 구성된 인공신경망 (ANN)
단층 퍼셉트론을 이용한 게이트 구현
"""
단층 퍼셉트론 이용한 AND NAND OR 게이트 쉽게 구현
1. AND
- 두 개의 입력 값이 모두1인 경우만 output 1 아닌경우 0
input : x1, x2 / output : y
w1 , w2 , b 라고 하면 (w 가중치 , b 편향 값)
"""
def AND_gate(x1, x2):
w1 = 0.5
w2 = 0.5
b = -0.7
result = x1 * w1 + x2 * w2 + b
print("result >> ", result)
if result <= 0:
return 0
else:
return 1
"""
NAND 게이트 :두개의 입력값이 1인 경우에만 출력값이 0 나머지 쌍에 대해서는 모두 출력 값 1
"""
def NAND_gate(x1, x2):
w1 = -0.5
w2 = -0.5
b = 0.7
result = x1 * w1 + x2 * w2 + b # 단층 퍼셉트론 공식
if result <= 0:
return 0
else:
return 1
# test = NAND_gate(1, 0)
# print("test >> ", test)
# # [0,0] [0,1] [1,0] [1,1]
# test = AND_gate(0, 1)
# print("test >> ", test)
"""
OR 게이트 두값이 0 , 0 - > 0 / 0, 1 -> 1 두값이 서로 다르면 1
"""
def OR_gate(x1, x2):
w1 = 0.5
w2 = 0.5
b = -0.4
result = x1 * w1 + x2 * w2 + b # 단층 퍼셉트론 공식
if result <= 0:
return 0
else:
return 1
test = OR_gate(1, 1)
print("Test>>", test)
"""
파이토치로 다층 퍼셉트론 구현하기
"""
import torch
import torch.nn as nn
"""
# GPU 사용가능한 여부 파악 test code -> CPU 인텔 엔비디아 GPU / AMD 엔비디아 GPU 맥북 M1
device = "cuda" if torch.cuda.is_available() else "cpu"
"""
# M1 사용중인 분들
device = torch.device("cpu")
# str_device = str(device)
# print("device info >> ", type(str_device))
# seed
torch.manual_seed(777)
if device == "cuda":
torch.cuda.manual_seed_all(777)
# 데이터 생성
x = [[0, 0], [0, 1], [1, 0], [1, 1]] # 학습 데이터
y = [[0], [1], [1], [0]] # 정답지
# 데이터 텐서 변경
x = torch.tensor(x, dtype=torch.float32).to(device)
y = torch.tensor(y, dtype=torch.float32).to(device)
"""
다층퍼셉트론 설계
"""
model = nn.Sequential(
nn.Linear(2, 10, bias=True),
nn.Sigmoid(),
nn.Linear(10, 10, bias=True),
nn.Sigmoid(),
nn.Linear(10, 10, bias=True),
nn.Sigmoid(),
nn.Linear(10, 1, bias=True),
nn.Sigmoid(),
)
model.to(device)
"""
Loss function BCELoss() 이진분류에서 사용되는 크로스엔트로피 함수
"""
criterion = torch.nn.BCELoss().to(device)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
"""
학습 코드 작성 하기
"""
for epoch in range(10001):
optimizer.zero_grad() # optimizer 초기화
# forward 연산
output = model(x)
# loss 계산
loss = criterion(output, y)
loss.backward()
optimizer.step()
# print show
if epoch % 100 == 0:
print(f"epoch >> {epoch} Loss >> {loss.item()}")
"""
학습된 다층 퍼셉트로의 예측값 확인
"""
with torch.no_grad():
output = model(x)
predicted = (output > 0.5).float()
acc = (predicted == y).float().mean()
print("모델의 출력값 output >> ", output.detach().cpu().numpy())
print("모델의 예측값 predicted >> ", predicted.detach().cpu().numpy())
print("실제값 >>> ", y.cpu().numpy())
print("정확도 >>> ", acc.item()*100)
다중 퍼셉트론으로 손글씨 분류
"""
다층 퍼셉트론으로 손글씨 분류
사이킷런 패키지에서 제공하는 분류용 예측 데이터를 사용
0~9까지의 숫자를 손으로 쓴 이미지 데이터로 load_digits() 명령어로 로드
각 이미지 사이즈는 8 * 8 = 64px 구성
흑백 이미지 갯수 1,797개
"""
import matplotlib.pyplot as plt
from sklearn.datasets import load_digits
import torch
import torch.nn as nn
from torch import optim
digits = load_digits()
print("image 행렬\n", digits.images[0])
print("타겟 >> ", digits.target[0])
print("전체 데이터 >> ", len(digits.images))
# 상위 5개만 샘플이미지 확인
# zip, image = [1, 2, 3, 4], label = [사과, 자몽, 바나나, 수박]
images_and_labels = list(zip(digits.images, digits.target))
# for index, (image, label) in enumerate(images_and_labels[:4]):
# plt.subplot(2, 5, index+1)
# plt.axis('off')
# plt.imshow(image, cmap=plt.cm.gray_r, interpolation='nearest')
# plt.title("sample : %i" % label)
# plt.show()
# 데이터 생성
x = digits.data
y = digits.target
# 모델 생성
model = nn.Sequential (
nn.Linear(64, 32), # 8*8, 64의 절반
nn.ReLU(),
nn.Linear(32, 16),
nn.ReLU(),
nn.Linear(16, 10) # 반의 반, output : 0 ~ 9, 총 9개
)
# 데이터 텐서
device = "cuda" if torch.cuda.is_available() else "cpu"
x = torch.tensor(x, dtype=torch.float32).to(device)
y = torch.tensor(y, dtype=torch.int64).to(device) # 64자리만큼 크기 할당, 경량화 모델은 8이나 16 사용
# loss function
loss_fn = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters())
loss_list = []
for epoch in range(101):
optimizer.zero_grad() # optimizer 초기화
output = model(x)
loss = loss_fn(output, y) # 오차범위 줄이기
loss.backward()
optimizer.step()
if epoch % 10 == 0:
print("epoch {:4d}/{} loss : {:.6f}".format(epoch, 100, loss.item()))
loss_list.append(loss.item()) # loss는 텐서값이라서 item() 값을 넣어야 함
plt.title("loss")
plt.plot(loss_list)
plt.show()
심화과정으로 넘어오기 전에 공통과정에서 수업했었던 것이 생각났다.
해봐서 실습하는 것은 조금 낯익은 느낌이지만
아직 정확하게 알고 구현하는 거라고 할 수 없는 것 같다.
복습을 해야겠다.