Story of CowHacker

딥러닝 3.4 신경망 학습 본문

공부/딥러닝

딥러닝 3.4 신경망 학습

Cow_Hacker 2020. 8. 13. 14:51
728x90

이번 글에서는 저번에 배웠던 기울기를 이제 신경망에서 구현해보겠다.

 

신경망에서 말하는 기울기는 가중치 매개변수에 대한 손실 함수의 기울기다.

 

예를 들어 2 x 3 인 형상에서

가중치가 W, 손실 함수가 L인 신경망을 생각해보면

 

그림1

가중치 W를 수식으로 나타내면 그림 1이 된다.

 

 

 

 

 

그림2

그림 2는 경사를 수식으로 나타 냈을 때다.

 

해석해보면 각 원소는 각각의 원소에 관한 편미분이다.

예를 들어 1 행 1 번째 원소는 w11을 조금 변경했을 때 손실 함수 L이 얼마나 변화하느냐를 나타낸다.

 

여기서 중요한 점은 그림 2의 형상이 W와 같다는 것이다.

 

이제 한번 신경망에서 기울기를 구하는 코드를 짜 보겠다.

 

 

 

 

 

 

신경망에서의 기울기 코드

 

import sys, os

sys.path.append(os.pardir)  # 부모 디렉터리의 파일을 가져올 수 있도록 설정

import numpy as num

from common.functions import softmax, cross_entropy_error

from common.gradient import numerical_gradient



class simpleNet:

    def __init__( self ) :

        self.W = num.random.randn ( 2,3 ) # 정규분포로 초기화

 

    def predict ( self, x ) :

        return num.dot ( x, self.W )

 

    def loss ( self, x, t ) :

        z = self.predict ( x )

        y = softmax ( z )

        loss = cross_entropy_error ( y, t )

 

        return loss

 

코드 해석을 해보겠다.

 

simpleNet 클래스는 형상이 2 x 3인 가중치 매개변수 하나를 인스턴스 변수로 갖는다.

밑에 메서드는 2개가 있다.

predict 함수는 예측 값 구하기를 수행한다.

loss 함수는 손실 함수의 값 구하기를 수행한다.

 

여기서 인수 x는 입력 데이터, t는 정답 레이블이다.

 

이제 한번 가중치 매게 변수를 구해 보겠다.

 

 

 

 

 

가중치 매개변수 코드

 

import sys, os

sys.path.append(os.pardir)  # 부모 디렉터리의 파일을 가져올 수 있도록 설정

import numpy as num

from common.functions import softmax, cross_entropy_error

from common.gradient import numerical_gradient



class simpleNet:

    def __init__( self ):

        self.W = num.random.randn ( 2,3 ) # 정규분포로 초기화

 

    def predict ( self, x ) :

        return num.dot ( x, self.W )

 

    def loss ( self, x, t ) :

        z = self.predict ( x )

        y = softmax ( z )

        loss = cross_entropy_error ( y, t )

 

        return loss

 

net = simpleNet()

print ( net.W )

 

다음은 최댓값의 인덱스 구하기 코드를 짜 보겠다.

 

 

 

 

 

최댓값 인덱스 구하는 코드

 

import sys, os

sys.path.append ( os.pardir )

import numpy as num

from common.functions import softmax, cross_entropy_error

from common.gradient import numerical_gradient

 

 

class simpleNet:

    def __init__( self ):

        self.W = num.random.randn ( 2,3 ) # 정규분포로 초기화

 

    def predict ( self, x ) :

        return num.dot ( x, self.W )

 

    def loss ( self, x, t ) :

        z = self.predict ( x )

        y = softmax ( z )

        loss = cross_entropy_error ( y, t )

 

        return loss

 

net = simpleNet()

 

x = num.array ( [ 0.6, 0.9 ] )

p = net.predict ( x )

print ( num.argmax ( p ) )

 

다음은 정답 레이블을 구하는 코드를 짜 보겠다.

 

 

 

 

 

정답 레이블 코드

 

import sys, os

sys.path.append ( os.pardir )

import numpy as num

from common.functions import softmax, cross_entropy_error

from common.gradient import numerical_gradient

 

class simpleNet:

    def __init__( self ):

        self.W = num.random.randn ( 2,3 ) # 정규분포로 초기화

 

    def predict ( self, x ) :

        return num.dot ( x, self.W )

 

    def loss ( self, x, t ) :

        z = self.predict ( x )

        y = softmax ( z )

        loss = cross_entropy_error ( y, t )

 

        return loss

 

net = simpleNet()

x = num.array ( [ 0.6, 0.9 ] )

p = net.predict ( x )

 

t = num.array ( [ 0, 0, 1 ] )

print ( net.loss ( x, t ) )

 

 

 

이제 마지막으로 기울기를 구하는 코드를 짜 보겠다.

 

 

 

 

 

 

기울기 구하는 코드

 

import sys, os

sys.path.append(os.pardir)  # 부모 디렉터리의 파일을 가져올 수 있도록 설정

import numpy as num

from common.functions import softmax, cross_entropy_error

from common.gradient import numerical_gradient



class simpleNet:

    def __init__( self ):

        self.W = num.random.randn ( 2,3 ) # 정규분포로 초기화

 

    def predict ( self, x ) :

        return num.dot ( x, self.W )

 

    def loss ( self, x, t ) :

        z = self.predict ( x )

        y = softmax ( z )

        loss = cross_entropy_error ( y, t )

 

        return loss

 

net = simpleNet()

 

x = num.array ( [ 0.6, 0.9 ] )

t = num.array ( [ 0, 0, 1 ] )

 

def f ( W ):

    return net.loss ( x, t )

 

dW = numerical_gradient ( f, net.W )

print ( dW )

 

 

앞에서 numerical_gradient ( f, x )를 언급했었는데,

인수 f는 함수이고, x는 함수 f의 인수다.

위 코드에서는 net.W를 인수로 받아 손실 함수를 계산하는 새로운 함수 f를 썼다.

그리고 새로 정의한 함수를 numerical_gradient ( f, x )에 넘긴다.

 

dW는 numerical_gradient ( f, net.W )의 결과 값이다.

 

기울기를 구하는 코드를 람다를 사용해서 구현해볼 수도 있다.

 

 

람다를 사용한 기울기 구하기 코드

 

import sys, os

sys.path.append(os.pardir)  # 부모 디렉터리의 파일을 가져올 수 있도록 설정

import numpy as num

from common.functions import softmax, cross_entropy_error

from common.gradient import numerical_gradient



class simpleNet:

    def __init__( self ):

        self.W = num.random.randn ( 2,3 ) # 정규분포로 초기화

 

    def predict ( self, x ) :

        return num.dot ( x, self.W )

 

    def loss ( self, x, t ) :

        z = self.predict ( x )

        y = softmax ( z )

        loss = cross_entropy_error ( y, t )

 

        return loss

 

net = simpleNet()

 

x = num.array ( [ 0.6, 0.9 ] )

t = num.array ( [ 0, 0, 1 ] )



f = lambda w : net.loss ( x, t )

dW = numerical_gradient ( f, net.W )

print ( dW )

 

이까지 신경망에서 기울기 구하는 것을 파이썬으로 구현해보았다.

 

 

 

728x90

'공부 > 딥러닝' 카테고리의 다른 글

딥러닝 4.0 오차역전파법  (0) 2020.08.16
딥러닝 3.5 신경망 학습  (0) 2020.08.14
딥러닝 3.3 신경망 학습  (0) 2020.08.13
딥러닝 3.2 신경망 학습  (0) 2020.08.13
딥러닝 3.1 신경망 학습  (0) 2020.08.12
Comments