규칙 기반의 한계 : 성능 개선에 한계
→ 딥러닝으로의 전환
데이터 수집 → 모델 선택 → 학습 → 예측
컴퓨터 비전의 문제 종류 : 회귀, 분류, 검출, 분할, 추적 등
선형 / 비선형 모델
🌿 학습 : 훈련 집합에 있는 샘플을 최소 오류로 맞히는 최적의 가중치 값 알아내는 작업
🌿 손실 함수(loss function) : 현재 가중치 값 W가 얼마나 좋은지, 오류를 얼마나 덜 범하는지 측정하는 함수 ⇒ 최적의 가중치 찾기에 사용!
➡️ 0에 가까울수록 좋음
🌿 그래프 설명
점선 = 오류
검은색 점 = 참값에 해당 하는 y'
직선상의 점 = 모델이 예측한 값 f(x)
점선 = 오차 f(x)-y'⇒ 모든 점선 길이의 제곱의 평균 = 평균제곱오차
파란색 모델의 평균제곱오차(MSE)가 더 작음 → 최적에 더 가까움
- 최적화 알고리즘 : MSE를 최소로 하는 가중치의 최적값 W을 찾아줌
- 기계학습에서 최적화 알고리즘 = 옵티마이저 (optimizer)
🌿 예측 : 학습을 마친 모델(=W을 가진 모델)에 학습에 사용하지 않던 새로운 특징 벡터 입력 → 출력 구하는 과정
⇒ 모델 성능 평가 가능
💡 데이터셋 분할하여 성능 측정 시 주의 점
🌿 k-겹 교차 검증(k-fold cross validation)
: 데이터셋을 k개 부분 집합으로 분할 후 성능 실험 k번 실행 → 평균 취함
텐서(tensor) : 다차원 배열
https://velog.io/@gawon1224/DL-2.-퍼셉트론
입력층(input layer) : d차원 특징 벡터를 받기 위한 4개 노드 & 1개의 bias 노드
bias 노드는 x_0=1로 설정하여 항상 1 입력됨
출력층(outut layer) : 1개 node
🌿 τ : 활성 함수activation function
: d차원 특징 벡터 + bias 값 1추가 ⇒ d+1 차원 백터로 확장
행렬 곱셈 가능하도록 전치 행렬 곱함
샘플 1 계산 ➡️ 데이터셋에 있는 n개 샘플 한꺼번에 계산
샘플 1 계산식
데이터셋에 있는 n개 샘플 한꺼번에 계산식
x^2를 신경망에 입력한 것 행렬로 표기
입력층 - 특징 통과만 시킴, 연산 X ⇒ 층 셀 때 제외함
이웃한 2개 층에 있는 노드의 모든 쌍에 에지 있음 ⇒ 완전 연결 구조(FC; Fully-Connected)
입력층 & 은닉층 연결하는 가중치 행렬 : U1 - 크기 : p x (d+1)
은닉층 & 출력층 연결하는 가중치 행렬 : U2 - 크기 : p x (d+1)
특징 벡터 : d차원, 부류 c개 이면,
➡️ 입력층 노드 d+1개 (+1: bias 노드)
➡️ 출력층 노드 c개
ex) MNIST 데이터셋 : 28X28맵
: 특징 벡터 x가 입력층 → 은닉층 → 출력층 거치면서 순차적으로 연산 수행하는 과정
노드 1개 연산
z : 은닉 노드의 출력
U^2 의 k번째 행 (= k번째 출력 노드에 연결된 p+1개 가중치
층에 있는 모든 노드의 연산으로 확대
*은닉층, 출력층 활성화 함수 종류 다름
L개 층의 다층 퍼셉트론
l번째 층의 가중치 행
출력 o의 최댓값 가진 부류에 해당함
학습 알고리즘은 결국 가중치 W를 알아내야 함!
1행 : 난수 생성
3행 : 전방 계산 수식 이용, 손실함수 J(W): MSE 사용
4행 : 수렴 조건 확인
- 수렴 조건 만족 O → 루프 break, 가중치 최적값 저장 후 종료
- 수렴 조건 만족 X → 5행 : 오류 줄이는 방향인 더해 가중치 갱신
💡 손실함수 줄이도록 가중치 갱신이 중요!
🌿 경사하강법 (GD method; Gradient Descent method) : 미분값을 보고 함수가 낮아지는 방향을 찾아 이동하는 일 반복하여 최저점에 도달하는 알고리즘
→ 감소하는 방향으로 얼마나 이동할지 정함
💡 딥러닝에 적용하려면 2가지 측면에서 확장해야 함
식 (7.22) 적용할 데이터의 단위 고려
➡️ 미니 배치 M 단위로 식 (7.22)를 적용
🌿 스토캐스틱 경사하강법(SGD; stochastic Gradient Descent) : 미니 배치를 사용하는 확장된 경사하강법
🌿 역전파(back propagation) : 역방향으로 진행하며 신경망의 그레이디언트를 구하는 알고리즘
🌿 하이퍼 파라미터 설정 요령
: 학습 알고리즘이 train data에 과다하게 맞춤 → 일반화 능력을 상실하는 현상
일반화(generalization) : 학습에 사용하지 않은 샘플 집합인 test data에 대해 높은 성능을 유지하는 능력
➡️ 과잉 적합 방지할 다양한 규제 기법 적용
; 드롭아웃, 데이터 증강, 조기 멈춤, 배치 정규화, 가중치 감쇠 등
🌿 사용자 인터페이스
import numpy as np
import tensorflow as tf
import cv2 as cv
import matplotlib.pyplot as plt
import winsound
model=tf.keras.models.load_model('dmlp_trained.h5')
# e : img라는 영상 생성
def reset():
global img # 전역 변수
img=np.ones((200,520,3),dtype=np.uint8)*255 # 3채널 컬러 영상 저장할 배열 생성(모든 화소값이 255로 흰색)
for i in range(5): # 5개 빨간색 박스 그림
cv.rectangle(img,(10+i*100,50),(10+(i+1)*100,150),(0,0,255))
cv.putText(img,'e:erase s:show r:recognition q:quit',(10,40),cv.FONT_HERSHEY_SIMPLEX,0.8,(255,0,0),1) # 명령어 집어넣음
def grab_numerals():
numerals=[]
# 5번 반복하며 img에서 숫자를 떼내 28×28 크기로 변환하여 리스트에 추가
for i in range(5):
roi=img[51:149,11+i*100:9+(i+1)*100,0]
roi=255-cv.resize(roi,(28,28),interpolation=cv.INTER_CUBIC)
numerals.append(roi)
numerals=np.array(numerals) # 리스트를 numpy 배열로 변환
return numerals
# s
def show():
numerals=grab_numerals() # grab_numerals()의 리턴값 받음
# 5개 숫자를 표시
plt.figure(figsize=(25,5))
for i in range(5):
plt.subplot(1,5,i+1)
plt.imshow(numerals[i],cmap='gray')
plt.xticks([]); plt.yticks([])
plt.show()
# r
def recognition():
numerals=grab_numerals()
numerals=numerals.reshape(5,784) # 신경망에 입력하기 위해 reshape 함수로 2차원 구조를 1차원으로 펼침
numerals=numerals.astype(np.float32)/255.0 # [0.1] 범위로 변환
res=model.predict(numerals) # 신경망 모델로 예측
class_id=np.argmax(res,axis=1)
for i in range(5):
cv.putText(img,str(class_id[i]),(50+i*100,180),cv.FONT_HERSHEY_SIMPLEX,1,(255,0,0),1)
winsound.Beep(1000,500)
BrushSiz=4
LColor=(0,0,0)
# 마우스 콜백 함수
# 마우스 왼쪽 버튼을 클릭하거나 누른 채 이동하면 circle 함수로 BrushSiz 크기의 원을 검은색으로 그려 글씨
def writing(event,x,y,flags,param):
if event==cv.EVENT_LBUTTONDOWN:
cv.circle(img,(x,y),BrushSiz,LColor,-1)
elif event==cv.EVENT_MOUSEMOVE and flags==cv.EVENT_FLAG_LBUTTON:
cv.circle(img,(x,y),BrushSiz,LColor,-1)
# 메인
reset()
cv.namedWindow('Writing') # 윈도우 생성
cv.setMouseCallback('Writing',writing) # 윈도우의 콜백 함수로 writing 함수 등록
while(True): # 무한 반복하며 사용자와 인터페이스
cv.imshow('Writing',img) # 변경된 내용을 윈도우에 반영
key=cv.waitKey(1) # 키보드 입력이 있으면 읽어서 key에 저장
if key==ord('e'):
reset()
elif key==ord('s'):
show()
elif key==ord('r'):
recognition()
elif key==ord('q'):
break
cv.destroyAllWindows()
실행 결과
: 종이에 쓴 숫자를 스캐너로 수집한 MNIST & 화면에 마우스로 쓴 패턴이 달라 차이 발생