root@의지박약공부노트 ~$

sklearn.linear_model.LogisticRegression

카테고리 없음
@2021-09-28 15:46:52

 sklearn의 여러 모델들을 사용하다 보니, 유독 logistic regressor에서만 다음과 같은 warning message가 나타나는 것을 볼 수 있습니다. 

/opt/conda/lib/python3.7/site-packages/sklearn/linear_model/_logistic.py:762: ConvergenceWarning: lbfgs failed to converge (status=1): STOP: TOTAL NO. of ITERATIONS REACHED LIMIT. Increase the number of iterations (max_iter) or scale the data as shown in: https://scikit-learn.org/stable/modules/preprocessing.html Please also refer to the documentation for alternative solver options: https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression extra_warning_msg=_LOGISTIC_SOLVER_CONVERGENCE_MSG)

 Warning message를 읽어보니 주어진 iteration안에서 모델이 수렴하지 못해서 나타나는 문제인것 같습니다. 그렇다면 iteration이 무엇인지 알아야할듯 합니다. epoch, iteration, batch는 항상 헷갈립니다. 우선 이해를 위해 정리하고 넘어가겠습니다.

 

epoch : 전체 학습을 몇회 진행할지에 대한 값입니다. 모델을 10회 학습시키고 싶다면, epoch = 10이 됩니다.

iteration : 1epoch를 몇 번에 나누어 진행할지에 대한 값입니다. 일반적으로 batch size에 의해 결정됩니다. 

batch size : 1회의 iteration에 몇개의 데이터를 담을지에 대한 값입니다. 

 


예를들어 볼까요? 우선 우리에겐 1024개의 데이터가 있다고 가정하겠습니다. 모델을 학습시키는데 batch size = 128이라면, iteration은 8이 되고, 8회의 iteration이 끝나면 1epoch가 종료되었다고 할 수 있습니다. 


 다시 우리의 문제로 넘어와보겠습니다. sklearn.linear_model.LogisticRegression의 max_iter의 default값은 100이라고 합니다. 100회의 iter에서 모델이 충분히 수렴하지 못해 발생하는 warning같습니다.

  여기까지 이해하셨다면 알 수 있겠지만, 이때 빠른 해결책은 크게 다음과 같습니다.

1. max_iter값을 늘려준다 : iter의 최대치를 늘려줘 데이터가 수렴하는 기회를 늘려줍니다.

2. 데이터를 normalize 해준다 : 데이터를 정규화해 빠르게 수렴할 수 있게 도와줍니다.

3. solver를 바꿔준다 : 최적화를 도와주는 알고리즘을 바꿔줍니다. default는 lbfgs이며, 선택시 여러 측면을 고려해야 합니다. 

 

참고 : sklearn 공식문서 sklearn.linear_model.LogisticRegression — scikit-learn 1.0 documentation 

 

sklearn.linear_model.LogisticRegression

Examples using sklearn.linear_model.LogisticRegression: Release Highlights for scikit-learn 1.0 Release Highlights for scikit-learn 1.0, Release Highlights for scikit-learn 0.23 Release Highlights ...

scikit-learn.org

 

Python microsoft visual C++ 14.0 설치 패키지가 없거나 손상되었습니다.

카테고리 없음
@2021-09-15 22:08:56

1. microsoft visual C++ 14.0 설치 패키지가 없거나 손상되었습니다.

python 패키지를 install하다 보면, 위와 같은 메시지가 뜨면서 다운되지 않는 경우가 종종 있습니다. 전 bottleneck이라는 패키지를 install하려다 발생했습니다. 해결 방법은 C++ Build Tools를 다운받는것입니다.

검색을 통해 2015버전으로 시도하였지만, 2015버전을 설치하려 하자 다음과 같은 오류가 발생하였습니다. 

2. Microsoft Visual C++ Build Tools 설치 패키지가 없거나 손상되었습니다.

검색을 통해 해당 오류는 인터넷에 연결되어 있지 않은 경우(오프라인인 경우) 발생할 수 있다고 나와있었지만 와이파이, 유선랜 모두 사용해봤지만 해당 오류가 지속적으로 발생하였습니다. 이에 tools를 2019버전으로 설치하니 해결되었습니다. 

ipynb를 py로 변환

카테고리 없음
@2021-07-19 17:52:49

보호글입니다.
비밀번호를 입력하셔야 내용을 보실 수 있습니다.


Github 업로드

Note
@2021-06-18 02:18:40

Github로 프로젝트 관리를 하면서도 너무 편하기에 마우스로 업로드를 해왔습니다..만..

파일을 드래그해도, choose your files로 추가해도 쉽게 업로드 가능!!

터미널을 활용해보자는 생각이 문득 들더군요.. 근데 안돼요.. 그래서 기본적인 Github 사용법에 대해 서보려고 합니다.

파일을 업로드 하는 법, 그리고 제가 막혔던 문제들에 대한 해결방안을 한번 써보려고 합니다.

 

우선 제가 하려는 작업은 단순했습니다. 일단 팀 프로젝트를 진행한 Github의 Repository(이하 repo)를 clone해서 제 로컬에 받고, 이를 다시 제 깃헙에 업로드 하는 것이었습니다. 분명 컴공 친구가 옆에서 봐줄때는 아무 문제 없이 진행 되었는데, 집에와서 혼자 해보려니 안되더군요.. 그냥 안돼요..

 

1. 일단 github에 새로운 repo를 만들었습니다. 해당 저장소에 저의 코드를 업로드할 것입니다. 말하는 화분을 만드는 프로젝트였기에, repo명은 ChatPot으로 정했습니다.

 

2. 이제 로컬에서 터미널을 사용합니다. 우선 저장할 경로로 이동합니다. 간단하게 C드라이브-python-chatpot이라는 폴더로 이동하겠습니다.

cd C:\python\chatpot

 

3. 로컬과 깃헙을 연결합니다. 아래와 같이 repo를 등록합니다. 

git remote add 지정이름 repo주소.git

 

4. 해당 위치에 git clone을 합니다. 

* 주의: 자동으로 init되어 해당 repo의 .git까지 복사해 오기 때문에 문제가 생길 수 있음

git clone repo주소.git

# 특정 branch만 clone할 때
git clone -b {branch_name} --single-branch {저장소 URL}

 

5. 변경사항을 Github에 올려보겠습니다. 일반적으로 아래의 3단계를 거칩니다.

git add 파일명(디렉토리의 파일 전체를 올리고 싶다면 git add .)

git commit -m "첨언하고싶은 메시지"

git push origin master

 쉽게 말하면 Github에 올릴 파일을 add로 모아놓고, commit으로 기록하고, push로 Github으로 업로드한다고 할 수 있습니다.

 

제가 겪었던 문제는, 팀 프로젝트를 진행한 Private repo에서 clone하는 과정에서 해당 repo의 .git파일까지 복사해온 것이었습니다. 이를 다시 제 Github에 올리려 하니 오류가 나서, 다음 코드로 .git파일을 삭제 후 다시 init해 해결했습니다.

git rm -rf .git

git init

주의: rm -rf는 매우 강력한 명령어로 사용시 주의할 필요가 있습니다!!

알고리즘 21.04.12

카테고리 없음
@2021-04-12 23:24:52

알고리즘: 입력을 받아 출력하는 일련의 과정을 설계하는 것

1. 완전탐색(naive, brute force)

해당 조건을 만족하는 모든 경우의 수를 모두 실행해 보는 것

 

2. 분할정복(devide and conquer)

나누고 정복하고 합치는 방법

2-1. 문제 나누기: 문제를 한번에 해결하기 어려울 때, 문제 자체를 나눠 보다 작은 단위로 재설정

2-2. 문제 정복(solve): 작은 단위로 나눈 문제를 해결

2-3. 문제 합치기: 정렬된 두가지 작은 문제를 결합

시간복잡도: O(log(n))

 

3. DP(dynamic programming)

3-1. 나누기

문제가 어려우면 작은 단위로 나눠서 해결하는 것은 분할정복의 나누는 과정과 동일

 

3-2. 저장

memoization을 활용하여 중복된 문제를 풀지 않도록 함

 

일반적으로 재귀문제를 푸는데 활용

피보나치 수열 시간복잡도: O(2**n)

이때 자신의 하위 단계를 지속적으로 호출하지 않게 이미 완료된 계산을 저장공간에 저장하고 필요할때 호출(back-propagation)

O(n)으로 줄어듬

 

4. Greedy(탐욕법)

  • 최적화문제
  • 가장 좋은 것 찾기(최적화, 최적해)
  • 현재 상태에서 가장 좋은것 찾기

ex) 동전문제

거스름돈에서 가장 적은 동전의 갯수 구하기

576W = 500*1, 50*1, 10*2, 5*1, 1*1

가장 큰것부터 대입

현재 상태에서 가장 좋은 선택을 반복

 

*가정필요

현재 상태의 최적해가 최종 최적해임을 증명해야 함

 

데이터 비식별화(De-Identification)

카테고리 없음
@2021-03-19 22:48:04

 

 

 얼마 전 인공지능 챗봇 이루다가 첫 선을 보임과 동시에 선풍적인 인기를 끌었습니다. 이루다는 설정처럼 20대 여성의 말투, 신조어등을 사용하는데 전혀 어색함이 없었습니다. 뿐만 아니라 먼저 메시지를 보내기도 하는 등 기존의 챗봇보다 월등히 뛰어난, 실제 사람과 대화하고 있다고 착각할 정도의 인공지능이 공개된 것이죠. 

 

 

 

 

 그러나 곧 여러 문제가 발견되었습니다. 무분별하게 학습시킨 대화로 예민한 주제의 대화에 차별적인 발언을 한다던지, 특정 기호를 사용하면 주소를 출력한다던지, 또는 인공지능의 특성을 활용하여 성적인 대화를 학습시켜 인증을 한다던지 하는 문제들이 발생했습니다. 이중 가장 큰 문제는 개인정보의 유출이었습니다. 어플 활용시 개발에 활용될 수 있음을 고지하였으나, 제대로 된 비식별화 처리를 하지 않아 특정인의 이름, 옛 연인의 애칭, 주소를 출력하기도 하였습니다. 또한 연구 윤리의 부재로 연인간의 은밀한 카톡 대화 내용이 개발자들 사이에서 놀잇감으로 전락했다는 폭로에, 많은 사람들이 큰 충격을 받았습니다.

 

이처럼 빅데이터를 기반으로 하는 여러 연구는 데이터 윤리의 문제를 해결해야만 합니다. 빅데이터를 활용하는 데 여러 사람들의 데이터를 수집하면서 개인의 사생활을 침해하지 않아야 하기 때문에, 데이터의 비식별화는 빅데이터를 활용한 분석의 근간이 되는 개념입니다.

 

1. 데이터 비식별화

 

1-1. 필요성

1) 개인정보 보안 관점

  • SNS등 비정형 데이터의 외부 수집 시 개인정보가 포함되어 있을 경우 삭제 또는 비식별화 필요

2) 데이터 연계 보안 관점

  • 데이터 분석 시 여러 다양한 데이터와 연계 처리 시의 보안 취약점 제거

3) 빅데이터 보안 관점

  • 수집, 저장, 분석 단계 진행 흐름에 따라 보안 고려
  • 데이터 자체의 암호화를 통해 유출시 무결성 유지 필요

 

1-2. 데이터 활용 단계별 보안 관리

1) 수집시

  • 데이터 수집 기술 취약성(오픈소스 활용 시 보안 검토 필요)
  • 수집 서버 및 네트워크 보안(DMZ, 방화벽, 접근 제어 등) 고려 필요
  • 개인정보 및 기밀 정보유출 방지(암호화, 비식별화)

2) 저장시

  • 데이터 저장소 취약성(보안인증강화 및 접근권한 제어)
  • 빅데이터 보안 등급 분류(기밀, 민감, 공개등의 등급 설정)
  • 보안 모니터링

3) 분석시

  • 내부 사용자(분석가, 내부 직원, 저장장치 반출을 통한 유출 방지)
  • 외부 사용자(해킹, 원격접근 차단)
  • 보안 로그(접근 기록등 사용자 로그 관리)

 

1-3. 데이터 비식별화에 사용되는 기법

 

1) 가명처리

  • 개인 식별이 가능한 데이터를 직접 식별할 수 없는 다른 데이터로 대체

1-1) 휴리스틱 익명화

  • 식별자에 해당하는 값들을 몇가지 정해진 규칙을 이용하여 개인정보를 감추는 방법

1-2) K-익명화

  • 지정된 속성이 가질 수 있는 데이터를 k개 이상으로 유지하여 개인정보를 감추는 방법

1-3) 암호화

  • 정보의 가공시 일정 규칙의 알고리즘을 적용하여 개인정보를 감추는 방법

1-4) 교환방법

  • 미리 정해진 변수들의 집합에 대해 데이터베이스의 레코드와 교환하여 개인정보를 감추는 방법

 

2) 총계처리

1-1) 기본방식

  • 민감한 개인정보는 통계처리(평균, 총합 등)하여 개인정보를 감추는 방법

1-2) 라운딩

  • 집계된 값을 올림, 내림하여 개인정보를 감추는 방법

1-3) 데이터 재배열

  • 개인정보를 타인의 정보와 뒤섞어 개인정보를 감추는 방법

 

3) 데이터값 삭제

3-1) 속성값 삭제

  • 개인식별 항목을 삭제하여 개인정보를 감추는 방법

3-2)속성값 부분 삭제

  • 민감한 속성값의 일부만 제거하여 개인정보를 감추는 방법

3-3) 데이터 행 삭제

  • 명확하게 구분 가능한 행을 삭제하여 개인정보를 감추는 방법

3-4) 준 식별자 제거를 통한 단순 익명화

  • 개인을 식별할 수 있는 준 식별자를 가진 행을 제거하여 보다 강력하게 개인정보를 감추는 방법

 

4) 범주화

4-1) 기본방식

  • 개인식별 데이터를 평균이나 범주로 대체하는 방법

4-2) 랜덤올림

  • 개인 정보에 대한 수치를 일정 기준으로 올림, 내림으로써 개인정보를 감추는 방법

4-3) 범위

  • 해당 값의 분포, 구간으로 대체하여 개인정보를 감추는 방법

4-4) 세분정보 제한

  • 민감항목(단일 항목으로 개인이 식별 가능한 항목)을 상한, 하한, 구간 코딩을 활용하여 개인정보를 감추는 방법

4-5) 제어 올림

  • 랜덤올림 방법에서 행과 열의 합이 일치하지 않는 것을 보정하는 방법

 

5) 데이터 마스킹

5-1) 임의 잡음 추가방법

  • 민감한 정보(소득, 세금 등)에 노이즈를 추가하여 개인정보를 감추는 방법

 

5-2) 공백과 대체 방법

  • 선택한 행을 공백으로 바꾼 후 보간법을 적용하여 개인정보를 감추는 방법

DEEPML(CS231n) Lec.07 Training Neural Networks, Part2

Note
@2021-02-21 18:16:31

 지난 강의에서 전반적인 내용을 살펴봤다면, 보다 자세한 내용을 다루는 강의입니다. 크게 Fancier optimization, Regularization, Transfer Learning에 대해 배웁니다.

 

Optimization

 최적화의 문제에서, SGD가 원하는 결과를 내는데 도움을 준다고 했습니다. 그렇다면 optimization은 '묻따말' SGD를 쓰면 되는걸까요?

 아쉽게도 SGD를 쓰기엔 몇가지 치명적인 문제점이 있습니다. 만약 loss가 한 방향으로만 빠르게 변화하고 다른 방향으로 느리게 전개된다면 어떤 결과가 나올까요? 위 그림은 수직방향으로 빠르게 변화하는 반면, 수평으로는 느리게 변화합니다. 이런경우 수직방향으로 zig-zag현상이 발생합니다. 학습을 방해하죠. 

 

 문제는 또 있습니다. 만약 우리의 loss function에 local minima나 saddle point가 있다면 어떻게 될까요?

 

 

 우리의 학습은 gradient가 작아지는 방향으로 진행되어야 하는데, local minima의 경우 현재의 위치가 최솟점이라고 착각하여 학습을 멈출 우려가 있습니다. 또 saddle point의 경우 변곡점에 속하게 되어 순간 기울기가 0이 되는 지점에서 학습을 중단할 가능성이 있습니다. 특히 local minima에 비해 saddle point가 적을것으로 보이지만, 실제 loss function에서는 saddle point가 더 자주 관찰되며 특히 고차원으로 갈수록 어디에나 존재한다고 볼 수 있습니다.

 

SGD에서 gradient는 mini batch를 바탕으로 하기 때문에 noise가 끼어있을 수 있습니다. 전체 데이터를 사용하는 것이 아니기에 순간의 방향을 판단할 뿐 전체적인 흐름과 일치하지 않기 때문이죠.

 

1. Fancier Optimization

1-1. momentum 계열(방향)

1-1-1. SGD + Momentum

위의 문제를 해결해줄 수 있는 방안으로 우선 SGD에 Momentum을 추가해 주는 방법이 있습니다.

 쉽게 말하면 기존의 SGD에 속도의 개념을 추가해 줄 뿐입니다. 진행 방향으로의 속도를 추가해준다면, 관성으로 인해 어느정도의 local minima나 saddle point에서 탈출하거나, 또는 어느정도의 'noise'는 상쇄할 수 있을 것입니다. 

 

1-1-2. Nesterov Momentum

actual step : Velocity와 gradient의 가중평균

 위의 그림에서 Momentum update는 현재 위치에서의 Velocity와 gradient를 계산하여 이를 결합하는 방식을 사용하는 반면, Nesterov Momentum은 현재 위치에서 Velocity만 계산하고 이동 위치에서 gradient를 계산하여 actual step을 구하는 방식입니다. Nesterov Momentum은 SGD+Momentum에 비해 빠르고 convex(볼록한) optimization에서는 뛰어난 성능을 보입니다. 고차원 딥러닝에서는 non-convex한 모양(saddle point의 사례)이 많기 때문에 잘 쓰이지 않습니다.

*velocity의 초기값은 0(하이퍼 파라미터가 아님)

*좁고 깊은 minima는 일반화를 통해 넓고 얕은 minima로 바꿔주는것이 좋음(robust)

 

1-2. Ada계열(보폭)

1-2-1. Adagrad

코드해석

  1. 우선 grad_squared값을 0으로 초기화합니다.
  2. 그리고 while문을 사용해 반복합니다. 
  3. dx는 현재 지점 x에서 계산한 gradient값입니다.
  4. dx를 이용해 grad_squared를 구합니다. dx를 제곱하여 계속 더해나갑니다. 이 grad_squared가 x를 구할 때 분모로 들어가는데, while문이 실행될때마다 누적되어 지속적으로 커지니 x값의 이동 정도가 점점 작아집니다.
  5. dx 를 np.sqrt(grad_squared)로 나눈값에 learning rate를 곱하여 초기 x값에서 뺍니다.
  6. 이를 활용해 다음 x값을 찾고 2번으로 돌아가 이 과정을 반복합니다.

 

세 번째로 AdaGrad라는 방법이 있습니다. adaptive gradient라는 이름처럼, 각 매개변수별로 적응하듯 확률을 조정해 나가는 방식입니다.  가속의 개념을 도입할 때 momentum 대신 gradient squared term을 이용합니다. 학습중 계산되는 gradient값을 제곱하여 계속 더해 나가며, 한 시점에서 계산된 gradient값을 squared gradient로 나눠줍니다. 여기서 알 수 있듯이 계산을 해나갈수록 분모가 점점 커지기 때문에 갈수록 탐색 속도가 느려집니다. convex한 경우 학습이 잘 이루어지지만 딥러닝은 말씀드린대로 non-convex 한 구간이 많습니다. 따라서 학습이 제대로 이루어 지지 않는 경우가 많을 것입니다. 이를 해소하기 위해 RMSProp이 도입됩니다.

 

1-2-2. RMSProp

코드해석

  1. 우선 grad_squared값을 0으로 초기화합니다.
  2. 그리고 while문을 사용해 반복합니다. 
  3. dx는 현재 지점 x에서 계산한 gradient값입니다.
  4. dx를 이용해 grad_squared를 구합니다. 다만 decay rate를 grad_squared에 곱해주고 1-decay_rate를 dx^2에 곱해서 두 항을 더해줍니다.
  5. dx 를 np.sqrt(grad_squared)로 나눈값에 learning rate를 곱하여 초기 x값에서 뺍니다.
  6. 이를 활용해 다음 x값을 찾고 2번으로 돌아가 이 과정을 반복합니다.

 AdaGrad를 변형시킨 것으로 누적된 squared gradient에 decay rate(일반적으로 0.9 또는 0.99)를 곱해주고 1-decay에 현재 gradient에 제곱한 값을 더해줍니다. 이렇게 하면 이전 시점의 gradient를 더 크게 반영하여 무조건 속도가 느려져 학습이 멈추는 구간이 생기는 현상을 극복할 수 있습니다.

 

1-3. Adam

 위의 속도와  보폭을 고려한 두 방식 모두 장단점이 있습니다. 그렇다면 이 두 방식의 장점을 결합한다면 어떨까요? 이러한 아이디어의 결과로 우리는 제대로 된 방향으로 진행하며 적절한 보폭으로 최적화를 진행하는 optimizer, Adam을 사용할 수 있게 되었습니다!

 

위 그림은 Momentum계열의 아이디어와 Ada계열의 아이디어를 섞어놓은 모습입니다. 처음 등장한 개념인 first moment와 second moment는 각각 실제 gradient의 기대값 E(gradient)와 E(gradient^2)의 추정치를 나타냅니다.  분모에 1^-e7의 값을 더해주는 것은 분모가 0이 되지 않도록 매우 작은 숫자를 더해주는 것입니다. 

 

 그러나 Adam(almost)의 그림처럼 Momentum과 Ada의 개념을 도입하는 것으로 식이 완성되는 것이 아닙니다. 우선 위의 코드대로 진행했을 때 첫 스탭이 어떻게 진행되는지 살펴봅시다.

 

 first_moment는 0, beta1은 0.9로 설정되어 있습니다. Momentum부분을 보면 beta1*first_moment는 0이 될 것이고 beta1은 1에 가깝게 설정되어 있기 때문에 1-beta1*dx의 값이 0에 가깝게 저장될 것입니다.(first_moment)

이 경우 해당 값이 x의 업데이트에 사용된다고 하면 분자가 너무 작은 값으로 설정되어 매우 작은정도밖에 이동하지 못할 것입니다(업데이트가 거의 일어나지 않음).

 

second_moment의 값이 0, beta2의 값이 0.99로 설정되어 있습니다. Momentum부분을 보면 beta2*second_moment는 0이 될 것이고 beta2은 1에 가깝게 설정되어 있기 때문에 1-beta2*dx^2의 값이 0에 가깝게 저장될 것입니다.(second_moment)

이 경우 해당 값이 x의 업데이트에 사용된다고 하면 분모가 너무 작은 값으로 설정되어 발산해 버릴 것입니다(업데이트가 일어나지 않음).

 

따라서 위와같은 문제점을 보완하기 위해 bias correction부분을 추가해 줍니다. 해당 부분이 추가되면 두가지 경우를 모두 완화해 준다고 합니다. 일반적으로 초기 설정값은 beta1은 0.9, beta2는 0/999, learning_rate는 1e-3이나 5e-4가 활용된다고 합니다.

 

 

1-4.그 외 방법

이외에도 학습이 정체되는 구간에서 learning rate를 낮춰서 학습을 촉진시키는 learning rate decay, 2차미분값을 활용하여 최솟값으로 바로 찾아가는 second order optimization등의 방법이 있다고 합니다.

 

2. Regularization

2-1. Model Ensembles

 앞서 다룬 optimization의 경우 모델을 학습하는 과정에 대한 내용이었습니다. 모델을 '학습한다'고 할때 학습이란 train data를 활용하여 결과를 출력하는 모델을 만들었을 때, 그 데이터 안에서 실제 레이블값을 출력하도록 최적의 W값을 찾기 위해 loss 값을 업데이트해 나가는 과정이었습니다.

 그러나 우리가 실제로 원하는 것은 단지 train data를 정확하게 알아보는 것이 아니라 새로운 data가 들어왔을 때 이를 얼마나 정확하게 예측할 수 있는냐 하는 문제입니다. 따라서 사실 validation accuracy에만 신경쓰면 되는 문제입니다.

 

 이를 위한 여러 방안들이 있습니다. 사실 regularization 기법은 아니지만 Ensemble 기법도 이와 같은 효과를 낼 수 있습니다. 앙상블 기법은 다음과 같은 2가지 방식이 있습니다.

 

  • 여러 모델을 독립적으로 학습하여 test 결과를 평균(모델별 성능의 차이 완화)
  • 하나의 모델의 학습과정에서 성능이 좋았던 부분을 개별 모델로 취급하여 여러 모델처럼 연산(학습률의 변동 완화)

2-2. Drop out

Drop out은 쉽게 말하면 랜덤하게 노드를 꺼주는 기법이라고 할 수 있습니다. 일반적으로 절만을 끈다고 하네요. 일반적으로 FC layer에서 사용하고, Conv에서도 사용할 수 있습니다(채널단위). 기본적으로 두 가지 특징이 있습니다.

  • 학습시 특정 feature끼리의 상호작용을 막아줍니다(overfitting 방지)
  • 한 모델로 여러 모델을 만들어서 훈련하는 효과(Ensemble)

이때 주의할 점은 뉴런을 일괄적으로 끄고 연산을 시작하는것이 아니라 학습을 해 나가면서  확률값을 계산해 뉴련을 꺼나가기 때문에 이를 위한 연산이 추가됩니다. 따라서 연산시간은 증가한다는 단점이 있습니다.

 

 일반적으로 위의 dropout은 train time의 dropout을 의미합니다. 그렇다면 test time에도 일관되게 진행하면 될까요?

답은 '아닙니다'입니다. 일반화 가능성을 위하여, test time에는 랜덤성을 부여하면 안됩니다. 따라서 dropout 비율(뉴런을 끈 비율,  확률값)을 곱하여 random성을 보정(왜곡을 줄임)하고 훈련뒤의 일반화 가능성을 향상시킵니다.(Average out)

 

 이와 유사한 방식을 이전 단계에서 보았는데요. 맞습니다. 같은 의미로, BN도 좋은 regularizarion 기법입니다. 위에서 살펴보았듯 train단계에서 batch별로 샘플링 후 정규화하여 랜덤성을 부여하고 test단계에서 전체 데이터를 활용하여 정규화하기 때문입니다(Dropout의 Averageout과 유사). 그러나 dropout은 하이퍼파라미터 p를 가지고 있다는 점에서 BN에 비해 유리합니다.

 

따라서 일반적으로 BN을 수행할 때는 따로 regularization기법을 적용하지 않아도 됩니다. 그러나 overfitting이 될 수도 있으니, 일단 BN을 실시한 후, overfitting의 조짐이 보인다면 Dropout을 추가하는 것도 좋은 선택입니다.

 

2-3. 그 외 기법들

 '모델의 과적합을 막는' 목적을 달성하기 위한 가장 좋은 방법은 dataset의 크기를 늘리는 것입니다. dataset의 절대적인 양이 많은 것이 가장 좋겠지만 비용, 시간, 자료없음 등의 문제로 데이터 스스로 완벽하게 학습하기 위한 조건을 만들기란 매우 어렵습니다(특히 의료데이터). 따라서 regularization을 실시하는데, 주어진 데이터를 변형하여 사용하는 것도 한가지 대안이 될 수 있습니다. 일반적으로 데이터를 뒤집거나, 특정 부분만 자르거나, 색을 조정하는 등의 방식을 사용합니다.

 

지금까지 살펴본대로 regularization과정에는 다음과 같은 일정한 패턴이 있습니다. 


train time : random성을 추가

test time : 정규화, 평균화 하여 랜덤성 제거

 

e.g

Dropout
Batch Normalization
Data Augmentation

DropConnect
Fractional Max Pooling
Stochastic Depth


3. Transfer learning

 우리의 모델을 훈련시킬 만큼의 충분한 데이터가 없다면, 우리의 데이터셋을 이미 학습된 모델에 적용하는 방법도 있습니다. 이를 Transfer learning(전이학습)이라고 합니다.

전이학습 시 만약 우리의 데이터가 적다면, 마지막 FC(출력층)의 가중치만 초기화하고 나머지 모든 층의 가중치를 고정하여 학습(fine tuning)시킵니다. 데이터의 크기가 커질수록, 초기화할 layer를 조금씩 늘려가며 학습시킬 수 있습니다. 뭔가 찝찝하지만, 이미 여러 대회나 프로젝트에서 자주 사용되는 방법입니다.

 

요약하자면


Optimization은 Adam을 사용합시다.


Regularization은 BN을 우선 적용하고, 과적합의 우려가 있을 시 Dropout을 사용합시다.

 

Transfer learning은 실제 프로젝트에서 많이 사용되니 잘 기억해 둡시다.


 

 

 


해당 글은 스탠퍼드 대학의 CS231n(Convolutional Neural Networks for Visual Recognition)을 정리한 글임을 밝힙니다.


 

DEEPML(CS231n) Lec.06 Training Neural Networks, Part1

Note
@2021-02-12 04:26:38

이번 강의에선 크게 세 가지를 다룹니다.

1. One time setup

  • activation functions, preprocessing, weight initialization, regularization, gredient checking

2. Training dynamics

  • babysitting the learning process, parameter updates, hyperparameter optimization

3. Evaluation

  • model ensembles

 

1. Activation Functions

그림 1. Activation Function

인간의 신경망과 비교하면 위와 같은 단계를 거치게 됩니다. 이전 뉴런의 정보(x1)를 다음 뉴런으로 전달하는 역할을 하는 시냅스(w0)를 거쳐 cell body에 저장됩니다. 이 결과를 또 다음 cell body에 전달해야 하는데, 이때 사용하는 함수 f(x)를 활성화 함수(activation function)라고 합니다. 일반적으로 활성화함수는 *비선형함수를 사용합니다.

*선형함수는 쌓아도 선형으로 돌아가기 때문(층이 쌓이지 않는다)

 

우리는 활성화 함수의 종류를 살펴보고, 각 함수의 특징과 단점을 살펴볼 것입니다. 일반적인 활성화 함수의 종류는 다음과 같습니다.

*특징과 단점의 비교를 위한 문장단위 구성 주의

1-1. Sigmoid

그림 1-1. Sigmoid, zig-zag path

특징

가장 전통적인 방법

이진분류에서 많이 사용(이마저도 최종출력에서만 사용)

기울기가 큰 0.3~0.7 구간에서 잘 작동함

 

단점

기울기 소실(Saturated neurons “kill” the gradients, gradient vanishing)

Sigmoid outputs are not zero-centered(Always all positive or all negative, zig zag path)

exp() is a bit compute expensive

 

1-2. tanh(x)

특징

Squashes numbers to range [-1,1]

zero centered (nice)

 

단점

still kills gradients when saturated :(

 

1-3. ReLU

좌 : ReLU, 우 : update problem

특징

Computes f(x) = max(0,x)

Does not saturate (in +region)

Very computationally efficient

Converges much faster than sigmoid/tanh in practice (e.g. 6x)

Actually more biologically plausible than sigmoid

(Rectified Linear Unit)

가장 많이쓰는 활성화함수

 

단점

Not zero-centered output

An annoyance

  • x < 0일 때 가중치가 업데이트 되지 않음(일반적으로 10~20%)
  • 초기 가중치 설정(초기값이 너무 크면 데이터로부터 떨어져 가중치 업데이트가 안됨)
  • learning rate가 높을 때(초기엔 잘 학습되다가 업데이트 안됨)

 

1-4. Leaky ReLU

특징

Does not saturate
Computationally efficient
Converges much faster than sigmoid/tanh in practice! (e.g. 6x)
will not “die”.

 

1-5. ELU

특징

All benefits of ReLU

Closer to zero mean outputs

Negative saturation regime

compared with Leaky ReLU

adds some robustness to noise

 

단점

Computation requires exp()

 

1-6. Maxout "Neuron"

특징

Does not have the basic form of dot product -> nonlinearity

Generalizes ReLU and Leaky ReLU

Linear Regime! Does not saturate! Does not die!

 

단점

doubles the number of parameters/neuron(메모리가 두배로 소모됨)

 

요약

 

ReLU를 씁시다

*learning rate, W 초기값 설정만 주의

 

다른 함수를 시도정도'는' 해볼 수 있습니다.

 

시그모이드는 쓰지 맙시다

 

2. Data Preprocessing

우리에게 주어진 데이터 뭉치가 있을 때, 이를 좌표 평면 위에 나타낼 수 있습니다. 보다 정확한 분석을 위해 데이터 전처리를 해줘야 합니다. 데이터 전처리에는 일반적으로 다음과 같은 3가지 방법을 사용합니다.

 

1. 우리는 위에서 데이터가 zero-centered하지 못하면 zig-zag path 문제가 생기는 것을 보았습니다. 이를 방지하기 위해 각 점에서 평균을 차감해주는 방법을 사용합니다. 기하의 관점에서 보면, 모든 점을 원점으로 모아주는 역할을 합니다. 

 

2. 다음으로 데이터를 정규화 해줍니다. 이는 다양한 데이터를 동등한 수준으로 분석할 수 있게 해줍니다.

 

 데이터 정규화와 표준화는 항상 헷갈리는 개념입니다. 한번 짚고 넘어가겠습니다. 둘 모두 데이터의 학습이 원할하게 진행되는 것을 돕기 위해(scale이 큰 feature의 영향력 과대를 방지하기 위해) 실시합니다. local minima에 빠질 위험이 감소하고 연산이 빠르게 진행되는 특징이 있습니다.

 


표준화(Standardization)

데이터의 진폭 감소(평균이 0, 분산이 1)

데이터의 간격이 감소하게 됨(0과 1을 벗어날 수 있음)

데이터가 평균으로 부터 얼마나 떨어져있는지를 보여줌

 

정규화(Normalization)

데이터를 0과 1 사이의 값으로 변환(Scaling)

최댓값은 1, 최솟값은 0을 벗어날 수 없음

데이터군 내에서 특정 데이터의 위치를 보여줌


3. PCA나 Whitening기법도 있습니다. PCA는 차원을 축소하는 역할을 하며, Whitening은 기존의 데이터가 가지고있던 상관성과 강도를 제거하여 아무 정보가 없는 데이터 분포로 만들어줍니다.

 

3. Weight Initialization

 초기 모델을 구상할 때 가중치를 어떻게 설정하는 것이 좋을까요? 물론 정방향, 역방향으로 반복 진행하며 가중치를 지속적으로 업데이트 할 것이지만, 초기 가중치를 설정하는 것 역시 중요합니다. 예를 들어 초기 가중치값을 0으로 설정한다면, '모든 뉴런이 같은 일'을 하게 됩니다. 모두 같은 W값을 사용하기 때문에 같은 출력값이 도출되고 이를 바탕으로 하는 가중치 업데이트 역시 진행되지 않습니다. 그렇다면 가중치는 어떤 수치로 초기화해야 할까요? 극단적이긴 하지만 다음 두 사례를 보면 감을 잡을 수 있습니다.

 

3-1. Initialization too small

 우선 매우 작은 수치로 초기화하는 경우입니다. 일반적으로 가중치는 0이 아닌 임의의 작은 수로 초기화합니다. 0을 평균으로 하고 표준편차가 0.01인 가우시안 분포에서 초기값을 추출해봅시다.

10 layer / 500 neuron per layer / activation function : tanh

 

 초기 가중치가 매우 작은 수치일 경우, 작은 네트워크에서는 평균을 0으로 하는 분포를 보이며 잘 작동하는것처럼 보이지만, 네트워크가 깊어질수록 편차가 0으로 수렴하는 것을 볼 수 있습니다. 너무 작은 값을 곱해 나가기 때문에 출력값이 빠르게 0에 가까워지는거죠. backward pass의 경우 역시 너무 작은 값의 기울기를 구해나가기 때문에 업데이트가 거의 일어나지 않습니다.

 

3-2. Initialization too big

 너무 작은 수치는 좋은 선택이 아니라는 것을 알았습니다. 그렇다면 큰 값을 주면 어떨까요? 이번엔 초기 가중치값을 1로 주고 실시해보겠습니다.

 반면 초기 가중치가 너무 클 경우엔 값이 발산해버립니다. 이번엔 초기 가중치를 1로 설정하겠습니다. 범위가 정해져있다면 빠르게 saturate되겠군요. tanh 함수를 activation function으로 사용하고 있기 때문에 1과 -1로 빠르게 saturate됩니다. gradient는 0이 되고 업데이트는 일어나지 않을 것입니다. 

 

3-3. Initialization just right

 그럼 어떻게 해야 하나.. 싶습니다만, 여기 한가지 대안이 있습니다. Xavier initialization을 사용하는 것입니다. 간단히 설명하면 가중치를 가우시안 정규분포에서 랜덤으로 뽑아 이를 입력 노드의 갯수로 나눠줍니다(normalization). 입력의 수가 작은 경우 작은수로 나눠 큰 값을 얻고, 큰 가중치를 곱해줍니다(반대의 경우엔 반대로!!). 이 방법은 근사적으로 동일한 출력 분포를 갖게 할 뿐만 아니라 신경망의 수렴률 또한 향상시키는 것으로 알려져 있습니다.

 

 ReLU의 경우 위의 Xavier initialization이 효율적이지 않습니다. 출력 분산의 절반이 죽어버리기 때문입니다. 이를 해결하기 위해 2로 나눠주면 출력값의 절반이 죽어 gradient update가 멈추던 현상이 사라지고 update가 잘 진행됩니다.

 

요약

 

선 Xavier, 후 다른방식 고려

 

4. Batch Normalization

Gradient descent를 할때, 모두 계산하는 것은 비효율적이기 때문에 batch를 활용한다고 했습니다. 이때 스케일이 다른 feature들이 입력되어 계산된다고 하면 입력 데이터와 출력값의 분포가 달라질 수 있습니다(scale이 큰 feature는 상대적으로 gradient가 크게 나타나기 때문에 결과적으로 weight와의 연산값이 크게 나타납니다).그렇기 때문에 학습시 사용하는 batch별로 normalize해야 합니다.

*batch normalize는 선형변환이기 때문에 구조를 변화시키지 않으며 Activation map당 각각의 분산, 표준편차를 구해야 합니다. 


 batch normalization은 gradient vanishing이 일어나지 않게 하는 방법입니다. activation function의 구조로 gradient vanishing을 조절하는것이 아니라, 학습 과정에서 이를 해소하려 합니다.


 한가지 의문이 생깁니다. 분석의 왜곡을 막기 위해 데이터를 normalize해줘야 하는데, 그렇다면 batch를 사용하는 분석에선 어떻게 normalize해야 할까요?

 학습 단계에선, 좌측 그림과 같이 만약 batch당 N개의 학습 데이터와 D개의 차원이 있다면 batch당 D개의 차원별로 평균을 계산한 후 normalize 해줍니다. 결과적으로 각 배치별 input distribution(입력값의 분포)이 N(0, 1)인 정규분포를 따르게 됩니다. 이 과정을 거치면 layer별, 또는 activation별 분포가 달라지지 않게 됩니다. 일반적으로 FC layer와 Conv layer의 뒤에 위치하며, non-linear function의 앞에 위치합니다. 

 반면에 예측 단계에선 우리가 실제로 원하는 것은 원본 데이터에서의 W이기 때문에, 전체 데이터를 반영하기 위해 전체 데이터의 평균과 분산을 사용합니다.

 

 batch normalization을 통해 regularization 한 후, 감마(scaling), 베타(shifting) 학습을 통해 scaling 및 shifting 실행(gradient vanishing 조절 가능)

*감마(scaling), 베타(shifting)를 다시 학습시켜서 업데이트하는 이유 : flexibility

 

 

장점

  • reduces gradient vanishing & exploding
  • 학습 속도 향상(Allows higher learning rates)
  • 가중치 초기화 의존 감소
  • 정규화 역할 수행(Acts as a form of regularization per every batch)

 

5. Babysitting the Learning Process

1. preprocess the data

2. choose the architecture

모델의 구조를 (대충이라도)결정

3. loss값이 잘 작동하는지 확인

규제(regularization)가 0 → 0.001일 때 변화를 관찰(loss가 증가하면 제대로 작동하는것)

4. 작은 데이터를 시험삼아 학습(sanity check, overfitting되면 제대로 작동하는것)

5. 학습을 반복하며 적절한 regularization값과 learning rate 탐색(작은 값부터 시작하여 loss가 감소하는 방향으로)

 

6. Hyperparameter Optimization

 하이퍼 파라미터의 탐색 역시 비슷한 방식으로 진행됩니다. cross validation, log scaling등을 진행하는데요. 처음엔 rough한 idea를 얻기 위해 몇개의 epoch만 진행합니다. 이후 runnung time을 늘려가며 더 나은 하이퍼 파라미터를 탐색하는 것이죠.

 

 예를 들어 봅시다. 사진에서 보듯 regularization값과 learning rate값의 범위를 지정해줍니다. 이때 log scaling을 해 주는데, 이는 결과를 안정적으로 만들어준다고 합니다(note it's best to optimize in log space!). 처음 범위를 10**(-5, 5)의 범위 사이의 임의의 수로 지정하고 학습을 진행하는데, learning rate가 e-4, regularization값이 e-01인 부분에서 높은 validation accuracy가 나옵니다.

 

 이를 기준으로 regularization값을 (-4, 0) 사이, learning rate값을 (-3, -4) 사이로 조정합니다. 이런식으로 validation accuracy가 높아지는 방향으로 수정해나가면 됩니다. 

 

 이런식으로 탐색하는 기법은 grid search와 random search 두 가지를 주로 사용합니다. 둘중에선 더 많은 경우의 수를 탐색할 수 있는 random search기법이 더 효과적입니다.(더 빠르게 더 좋은 결과를 도출)

 

이처럼 탐색해야하는 하이퍼 파라미터는 network architecture, learning rate, regularization값 등이 있습니다. 

 

 loss curve를 모니터링하며 탐색할 수도 있습니다. 우리가 원하는 loss그래프는 초기엔 빠르게 감소하다가 점점 감소폭이 작아지는 우측의 빨간 그래프입니다. 

 

 모니터링을 하다 보면 왼쪽과 같은 그래프가 나타날 수도 있습니다. 초반엔 전혀 학습이 일어나지 않다가 어느순간 loss값이 급격하게 감소하는 형태입니다. 이는 초기 initialization이 제대로 수행되지 않은 것으로, 초기 W값이 너무 작은 경우 발생합니다. 

 

 우측의 그래프는 학습이 제대로 진행되는지를 보여줍니다. 만약 두 선이 멀다면(train acc는 높아지고 val acc는 낮아짐 or train loss는 낮아지고 val loss는 높아짐) 이는 over fitting되었을 가능성이 매우 높습니다. 

 

요약하자면


Activation Functions은 ReLU를 씁시다


Image의 경우 Data Preprocessing단계에서 zero-centered하게만 만듭시다


Weight Initialization는 Xavier init을 씁시다


Batch Normalization은 하는게 좋습니다


Hyperparameter Optimization도 중요합니다


 

 

 


해당 글은 스탠퍼드 대학의 CS231n(Convolutional Neural Networks for Visual Recognition)을 정리한 글임을 밝힙니다.


 

DEEPML(CS231n) Lec.05 Convolutional Neural Networks

Note
@2021-01-31 19:35:32

 이전 강의까지 우리는 가중치를 조절하는 방법에 집중해서 공부했습니다. 그리고 그 과정에서 '괴랄한' 모델들을 얼핏 본 것 같습니다. 오늘은 이미지 학습에 주로 쓰이는 '괴랄한' 모델 중 하나인 CNN(Convolutional Neural Networks)에 대해 공부할 것입니다.

 

1.  FC(Fully Connected Layer)와 Conv(Convolution Layer)의 차이

 

그림 1. Fully Connected Layer

 우리가 이제까지 공부한 linear classifier를 간단하게 도식화하면 위의 그림 1과 같습니다. 이미지를 쭉 늘여서 한줄로 만들어서 가중치와 곱해줬었죠? 그 결과 이미지에 대한 하나의 Score값으로 표현되었습니다.

 

 

그림 2. Convolution Layer

 Conv는 구조부터 차이가 있습니다. 그림 2와 같이 원본 그대로의 형태를 유지(공간의 구조에 대한 정보를 유지하는 것입니다!)하면서, filter를 사용해서 레이어를 훑습니다(표현이 이상하지만 뒤에 설명을 보시면 '훑는다'는 표현이 이해되실겁니다). 한 연산의 과정을 거치면 하나의 숫자를 얻는데, 이는 필터의 dimensional dot product의 크기 * 채널수 + 분산의 결과입니다(위의 예에서 5 * 5 * 3 + 1). 

 

 이때 필터는 다음과 같은 조건이 있습니다.


1. Convolution Layer와 채널수가 같아야 한다.

2. 크기는 제한이 없지만, Convolution Layer의 크기를 넘으면 안 된다.


2. Convolution Layer의 성질

 앞에서 Layer를 필터로 훑는다고 했습니다. 1개의 필터로 이러한 과정을 거치면 1채널의 activation map 1개를 얻게 됩니다. 이 과정은 다음과 같습니다.

 

그림 3. 다양한 필터는 각각 다른 특징을 추출합니다.

 하나의 필터를 거칠 때마다 하나의 activation map이 나옵니다. 그리고 필터는 각각 다른 특징을 추출합니다.

 

그림 4. 필터 하나당 1장의 activation map을 만듭니다.

 만약 5 * 5 * 3인 필터가 6개 있다면, 그림 4와 같이 28 * 28 사이즈의 activation map 6장이 나올 것입니다.

 

그림 5. 이미지*필터의 결과*활성화함수의 구조를 갖는다.

 이미지를 다중 필터로 훑고, 활성화 함수를 거치는 것이 하나의 단계로 구성됩니다. 단계를 거듭할수록 이미지의 크기가 작아지는 것이 보입니다. 첫 단계에서 5*5*3의 필터 6개로 훑었기 때문에 두 번째 단계에서 6채널(6장)이 되었고, 두번째 단계에서 10개의 필터로 훑었기 때문에 10채널(10장)로 구성됩니다.

 

 

그림 6. 필터 시각화

 필터를 시각화하면 그림 6과 같은 모양이 될 것입니다. 필터를 거칠수록 저 차원에서 고차원의 특징을 추출합니다(6장의 필터일 때, 1번 필터에서는 점을, 2번 필터에서는 선을, ... , 6번 필터에서는 형태를 추출).

 

 미리 살펴보자면, Convolution Neural Networks는 결과적으로 다음과 같은 구조를 갖게 됩니다.

그림 7. Convolution Neural Networks의 구조

 

3. 필터(receptive field)의 동작 원리와 연산과정

 다음 이미지는 필터의 동작 과정을 직관적으로 보여줍니다. 필터는 좌상단에서 시작해, 오른쪽으로 훑어가며 특징을 추출합니다. 한 장의 필터가 이미지에 한번 닿을때마다, 하나의 값을 추출(내적)합니다. 이 값이 모이면 한장의 activation map이 출력됩니다.

그림 8. filter의 적용과정

 

그림 9. activation map

 

 연산의 결과는 어떻게 나타날까요? 쉽게 알 수 있게 7*7픽셀의 이미지를 3*3 필터로 훑어간다고 생각해 봅시다. 앞서 언급한 대로 좌상단부터 훑어갑니다. 직접 손으로 그려보면 쉽게 몇 번의 연산을 하는지 알 수 있습니다. 제가 해본 결과 4회 우로 이동하고 5회의 연산을 하는군요(시작 부분도 연산해야죠!). 7*7의 이미지니까 세로로도 같은 횟수의 연산을 하겠죠? 결과적으로 5*5의 출력물을 얻을 수 있습니다.

 

그림 10. 필터의 연산과정

 7칸이면 5회 연산이라.. 뭔가 일반화할 수 있을 것 같습니다. 간단하게 4*4의 이미지를 2*2 필터로 훑는다고 생각해봅시다. 2회 이동에 3번의 연산을 하게 되는군요. 최종 출력물의 크기는 3*3입니다. 뭔가 보이십니까?

 

7과 3을 가지고 5를 만들려면 (7-3) + 1 하면 되겠군요. 4와 2를 가지고 같은 방식으로 3을 만들 수 있을까요? (4-2) + 1로 동일하군요!! 뭔가 보입니다.

 

 여기서 한 가지 의문이 생깁니다. 이동은 반드시 한 칸만 해야 할까요? 아닙니다. 이동하는 칸수는 하이퍼 파라미터로, stride라고 합니다. 7*7 이미지에 5*5 필터를 적용하여 2칸씩 이동해볼까요? 이번엔 출력 이미지가 3*3이 되겠죠?(2회 이동에 3회 연산입니다!)

 

 우리가 알아낸 패턴을 적용해 보겠습니다. (7-3) + 1은 5였는데요.. 하지만 달라진 점이 있습니다. 2칸씩 이동했다는 것이죠. 7-3과 1을 가지고 3을 만들 수 있는 방법이 있을까요? 바로 7-3을 2로 나눠주는 것입니다. 그럼 2+1 = 3이 되겠죠? 

 

 여기서 한 가지 패턴을 찾을 수 있을 것 같습니다. 이미지의 한 변의 크기를 N, 필터의 한 변의 크기를 F,  이동하는 칸 수를 stride라고 할 때, 공식은 다음과 같습니다.

 

Output size = (N - F / stride) + 1

 

4. Padding(zero padding)

 만약 3칸씩 이동한다면 어떻게 될까요? (7-3)/3 + 1이 되고 결과 이미지는 2.33*2.33이 될 것입니다. 칸수는 정수로 나와야겠죠? 따라서 3칸 이동은 안된다는 것을 알 수 있습니다. 굳이 3칸 stride를 하고 싶다면 1칸 padding을 하면 됩니다. 그럼 우리의 이미지를 둘러싼 0으로 9*9 크기의 이미지가 생길 것입니다. (9-3)/3 + 1 = 3으로 3*3의 출력물을 얻을 수 있을 것입니다. 

 

 여기서 padding의 개념이 나옵니다. padding은 이미지의 외곽에 0으로 구성된 칸을 채워 넣는 것입니다(zero padding). padding을 하는 이유는 크게 두 가지가 있습니다.

그림 11. filter적용 결과

 

 먼저 이미지의 축소를 막아줍니다. 필터를 거친 이미지는 항상 작아졌습니다. 7*7 이미지를 3*3 필터로 연산한 출력 값은 5*5 이미지가 되었죠. 이미지가 축소된다는 건 원본 이미지로부터 왜곡이 생긴다는 것입니다. 이때 1칸 패딩을 한다면? (9 - 3) / 1 + 1로 7*7 이미지가 유지되었습니다!! 이처럼 우리는 원본의 형태를 유지하기 위해 padding을 사용할 수 있습니다.(잘 사용하면 출력값의 크기를 조절할 수도 있겠죠!)

 

 두 번째는 연산의 불균형을 해소할 수 있습니다. 이미지의 연산과정 중 외곽의 픽셀은 연산이 1회밖에 되지 않아 내부의 픽셀에 비해 평가절하됩니다. 따라서 padding을 해줌으로써 이러한 평가절하를 완화해줄 수 있습니다.

 

일반적으로

3*3 필터에는 1칸의 zero pad를

5*5 필터에는 2칸의 zero pad를

7*7 필터에는 3칸의 zero pad를

사용합니다.

 

 연산을 거치는 파라미터(가중치)의 수는?

3개의 채널을 가진 5*5 필터로 연산합니다. 따라서 연산에 활용되는 파라미터의 수는 (5*5*3+1(bias))*10으로 760개입니다. 하나의 필터에 25개의 파라미터*3층으로 75에 1층마다 bias 1을 더해줍니다. 76*10의 필터로 총 760개의 파라미터를 갖게 됩니다.

 

 앞에서 우리는 필터의 개수에 따라 이미지의 차원이 바뀐다는 것을 알 수 있었습니다. 여기서 한발 나아가 차원을 마음대로 조정할 수도 있습니다. 7*7*3의 이미지에 1*1(*3)의 필터, stride 1을 사용하면, 출력 이미지의 크기는 동일하게 유지되겠죠?((7 - 1) / 1 + 1  = 7). 이때 필터를 1개만 쓰면?  7*7*1의 이미지가 되었습니다! 이처럼 차원 축소의 방법으로 활용할 수 있습니다.

 

 

5. FC와 CONV의 한 점(시점)에서의 차이

 

그림 12. FC와 Conv의 차이

 FC의 출력값의 한 점(1 number, dot product)은 입력 이미지의 전체 연산을 통한 한 클래스의 결괏값입니다. 반면 CL의 5중 필터를 거친 한 시점의 dot products(5 neurons)는 한 시점의 입력 이미지의 5가지 서로 다른 특징을 나타냅니다. 풀어쓰자면 FC의 한 점은 고양이로 예측하는 점수를 나타내는 것이라면, CONV의 한 시점은 입력 이미지의 특정 부분(고양이 귀)의 여러 특징(점, 선, 각도, 방향, 색 등)을 나타냅니다.

 

 이 차이점을 바탕으로 서로 뭐가 다른지 살펴봅시다. 우선 같은 이미지(우리의 고양이 이미지를 예로 들어볼까요?)를 FC는 한 줄로 늘려서, Conv는 형태를 유지해서 연산한다고 했습니다. 우리의 목표는 컴퓨터가 고양이라고 말하게 하는 것이었습니다. 두 가지 모두 고양이라고 출력하는 게 가능하다면, FC로만 수행해도 될 텐데 굳이 이 어렵고 복잡한걸 왜 읽고 있어야 할까요?

 

 간단합니다. conv가 더 잘 맞춥니다.  FC는 이미지의 각 픽셀에서의 특징을 점수화하여 훈련합니다. 새로운 이미지가 들어왔을 때 같은 위치의 같은 특성을 갖는 데이터만 명확히 판단할 수 있습니다. 바꿔 말하면 유사한 각도의 다른 이미지를 오분류할 가능성도 높은 것입니다. 반면에 Conv는 필터를 거치며 점점 다양한 고차원의 특성을 추출하기 때문에 일반화해서 판단할 수 있습니다.

 또 연산의 양이 훨씬 줄어듭니다. 성능적인 면, 그리고 효율성의 면에서 모두 Conv가 우월한 거죠.

 

 대신 Conv는 특징을 추출할 뿐 결과가 어떤 class에 속하는지 판단할 수 없습니다. 따라서 Conv의 마지막에 FC를 추가해 class를 분류해줘야 합니다. 다음 그림처럼요.

 

그림 13. CNN의 구조

 

6. Pooling Layer

 

그림 14. pooling layer의 과정

 

 Pooling Layer는 activation map을 입력으로 받아 크기를 줄여 특징을 강화-추출하기 위한 용도로 사용합니다. 연산을 간소화해주는 역할도 수행합니다. 이미지의 픽셀을 줄이면 같은 크기의 필터에 더 많은 부분을 투영할 수 있습니다. 그렇다면 pooling을 반복할수록 점점 전체적인 특징을 추출(추상화)하는 것이 가능해질 것입니다.

 

그림 15. max pooling

 Pooling에는 여러 방식이 있는데, 그중 가장 많이 사용하는 Max pooling을 알아봅시다. 이번엔 빈 필터를 준비합니다. 2*2의 형태만 가지고 있는 필터입니다. 4*4의 이미지에 stride를 2로 주고 적용한다면, 왼쪽 그림처럼 4 구역으로 구분할 수 있습니다. 각 구역별 Max값만 추출하여 필터를 채워 넣습니다. 이로써 필터를 적용한 구역별 가장 큰 특징만 추출되었습니다. 출력물을 구하는 공식은 다음과 같습니다. W1*H1*D1의 이미지가 있을 때 pooling layer의 filter의 변의 크기를 F, stride를 S로 설정한다면

 

output size = W2*H2*D2

W2=(W1-F)/S + 1

H2=(H1-F)/S + 1

D2=D1

 

일반적으로 아래와 같이 설정합니다.

F = 2, S = 2
F = 3, S = 2

 

여기까지 Conv Network에 대해 공부했습니다. Conv Network는 특히 이미지 처리에서 월등한 성능을 보여줍니다. Alex Krizhevsky는 「ImageNet Classification with Deep Convolutional Neural Networks」에서, 다음 두 가지 가정을 통해 왜 CNN이 이미지 학습에 잘 들어맞는지를 설명합니다.

 stationarity of statistics : 같은 특징이라면 한 데이터 내의 다른 부분에서도 동일할 것이며, 이는 다른 데이터에서도 동일하게 나타날 것입니다. 이는 한 가지 특징을 추출하면 다른 각도, 위치, 크기에 모두 적용할 수 있습니다(파라미터 공유).

and locality of pixel dependencies : 픽셀 데이터의 특성상 한정된 범위 안에서 종속성을 갖는다는 의미로, 인물사진에서 얼굴 전체가 아닌 눈, 코, 입의 객체를 따로 구분하게 하여 특징을 인접한 픽셀에 한정하게 합니다. 이는 다른 특징을 추출할 때 오류를 줄일 수 있습니다.

 

요약하자면


 

ConvNet은 Conv, pool. FC layer들을 쌓은 것입니다.

 

Filter는 작게, 구조는 깊게 쌓는 방식이 트렌드입니다.

 

Pool이나 FC레이어는 제거하는 것이 트렌드입니다(Conv만으로 구성).

 

일반적인 구조는 C[(CONV-RELU)*N-POOL?]*M-(FC-RELU)*K,SOFTMAX이며

N은 5를 넘지 않고, M은 제한이 없으며, 0 <=K <=2가 일반적입니다.

but recent advances such as ResNet/GoogLeNet challenge this paradigm


 

 

 

 

 


해당 글은 스탠퍼드 대학의 CS231n(Convolutional Neural Networks for Visual Recognition)을 정리한 글임을 밝힙니다.


 

DEEPML(CS231n) Lec.04_1 Backpropagation

Note
@2021-01-25 19:30:59

 우리가 이제까지 배운걸 한 덩어리로 뭉치면 Linear Classifier가 만들어집니다. 입력값 X와 임의의 가중치 W, Score function, Loss function, 그리고 Regularization term으로 이루어진 덩어리였습니다. 우리는 이를 학습시켜 loss가 가장 낮게 나타나는 W값을 찾는 것이 목표였습니다. 이 과정을 도식화하면 다음 하나의 그림으로 나타낼 수 있습니다.

 

 

Why backpropagation?

 학습을 통해 최적의 가중치 W를 찾고 싶다는 건 이제 알겠습니다. 이제까지 우리가 그려온 대로 저런 단순한 식이라면 가중치를 학습시키는게 크게 어렵지 않을 것입니다. 그러나 앞으로 우리가 배울 것들은 이런 단순한 모델이 아닙니다.

 

예를 들면

 

 

이런 거라던지

 

 

이런 끔찍한 것들입니다

 

 이처럼 파라미터가 매우 많고 여러 개의 레이어로 구성되어 있다면 기존의 방식들로는 학습이 어렵습니다. 그래서 새로운 방식을 적용합니다. 각 레이어별 기울기를 구하고 그 기울기를 이용해서 경사 하강법을 적용하면 가중치 W를 update 시켜 나가며 학습시킬 수 있습니다. 이때 역전파 알고리즘을 활용합니다.

 


미분값은 한 지점에서의 기울기를 나타냅니다. 이는변화하는 정도를 보여주죠. 즉 우리는 미분을 통해서 해당 노드가 loss에 미치는 영향을 알 수 있습니다.


역전파 알고리즘(Back propagation)

 우선 우리가 하고자 하는 것을 명확히 하고 넘어가겠습니다. 우리는 각 노드(아래 그림의 x, y, z,)가 출력 노드(아래 그림의 f)에 미치는 영향력의 크기를 알고 싶은 것입니다(미분을 하는 이유를 생각해 보세요!). 이를 이해하면 지금부터의 과정을 보다 직관적으로 이해할 수 있습니다.

 

 우리가 설계한 모델의 최적의 W를 구하기 위해 우선 임의의 W값과 각 노드별 정답 값을 가지고 순방향으로 나아가며 계산합니다(그리고 이 과정 속에서 우리는 local geadient를 얻습니다. 기억해두세요!). 최종적으로 우리는 loss값을 얻습니다. 이 loss는 임의로 설정한 W를 바탕으로 도출되었기 때문에, 우리는 최적의 값을 찾기 위해 W값을 지속적으로 update 시켜야 합니다. 

 

 가중치값을 지속적으로 update 해줘야 하는 것은 알겠습니다. 그러나 마구잡이로 update 하는 것은 너무 비효율적이겠죠? 보다 효과적으로 가중치를 조절하기 위해 우리는 미분을 사용합니다(큰 영향을 미치는 것은 크게, 또 부정적인 영향을 미치는 것은 작게!). 그러나 이 과정에서 우리는 각 노드들의 W값의 기울기를 구하기 위해서 또다시 많은 연산을 수행해야 합니다. 이 문제를 역전파 알고리즘을 통해 해소할 수 있습니다. 역전파 알고리즘은 Computational graph를 그려서 생각하면 이해하기 좋습니다. 우리가 이번에 볼 예제는 사실 이 한 장으로 요약 가능하죠.

 

 

다음은 x, y, z가 f에 미치는 영향을 알아내기 위해 계산해 나가는 과정입니다.


1. 재귀적으로 계산해 나갑니다. 우선 q와 z를 구합니다.


q의 영향력 : df/dq는 -12/3으로 -4가 됩니다.

 

z의 영향력 : df/dz는 -12/-4로 3이 됩니다.   

 

*곱 연산 시 노드별 미분값은 이전 노드의 변화량(미분값)*서로의 노드 값이 된다


 

2. x와 y는 바로 구할 수 없습니다. 따라서 위의 chain rule을 사용합니다.


x의 영향력 : df/dx는 df/dq*dq/dx로 df/dq*1입니다. 따라서 -4가 됩니다.

 

y의 영향력 : df/dy는 df/dq*dq/dy로 df/dq*1입니다. 따라서 -4가 됩니다.

 

*합연산시 노드별 미분값은 이전 노드 값이 된다

1. q = x + y에서 x로 편미분을 실시하면 dq/dx = dx/dx=1이 된다

2. df/dx = df/dq*1이 되므로, 이전 노드의 값이 된다



 간단한 미분을 통해 각 노드가 score값에 미치는 영향력을 알아봤습니다. x는 -4, y는 -4, z는 3입니다. 이 각각의 값은 가중치를 update 할 때, 어떻게 업데이트해야 하는지 방향을 제시해줍니다.

 

 위의 과정을 일반화해보면 다음과 같습니다(내용은 위의 예시와 동일하며, local gradient의 활용법에 집중하여 지켜봅시다). 순방향으로 계산해 나가서 z를 얻었습니다. local gradient값은 순방향으로 계산해 나가며 알 수 있으므로 이를 잘 기억해 둡니다. 이제 구해진 L(loss) 값을 가지고 역방향으로 계산해 나갑니다. 앞서 구해놓은 local gradient값과 global gradient(dL/dz)chain rule에 대입하여 gradient값을 계산해 나갈 수 있습니다.

 

 

 위의 내용을 이해했다면 다음의 예제도 어렵지 않게 풀 수 있습니다(조금 복잡하긴 하지만요). gate별로 어떻게 대입해야 하는지는 아래 나와있으니 적절히 대입만 해주면 뚝딱입니다.

 

 

 여기서 눈여겨보아야 할 점은 아래 그림의 파란색 네모 부분입니다. sigmoid function(활성화 함수)이라는 것을 활용하면 sigmoid gate라는 부분을 한 번에 계산할 수 있습니다(!!!).

*sigmoid gate와 같은 활성화 함수는 최종 값의 바로 앞에 위치해야 합니다.

 

 지금까지의 예제를 잘 헤쳐 나오셨다면, 위와 같은 몇 가지 특징을 눈치채셨을 수도 있습니다. 이를 잘 기억한다면 각 gate별로 굳이 계산을 하지 않아도 빠르게 미분값을 구할 수 있습니다. 

 


add gate : 이전 노드의 미분값을 배분합니다.

max gate : 이전 노드의 미분값을 큰 쪽에만 넘겨줍니다(작은 쪽은 0).

mul gate : 이전 노드의 미분값을 현재 노드의 값과 곱해 교환합니다.


 

 

 

 

 

요약하자면


NN(Neural Network)은 일일이 계산하기엔 너무 거대합니다. 따라서 역전파를 사용합니다.

Back propagation(역전파)는 모든 gradient(기울기, 미분값)를 계산하기 위한 알고리즘입니다.

forward pass : 순방향으로 진행하며 gate별 결과를 계산하고 local gradient를 메모리에 저장합니다.

backward pass : loss function의 gradient를 계산하기 위해 chain rule을 적용합니다.


 


해당 글은 스탠퍼드 대학의 CS231n(Convolutional Neural Networks for Visual Recognition)을 정리한 글임을 밝힙니다.