Ch 7. 딥러닝 비전

wonnie1224·2023년 4월 27일
0

7.1 방법론의 대전환

규칙 기반의 한계 : 성능 개선에 한계

→ 딥러닝으로의 전환

Untitled

7.2 기계학습 기초

7.2.2 기계학습의 4단계

데이터 수집 → 모델 선택 → 학습 → 예측

📌 1단계 : 데이터 수집

  • 모델의 입력 : 특징 벡터 (feature vector) → x로 표기
  • 모델의 출력 : 참값 (GT: Ground Truth) / 레이블 (label) → y로 표기

Untitled

컴퓨터 비전의 문제 종류 : 회귀, 분류, 검출, 분할, 추적 등

📌 2단계 : 모델 선택

선형 / 비선형 모델

  • 가중치 : 행렬 W
  • 층마다 가중치 있음 (L : 층의 개수)

Untitled

📌 3단계 : 학습

🌿 학습 : 훈련 집합에 있는 샘플을 최소 오류로 맞히는 최적의 가중치 값 알아내는 작업

  • 분석적 방법(analytical method) : 모델 함수에 데이터셋 대입하여 만든 방정식 풀어 가중치 최적값 구하는 방식
  • 수치적 방법(numerical method) : 오류를 조금씩 줄이는 과정을 반복

🌿 손실 함수(loss function) : 현재 가중치 값 W가 얼마나 좋은지, 오류를 얼마나 덜 범하는지 측정하는 함수 ⇒ 최적의 가중치 찾기에 사용!

Untitled

➡️ 0에 가까울수록 좋음

Untitled

🌿 그래프 설명

점선 = 오류
검은색 점 = 참값에 해당 하는 y'
직선상의 점 = 모델이 예측한 값 f(x)
점선 = 오차 f(x)-y'

⇒ 모든 점선 길이의 제곱의 평균 = 평균제곱오차

파란색 모델의 평균제곱오차(MSE)가 더 작음 → 최적에 더 가까움

  • 최적화 알고리즘 : MSE를 최소로 하는 가중치의 최적값 W을 찾아줌
  • 기계학습에서 최적화 알고리즘 = 옵티마이저 (optimizer)

📌 4단계 : 예측

🌿 예측 : 학습을 마친 모델(=W을 가진 모델)에 학습에 사용하지 않던 새로운 특징 벡터 입력 → 출력 구하는 과정

⇒ 모델 성능 평가 가능

  • 데이터셋을 일정 비율로 분할 → train data : 학습에 사용 & test data : 예측에 사용

💡 데이터셋 분할하여 성능 측정 시 주의 점

  • 객관성 보장 가능
  • but 데이터셋 충분히 크지 X → 우연히 좋은 or 나쁜 성능 발생 가능
    • ex) 인식이 쉬운 샘플이 test data로 많이 가면 실제보다 좋은 성능 출력됨

🌿 k-겹 교차 검증(k-fold cross validation)

: 데이터셋을 k개 부분 집합으로 분할 후 성능 실험 k번 실행 → 평균 취함

  • i=1~k, i번째 실험에선 i번 부분집합 - test data, 나머지 k-1개 부분 집합 - train data로 사용

Untitled

7.3 딥러닝 소프트웨어 맛보기

📌 데이터와 텐서

텐서(tensor) : 다차원 배열

7.4 인공 신경망의 태동

https://velog.io/@gawon1224/DL-2.-퍼셉트론

7.4.2 퍼셉트론

📌 구조와 연산

Untitled

  1. 입력층(input layer) : d차원 특징 벡터를 받기 위한 4개 노드 & 1개의 bias 노드

    bias 노드는 x_0=1로 설정하여 항상 1 입력됨

  2. 출력층(outut layer) : 1개 node

    • 입력 노드 : 특징값을 통과시키기만 함 → 빈 원
    • 출력 노드 : 연산 수행 → 파란 색 원
    • 가중치 :입력 노드 & 출력 노드를 연결하는 에지에 있는 u

🌿 τ : 활성 함수activation function

  • 퍼셉트론의 활성 함수 : 계단 함수
  • 활성 함수를 적용하기 전의 값s = 로짓 (logit)

📌 퍼셉트론 = 특징 공간을 2개로 나누는 분류기!

Untitled

Untitled

📌 행렬 표기

xx : d차원 특징 벡터 + bias 값 1추가 ⇒ d+1 차원 백터로 확장

행렬 곱셈 가능하도록 전치 행렬 곱함

샘플 1 계산 ➡️ 데이터셋에 있는 n개 샘플 한꺼번에 계산

  • 특징 벡터 xx → 행렬 XX
  • 출력 스칼라 oo → 행렬 OO
  • 설계 행렬design matrix : 모든 샘플 담은 행렬 XX

샘플 1 계산식

샘플 1 계산식

데이터셋에 있는 n개 샘플 한꺼번에 계산식

데이터셋에 있는 n개 샘플 한꺼번에 계산식

x^2를 신경망에 입력한 것 행렬로 표기

x^2를 신경망에 입력한 것 행렬로 표기

Untitled

Untitled

7.5 깊은 다층 퍼셉트론

Untitled

7.5.1 다층 퍼셉트론

📌 구조

  • 은닉층 : 입력층 & 출력층 사이에 생긴 층
  • 은닉/잠복 공간 : 은닉층이 형성하는 새로운 특징 공간

입력층 - 특징 통과만 시킴, 연산 X ⇒ 층 셀 때 제외함

이웃한 2개 층에 있는 노드의 모든 쌍에 에지 있음 ⇒ 완전 연결 구조(FC; Fully-Connected)

Untitled

입력층 & 은닉층 연결하는 가중치 행렬 : U1 - 크기 : p x (d+1)

은닉층 & 출력층 연결하는 가중치 행렬 : U2 - 크기 : p x (d+1)

Untitled

특징 벡터 : d차원, 부류 c개 이면,

➡️ 입력층 노드 d+1개 (+1: bias 노드)

➡️ 출력층 노드 c개

ex) MNIST 데이터셋 : 28X28맵

  • 특징 : 화소 d=784, c=10 →입력 노드 785개, 출력 노드 10개

📌 전방 계산

: 특징 벡터 x가 입력층 → 은닉층 → 출력층 거치면서 순차적으로 연산 수행하는 과정

Untitled

  1. 노드 1개 연산

    z : 은닉 노드의 출력

Untitled

Untitled

Untitled

 U^2 의 k번째 행 (= k번째 출력 노드에 연결된 p+1개 가중치

U^2 의 k번째 행 (= k번째 출력 노드에 연결된 p+1개 가중치

  1. 층에 있는 모든 노드의 연산으로 확대

    *은닉층, 출력층 활성화 함수 종류 다름

Untitled

  • 위의 식을 아래의 복합함수 형태로 바꿈

Untitled

  • 행렬로 표현 : x → 행렬 X, o → 행렬 O x_i : bias 노드 추가한 (d+1)차원 벡터

Untitled

Untitled

7.5.2 딥러닝의 서막 : 깊은 다층 퍼셉트론

📌 깊은 다층 퍼셉트론의 전방 계산

L개 층의 다층 퍼셉트론

l번째 층의 가중치 행

l번째 층의 가중치 행

Untitled

Untitled

📌 신경망 출력을 부류 정보로 해석

출력 o의 최댓값 가진 부류에 해당함

Untitled

7.5.3 활성 함수

  • 퍼셉트론 : 계단 함수
  • 다층 퍼셉트론 : 시그모이드 함수
  • 층이 깊은 딥러닝 : relu
    • 그레이디언트 소멸 : 신경망 학습 - 출력층→입력층 진행하면서 미분값을 이용해 가중치 갱신함 ⇒ 미분값 계속 곱하는데, 활성화 함수의 미분값이 작아 가중치 갱신이 일어나지 않는 문제
    • relu는 양수 구간에서 미분값 1 → 그레이디언트 소멸 방지
  • 신경망 : softmax 모든 노드값 더하면 1 → 확률로 간주 가능

Untitled

Untitled

Untitled

  • s : 활성함수의 입력
  • 베타 : 함수의 모양 제어

7.6 학습 알고리즘

7.6.1 발상

학습 알고리즘은 결국 가중치 W를 알아내야 함!

  • 가중치 초기값을 어떻게 설정해야 높은 정확률 얻을 수 있는지 모름 → 난수로 설정
  • 충분히 높은 정확률 달성, 더 이상 개선 불가능이라 판단할 때까지 정확률 향상

Untitled

1행 : 난수 생성
3행 : 전방 계산 수식 이용, 손실함수 J(W): MSE 사용
4행 : 수렴 조건 확인

  • 수렴 조건 만족 O → 루프 break, 가중치 최적값 저장 후 종료
  • 수렴 조건 만족 X → 5행 : 오류 줄이는 방향인 triangleWtriangleW 더해 가중치 갱신

7.6.2 스토캐스틱 경사하강법

💡 손실함수 줄이도록 가중치 갱신이 중요!

📌 경사하강법 기초

🌿 경사하강법 (GD method; Gradient Descent method) : 미분값을 보고 함수가 낮아지는 방향을 찾아 이동하는 일 반복하여 최저점에 도달하는 알고리즘

Untitled

  • 학습률(learning rate) ρ : 이동량

→ 감소하는 방향으로 얼마나 이동할지 정함

Untitled

📌 스토캐스틱 경사하강법으로 확장

💡 딥러닝에 적용하려면 2가지 측면에서 확장해야 함

  1. 신경망의 가중치는 층을 구성, 수만~수억 개라는 걸 반영
    • 가중치 1개일 때 식 (7.21) ➡️ 가중치 #개인 식 (7.22)로 확장
    • 맨 마지막 L층에서 시작해 왼쪽으로 진행하면서 가중치 갱신
    • 역전파 **:** 역방향으로 진행하면서 미분값, 즉 그레이디언트 계산하는 방법

Untitled

  1. 식 (7.22) 적용할 데이터의 단위 고려

    • 데이터셋에 n개 샘플이 있다면 n번의 미분 & 가중치 갱신 일어남
    • 세대epoch : 모든 샘플을 처리하는 한 사이클

    ➡️ 미니 배치 M 단위로 식 (7.22)를 적용

    • 식 (7.22)를 [n/M][n/|M|]번 반복하여 한 세대를 처리 ex) MNIST 데이터셋; n=60000, 미니 배치 크기 = 128로 설정 → 60,000개에서 128개 랜덤 선택하여 식 (7.22)로 가중치 갱신하는 걸 반복 → 마지막엔 나머지 96개로 가중치 갱신하면 한 epoch가 끝남
    • 미니 배치 방식에서 평균제곱 오차 MSE Untitled

🌿 스토캐스틱 경사하강법(SGD; stochastic Gradient Descent) : 미니 배치를 사용하는 확장된 경사하강법

  • 옵티마이저optimizer : 신경망에서의 최적화 방법 이후 SGD를 개선한 Adam, AdaGrad, RMSProp 등 등장

📌 역전파

🌿 역전파(back propagation) : 역방향으로 진행하며 신경망의 그레이디언트를 구하는 알고리즘

  • L층에서 시작 ~ 1층으로 진행하며 그레이디언트 계산 & 가중치 갱신
  • l층의 그레이디언트 = l+1층 그레이디언트 X 두 층 사이의 그레이디언트 07-05 역전파(BackPropagation) 이해하기
  • 신경망 계층 구조 이용하여 그레이디언트 매우 빨리 계산 가능

Untitled

Untitled

Untitled

7.7 다층 퍼셉트론 구현하기

7.7.2 성능 시각화

Untitled

7.7.3 하이퍼 매개변수 다루기

Untitled

Untitled

🌿 하이퍼 파라미터 설정 요령

  1. tensorflow가 제공하는 기본값 사용
  2. 논문 등의 권고 사항 따름
  3. 중요한 하이퍼 파라미터 1~3개에 대해 성능 실험 → 최적값 스스로 설정
    • 교차 검증 사용

📌 과잉 적합 (overfitting)

: 학습 알고리즘이 train data에 과다하게 맞춤 → 일반화 능력을 상실하는 현상

일반화(generalization) : 학습에 사용하지 않은 샘플 집합인 test data에 대해 높은 성능을 유지하는 능력

  • 신경망 모델의 용량은 큰데 데이터셋 크기가 작은 경우 주로 발생
  • 신경망 모델의 용량 - 가중치 개수로 측정 가능 ex) [프로그램 7-6]의 신경망에는 3,939,338개의 가중치 but CIFAR-10의 train data 샘플이 50,000개 → 모델 용량이 데이터셋보다 훨씬 크다
  • 모델의 용량을 줄이면 학습이 제대로 안 됨, train data에 대한 성능까지 낮아질 수 있음

➡️ 과잉 적합 방지할 다양한 규제 기법 적용

; 드롭아웃, 데이터 증강, 조기 멈춤, 배치 정규화, 가중치 감쇠 등

7.8 [비전 에이전트 5] 우편번호 인식기 v.1

🌿 사용자 인터페이스

  1. 5개 빨간색 박스 : 마우스로 숫자 써 넣는 곳
  2. e : 박스 지움
  3. s : 박스에서 숫자 떼내어 명암 영상으로 표시
  4. r : 숫자 인식
  5. q : 종료
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 & 화면에 마우스로 쓴 패턴이 달라 차이 발생

profile
안녕하세요😊 컴퓨터비전을 공부하고 있습니다 🙌

0개의 댓글