1. 아나콘다 설치

링크주소 (2020.02.27 기준) : https://www.anaconda.com/distribution/#download-section

 

Anaconda Python/R Distribution - Free Download

Anaconda Distribution is the world's most popular Python data science platform. Download the free version to access over 1500 data science packages and manage libraries and dependencies with Conda.

www.anaconda.com

 

(1) python 3.7 version - 64bit 설치

(2) 설치도중  나오는 아래 화면에서 첫번째 체크박스 선택

 (3) 설치완료 후 정상설치 확인

 

 

아나콘다 프롬프트 관리자모드로 실행

python --version 입력하여 설치된 파이썬 버전확인되면 정상설치

 

pip list 입력하여 아나콘다를 통해 설치된 라이브러리 리스트 확인가능

2. tensorflow 설치 (아나콘다는 텐서플로우는 자동설치 안됨)

 

pip install tensorflow 명령을 사용하면 tensorflow 2.1이 설치되지만 실제 사용하기 위해 소스코드에서 

import tensorflow 를 하게되면 아래와 같은 에러발생

"ImportError: DLL load failed: 지정된 모듈을 찾을 수 없습니다"

이런 이유때문에 pip install tensorflow==2.0 명령으로 tensorflow 2.0 버전 설치 (왜 에러가 나지 않는지 이유는 파악 안되었음)

 

3. Visual Studio Code 설치

링크주소(2020.02.27 기준) : https://code.visualstudio.com/download

 

Download Visual Studio Code - Mac, Linux, Windows

Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows. Download Visual Studio Code to experience a redefined code editor, optimized for building and debugging modern web and cloud applications.

code.visualstudio.com

User Installer 64bit (현재 윈도우 계정 사용자만 사용)또는 System Installer 64bit(모든 사용자 사용) 다운받아 설치

 

4. 설치완료 후 vscode 실행

위 그림처럼 python , python for vscode, python extension pack 설치

위 그림처럼 Code Runner 설치

 

 

 

 

(* DeepLearning from scratch2 서적을 학습한 후 정리한 내용임 )

역전파(back-propagation)를 살펴보기 전에 "계산 그래프"를 설명한다.

 

덧셈노드

위 그림은 z = x + y 식을 계산 그래프로 나타낸 것이다.

연산자 + 는 노드로 표시하고 입력과 출력을 화살표로 나타낸다.

계산그래프의 장점은 계산과정을 시각적으로 파악할 수 있다.

계산 그래프에서 연산자를 이용한 정상적인 계산 흐름을 순전파라고 한다.

역전파는 정상계산 흐름의 반대방향으로 흘러간다.

 

역전파 상황을 좀 더 자세히 살펴보기 위해 예를들어 설명한다.

z = x + y 계산 과정의 이전과 이후에 어떤 계산과정이 있다고 가정한다. 그리고 최종적으로는 스칼라 값인 L이 출력된다고 가정한다.

이 상황을 계산 그래프로 그리면 다음과 같다. 검은색 화살표가 순전파, 푸른색 화살표가 역전파를 나타낸다.

 

∂L/x 은 x가 L에 미치는 영향을 의미한다

x와 L 사이에는 복잡한 합성함수들이 들어있어 직접적으로 미분이 어려운 상황이다. 이런 경우 바로 앞절에서 언급한 연쇄법칙을 활용하여 계산한다

즉, 

∂L/∂x = ∂L/∂z * ∂z/∂x

여기서 ∂z/∂x 는 z = x + y 공식에서 계산이 가능하다.

 ∂z/∂x = 1

따라서,

∂L/∂x = ∂L/∂z * 1 이 된다.

 

∂L/∂y = ∂L/∂z * ∂z/∂y

∂z/∂y 는 z = x + y 공식에서 계산이 가능하다.

∂z/∂y = 1

따라서,

∂L/∂y = ∂L/∂z * 1 이 된다.

 

이 결과를 적용하면 역전파에서 덧셈노드는 상류로 부터 받은 미분값을 그대로 흘려보낸다.

 

계산 그래프를 구축하는 연산 노드로는 덧셈노드 외에 다양한 연산을 생각할 수 있다.

대표적인 연산노드 몇 가지를 소개한다

 

곱셈노드

z = x × y 를 계산그래프로 표현해보면 다음과 같다.

검은색 화살표는 순전파를 의미하며 푸른색 화살표는 역전파를 의미한다.

z = x × y 에 대해서 ∂L/∂x 값을 연쇄법칙을 이용하여 다음과 같이 정리할 수 있다.

z = x × y 에서 ∂z/∂x를 계산하면 

 

이 결과를 ∂L/∂x 공식에 대입하면 다음과 같다.

같은 방식으로 ∂L/∂y 에 대해 계산하면 결과는 다음과 같다.

결과적으로 곱셈노드의 역전파는 상류로부터 받은 기울기에 순전파시 입력을 서로 바꾼 값을 곱한다

 

분기노드

 

 

분기노드는 노드표시 원을 그리지 않고 선이 나뉘도록 그린다. 분기전의 입력값이 분기하면서 같은 값들이 복사되는 특징이 있다. 이런 이유때문에 "복제노드" 라고도 한다.

 

분기노드의 역전파는 위 그림에서 푸른색 화살표로 나타내고 있다.

상류에서 전달되어 온 미분값들을 하류로 흘러보낼 때 미분값(기울기)들을 합산하게 된다.

 

Repeat 노드

 

위의 2개로 분기하는 분기노드를 N개로의 분기로 확장할 수 있으며 이것을 "Repeat 노드" 라고 한다.

 

길이가 D인 배열을 N개로 복제하는 예

 

길이가 D인 배열을 N개 복제하는 Repeat 노드의 순전파

 

해당 그래프의 역전파는 아래와 같다.

 

길이가 D인 배열을 N개 복제하는 Repeat 노드의 역전분기

 

앞의 분기노드에서 설명했듯이 상류에서 흘러온 N개의 미분값(기울기)를 합산하여 하류로 흘려보낸다.

 

MatMul 노드

 

행렬의 곱셈을 MatMul(Maxtrix Multiply) 노드로 표현한다.

 

y = xW 라는 행렬곱셈 계산식을 생각해보자.

여기서 각 행렬의 형상은 다음과 같다.

x : 1 × D,  W : D × H,  y : 1 × H

 

x행렬의 i번째 원소에 대한 미분 ∂L/∂xi 는 다음과 같다.

이것은 xi를 (조금)변화시켰을 때 L이 얼마나 변할 것인가라는 "변화의 정도"를 나타낸다.

위 식이 나오게 된 과정을 좀 더 살펴보자.

각 행렬의 크기가 다음과 같다.

x : 1 × D,  W : D × H,  y : 1 × H 

여기서 

위 식에서 알 수 있듯이 xi는  y행렬의 모든 원소에 영향을 주고 있다.

 

(* DeepLearning from scratch2 서적을 학습한 후 정리한 내용임 )

 

신경망은 학습과정을 거쳐 손실값을 얻어낼 수 있다.

얻어진 손실값을 이용해 학습과정에 사용된 가중치 행렬의 기울기를 계산해낸다.

그리고 그 기울기를 이용해 가중치 각 원소값들을 조정한 후 학습을 진행한다. 그 결과로 나온 손실값을 이용해 기울기 계산을 하고 가중치 값을 조정한 후 다시 학습과정을 거친다. 이런 과정들을 반복하여 손실값을 줄여나가는 방향으로 가중치 값들을 최적화한다.

 

앞 절까지 과정에서 손실값을 얻어낼 수 있었다.

이제 가중치 행렬의 기울기를 계산해낼 차례다.

 

기울기를 계산하기 위해 오차역전파법(back - propagation)을 사용하게 된다.

오차역전파법의 핵심은 연쇄법칙이다.

 

예를 들어 연쇄법칙을 설명한다.

y = f(x) 와  z = g(y) 라는 두 함수가 있다고 가정한다.

z = g( f(x) ) 가 된다.

이 합성함수의 미분(x에 대한 z의 미분)은 다음의 공식이 된다.

 

즉 y에 대한 z 미분값과 x에 대한 y 미분값을 곱하면 x에 대한 z 미분값이 된다.

 

정리하면, 위의 가정이 조건으로 주어진 경우에 대해, 

x가 z에 미치는 영향도를 계산하기 위해서는 y에 대한 z 미분값과 x에 대한 y 미분값을 곱하면 된다.

 

이 법칙을 이용하게 되면 학습 과정이 합성함수들로 복잡하게 구성되어 있더라도 개별과정의 함수들을 미분한 값을 곱하면 전체 과정의 미분을 구할 수 있다.

 

 

(* DeepLearning from scratch2 서적을 학습한 후 정리한 내용임 )

 

y = f(x) 함수에서 "x에  관한 y의 미분"은 "∂y/x"라고 표현한다.

"x에 대한 y의 미분"은 "x를 조금 변화 시킬 때 y값이 변화하는 정도"를 의미한다. 또는 "y에 대한 x의 영향도" 를 의미한다. 수학적으로 보면 x의 임의의 위치에 대한 기울기를 의미하기도 한다.

L = f(x), L은 스칼라 값, x는 벡터인 경우 ,

x의 i번째 원소  xi 에 대한 L의 미분은 L / xi 이다.

따라서, 벡터 X에 대한 미분도 가능한다.

 

  L / x = (L/x1, L/x2, L/x3, .... L/xn)

 

위의 식처럼 벡터의 각 원소에 대한 미분을 정리한 것을 기울기라고 한다.

 

행렬에도 기울기를 생각할 수 있다.

W 가 m × n 행렬인 경우 L = g(W) 공식에 대한 미분 즉 기울기는 다음과 같다.

 

여기서 중요한 것은 W 와  L / W의 형상이 같다는 것이다.

즉  임의의 행렬 형상과 해당 행렬을 미분한 기울기 행렬의 형상이 같다

 

 

 

 

 

 

(* DeepLearning from scratch2 서적을 학습한 후 정리한 내용임 )

 

일반적으로 학습단계의 특정 시점에서 신경망의 성능을 나타내는 척도로 손실(loss)을 사용한다.

손실은 학습시 주어진 정답 데이터와 신경망이 예측한 결과를 비교하여 예측이 얼마나 나쁜가를 산출한 단일값이다.

 

다중 클래스 분류 신경망에서는 손실을 구하는 함수로 교차 엔트로피 오차(Cross Entropy Error)를 이용한다

앞 절에서 이야기 된 TwoLayerNet 모델에 SoftMax계층(SoftMax함수처리계층)과 Cross EntropyError계층(SoftMax처리결과와 정답데이터를 이용해 Cross Entropy Error를 계산하는 계층)을 추가한다.

 

추가된 계층을 포함한 구조도는 아래와 같다.

X는 입력 데이터, t는 정답 레이블, L은 손실을 의미한다.

 

소프트맥스 함수 공식은 다음과 같다.

위 식은 출력이 총 n개일 때, k번째 출력 Sk를 구하는 식이다. 즉, Sk는 k번째 클래스에 해당하는 소프트맥스 함수의 출력이다.

소프트맥스 함수 결과는 0.0이상 1.0 이하의 값을 가지는 실수이며 모든 출력들 n개의 S값을 합하면 1.0이 된다. 따라서 소프트맥스 함수 결과값을 확률로 해석할 수 있다.

 

손실값을 얻기 위해서는 소프트맥스 함수의 결과값을 입력으로 하여  Cross Entropy Error 함수 계산을 해야 한다.

공식은 아래와 같다.

여기서 tk는 k번째 클래스에 해당하는 정답레이블이다. log는 e를 밑으로 하는 로그이다.

또한 정답레이블은 t = [0, 0, 1]과 같은 원핫 벡터로 표기한다.

 

원핫벡터란 단 하나의 원소만 1이고 나머지 원소들은 모두 0인 벡터를 의미한다.

보통 신경망이 추론 결과가 숫자가 아닌 경우 결과로 나올 수 있는 모든 경우의 결과 개수만큼을 원소 개수로 가지는 벡터를 구성하고 각 경우의 결과와 매칭하여 원소 하나만 1로 하고 나머지는 0으로 하는 벡터를 구성한다. 이런 방식으로 구성된 벡터를 원핫벡터라고 한다. 예를 들면 결과값이 a, e, g, z 알파벳 4개 중 하나를 추론 해야 하는 신경망을 구성한다고 할 경우 결과 개수는 4개 (클래스 개수가 4개) 이므로 원소 개수가 4인 벡터를 구성하되 각 알파벳과 매칭되는 벡터들을 구성한다.

즉,

a = [1, 0, 0, 0]

e = [0, 1, 0, 0]

g = [0, 0, 1, 0]

z = [0, 0, 0, 1]

이렇게 구성된 벡터들을 원핫벡터(one hot vector)라고 하고 이런 처리 방식을 원핫 인코딩(one hot encoding) 이라고 한다

위의 Cross Entropy Error 공식을 입력 데이터가 N개 인 경우로 확장시키면 아래의 공식으로 구성할 수 있다.

여기서 tnk는 n번째 입력데이터에 대한 k번째 클래스 정답 원핫벡터를 의미한다

ynk는 n번째 입력데이터를 이용해 신경망 학습한 결과로 SoftMax 함수계산과정을 거쳐 나온 결과의 k번째 결과이다

 

N개의 입력데이터를 이용한 Cross Entropy Error 공식은 결국 각각의 입력 데이터에 대한 손실함수 결과를 N개만큼 합산하여 N으로 나눠 평균낸 것이다.

 

이 과정을 파이썬으로 구현할 때 Softmax with Loss 계층 하나로 구현한다.

 

앞의 신경망 추론 과정을 파이선과 넘파이를 이용해 구현해보자

가중치와 편향을 이용해 결과값을 도출하는 과정을 Affine(아핀) layer라고 정의한다
Affine layer 과정에서 나온 결과값을 Sigmoid 함수를 이용해 비선형화 하는 것을 Sigmoid layer라고 정의한다
앞에서 설명된 신경망 추론과정과 그에 매칭시켜 구현하기 위한 구성도는 아래와 같다.

구현 규칙 : 

파이썬을 이용해 위 모델을 구현시 Affine, Sigmoid 모두 클래스로 구현할 것이며 

각 클래스는 params, grads 속성을 갖도록 한다

params는 가중치 행렬과 편향행렬을 저장한다, 

grads는 params에 저장된 각 행렬에 대응되는 기울기(미분)행렬을 저장

각 클래스는 신경망 추론, 학습과정을 위해 대표 함수 forward를 제작하여 제공하도록 한다.

 

Affine layer 클래스 구현소스

class Affine:

       def __init__(self, W, b):

            self.params = [W, b]

 

       def forward(self, x):

            W, b = self.params

            out = np.matmul(x, W) + b

            return out

 

Sigmoid layer 클래스 구현소스

class Sigmoid:

       def __init__(self):

            self.params = []

 

       def forward(self, x):

            return 1 / (1 + np.exp(-x))

 

이제 신경망의 기본이 되는 위 두개 클래스 Affine과 Sigmoid를 이용하여 신경망 추론을 모델링한 클래스를 제작한다

이름은 TwoLayerNet 으로 한다

class TwoLayerNet:

 

        #클래스 생성자에서 입력층, 은닉층, 출력층의 행렬 사이즈를 입력받고 가중치, 편향 초기화

        #Layer들을 구성하여 params 속성에 가중치, 편향 행렬을 저장한다

       def __init__(self, input_size, hidden_size, output_size):

            I, H, O = input_size, hidden_size, output_size;

 

           #가중치와 편향 초기화

            Wh = np.random.randn(I, H)

            bh  = np.random.randn(H)

            Wy = np.random.randn(H, O)

            by  = np.random.randn(O)

 

            #계층 생성(위 구성도 기준으로 구현)

            self.layers = [

                    Affine(Wh, bh),

                    Sigmoid(),

                    Affine(Wy, by)

            ]

            #모든 가중치를 리스트에 모은다

            self.params = []

            for layer in self.layers:

                self.params += layer.params

 

     def predict(self, x):

          for layer in self.layers:

              x = layer.forword(x)

              return x

 

 

(* DeepLearning from scratch2 서적을 학습한 후 정리한 내용임 )

1.2.1 신경망 추론 전체 그림

2개 데이터를 입력하여 3개 데이터를 결과로 출력하는 신경망 구현을 가정합니다.

3개의 층으로 구현됩니다.

(1) 입력층 : 2개의 뉴런으로 구성

(2) 은닉층 : 4개의 뉴런으로 구성

(3) 출력층 : 3개의 뉴런으로 구성

(* 3개의 층으로 구성되어 있지만 가중치를 지니고 있는 층은 입력층과 은닉층 사이, 은닉층과 출력층 사이 2개 이므로 이 책에서는 이 모델을 "2층 신경망" 이라고 부릅니다. )

 

위의 그림에서 원은 뉴런을 의미한다.

x1, x2:입력값

Wh11, Wh12,Wh13, Wh14 : X1값이 은닉층 4개의 뉴런에 영향을 주는 가중치값

Wh21, Wh22,Wh23, Wh24 : X2값이 은닉층 4개의 뉴런에 영향을 주는 가중치값

h1, h2, h3, h4 :  x1, x2 입력값이 가중치에 따라 은닉층 4개의 뉴런에 전달된 값

Wy11, Wy12, Wy13 : h1값이 출력층 3개의 뉴런에 영향을 주는 가중치값

Wy21, Wy22, Wy23 : h2값이 출력층 3개의 뉴런에 영향을 주는 가중치값

Wy31, Wy32, Wy33 : h3값이 출력층 3개의 뉴런에 영향을 주는 가중치값

Wy41, Wy42, Wy43 : h4값이 출력층 3개의 뉴런에 영향을 주는 가중치값

y1, y2, y3 : h1, h2, h3, h4 히든층 뉴런값으로 부터 가중치에 따라 출력층 3개의 뉴런에 전달된 값

 

은닉층의 4개 뉴런값을 수식으로 정리하면 다음과 같다

h1 = X1 * Wh11 + X2 * Wh21 + bh1

h2 = X1 * Wh12 + X2 * Wh22 + bh2

h3 = X1 * Wh13 + X2 * Wh23 + bh3

h4 = X1 * Wh14 + X2 * Wh24 + bh4

 

위 공식을 행렬 곱으로 표현하면 다음과 같다.

[ X1  X2] * [Wh11  Wh12   Wh13   Wh14]   + [ bh1  bh2  bh3  bh4 ] =  [ h1  h2  h3  h4]

                    [Wh21  Wh22   Wh23   Wh24]

 

위 행렬 곱 공식에서 각 행렬을 간소화하면 다음과 같다

 

X * Wh + bh = h

(이후 행렬을 간소화해서 알파벳으로 표현할 때는 굵은 글씨체 사용)

 

행렬 곱 연산이 정상처리되려면 각 행렬의 형태가 규칙에 맞아야 한다. 즉, 행렬 곱 연산자 좌측행렬의 열 개수와 우측행렬의 행 개수가 같아야 한다

 

위의 간소화 공식에서 X 행렬은 1 * 2  (행 개수가 1개 , 열 개수가 2개 의미)

                                   Wh 행렬은 2 * 4 (행 개수가 2개, 열 개수가 4개 의미)

                                    bh 행렬은 1 * 4 (행 개수가 1개, 열 개수가 4개 의미)

                                     결과 행렬인 h 행렬은 1 * 4 (행 개수가 1개, 열 개수가 4개 의미)

 

위 행렬 형태는 입력데이터가 (X1, X2) 한 개인 경우이고 보통 복수 개(N개)의 데이터를 준비한 경우 반복적으로 미니 배치 형식으로 학습을 시키게 되므로 실제 학습진행 시 행렬 형태는 아래와 같게 된다.

X (N × 2) * Wh (2 × 4) + bh( N × 4) = h(N × 4)

 

신경망은 사람의 뇌에서  뉴런으로 전기신호가 전달되는 과정을 모델링 한 것이다.

뉴런으로 전기신호가 전달 될 때 어느 크기 이상이 되어야 다음 뉴런으로 전달되게 되는 특성이 있다.

이를 신경망으로 구현하려면 비선형 함수가 추가되어야 한다. 이 비선형함수를 활성화함수라고 하며 여러 종류의 활성화함수 중에서 쉬운 Sigmoid 함수를 사용한다. 임의의 실수를 입력받아 0에서 1사이의 실수를 출력한다.

파이썬으로 구현해보면

def  sigmiod(x):

      return 1 / (1 + np.exp(-x))

 

 

+ Recent posts