본문 바로가기

deeplearning

4장. 인공 신경망을 학습시킴(손실(오차)함수, 수치 미분, 경사하강법, 학습 알고리즘 구현)

728x90
반응형

3장까지의 전체 코드:

 

import sys, os

sys.path.append(os.pardir)

import numpy as np

from dataset.mnist import load_mnist

from PIL import Image

import  pickle

import  numpy  as np

 

# 신경망 함수들

def sigmoid(num):

    rst = (1 / (1 + np.exp(-num)))

    return (rst)

 

 

def identity_function(x):

    return x

 

 

def softmax(a):

    c = np.max(a)

    minus = a - c

    exp_a = np.exp(minus)

    sum_exp_a = np.sum(exp_a)

    y = exp_a / sum_exp_a

    return y

 

def  init_network():

    with open("C:\\Users\itwill\sample_weight\sample_weight.pkl",'rb')  as  f:

        network = pickle.load(f)

    return  network

 

 

def  predict(network, x):

    W1, W2, W3 = network['W1'], network['W2'], network['W3']

    b1, b2, b3 = network['b1'], network['b2'], network['b3']

 

    a1 = np.dot(x,W1) + b1

    z1 = sigmoid(a1)

    a2 = np.dot(z1,W2) + b2

    z2 = sigmoid(a2)

    a3 = np.dot(z2,W3) + b3

    y = softmax(a3)

    return  y

 

def  get_data():

    (x_train, t_train) , (x_test, t_test) = \

    load_mnist(normalize=True, flatten=True, one_hot_label=False)

    return  x_test, t_test

 

##############################################################

x, t = get_data()

network = init_network()

 

 

batch_size = 100

 

result = 0

for i in range(0,len(x),batch_size):

   

    x_batch = x[i:i+batch_size]  

    y = predict(network, x_batch)

    p = np.argmax(y,axis=1)   #예상값

    #print(p)

   

    t_batch = t[i:i+batch_size]    #실제값 (t 라벨. 이미 최대값 뽑아서 나온 실제답임)

   

    result += np.sum( p==t_batch )

 

print("정확도:",result/len(x))

정확도: 0.9352

 

 

 

 

 

 

4. 신경망 학습

 

앞장에서는 저자가 만들어온 가중치값을 가지고 신경망을 구성했기 때문에

신경망을 학습 시킬 필요가 없었다.

 

 

필기체 7 ----------------> 신경망 --------------------> 예측값 == 실제값

                                                                               

          저자가 만들어 가중치값 세팅                         정확도

 

4장에서는 우리가 직접 신경망을 학습 시킬 인데

학습을 시키기 위해서 알아야 하는 내용?

 

1. 오차함수

 

2. 가중치를 갱신하는 방법(수치 미분)

"경사법에서는 기울기(경사)값을 기준으로 나아갈 방향 결정."

"함수 f(x)의 x에 대한 미분값을 수치해석으로 구하기"

"x의 차수를 끌어내려와 연산시켜줌"

 

3. 미니배치 (mini batch)

 

 

 

 

 

오차함수

 

" 예상값과 실제값과의 오차를 신경망에 역전파 시켜주기 위해서

 필요한 함수 "

 

오차가 최소화 때까지 신경망을 학습시키기 위해서 필요한 함수

 

1. 평균제곱 오차함수        : 회귀분석을 일반적으로 사용

2. 교차 엔트로피 오차함수 : 분류문제를 사용

 

 

                                         출력층 함수            오차 함수

회귀문제를 해결할 ------>   항등 함수              평균제곱 오차함수

 

분류문제 해결할 ------>   소프트맥스 함수     교차 엔트로피 함수

 

 

 

p.112

■ 평균제곱 오차함수

 

 

y 예상값

t 실제값(라벨값)

k 차원

 

1/2곱해주는 이유는 미분시키면 2값이 나오는데, 군더더기를 없애주려고

1/2 곱하는 것이다.

아직 식에서는 평균낸거 아님.

 

 

문제141.

위의 식을 가지고 평균제곱 오차함수 파이썬으로 구현하시오

 

import numpy as np

def mean_squared_error(y,t):

    return 0.5 * np.sum( ( y-t)**2 )

 

t = [0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0]

y = [0.1 , 0.05 , 0.6 , 0.0 , 0.05 , 0.1 , 0.0 , 0.1 , 0.0 , 0.0]

 

# t (-핫코딩 시킨)실제값, y예상값 인데, mnist 의 숫자 2에서

# y 가장 큰값을, t 1을 나타내는 걸 볼 수 있다.

 

print( mean_squared_error( np.array( y ) , np.array( t ) ) )

0.0975

 

0.0975 오차를 신경망으로 역전파 시켜서 가중치(w) 갱신한다.

 

 

 

 

 

문제142.

아래의 확률벡터를 평균제곱오차 함수를 이용해서

target(실제값) 예측값의 오차율이 어떻게 되는지

for loop 문으로 한번에 알아내시오

 

import numpy as np

 

def mean_squared_error(y,t):

   

    for i in y:

        print (0.5 * np.sum( ( i-t )**2))

 

t = [0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0]

y = [

     [0.1,0.05,0.1,0.0,0.05,0.1,0.0,0.1,0.0,0.0], 

 [0.1,0.05,0.2,0.0,0.05,0.1,0.0,0.6,0.0,0.0],

 [0.0,0.05,0.3,0.0,0.05,0.1,0.0,0.6,0.0,0.0],

 [0.0,0.05,0.4,0.0,0.05,0.0,0.0,0.5,0.0,0.0],

 [0.0,0.05,0.5,0.0,0.05,0.0,0.0,0.4,0.0,0.0],

 [0.0,0.05,0.6,0.0,0.05,0.0,0.0,0.3,0.0,0.0],

 [0.0,0.05,0.7,0.0,0.05,0.0,0.0,0.2,0.0,0.0],

 [0.0,0.1,0.8,0.0,0.1,0.0,0.0,0.2,0.0,0.0],

 [0.0,0.05,0.9,0.0,0.05,0.0,0.0,0.0,0.0,0.0]

 ]

 

# t (-핫코딩 시킨)실제값, y가 예상값 인데, mnist 의 숫자 2에서

# y 가장 큰값을, t 1을 나타내는 걸 볼 수 있다.

mean_squared_error( np.array( y ) , np.array( t ) )

 

==========================================

 

import numpy as np

 

def mean_squared_error(y,t):

   

    return 0.5 * np.sum( ( y-t )**2)

 

#print(mean_squared_error( np.array( y ) , np.array( t ) ) )

 

t = [0,0,1,0,0,0,0,0,0,0]    # 숫자2

 

y1 = [0.1,0.05,0.1,0.0,0.05,0.1,0.0,0.1,0.0,0.0] 

y2 = [0.1,0.05,0.2,0.0,0.05,0.1,0.0,0.6,0.0,0.0]

y3 = [0.0,0.05,0.3,0.0,0.05,0.1,0.0,0.6,0.0,0.0]

y4 = [0.0,0.05,0.4,0.0,0.05,0.0,0.0,0.5,0.0,0.0]

y5 = [0.0,0.05,0.5,0.0,0.05,0.0,0.0,0.4,0.0,0.0]

y6 = [0.0,0.05,0.6,0.0,0.05,0.0,0.0,0.3,0.0,0.0]

y7 = [0.0,0.05,0.7,0.0,0.05,0.0,0.0,0.2,0.0,0.0]

y8 = [0.0,0.1,0.8,0.0,0.1,0.0,0.0,0.2,0.0,0.0]

y9 = [0.0,0.05,0.9,0.0,0.05,0.0,0.0,0.0,0.0,0.0]

 

y=np.array([y1,y2,y3,y4,y5,y6,y7,y8,y9])

#print(y)

 

for i in range(len(y)):

    print ( "y"+str(i+1)+" 오차율:" , ( mean_squared_error( y[i] , np.array(t) ))*100, "%" )

 

y1 오차율: 42.25 %

y2 오차율: 51.25 %

y3 오차율: 43.25 %

y4 오차율: 30.75 %

y5 오차율: 20.75 %

y6 오차율: 12.75 %

y7 오차율: 6.75 %

y8 오차율: 5.0 %

y9 오차율: 0.75 %

 

 

 

 

 

2. 교차 엔트로피 오차 함수

 

수식 : 4.2

 

t = 실제값

y = 예상값 log 씌움 (log를 안씌우면 순식간에 큰값이 되버림)

 

t 1값이

y 가장 값이랑 매칭된다.

 

 

 

문제143.

확률0.1 확률 0.9 교차 엔트로피 공식에 대입한 결과가

각각 어떻게 되는지 확인하시오 !

 

import numpy as np

 

print(-np.log( 0.1), -np.log( 0.9))

#0.9 90% 확률로 오차를 알려주는 것이고

 0.1 10% 확률로 오차를 알려주는 것이다.

 

2.30258509299 0.105360515658

확률 : 0.1        확률 : 0.9

오차 : 2.3        오차 : 0.1

결과를 보면

0.9 돌린 값이 훨씬 작다.

 

 

설명: p.114  자연로그 y = logx 그래프

x 축이 확률

y 축이 오차

 

 

 

***-log 그래프

 

화면 캡처: 2019-01-16 오후 5:28

 

 

 

 

 

문제144.

교차 엔트로피 함수를 생성하시오 (p.115)

 

def cross_entropy_error(y,t):

    import numpy as np

    delta = 1e-7   #log=0 에러나서 y에 델타를 더해주기 위함이다.

    return -np.sum( t * np.log(y + delta ) )

 

설명:

delta 더하는 이유는 np.log() 함수에 0 입력하면

마이너스 무한대를 뜻하는 -inf 되어

이상 계산을 진행할 없기 때문에

아주 작은값인 0.0000001(=1e-7) 더해주는 것이다.

 

 

import numpy as np

t = [0,0,1,0,0,0,0,0,0,0]    # 숫자2

y = [0.1 , 0.05 , 0.6 , 0.0 , 0.05 , 0.1 , 0.0 , 0.1 , 0.0 , 0.0]

print( cross_entropy_error( np.array( y ) , np.array( t ) ) )

 

0.510825457099

 

 

 

 

문제145.

아래의 예측값(=y)으로 오차를 구했을 오차는 어떻게 되는가?

 

t = [0,0,1,0,0,0,0,0,0,0]  

y = [0.1 , 0.05 , 0.1 , 0.0 , 0.05 , 0.1 , 0.0 , 0.1 , 0.0 , 0.0]

*** t 자리 y 값을 0.1 바꿨다(위에는 0.6)

 

import numpy as np

t = [0,0,1,0,0,0,0,0,0,0]    # 숫자2

y = [0.1 , 0.05 , 0.1 , 0.0 , 0.05 , 0.1 , 0.0 , 0.1 , 0.0 , 0.0]

print( cross_entropy_error( np.array( y ) , np.array( t ) ) )

 

2.30258409299

 

문제144번의 답과 다르게 오차를 리턴해주고 있다.

 

 

 

문제146.(오늘의 마지막 문제)

평균제곱 오차함수와 교차엔트로피 오차함수중에

어떤것이 오차를 신경망에 역전파 시켜주겠는지

테스트 해보시오

 

t = [0,0,1,0,0,0,0,0,0,0]    # 실제값, mnist 숫자2

y1 = [0.1 , 0.05 , 0.6 , 0.0 , 0.05 , 0.1 , 0.0 , 0.1 , 0.0 , 0.0]  #예상값

y2 = [0.1 , 0.05 , 0.1 , 0.0 , 0.05 , 0.1 , 0.0 , 0.1 , 0.0 , 0.0]  #예상값

 

 

---교차엔트로피 오차함수:

확률: 0.6    오차: 0.51083

확률: 0.1    오차: 2.30258

 

def cross_entropy_error(y,t):

    import numpy as np

    delta = 1e-7   #log=0 에러나서 y에 델타를 더해주기 위함이다.

    return -np.sum( t * np.log(y + delta ) )

 

import numpy as np

t = [0,0,1,0,0,0,0,0,0,0]    # 숫자2

y1 = [0.1 , 0.05 , 0.6 , 0.0 , 0.05 , 0.1 , 0.0 , 0.1 , 0.0 , 0.0]

y2 = [0.1 , 0.05 , 0.1 , 0.0 , 0.05 , 0.1 , 0.0 , 0.1 , 0.0 , 0.0]

 

y = np.array([y1,y2])

 

for i in y:

    print( "확률:",i[np.argmax(i)], \

                   "   오차:", cross_entropy_error( np.array(i) , np.array(t) ).round(5) )

 

 

 

 

---평균제곱 오차함수:

확률: 0.6     오차: 0.0975

확률: 0.1     오차: 0.5975

 

import numpy as np

def mean_squared_error(y,t):   

    return 0.5 * np.sum( ( y-t )**2)

 

import numpy as np

t = [0,0,1,0,0,0,0,0,0,0]    # 숫자2

t_index = t.index(1)

y1 = [0.1 , 0.05 , 0.6 , 0.0 , 0.05 , 0.1 , 0.0 , 0.1 , 0.0 , 0.0]

y2 = [0.1 , 0.05 , 0.1 , 0.0 , 0.05 , 0.1 , 0.0 , 0.6 , 0.0 , 0.0]

y=np.array([y1,y2])

 

for i in y:

    print("확률:" ,i[t_index], \

          "    오차:" ,mean_squared_error( np.array(i), np.array(t) ).round(5) )

 

 

※설명:

y2 = [0.1 , 0.05 , 0.1 , 0.0 , 0.05 , 0.1 , 0.0 , 0.6 , 0.0 , 0.0]

#평균제곱 오차함수는 더해서 평균내는 오차함수법이라서

   y2 세번째 숫자와 8번째 숫자 자리를 서로 바꿔준다.

 

 

 

 

미니배치 (minibatch)학습  p.115

"훈련 데이터 중에 일부만 골라서 학습하는 방법"

"표본 뽑아서 학습 시킨다"

: 된장찌개의 맛을 확인하기 위해서 수저(=표본) 간을 본다

 

복원추출 이든 비복원추출 이든 mnist 경우 100장씩 배치처리 한다면

100장씩 600번을 훈련시키면 그게 1 epoch .

 

여러번 에폭이 반복되면서 비용함수(오차함수) global minima

찾아가게 된다.

 

설명:

복원 추출?    추출한 것을 다시 뽑을 있는 추출

비복원 추출? 추출한 것을 다시 뽑을 없는 추출

 

 

화면 캡처: 2019-01-17 오후 1:59

 

 

에폭?epoch

 

 

60000장을 100장씩 600 시키는게 1 에폭이다

그렇게 Global cost minimum 지점까지 가기위한 에폭을 찾는거다.

**600장씩 100번으로 돌리는 이유는 컴퓨터안전을 위해서.

 

1에폭 돌면 빨간화살표이 저렇게 이동한다.(=오차를 줄여나간다)

이렇게 n번의 에폭이 돌면 global minimum (최적의 가중치)

찾아낸다.

 

 

 

문제152.

1~60000개의 숫자중에 무작위로 10개를 출력하시오

 

import numpy as np

print( np.random.choice( np.arange(60000), 10 ) )

 

[11882 59774 18864 22356 16868 18575 50014 53451 44508 58383]

***코드실행할 때마다 값이 다르게 나온다.

[51835 20726  8898 42379 29605 49912 29791 19515  9947 38958]

 

[ 5119 26806 53424 27060  5161  4245 55450 47885 35941 49317]

 

[ 2154 49402 55745 31473  5705 14930  1449  4533 12439 58915]

 

[ 9058 57518 56537 27119 11089  3010 54576 31172 34541 53821]

 

[27876 27607  5783  9982 13193 25979   791 57308 29670 56173]

 

 

 

문제153.

mnist 테스트 데이터 10000 중에 랜덤으로 100장을 추출하는

코드를 작성하시오

(랜덤 추출이 + 복원추출: 출력랜덤값 제거 안했으니까)

 

import sys, os

sys.path.append(os.pardir)

import numpy as np

from dataset.mnist import load_mnist

from PIL import Image

import  pickle

import  numpy  as np

 

# 신경망 함수들

def sigmoid(num):

    rst = (1 / (1 + np.exp(-num)))

    return (rst)

 

 

def identity_function(x):

    return x

 

 

def softmax(a):

    c = np.max(a)

    minus = a - c

    exp_a = np.exp(minus)

    sum_exp_a = np.sum(exp_a)

    y = exp_a / sum_exp_a

    return y

 

def  init_network():

    with open("C:\\Users\itwill\sample_weight\sample_weight.pkl",'rb')  as  f:

        network = pickle.load(f)

    return  network

 

 

def  predict(network, x):

    W1, W2, W3 = network['W1'], network['W2'], network['W3']

    b1, b2, b3 = network['b1'], network['b2'], network['b3']

 

    a1 = np.dot(x,W1) + b1

    z1 = sigmoid(a1)

    a2 = np.dot(z1,W2) + b2

    z2 = sigmoid(a2)

    a3 = np.dot(z2,W3) + b3

    y = softmax(a3)

    return  y

 

def  get_data():

    (x_train, t_train) , (x_test, t_test) = \

    load_mnist(normalize=True, flatten=True, one_hot_label=False)

    return  x_test, t_test

 

 

x,t = get_data()

 

for i in range(0,10000,100):

 

    batch_mask = np.random.choice(10000,100)

 

    print( batch_mask )  #0~10000랜덤하게 100

 

    x_batch = x[batch_mask]

 

    print( len( x_batch ) )

 

 

 

 

문제154.

위의 코드는 복원추출인데

비복원 추출 되게끔 코드를 수정하시오

 

x,t = get_data()

 

for i in range(0,10000,100):

    #batch_mask = np.random.choice(10000,100)  # 차례대로 뽑아야 하니까.

    #print( batch_mask )

    #x_batch = x[batch_mask]   # 랜덤값 넣을 필요 없음

    x_batch = x[i:i+100]           # 순차적으로 갖고오기

    print( len( x_batch ) )

 

 

 

 

 

문제155.

위의 코드를 5epoch 돌게 코드를 수정하시오

 

batch_size=100

for j in range(1,5+1):

    print('--------------------------------------', j,'에폭')

    for i in range(0,len(x),batch_size): #비복원추출

        x_batch = x[i:i+batch_size]

        t_batch = t[i:i+batch_size]

 

 

        print(len(x_batch))

    print('--------------------------------------', j,'에폭')

 

 

 

 

 

 

미니배치 처리에 맞게끔 교차 엔트로피 함수를 구성하는 방법

 

-미니배치 처리하기 교차 엔트로피 함수(한장씩 출력)

 

y = np.array([0,0,0.9,0,0,0,0,0,0,0.1])  #확률벡터 예상값

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

 

def cross_entropy_error(y,t):

    delta = 1e-7

    return -np.sum(t * np.log(y+delta))

 

print(cross_entropy_error(y,t))

 

 

 

 

 

문제156.

미니배치 (100) 맞게끔 교차엔트로피 함수를 수정하시오

 

#- 100장씩 미니배치한후의 교차 엔트로피 함수

 

y = np.array([ [0, 0, 0.9, 0, 0, 0, 0, 0, 0,  0.1],

               [0.9, 0, 0.1, 0, 0, 0, 0, 0, 0, 0.1],

               [0, 0, 0.1, 0, 0.8, 0, 0, 0, 0, 0.1],    

                           : 

                           :  100 

                           :

               [0, 0, 0.9, 0, 0, 0, 0, 0, 0, 0.1]  )

 

*** t값도 100 있음(여기에 기재하지 않겠음)

 

y shape 찍어보면  ( 100 , 10 ) 나온다. (,)

y.shape[0] 하면 행값이므로 100 나온다.


batch_size = y.shape[0]

 

def cross_entropy_error(y,t):

    delta = 1e-7

    return -np.sum(t * np.log(y+delta)) / batch_size

 

print(cross_entropy_error(y,t))

 

랜덤으로 추출한 100개를 가지고 배치로 오차함수 역전파 시키는 이유는

한장씩 한장씩 하는 것보다

100장씩 하는게 빠르게 최적의 가중치값으로 회귀하기 때문이다.

 

 

 

 

수치 미분(p.121)

신경망 학습 시킬 미분을 알아야 하는가?

가중치를 갱신해주기 위해서 미분이 필요하다

 

가중치 = 기울기 - 기울기

할선= 나누는

접선= 닿는

 

점에서의 속도를 구하려면 접선의 방정식을 구해야 하는데

구하는 방법이 바로 미분(기울기)

 

               f(x+h) - f(x)

lim  --------------------------------

h->0              h

 

121p

 

위의 미분 공식을 파이썬 함수로 구현해서 실행을 해본다.

def numerical_diff(f,x):

    h = 10e-50  #0 가까운 숫자(0 50)

    return ( f(x+h) -f(x)) / h

 

그런데

import numpy as np

print(np.float32(1e-50))

0.0

1e-50 출력해보면 너무 작은값이라서 0.0 이라고 출력된다.

, h 사용하기에 적절치 못하다.

 

저자가 테스트를 해보니 최적의 미세값으로

h = 1e-4 라는 것을 알아냈다.

 

h 10 -4승의 값을 사용하면 좋은 결과가 나온다고 알려져 있다.

 

미분계산을 위한 함수를 만들고 다듬어 가자.

 

1. 미분함수의 첫 번째 개선

def numerical_diff(f,x): 

    h = 10e-4   #컴퓨터로 극한값을 구하기 어려우므로 이렇게 미세값지정해준다.

    return ( f(x+h) -f(x)) / h

 

      컴퓨터로는 미분을 하지 못하니 도함수를 구현해야 한다.

 

2. 번째 개선

         접선공식                        할선공식

         f(x+h) - f(x)                                    f(x+h) - f(x-h)

lim  ----------------------                     lim-------------------------

h->0          h                                    h->0      (x+h) - (x-h)

 

                                                                       

 

                                                               f(x+h) - f(x)                  

                                                     lim  ----------------------                    

                                                     h->0          2h                                   

접선공식을 이용해서

h값을 구하면 좋겠지만, 컴퓨터가 h값을 구현 못한다.

(꽤나 작은값들은 모두 그냥 0으로 표시해버린다)

 

 

가중치에서 기울기를 빼주는 이유는

기울기가 0 되는 지점이 왔을

가중치에서 기울기 0 빼주면

가중치에 변화가 없으니까

그것을 최적의 가중치라 생각하고 출력하면 된다.

 

 

 

 

문제157.

y = 2x^2 + 2 함수를 loss2 라는 이름으로 생성하시오

(2차함수)

 

def loss2(x):

    return 2*x**2+2

 

print(loss2(4))

 

 

 

문제158.

y = 2x^2 + 2 함수의 x = 7 곳의 기울기를 손으로 구하시오

: 28

 

기울기를 구하려면 도함수를 구해야 한다.

도함수?

함수를 미분해서 얻은 함수

순간변화율. 유도함수.라고도 한다.

 

 

 

 

 

문제159.

y = 2x^2 + 2 함수의 x = 7 곳의 기울기를 컴퓨터로 구현하시오

( 123p_ 할선공식을 이용한 기울기 구하기)

 

def numerical_diff(f,x):   #할선공식

    h = 1e-4   #컴퓨터로 극한값을 구하기 어려우므로 이렇게 미세값지정해준다.

    return ( f(x+h) -f(x-h) ) / (2*h)

 

 

def loss2(x):

    return 2*x**2+2

 

print(numerical_diff( loss2, 7) )

27.999999999934744

 

 

 

 

문제160.(오늘의 마지막 문제)

문자 159번의 함수를 접선의 미분 공식으로 만든 함수로

미분했을 때의 x=7 에서의 기울기를 구하시오

( 121p_ 접선공식을 이용한 기울기 구하기)

 

def numerical_diff2(f,x):  #접선의 공식

    h = 1e-4   #컴퓨터로 극한값을 구하기 어려우므로 이렇게 미세값지정해준다.

    return ( f(x+h) -f(x) ) / h

 

def loss2(x):

    return 2*x**2+2

print(numerical_diff2( loss2, 7) )

28.000199999951292

 

 

----------------할선과 접선을 통해서 나온 값들을

기울기 28에서 빼서

차가 작은것을 알아보자!

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

def numerical_diff(f,x):     #할선의 공식

    h = 1e-4   #컴퓨터로 극한값을 구하기 어려우므로 이렇게 미세값지정해준다.

    return ( f(x+h) -f(x-h) ) / (2*h)

 

def loss2(x):

    return 2*x**2+2

print(28-numerical_diff( loss2, 7) )

6.52562448522076e-11

 

 

def numerical_diff2(f,x):  #접선의 공식

    h = 1e-4   #컴퓨터로 극한값을 구하기 어려우므로 이렇게 미세값지정해준다.

    return ( f(x+h) -f(x) ) / h

 

def loss2(x):

    return 2*x**2+2

print(28-numerical_diff2( loss2, 7) )

-0.00019999995129182935

 

2 값을

a=6.52562448522076e-11

b=0.00019999995129182935  (음수 지우고)

print(min(a,b))

6.52562448522076e-11

 

설명:

적은값이 할선인 것을 확인할 있다.

그래서 파이썬으로 할선의 공식을 이용하여 실제 기울기와 가장 근접한

값을 구하는 것이다.

 

 

 

 

 

  • 손실 함수의 목적

머신러닝 모델의 최종적인 목적은 높은 정확도를 끌어내는

매개변수(가중치, 편향)를 찾는 것이다.

 

신경망 학습에서는 최적의 매개변수를 탐색할 때

손실함수의 값을 가능한 한 작게 하는 매개변수 값을 찾는다.

 

이 때, 매개변수의 미분(기울기)을 계산하고, 그 미분 값을 토대로 매개변수 값을 갱신하는 과정을 반복한다.


 

 - 주요한 점은,

정확도와는 달리 손실 함수는

 

매개변수의 변화에 따라 연속적으로 변화한다는 점이다.

 

손실 함수와는 달리 정확도는 매개변수의 변화에 둔감하고,

 

또한 변화가 있다하여도

 

불연속적으로 변화하기 때문에 미분을 할 수 없다.

 

미분이 되지 않으면 최적화를 할 수 없으므로 정확도가 아닌

손실 함수를 지표로 삼아 학습을 해나가는 것이다.

 

 

 

4장의 목차

 

1. 오차함수 : 예상값과 실제값의 오차를 구하기 위해 필요한 함수

2. 미니배치 : 신경망 학습시 한장 처리하는 것보다 배치로 처리하는

학습이 빠르기 때문이다.

3. 수치미분 : 신경망을 학습 시킬

"가중치 = 가중치 - 기울기" 공식으로 가중치를

갱신해 나가는데 이때 기울기를 구할려면

미분을 해야 한다.

 

"아주 작은 차분으로 미분하는 것"

P.123 NOTE

 

3가지를 통해서 3 신경망을 학습을 시키는 챕터가 4장의 내용

 

 

 

문제162.

아래의 비용함수를 시각화 하시오

 

구글 검색창에

x**2 + 4**2

넣으면 함수위치가 실시간으로 나온다.

 

 

문제163.

아래의 그래프를 구글에서 시각화 하시오

f(x0, x1) = x0**2 + x1**2

z= x^2 + y^2

 

 

 

 

화면 캡처: 2019-01-18 오전 11:44

 

3차원 그래프

 

 

 

 

문제164.

아래의 비용함수를 만들고 비용함수의 x=6 지점에서의

미분계수(기울기) 손으로 구하시오

 

y = 4x^2 + 7^2

: 48

 

 

 

 

문제165.

위의 식을 loss3 라는 비용함수 만들고

loss3 함수를 파이썬으로 미분해서 x=6 지점의 미분계수(기울기)

구하시오

 

def loss3(x):   

    return 4*x**2 + 7**2

 

 

def numerical_diff(f,x):     #할선의 공식

    h = 1e-4   #컴퓨터로 극한값을 구하기 어려우므로 이렇게 미세값지정해준다.

    return ( f(x+h) -f(x-h) ) / (2*h)

print(numerical_diff( loss3, 6 ))

 

47.99999999988813

 

 

※설명:

컴퓨터로는 진정한 미분을 구현할 없기 때문에 오차가 발생한다

?

1. 극한값을 구현하기가 어렵다.

2. 접선의 방정식이 아니라 할선의 방정식의 기울기로 미분함수를

만들어야하기 때문이다.

 

 

지금까지 구현한 비용함수는 2차원에 해당하는 비용함수 였다.

w(가중치) 하나만 두고 만든 함수였다.

 

그런데

 

신경망에 들어가는 가중치는 w(가중치) w1 하나만이 아니라

w0 있고

w2 있고

여러개의 w 있을 있기 때문에 2차원을 넘어설 있다.

 

 

2차원 그래프가 아니라 3차원 그래프를 미분할 사용한 미분방법이?

편미분! p.125

 

 

편미분

"변수가 2 이상인 함수를 미분할 미분 대상 변수외에

나머지 변수를 상수처럼 고정시켜 미분하는 것을 편미분이라고 한다"

 

f(x0,x1)   = x0**2 + x1**2

f(w0,w1) = w0**2 + w1**2

 

문제166. 손으로 먼저 편미분을 수행하시오

 

f(x0,x1)   = x0^2 + x1^2  

함수를 편미분 하는데

x0 = 3

x1 = 4 일때 x0 대해서 편미분 하시오

 

"변수가 2 이상인 함수를 미분할 미분 대상 변수외에

나머지 변수를 상수처럼 고정시켜 미분하는 것을 편미분이라고 한다"

 

f(x0,x1)   = x0^2 + x1^2  

y = 3^2 + 4^2

: 6

 

 

 

 

문제167.

f(x0,x1)   = x0^2 + x1^2   함수를 편미분 하는데

x0=3, x1=4 x0 대해서 편미분한 미분계수(기울기)

파이썬으로 구현하시오

 

def loss5(x):   

    return x**2 + 4**2

 

# 구하고자 하는 자리에만 x 남겨놓고

   다른 x 상수로 대체시켜줌.

 

def numerical_diff(f,x):     #할선의 공식

    h = 1e-4   #컴퓨터로 극한값을 구하기 어려우므로 이렇게 미세값지정해준다.

    return ( f(x+h) -f(x-h) ) / (2*h)

print(numerical_diff( loss5, 3 ))

6.00000000000378   ##기울기 6

 

 

 

 

 

문제168.

문제에서 x1=4 대해서 편미분 하시오

 

def loss5(x):   

    return 3**2 + x**2

##########################################################

 

def numerical_diff(f,x):     #할선의 공식

    h = 1e-4   #컴퓨터로 극한값을 구하기 어려우므로 이렇게 미세값지정해준다.

    return ( f(x+h) -f(x-h) ) / (2*h)

print(numerical_diff( loss5, 4 ))

7.999999999999119      ###기울기 8

 

 

f(x0,x1) = x0^2 + x1^2

x=np.array([3.0 , 4.0])

기울기 = [6,8]

 

 

 

 

 

문제169.

위에서는 f(x0,x2) = x0^2 +x1^2 함수를 편미분 하는 것을

각각 수행했는데

이제 편미분이 번에 수행하게 코드를 작성하시오

 

import numpy as np

 

def loss_func(x):   

    return x[0]**2 + x[1]**2

 

 

def numerical_diff(f,x):     #할선의 공식

    h = 1e-4   #컴퓨터로 극한값을 구하기 어려우므로 이렇게 미세값지정해준다.

    return ( f(x+h) -f(x-h) ) / (2*h)

 

print(numerical_diff( loss_func, np.array([3,4])  ))

 

 

 

 

문제169-1.

아래와 같이 결과를 출력하시오

[0 0]

 

import numpy as np

x = np.array([3.0 , 4.0])

print(np.zeros_like(x))

[ 0.  0.]

# 작업을 하는 이유는 6.0 8.0 자리에 넣으려고 !

 

 

 

 

문제169-2.

x 넘파이 배열의 원소중에서 3 받아서
아래의 식을 아래와 같이 구현하시오

 

f(x+h) - f(x-h)

          

f(3.0 + 0.0001) - f(3.0 - 0.0001)

                                  

(3.0001^2 + 4^2) - (2.9999^2 + 4^2)  = 0.0012

 

 

import numpy as np

 

def loss_func(x):   

    return x[0]**2 + x[1]**2

   

##########################################################

 

def numerical_diff(f,x):     #할선의 공식

    h = 1e-4   #컴퓨터로 극한값을 구하기 어려우므로 이렇게 미세값지정해준다.

    return ( f(x+h) -f(x-h) )

 

x=np.array([3.0 , 4.0])

print(numerical_diff( loss_func, x))

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

import numpy as np

 

 

def loss_func(x):

    return x[0] ** 2 + x[1] ** 2

 

 

x = np.array([3.0, 4.0])

 

 

def numerical_gradient(f, x):

    h = 0.0001

    grad = np.zeros_like(x)  # [0  0]

 

    for idx in range(x.size):  # 0, 1

        tmp_val = x[idx]  # x[0] =3.0

 

        x[idx] = tmp_val + h  # x[idx] = 3.0 + 0.0001

        fxh1 = f(x)  # f(x+h) 계산,  3.0001^2 + 4^2 = 25.00

 

        x[idx] = tmp_val - h  # 3- 0.0001 =2.9999

        fxh2 = f(x)  # f(x-h) 계산 # 2.9999^2 + 4^2 =24.999

 

        grad[idx] = (fxh1 - fxh2)       

    return grad

 

x = np.array([ 3.0 , 4.0 ])

print(numerical_gradient(loss_func, x))

[ 0.0012  0.0016]

 

 

 

문제169-3.

아래의 식으로 numerical_gradient 함수 코드를 완성 시키시오

** 코드에서 가지 수정

 

import numpy as np

 

 

def loss_func(x):

    return x[0] ** 2 + x[1] ** 2

 

 

x = np.array([3.0, 4.0])

 

 

def numerical_gradient(f, x):

    h = 0.0001

    grad = np.zeros_like(x)  # [0  0]

 

    for idx in range(x.size):  # 0, 1

        tmp_val = x[idx]  # x[0] =3.0

 

        x[idx] = tmp_val + h  # x[idx] = 3.0 + 0.0001

        fxh1 = f(x)  # f(x+h) 계산,  3.0001^2 + 4^2 = 25.00

 

        x[idx] = tmp_val - h  # 3- 0.0001 =2.9999

        fxh2 = f(x)  # f(x-h) 계산 # 2.9999^2 + 4^2 =24.999

 

        grad[idx] = (fxh1 - fxh2) / (2*h)

       

        x[idx] = tmp_val           #x[idx] 2.9999 로 되어있어서 3.0으로 바꿔줘야함

    #다음 for 돌면 3.9999 4.0으로 바꿔주고.

       

    return grad

 

x = np.array([ 3.0 , 4.0 ])

print(numerical_gradient(loss_func, x))

 

[ 6.  8.]         #  <<-----기울기

 

 

 

 

 

문제170.

아래의 x0, x1 지점에서의 기울기를 각각 구하시오

 

f(x0,x1) = x0^2 + x1^2

 

  x0  ,  x1 ----------------------------------> grad1 , grad2

[3.0   4.0] --------------------------------> [6.0        8.0]

[0.0   2.0] --------------------------------> [0.0        4.0]

[3.0   0.0] --------------------------------> [6.0        0.0]

 

 

공식에서 x 대입시킴.

 

x들은 가중치고 grad들은 기울기다.

 

p.129

 

첫번째 3차원 함수를 윗방향에서 바라보면 아래 그림같은 모습이다.

 

기울기 그림은 마이너스 방향을 가진 벡터(화살표) 그려집니다.

그림을 보면 기울기는 함수의 '가장 낮은 장소(최솟값)' 가리키는

같습니다.

마치 나침반처럼 화살표들은 점을 향하고 있지요.

'가장 낮은 '에서 멀어질 수록 화살표의 크기가 커짐을 있습니다.

 

기울기가 가리키는 쪽은 장소에서 함수의 출력값을 가장 크게

줄이는 방향 입니다.중요!!

 

 

 

 

경사하강법

p.131

"특정 가중치의 위치에서 기울기를 빼서 점차 global minima

진행하는 학습 방법"

 

 

 

기계학습은 최적의 매개변수를 찾아내는 과정입니다.

 

최적값 = 손실 함수 최솟값----> 매개변수 값

 

최적을 찾기 위해 :

 

기울기를 이용.

 

가중치에서 기울기를 빼서 가중치값을 갱신시키는데,

기울기가 0이 되는 지점에 오면

 

가중치값도 더 이상 갱신이 안된다. (최솟값을 얻음)

그 지점을 바로 최적값 이라 부른다.

 

최솟값 ===> 최적값

 

 

 

경사하강법 공식

 

가중치   =   가중치 - 러닝레이트 * 기울기

 

                                                        비용함수

w0            =     w0   -   학습률*--------------------

                                                          W0

 

 

                                    비용함수
w1           =      w1   -  
학습률* --------------------

                                                          W1

* : 편미분

 

학습률을 곱해주는가?

학습률을 곱해주지 않으면 너무 촘촘히 내려가서 학습이 될수도 있다.

 

*학습률이란?

" 번의 학습으로 얼마만큼 학습행 할지, 매개변수 값을 얼마나

갱신하느냐를 정하는 것이 학습률 입니다"

 

"학습률 값은 0.01 이나 0.001 미리 특정값으로 정해두어야 하는데,

일반적으로 값이 너무 크거나 작으면 '좋은장소' 찾아갈 없습니다.

신경망 학습에서는 보통 학습률값을 변경하면서 올바르게 학습하고

있는지를 확인하면서 진행합니다"

 

 

 

 

문제171.

131페이지에 나오는 경사 하강 함수(gradient_descent)함수를 생성하시오

 

 

문제172.

위에서 만든 gradient_descent 함수를 가지고

x[0] = 3.0

x[1] = 4.0

지점에서 학습을 100 수행했을 global minima 도착하는지

확인하시오

 

러닝레이트: 0.01

학습 횟수: 100

 

import numpy as np

def loss_func(x):    # 할선공식

    return x[0] ** 2 + x[1] ** 2

 

#기울기는 나아갈 방향을 정해줌

# 기울기가 0이 되는 지점을 찾아내어

# 가중치 - 기울기 = 가중치 (즉 가중치 갱신 안됨)

# 위 내용이 성립되는 기울기를 찾아내고

# 오차(손실함수)의 최솟값도 찾아내어

# (손실함수가 최솟값을 가질 때 => 최적의 매개변수)

# 학습률을 끌어올리는 함수

 

def gradient_descent(f, init_x, lr=0.01, step_num=100):    # 디폴트값

# 프린트에 함수조건 안주면 디폴트로 돌아간다.

    x = init_x

   

    for i in range(step_num):

        grad = numerical_gradient(f,x)  #  기울기 구하는 함수

        x -= lr * grad

       

    return x

 

x = np.array([3.0, 4.0])

print( gradient_descent( loss_func, init_x=x, lr=0.1, step_num=100 ) )

 

*lr = 러닝레이트

lr 0.01 : [ 0.39785867  0.53047822]

lr  0.1 : [  6.11110793e-10   8.14814391e-10]

 

 

문제173. 학습율을 0.1 변경해서 수행해보시오

러닝레이트: 0.1

lr  0.1 : [  6.11110793e-10   8.14814391e-10]

 

return x.round() 시켜보면 0 출력된다.

0 가까운 값이라는 있다.

 

 

 

문제174.

러닝레이트(학습률) 크게 주고 학습을 하면 결과가 어떻게 나오는지

확인하고 러닝레이트(학습률) 작게 주고 학습을 하면

결과가 어떻게 나오는지 확인하시오

 

1. 학습률: 10          [  2.58983747e+13  -1.29524862e+12]

2. 학습률:1e-10     [ 2.99999994  3.99999992]

 

너무 크거나, 너무 작은값으로 주면

1번같은 경우 global minima 도달하지 못하고 발산을 한다.

 

 

 

위에서 배운 3가지 방법으로 3 신경망을 학습 시키는 방법 구현

1. 오차함수

2. 미니배치

3. 수치미분(편미분)

 

 

 

학습이 스스로 되는 3 신경망 구현

 

문제175.

2x3 행렬을 생성하는데 값은 랜덤값으로 생성되게 하시오

 

import numpy as np

 

w = np.random.randn(2,3)

print(w)

 

 

[[ 0.63731947 -0.32702381 -0.48764098]

 [-1.56229829  0.88644744  0.89773323]]

 

프린트 마다 값이 변한다.

 

 

 

 

 

문제176.

위에서 구한 w값으로 아래의 입력값 과의 행렬 내적을 출력하시오

 

import numpy as np

 

w = np.random.randn(2,3)

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

 

print(np.dot(x,w))

 

[ 1.1661284  -0.51610649 -1.48958246]

 

 

 

 

문제177.

175번문제의 코드를 __init__ 라는 함수로 생성하시오

 

import numpy as np

w = np.random.randn(2,3)

print(w)

 

실행문: __init__()

 

 

def __init__():       

    import numpy as np   

    w = np.random.randn(2,3)   

    return w

print(__init__() )

 

 

 

 

 

 

문제178.

위에서 만든 가중치와 아래의 입력값을 받아

행렬을 내적하는 predict 라는 함수를 만드시오

 

import numpy as np

 

def __init__():

    w = np.random.randn(2,3)

    return w

 

def predict(x,w):

    return np.dot(x, w )  

 

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

w=__init__()

print( predict( x,w ) )

[ 0.69548293  0.71253162 -1.03456288]

 

 

 

 

문제179.

위의 predict 함수에 나온 결과를 softmax 출력층 함수에 통과시킨

결과를 출력하시오

 

import numpy as np

 

def __init__():

    w = np.random.randn(2,3)

    return w

 

 

def predict(x,w):

    return np.dot(x, w )

 

 

def softmax(x):   

    c = np.max(x)

    return np.exp(x-c) / np.sum( np.exp(x - c) )

 

 

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

w=__init__()

 

print(softmax(predict(x,w)))

[ 0.43801051  0.44629298  0.11569652]

 

 

 

 

문제180.

위에서 출력된 소프트맥스 함수의 결과와 아래의 target값과의 오차를

출력하기 위해 cross_entropy_error 함수를 통과한 결과를 출력하시오

 

 

import numpy as np

def __init__():

    w = np.random.randn(2,3)  # 평균이 0 이고 분산이 1 여러개의

  #숫자가 랜덤으로 출력됨

    return w

 

def predict(x,w):

    return np.dot(x, w )

   

def softmax(x):   

    c = np.max(x)

    return np.exp(x-c) / np.sum( np.exp(x - c) )

 

def cross_entropy_error(y,t):

    import numpy as np

    delta = 1e-7   #log=0 에러나서 y에 델타를 더해주기 위함이다.

    return -np.sum( t * np.log(y + delta ) )

 

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

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

w=__init__()

 

print(cross_entropy_error( softmax( predict(x,w) ),t ) )

 

 

 

 

문제181.(오늘의 마지막 문제)

위의 3가지 함수를 사용한 simpleNet 이라는 클래스를

134페이지를 보고 생성하고

생성되었는지 확인하시오

 

import numpy as np

 

class simpleNet:

 

    #import numpy as np  #클래스안에서 넘파이 부르면 작동 안됨. 그래서 맨 위에 둠.

   

    def __init__(self):   # 랜덤의 w값을 생성한다.

        self.w = np.random.randn(2,3) 

        #return w

   

    def predict(self,x):  # 23열 랜덤 w값과 x를 내적시킨다.

        return np.dot(x, self.w )   #내적결과 출력

   

   

    def softmax(self,x):  # 출력층 함수 (확률출력)

        c = np.max(x)

        return np.exp(x-c) / np.sum( np.exp(x - c) )

   

   

    def cross_entropy_error(self,y,t):  # 분류를 위한 오차함수

        import numpy as np

        delta = 1e-7   #log=0 에러나서 y에 델타를 더해주기 위함이다.

        return -np.sum( t * np.log(y + delta ) )

   

   

    def loss(self, x, t):  # 소프트맥스를 통과시킨 확률과, 실제 t값을

                            #크로스_엔트로피_오차함수에 통과시킨다.

        z = self.predict(x)

        y = self.softmax(z)

        loss = self.cross_entropy_error(y,t)       

        return loss

   

   

 

net = simpleNet()

print(net.w)

   

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

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

 # x 12열로 주고

# __init__ 함수에서 임의로 만드는 w값은 23열로 제작하여

#내적시켜줌.

 

       

[[ 1.0920435  -0.5548598   1.10784619]

 [ 0.91498452  0.47295498  0.87371092]]

 

 

 

 

문제191.

위의 simpleNet 클래스의 loss 함수를 실행시켜보시오

 

net = simpleNet()

   

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

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

 

print(net.loss(x,t)) 

 

 

 

 

문제192.

simpleNet 클래스의 가중치W 몇행몇열인지 출력하시오

 

net = simpleNet()

print(net.w.shape)

 

(2, 3)

 

 

 

 

문제193.

simpleNet 클래스의 __init__함수를 가중치 w1 784*50 으로

생성되게 하고

가중치 w2 50*10으로 가중치가 랜덤으로 생성되게

코드를 수정하시오

 

 

    def __init__(self):   # 랜덤의 w값을 생성한다.

        self.params = {}    #가중치 초기화

        self.params['w1'] = 0.01*np.random.randn(784,50)

        self.params['b1'] = np.zeros(50)  #numpy array 0 50개 채우겠다.

        self.params['w2'] = 0.01*np.random.randn(50,10)

        self.params['b2'] = np.zeros(10)

        #은닉층 1층이 50, 은닉층2층이 10개라서 바이어스값도 50, 10 .

※ 0.01 곱하는건 가중치 초기화에 대한 값으로 6장에서 학습함

       

 

 

 

 

문제194.

simpleNet 클래스의 가중치 w1 w2 shape 출력하시오

 

print('w1',net.params['w1'].shape)

print('w1',net.params.get('w1').shape)  # 밸류갖고 오는것과 같다.

print('w2',net.params['w2'].shape)

print('b1',net.params['b1'].shape)

print('b2',net.params['b2'].shape)

 

w1 (784, 50)

w2 (50, 10)

b1 (50,)

b2 (10,)

 

 

 

 

문제195.

simpleNet 클래스를 객체화 시킬 아래와 같이 실행되게 하시오

***매번 클래스 함수값을 바꿔쓰는것보다

__init__ 함수에서 인자지정 해주면 된다.

 

  def __init__(self , input_size = 784, hidden_size = 50, output_size = 10 ):  

# 랜덤의 w값을 생성한다.

        self.params = {} #가중치 초기화

       

        self.params['w1'] = 0.01*np.random.randn(input_size,hidden_size)

        self.params['b1'] = np.zeros(hidden_size)  #numpy array 0 50개 채우겠다.

        self.params['w2'] = 0.01*np.random.randn(hidden_size,output_size)

        self.params['b2'] = np.zeros(output_size)

        #은닉층 1층이 50, 은닉층2층이 10개라서 바이어스값도 50, 10

        # 0.01 곱하는건 가중치 초기화에 대한 값으로 6장에서 학습함

 

net = simpleNet()

print('w1',net.params['w1'].shape)

#print('w1',net.params.get('w1').shape)  # 밸류갖고 오는것과 같다.

print('w2',net.params['w2'].shape)

print('b1',net.params['b1'].shape)

print('b2',net.params['b2'].shape)

 

w1 (784, 50)

w2 (50, 10)

b1 (50,)

b2 (10,)

 

 

 

 

문제196.

predict 함수를 위의 가중치에 맞게 변경하시오

 

 def predict(self,x):  # 23열 랜덤 w값과 x를 내적시킨다.

        w1, w2 = self.params['w1'], self.params['w2']

        b1, b2 = self.params['b1'], self.params['b2']

       

        a1 = np.dot(x, w1) + b1

        z1 = self.sigmoid(a1)

       

        a2 = np.dot(z1, w2) + b2

        y = self.softmax(a2)

       

        return y

   

 

 

 

 

문제197.

mnist 데이터 100 입력해서 predict 함수를 통과한 결과가

어떻게 되는지 확인하시오

 

import sys, os

 

sys.path.append(os.pardir)

 

import numpy as np

from dataset.mnist import load_mnist

from PIL import Image

import  pickle

import  numpy  as np

import  numpy as np

 

def  get_data():

    (x_train, t_train) , (x_test, t_test) = \

    load_mnist(normalize=True, flatten=True, one_hot_label=False)

    return  x_test, t_test

x, t = get_data()

 

net = simpleNet()#( input_size = 784, hidden_size = 50, output_size = 10 )

#net = simpleNet()

 

y = net.predict(x[:100])

print(y)

print(y.shape)

*소프트맥스값 10 확률이 100 출력됨.

(100, 10) #shape 으로 형태확인

 

 

 

 

accurace (정확도) 구하는 함수의 이해

"예상한 숫자와 실제숫자를 비교해서 정확도를 출력하는 함수"

예제:

def accuracy(self, x, t):

    y = self.predict(x)  # 10개짜리 확률벡터 100개 출력

                        # 100 * 10

 

 

 

- y 값의 행렬

 

 [ [ 0.1 0.1 0.05 0.4 0.05 0.1 0.05 0.05 0.05 0.05 0.00],  # 3

   [ 0.4 0.1 0.05 0.1 0.05 0.1 0.05 0.05 0.05 0.05 0.00],  # 0

                 :  100                                    :  100

                 :                                           :

   [ 0.1 0.1 0.05 0.4 0.05 0.1 0.05 0.05 0.05 0.05 0.00] ]

 

- target 행렬 (one hot encoding)

 

            [ [ 0 0 1 0 0 0 0 0 0 0  ],   # 2

              [ 1 0 0 0 0 0 0 0 0 0  ],   # 0

                         :

                         :     100

              [ 0 0 1 0 0 0 0 0 0 0  ] ]

 

 

        y = np.argmax(y, axis=1) # [ 3 0 1 5 6 .......... 3 ]  # 100

 

        t = np.argmax(t, axis=1) # [ 2 0 2 1 3 ...........3 ]  # 100

 

        accuracy = np.sum(y == t) / float(x.shape[0])

# y t 같은것만 골라서 sum 시키고

# shape[0] 으로 나눈다. (100)

 

        return accuracy

 

 

 

 

 

 

 

 

문제198.( 예시 참고)

정확도를 구하는 accuracy 함수를 simpleNet 클래스에 추가하고

100장을 입력해서 정확도를 출력해보시오.

 

 

 def accuracy(self, x, t):

        y = self.predict(x)  # 10개짜리 확률벡터 100개 출력

                        # 100 * 10

        y = np.argmax(y, axis=1)

        t = np.argmax(t, axis=1)

       

        accuracy = np.sum(y==t) / float(x.shape[0])

        return accuracy

 

def  get_data():

    (x_train, t_train) , (x_test, t_test) = \

    load_mnist(normalize=True, flatten=True, one_hot_label=True)

    return  x_test, t_test

x, t = get_data()

 

net = simpleNet()#( input_size = 784, hidden_size = 50, output_size = 10 )

#net = simpleNet()

 

y = net.accuracy(x[:100],t[:100])

print(y)

 

0.15

 

 

 

 

 

numerical_gradient 함수 생성

"비용함수와 가중치 또는 바이어스를 입력받아 기울기를 출력하는 함수"

예제:

  def numerical_gradient(self, x, t):

        loss_W = lambda K: self.loss(x, t)

 

        grads = {}

        #

        # grads['W1'] = numerical_gradient(self.loss(x,t), self.params['W1']) self.loss 바로 쓰면

        # grads['b1'] = numerical_gradient(self.loss(x,t), self.params['b1']) 안나온다.

        # grads['W2'] = numerical_gradient(self.loss(x,t), self.params['W2'])

        # grads['b2'] = numerical_gradient(self.loss(x,t), self.params['b2'])

        #

        grads['W1'] = numerical_gradient(loss_W, self.params['W1'])

        grads['b1'] = numerical_gradient(loss_W, self.params['b1'])

        grads['W2'] = numerical_gradient(loss_W, self.params['W2'])

        grads['b2'] = numerical_gradient(loss_W, self.params['b2'])

 

        return grads

 

 

 

 

비용함수 생성방법

net=simpleNet(input_size = 784,hidden_size = 50, output_size =10)

 

def f(w):

    return network.loss(x,t)

 

설명: 135 p

여기서 정의한 f(w) 함수의 w 의미는 더미로 만든 것입니다.

numerical_gradient(f,x) 내부에서 f(x) 실행하는데

그와의 일관성을 위해서 f(w) 정의한 것입니다.

lambda 표현식으로 줄로 표현하면 아래와 같습니다.

 

f = lambda W: network.loss(x,t)

dW = numerical_gradient(f, net.W)

W 기울기

 

 

 

 

 

 

 

문제199.

x[0] t[0] 입력해서 얻은 기울기 grads['W1'], grads['W2'],

grads['b1'], grads['b12] 행렬의 shape 각각

어떻게 되겠는가?

 

import sys, os

 

sys.path.append(os.pardir)

 

import numpy as np

from dataset.mnist import load_mnist

from common.gradient import numerical_gradient

from PIL import Image

import  pickle

import  numpy  as np

 

import  numpy as np

 

class simpleNet:

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

        self.params = {}

        self.params['W1'] =0.01 * np.random.randn(input_size, hidden_size)

        self.params['b1'] = np.zeros(hidden_size)

        self.params['W2'] =0.01 * np.random.randn(hidden_size, output_size)

        self.params['b2'] = np.zeros(output_size)

 

    def softmax(self,a):

        minus = a - np.max(a)

        return np.exp(minus) / np.sum(np.exp(minus))

 

    def sigmoid(self,num):

        rst = (1 / (1 + np.exp(-num)))

        return (rst)

 

    def predict(self, x):

        W1, W2 = self.params['W1'], self.params['W2']

        b1, b2 = self.params['b1'], self.params['b2']

 

        a1 = np.dot(x, W1) + b1

        z1 = self.sigmoid(a1)

        a2 = np.dot(z1, W2) + b2

        y = self.softmax(a2)

        return y

 

    def cross_entropy_error(self,y,t):

        delta = 1e-7

        if y.ndim ==1:

            t=t.reshape(1,t.size)

            y=y.reshape(1,y.size)

        batch_size=y.shape[0]

        return -np.sum(t*np.log(y+delta)) / batch_size

 

    def loss(self,x,t):

        z = self.predict(x)

        y = self.softmax(z)

        return self.cross_entropy_error(y,t)

 

    def accuracy(self, x, t):

        y = self.predict(x)

        y = np.argmax(y, axis=1)

        t = np.argmax(t, axis=1)

        accuracy = np.sum(y == t) / float(x.shape[0])

 

        return accuracy

 

 

    def numerical_gradient(self, x, t):

        loss_W = lambda K: self.loss(x, t)

 

        grads = {}

        #

        # grads['W1'] = numerical_gradient(self.loss(x,t), self.params['W1']) self.loss 바로 쓰면

        # grads['b1'] = numerical_gradient(self.loss(x,t), self.params['b1']) 안나온다.

        # grads['W2'] = numerical_gradient(self.loss(x,t), self.params['W2'])

        # grads['b2'] = numerical_gradient(self.loss(x,t), self.params['b2'])

        #

        grads['W1'] = numerical_gradient(loss_W, self.params['W1'])

        grads['b1'] = numerical_gradient(loss_W, self.params['b1'])

        grads['W2'] = numerical_gradient(loss_W, self.params['W2'])

        grads['b2'] = numerical_gradient(loss_W, self.params['b2'])

 

        return grads

 

 

def  get_data():

    (x_train, t_train) , (x_test, t_test) = \

    load_mnist(normalize=True, flatten=True, one_hot_label=True)

    return  x_test, t_test

 

x, t = get_data()

 

net=simpleNet(input_size = 784,hidden_size = 50, output_size =10)

 

y = net.numerical_gradient(x[0],t[0])

 

print(y['W1'].shape)

print(y['W2'].shape)

print(y['b1'].shape)

print(y['b2'].shape)

 

(784, 50)

(50, 10)

(50,)

(10,)

 

 

 

 

 

문제200.

지금까지 완성한 simpleNet 클래스를 가지고 만든 신경망에

훈련data 100장씩 미니배치해서 학습시키는 코드를 구현하시오

(p. 141~142)

 

 

import sys, os

 

sys.path.append(os.pardir)

 

import numpy as np

from dataset.mnist import load_mnist

 

from common.gradient import numerical_gradient

 

from PIL import Image

import  pickle

import  numpy  as np

 

import  numpy as np

 

class simpleNet:

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

        self.params = {}

        self.params['W1'] =0.01 * np.random.randn(input_size, hidden_size)

        self.params['b1'] = np.zeros(hidden_size)

        self.params['W2'] =0.01 * np.random.randn(hidden_size, output_size)

        self.params['b2'] = np.zeros(output_size)

 

    def softmax(self,a):

        minus = a - np.max(a)

        return np.exp(minus) / np.sum(np.exp(minus))

 

    def sigmoid(self,num):

        rst = (1 / (1 + np.exp(-num)))

        return (rst)

 

    def predict(self, x):

        W1, W2 = self.params['W1'], self.params['W2']

        b1, b2 = self.params['b1'], self.params['b2']

 

        a1 = np.dot(x, W1) + b1

        z1 = self.sigmoid(a1)

        a2 = np.dot(z1, W2) + b2

        y = self.softmax(a2)

        return y

 

    def cross_entropy_error(self,y,t):

        delta = 1e-7

        if y.ndim ==1:

            t=t.reshape(1,t.size)

            y=y.reshape(1,y.size)

        batch_size=y.shape[0]

        return -np.sum(t*np.log(y+delta)) / batch_size

 

    def loss(self,x,t):

        z = self.predict(x)

        y = self.softmax(z)

        return self.cross_entropy_error(y,t)

 

    def accuracy(self, x, t):

        y = self.predict(x)

        y = np.argmax(y, axis=1)

        t = np.argmax(t, axis=1)

        accuracy = np.sum(y == t) / float(x.shape[0])

 

        return accuracy

 

 

    def numerical_gradient(self, x, t):

        loss_W = lambda K: self.loss(x, t)

 

        grads = {}

        #

        # grads['W1'] = numerical_gradient(self.loss(x,t), self.params['W1']) self.loss 바로 쓰면

        # grads['b1'] = numerical_gradient(self.loss(x,t), self.params['b1']) 안나온다.

        # grads['W2'] = numerical_gradient(self.loss(x,t), self.params['W2'])

        # grads['b2'] = numerical_gradient(self.loss(x,t), self.params['b2'])

        #

        grads['W1'] = numerical_gradient(loss_W, self.params['W1'])

        grads['b1'] = numerical_gradient(loss_W, self.params['b1'])

        grads['W2'] = numerical_gradient(loss_W, self.params['W2'])

        grads['b2'] = numerical_gradient(loss_W, self.params['b2'])

 

        return grads

 

 

def  get_data():

    (x_train, t_train) , (x_test, t_test) = \

    load_mnist(normalize=True, flatten=True, one_hot_label=True)

    return  x_test, t_test

 

x, t = get_data()

 

#net=simpleNet(input_size = 784,hidden_size = 50, output_size =10)

###############################################

train_loss_list = []

 

iters_num = 1  #반복횟수

train_size = x.shape[0]  # 60000

batch_size = 100   #미니배치

learning_rate = 0.1

 

network = simpleNet(input_size = 784, hidden_size = 50, output_size = 10)

 

for i in range(iters_num):

    #미니배치 획득

    batch_mask = np.random.choice(train_size, batch_size)

    x_batch = x[batch_mask]

    t_batch = t[batch_mask]

   

grad = network.numerical_gradient(x_batch, t_batch)

# grad = network.gradient(x_batch, t_batch)  #성능 개선판 !

 

#매개변수 갱신

for key in ('W1', 'b1', 'W2', 'b2'):

    network.params[key] -= learning_rate * grad[key]

   

#학습 경과 기록

loss = network.loss(x_batch, t_batch)

train_loss_list.append(loss)

 

print(train_loss_list)

 

 

 

 

 

 

 

수치 미분을 이용한 2 신경망 구현 코드

*신경망에 들어간 함수들

1. softmax 함수-------------------->입력값,가중치 총합을 받아

0~1 사이의 확률벡터를 출력하는 함수

2. sigmoid 함수-------------------->입력과,가중치 총합을 받아

0~1사이의 확률값을 출력하는 함수

3. predict 함수--------------------->입력층->은닉층->출력층을 구현한 함수

4. cross_entropy_error 함수--->예측값과 라벨(target) 입력받아 오차를

출력하는 함수

5. loss 함수-------------------------->출력층->오차함수를 구현한 함수

6. accuracy 함수------------------->예측값과 라벨(target)값을 받아 정확도를 출력하는

함수

7. numerical_gradient 함수---->비용함수와 가중치를 입력받아

해당 가중치의 기울기를 출력하는 함수

8. simpleNet 클래스를 객체화 시켜서 훈련 데이터를 100장씩 입려해서

학습시키는 코드

 

 

 

 

문제200 코드설명

(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)

                      

6만장     6만개

(훈련      (훈련

데이터      데이터

이미지)     라벨)

 

# x_train = 60000 * 784 (28*28 일렬로 늘어놔서)

# t_train = 60000 * 10

 

train_loss_list = []  # [6.9, 6.7, 6.5,.....] 오차를 에폭마다 입력

# 하이퍼 파라미터 (신경망 학습을 최적화 하기 위해 사람이 조절해야 하는 )

 

 

iters_num = 10000      # 반복횟수

train_size = x_train.shape[0]    # x_train.shape = 60000 * 784

batch_size = 100                       # 미니배치 크기

learning_rate = 0.1                 # 학습률( 학습발자국 )

 

network = simpleNet(input_size=784, hidden_size=50, output_size=10)

 

for i in range(iters_num):   # 10000   만약1에폭 하고 싶으면 600, 2에폭은 1200

    batch_mask = np.random.choice(train_size, batch_size)  # 60000, 100

#batch_mask 0~60000 랜덤뽑은거 100

 

    x_batch = x_train[batch_mask]   # 100 * 784

    t_batch = t_train[batch_mask]    # 100 * 10

 

 

   grad = network.numerical_gradient(x_batch, t_batch)  #오차역전파 구현 함수

    #grad = network.gradient(x_batch,t_batch)       #수치미분 구현 함수

#수치미분으로 돌리면 오래걸려서

#주석처리 하고, grad = 오차역전파법 코드수행한다.

 

    for key in ('W1', 'b1', 'W2', 'b2'):

        network.params[key] -= learning_rate * grad[key]

# 가중치, 바이어스의 기울기들을 for 돌리는데

# running rate 곱한 grad 빼줌으로서

#0 가깝게 갱신시켜준다.

 

    loss = network.loss(x_batch, t_batch)

    train_loss_list.append(loss)

# loss (오차값) 점점 줄어드는걸 있다. p142 그래프

# train_loss_list append 시킨 이유가 그래프 그릴려고.

# 145p 보면 정확도 올라가는 있다.

 

 

 

문제201.

위의 train_loss_list 들어간 오차들을 그래프로 시각화 하면

어떻게 되겠는가?

 

 

 

문제202.

위의 신경망의 정확도를 시각화 하면 어떻게 되겠는가?

 

 

문제203.

위의 정확도 그래프를 실제로 파이썬 코드로 시각화 하시오

(수치미분법 말고, 오차역전파로 구현했다.

 문제 200번은 수치미분으로 구현시켰는데

 사진1개에 1 걸릴만큼 오래 걸렸다.

 하지만 오차역전파법은 바로바로 출력된다.)

 

출력값:

train acc, test acc | 0.1292, 0.1342

train acc, test acc | 0.902566666667, 0.9082

train acc, test acc | 0.922083333333, 0.9238

train acc, test acc | 0.935516666667, 0.9344

train acc, test acc | 0.943633333333, 0.9451

train acc, test acc | 0.950516666667, 0.9504

train acc, test acc | 0.956283333333, 0.9537

train acc, test acc | 0.96035, 0.959

train acc, test acc | 0.964266666667, 0.9599

train acc, test acc | 0.966283333333, 0.9624

train acc, test acc | 0.9686, 0.9644

train acc, test acc | 0.970383333333, 0.9647

train acc, test acc | 0.9728, 0.9666

train acc, test acc | 0.973416666667, 0.9674

train acc, test acc | 0.97675, 0.9687

train acc, test acc | 0.976266666667, 0.9676

train acc, test acc | 0.97855, 0.9701

 

점점 정확도가 올라가는걸 있다.

 

 

 

코드:

 

# coding: utf-8

 

import sys, os

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

import numpy as np

from common.layers import *

from common.gradient import numerical_gradient

from collections import OrderedDict

import matplotlib.pyplot as plt

from dataset.mnist import load_mnist

 

 

class TwoLayerNet:

    def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01):

 

        # 가중치 초기화

        self.params = {}

        self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size)

        self.params['b1'] = np.zeros(hidden_size)

        self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size)

        self.params['b2'] = np.zeros(output_size)

 

 

        # 계층 생성

 

        self.layers = OrderedDict()

        self.layers['Affine1'] = Affine(self.params['W1'], self.params['b1'])

        self.layers['Relu1'] = Relu()

        self.layers['Affine2'] = Affine(self.params['W2'], self.params['b2'])

        self.lastLayer = SoftmaxWithLoss()

 

 

    def predict(self, x):

        for layer in self.layers.values():

            x = layer.forward(x)

 

        return x

 

 

    # x : 입력 데이터, t : 정답 레이블

 

    def loss(self, x, t):

        y = self.predict(x)

        return self.lastLayer.forward(y, t)

 

 

    def accuracy(self, x, t):

        y = self.predict(x)

        y = np.argmax(y, axis=1)

        if t.ndim != 1: t = np.argmax(t, axis=1)

        accuracy = np.sum(y == t) / float(x.shape[0])

        return accuracy

 

 

    # x : 입력 데이터, t : 정답 레이블

 

    def numerical_gradient(self, x, t):

        loss_W = lambda W: self.loss(x, t)

        grads = {}

        grads['W1'] = numerical_gradient(loss_W, self.params['W1'])

        grads['b1'] = numerical_gradient(loss_W, self.params['b1'])

        grads['W2'] = numerical_gradient(loss_W, self.params['W2'])

        grads['b2'] = numerical_gradient(loss_W, self.params['b2'])

        return grads

 

 

    def gradient(self, x, t):

        # forward

        self.loss(x, t)

        # backward

        dout = 1

        dout = self.lastLayer.backward(dout)

        layers = list(self.layers.values())

        layers.reverse()

 

        for layer in layers:

            dout = layer.backward(dout)

 

 

        # 결과 저장

 

        grads = {}

        grads['W1'], grads['b1'] = self.layers['Affine1'].dW, self.layers['Affine1'].db

        grads['W2'], grads['b2'] = self.layers['Affine2'].dW, self.layers['Affine2'].db

 

        return grads

 

# 데이터 읽기

 

(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)

 

network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10)

 

 

# 하이퍼파라미터

 

iters_num = 10000  # 반복 횟수를 적절히 설정한다.

train_size = x_train.shape[0] # 60000

batch_size = 100  # 미니배치 크기

learning_rate = 0.1

 

# 그래프 그리기 위해 필요한 리스트

train_loss_list = []   # 오차를 에폭마다 담기 위한 리스트

train_acc_list = []    #  훈련데이터의 정확도를 에폭마다 담기 위한 리스트

test_acc_list = []     # 테스트 데이터의 정확도를 에폭마다 담기 위한 리스트

 

 

 

# 1에폭당 반복 수

 

iter_per_epoch = max(train_size / batch_size, 1)

                                           #60000 / 100              , 1

                              #max ( 600 , 1)

                             # iter_per_epoch = 600

 

 

 

for i in range(iters_num): # 10000  ,  1에폭 : 600/// 2에폭 : 1200

 

       batch_mask = np.random.choice(train_size, batch_size)

 

   #숫자 100개를 랜덤으로 선택해서 x_batch t_batch 구성

    x_batch = x_train[batch_mask]

    t_batch = t_train[batch_mask]

 

 

    # 기울기 계산

    #grad = network.numerical_gradient(x_batch, t_batch)  #수치미분

    grad = network.gradient(x_batch, t_batch)                       #오차 역전파

 

 

    # 매개변수 갱신 (2 신경망)

    for key in ('W1', 'b1', 'W2', 'b2'):

        network.params[key] -= learning_rate * grad[key]

 

 

    # 학습 경과 기록

    loss = network.loss(x_batch, t_batch)   # 100 학습할 마다 오차를 출력

    train_loss_list.append(loss) # cost 점점 줄어드는것을 보려고

 

 

    # 1에폭당 정확도 계산

# 여기는 훈련이 아니라 1에폭 되었을때 정확도만 체크

 

    if i % iter_per_epoch == 0:     # 600%600 , 1200%600   # 600 번마다 정확도 쌓는다.

 

        train_acc = network.accuracy(x_train, t_train)

 

        test_acc = network.accuracy(x_test, t_test)

 

        train_acc_list.append(train_acc) # 10000/600   16 # 정확도가 점점 올라감

 

        test_acc_list.append(test_acc)  # 10000/600 16 # 정확도가 점점 올라감

 

        print("train acc, test acc | " + str(train_acc) + ", " + str(test_acc))

 

 

 

# 그래프 그리기

 

markers = {'train': 'o', 'test': 's'}

x = np.arange(len(train_acc_list))

plt.plot(x, train_acc_list, label='train acc')  #정확도 plot 그래프 그림

plt.plot(x, test_acc_list, label='test acc', linestyle='--')

plt.xlabel("epochs")

plt.ylabel("accuracy")

plt.ylim(0, 1.0)

plt.legend(loc='lower right')

plt.show()

 

 

 

 

 

문제204.

위의 코드를 수정해서 그림4-11 해당하는 오차 그래프를 그리시오

(오차가 점점 줄어드는 그래프)

# 그래프 그리기

       

markers = {'train': 'o', 'test': 's'}

x = np.arange(len(train_loss_list))

plt.plot(x, train_loss_list, label='train loss')  #정확도 plot 그래프 그림

#plt.plot(x, train_loss_list, label='test loss', linestyle='--')

plt.xlabel("epochs")

plt.ylabel("loss")

plt.ylim(0, 2.0)   # 정확도와 다르게 범위 좀더 넓게 보려고

plt.legend(loc='upper right')   #아래에 있으면 자료 가려서

plt.show()

 

 

 

 

 

 

힘들게 학습시켜 만들어 놓은 가중치를 파일로 생성하는 방법

" pickle 이용하면 된다"

 

 

*pickle 모듈을 이용하는 예제

 

---리스트 데이터를 pickle 파일로 생성하는 예제

import pickle

list = ['a', 'b', 'c']

with open('d:\\list.pkl', 'wb') as f:

    pickle.dump(list, f)

 

 

---pickle 파일을 파이썬으로 로드하는 예제

with open('d:\\list.pkl','rb') as f:

    data = pickle.load(f)

print(data)

 

['a', 'b', 'c']

 

 

 

---이미 저자가 만들어놓은 가중치와 바이어스로 신경망을 구현하는 코드

# 가중치와 bias 값을 가져오는 함수

def init_network():

    with open("sample_weight.pkl", 'rb') as f:

        network = pickle.load(f)

    return network

 

3 신경망의 가중치와 바이어스의 pickle 파일

(w1, w2, w3, b1, b2, b3)

 

 

 

 

문제205.

방금 학습시킨 2 신경망의 가중치 바이어스 two_layer_w.pkl 이라는

피클파일을 생성하시오

 

 

:

network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10)

import pickle

 

with open('d:\\two_layer_w.pkl', 'wb') as f:

    pickle.dump(network.params, f)

 

설명: 지금 생성한 pickle 파일은 2 신경망의 가중치와 바이어스

(w1, w2, b1, b2) 값을 저장한 파일이다

 

 

 

문제206.

지난번 저자가 만들어온 가중치와 바이엇의 pickle 파일을 로드해서

만든 3 신경망에 mnist 숫자 데이터 한장을 넣어서

인공지능이 맞추는지 확인하는 코드를 다시 돌려보시오 !

 

 

 

# 저자가 이미 최적화 해놓은 W1,W2,W3,b1,b2,b3 를 가지고 만든

 #  3 신경망 코드

 

 

import sys, os

 

sys.path.append(os.pardir)

 

import numpy as np

from dataset.mnist import load_mnist

from PIL import Image

import  pickle

import  numpy  as np

 

 

# 신경망 함수들

def sigmoid(num):

    rst = (1 / (1 + np.exp(-num)))

    return (rst)

 

 

def identity_function(x):

    return x

 

 

def softmax(a):

    c = np.max(a)

    minus = a - c

    exp_a = np.exp(minus)

    sum_exp_a = np.sum(exp_a)

    y = exp_a / sum_exp_a

    return y

 

def  init_network():

    with open("C:\\Users\itwill\sample_weight\sample_weight.pkl",'rb')  as  f:

        network = pickle.load(f)

    return  network

 

 

def  predict(network, x):

    W1, W2, W3 = network['W1'], network['W2'], network['W3']

    b1, b2, b3 = network['b1'], network['b2'], network['b3']

 

    a1 = np.dot(x,W1) + b1

    z1 = sigmoid(a1)

    a2 = np.dot(z1,W2) + b2

    z2 = sigmoid(a2)

    a3 = np.dot(z2,W3) + b3

    y = softmax(a3)

 

    return  y

 

def  get_data():

    (x_train, t_train) , (x_test, t_test) = \

    load_mnist(normalize=True, flatten=True, one_hot_label=False)

    return  x_test, t_test

 

x, t = get_data()

network = init_network()

y = predict(network,x[0])

print(np.argmax(y))

print(t[0])

 

7

7

 

 

 

 

문제207.

위의 코드를 수정해서 지금 방금 만든 two_layer_w.pkl 파일을 로드해서

x[0] 숫자를 맞추는지 확인하시오

 

저자가 만든 신경망        vs           우리가 만든 신경망

 

   3 신경망                                  2 신경망

(w1,w2,w3,                                                        (w1,w2,b1,b2)

b1,b2,b3)

 

 

 

 

 

 

 

문제208.(점심시간 문제)

지금 pickle파일 로드해서 만든 2 신경망에 선혜가 만든 필기체 그림을

입력해서 숫자 2 맞추는지 확인하시오

 

 

 

#1. 흑백으로 변경

 

j = 'd:\\num2.png'   #역슬래시 2개씩 안쓰면 에러뜸

import numpy as np

import matplotlib.pyplot as plt

import matplotlib.image as mpimg

 

def rgb2gray(rgb):

    return np.dot(rgb[...,:3], [0.299, 0.587, 0.114])

 

img = mpimg.imread(j)

gray = rgb2gray(img)

plt.imshow(gray, cmap = plt.get_cmap('gray'))

plt.show()

print(gray.shape)

 

 

#2. 입력값으로 쓰이기 위해 (784,) 로 변경해줌

 

a = np.array(gray)

x= a.flatten()

print(x.shape)

 

 

#3. 신경망에 넣어줌

 

import sys, os

 

sys.path.append(os.pardir)

 

import numpy as np

from dataset.mnist import load_mnist

from PIL import Image

import  pickle

import  numpy  as np

 

 

# 신경망 함수들

def sigmoid(num):

    rst = (1 / (1 + np.exp(-num)))

    return (rst)

 

 

#def identity_function(x):

#    return x

 

 

def softmax(a):

    c = np.max(a)

    minus = a - c

    exp_a = np.exp(minus)

    sum_exp_a = np.sum(exp_a)

    y = exp_a / sum_exp_a

    return y

 

def init_network():

    with open("d:\\two_layer_w.pkl",'rb') as f:

 #지금 코드는 2 신경망

#저자가 만든 피클샘플은 3 신경망

#그래서 내꺼 2 신경망 피클 가져온 .

        network = pickle.load(f)       

    return network

 

 

def  predict(network, x):

    W1, W2 = network['W1'], network['W2']

    b1, b2 = network['b1'], network['b2']

 

    a1 = np.dot(x,W1) + b1

    z1 = sigmoid(a1)   

    a2 = np.dot(z1,W2) + b2

    y = softmax(a2)

   

    return  y

 

"""def  get_data():

    (x_train, t_train) , (x_test, t_test) = \

    load_mnist(normalize=True, flatten=True, one_hot_label=False)

    return  x_test, t_test"""

 

#x, t = get_data()  #우리가 손으로 그린 그림 넣어야 되니까

# get_data 함수도 안 씀. mnist 안쓰고

#우리가 만든 그림으로 학습시키니까.

 

network = init_network()

y = predict(network,x)

y1 = np.argmax(y)

print(y1)

 

#print(t[0])

 

(28, 28)

(784,)

5

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90
반응형