본문 바로가기

deeplearning

7장. 합성곱 신경망(CNN)

728x90
반응형

CNN ( 합성곱 신경망 )  Convolution   Neural   Network

합성곱            신경      

합성곱 신경망?

"Convolution 층과 pooling 층을 포함하는 신경망"

 

기존 신경망과의 차이?

-기존 방법: Affine ---> Relu (완전연결계층)

-CNN      : Conv ----> Relu ----> Pooling ----> 완전연결계층

 

CNN 배워야 하는 이유?

-기존에 구현했던 완전 연결 계층(완전연결계층) 문제점

극복하기 위해서

*문제점: 이미지 형상을 무시한다

 

 

 

 

기존에 구현했던 완전 연결 계층의 문제점

"데이터의 형상이 무시된다"

 

http://cafe.daum.net/oracleoracle/SY3L/174

 

*CNN 이용하지 않은 기존층의 문제점

필기체 ---> 28 x 28 = 784 1차원 데이터로 변경해서

784개의 데이터를 Affine 계층에 입력한게

기존방법이다.

 

형상을 무시하고 모든 입력 데이터를 동등한 뉴런으로 취급하기 때문에

이미지가 갖는 본질적인 패턴을 읽지 못한다.

 

그래서 합성곱 계층이 필요하다

 

결국 원본 이미지에서 조금만 모양이 달라져도 같은 이미지로 인식하지

못하는 문제를 합성곱이 해결해 있다.

 

어떻게 해결하는가?

원본 이미지를 가지고 여러개의 feature map 만들어서

분류하는 완전 연결 계층에 입력한다.

 

 

 

 

*합성곱 연산을 컴퓨터로 구현하는 방법

 

1 2 3 0

0 1 2 3        2 0 1  = 15  16

3 0 1 2              0 1 2          6     15

2 3 0 1              1 0 2

입력           필터      결과

데이터        (3,3)      (2,2)

(4,4)

 

 

순서1:

1 2 3      2 0 1      

0 1 2    0 1 2 

3 0 1      1 0 2

  ||  *그냥 곱셈(내적아님)

[[2 0 3]

 [0 1 4]

 [3 0 2]]

 

import numpy as np

a=np.array([[1,2,3],[0,1,2],[3,0,1]])

b=np.array([[2,0,1],[0,1,2],[1,0,2]])

print(np.sum(a*b))

행렬 더한 값이 15

 

 

순서2: 16

순서3:

a=np.array([[0,1,2],[3,0,1],[2,3,0]])

b=np.array([[2,0,1],[0,1,2],[1,0,2]])

print(np.sum(a*b))

 

순서4: 15

 

순서 1,2,3,4 배열시키면

15  16

6    15

 

 

 

문제249.

아래의 행렬을 만들고 합성곱 결과인 15 파이썬으로 출력하시오

import numpy as np

a=np.array([[1,2,3],[0,1,2],[3,0,1]])

filter=np.array([[2,0,1],[0,1,2],[1,0,2]])

print(np.sum(a*filter))

15

 

 

 

문제250.

아래의 4x4 행렬에서 아래의 3x3 행렬만 추출하시오!

 

1 2 3 0

0 1 2 3 ----->  1 2 3

3 0 1 2           0 1 2

2 3 0 1           3 0 1

 

a=np.array([ [1,2,3,0],[0,1,2,3],[3,0,1,2],[2,3,0,1] ])

print(a[ 0:3,0:3])

[[1 2 3]

 [0 1 2]

 [3 0 1]]

 

 

 

 

 

문제251.

아래의 행렬에서 아래의 결과 행렬을 추출하시오

[[2 3 0]

 [1 2 3]

 [0 1 2]]

a=np.array([ [1,2,3,0],[0,1,2,3],[3,0,1,2],[2,3,0,1] ])

print(a[0:3,1:4])

 

합성곱 패턴

a[0:3][0:3]

a[0:3][1:4]

a[1:4][0:3]

a[1:4][1:4]

 

 

 

문제252.

아래의 행렬에서 for loop 문을 이용해서 아래의 결과를 출력하시오

[[1 2 3]

 [0 1 2]

 [3 0 1]]

[[2 3 0]

 [1 2 3]

 [0 1 2]]

[[0 1 2]

 [3 0 1]

 [2 3 0]]

[[1 2 3]

 [0 1 2]

 [3 0 1]]

b=np.array([[1,2,3],[0,1,2],[3,0,1]]) #뽑고자 하는 형태

a=np.array([ [1,2,3,0],[0,1,2,3],[3,0,1,2],[2,3,0,1] ])

# len(a), len(b)  = 4, 3

for i in range(len(a)-len(b)+1):

    for j in range(len(a)-len(b)+1):

        print(a[i:3+i,j:3+j])

 

 

다른답:

import numpy as np

x = np.array([[1,2,3,0],[0,1,2,3],[3,0,1,2],[2,3,0,1]])

for i in range(2):

    for j in range(2):

        x1 = np.array(x[i:i+3, j:j+3])

        print(x1)

 

 

 

 

 

 

문제253.

아래의 합성곱을 파이썬으로 구현하시오

1 2 3 0      

0 1 2 3    2 0 1  = [ 15, 16, 6, 15 ]

3 0 1 2         0  1  2 

2 3 0 1         1  0  2

 

a=np.array([ [1,2,3,0],[0,1,2,3],[3,0,1,2],[2,3,0,1] ])

b=np.array([[2,0,1],[0,1,2],[1,0,2]]) #뽑고자 하는 형태, 또는 필터

result=[]

for i in range(len(a)-len(b)+1): #4 - 3+1 = 0

    for j in range(len(a)-len(b)+1):

        result.append( np.sum( a[i:3+i,j:3+j] * b  ))

print(result)

[15, 16, 6, 15]

 

=====

 

import numpy as np

x = np.array([[1,2,3,0],[0,1,2,3],[3,0,1,2],[2,3,0,1]])

filter = np.array([[2,0,1],[0,1,2],[1,0,2]])

res = []

for i in range(len(x)-2): # 4-2=2 0,1

    for j in range(len(x)-2):

        a = x[i:i+len(x)-1,j:j+len(x)-1]

        res.append(np.sum(a*filter))

print(res)

 

 

 

 

 

 

문제254.

위에서 출력한 1차원 배열인 [15,16, 6, 15] 결과를 2x2 행렬로

변경하시오

[[15 16]

 [ 6 15]]

import numpy as np

a=np.array([ [1,2,3,0],[0,1,2,3],[3,0,1,2],[2,3,0,1] ])

b=np.array([[2,0,1],[0,1,2],[1,0,2]]) #뽑고자 하는 형태, 또는 필터

result=[]

for i in range(len(a)-len(b)+1): #4-3+1 = 0

    for j in range(len(a)-len(b)+1): # 4-3+1 = 0

        result.append( np.sum( a[i:3+i,j:3+j] * b  ))

 

result = np.array(result)

result = result.reshape(2,2)

print(result)

 

 

 

 

문제255.

아래의 그림의 convolution 연산을 파이썬으로 구현하시오!

import numpy as np

a=np.array([ [1,2,3,0],[0,1,2,3],[3,0,1,2],[2,3,0,1] ])

b=np.array([[2,0,1],[0,1,2],[1,0,2]]) #뽑고자 하는 형태, 또는 필터

result=[]

for i in range(len(a)-len(b)+1): #4-3+1 = 0

    for j in range(len(a)-len(b)+1): # 4-3+1 = 0

        result.append( np.sum( a[i:3+i,j:3+j] * b  ))

 

result = np.array(result)

result = result.reshape(2,2)

print ( result + np.array([[3]]) )

[[18 19]

 [ 9 18]]

 

**숫자 3 그냥 더해도 ! 행렬에 자연수 더하는건 알아서 브로드캐스트

 

 

 

패딩(p 231)

 

 

화면 캡처: 2019-01-28 오후 3:44

 

"합성곱 연산을 수행하기 전에 입력 데이터 주변을 특정값으로

채워 늘리는 것을 말한다"

 

-패딩이 필요한 이유?

 

패딩을 하지 않을 경우 data 공간크기는 합성곱 계층이

지날 마다 작아지게 되므로 가장 자리 정보들이 사라지게 되는

문제가 발생하기 때문에

 

4 x 4    3 x 3 = 2 x 2

conv---->pooling-->conv---->pooling

 

 

 

문제256.

문제255번에서 출력한 아래의 2x2 행렬에 제로패딩 1 수행하시오

 

                            0  0     0    0

15   16 ----------->  0 18   19    0

 6    15                  0  9    18   0

                            0  0    0    0      

 

코드:

import numpy as np

a=np.array([ [1,2,3,0],[0,1,2,3],[3,0,1,2],[2,3,0,1] ])

b=np.array([[2,0,1],[0,1,2],[1,0,2]]) #뽑고자 하는 형태, 또는 필터

result=[]

for i in range(len(a)-len(b)+1): #4-3+1 = 0

    for j in range(len(a)-len(b)+1): # 4-3+1 = 0

        result.append( np.sum( a[i:3+i,j:3+j] * b  ))

 

result = np.array(result)

result = result.reshape(2,2)

sum_result =  result + np.array([[3]])

#print(sum_result)

 

pad_result = np.pad(sum_result, pad_width=1, mode='constant', \

                    constant_values=0)

 

print(pad_result)

 

 

결과:

[[ 0  0  0  0]

 [ 0 18 19  0]

 [ 0  9 18  0]

 [ 0  0  0  0]]

 

 

                                0  0     0   0

15   16 ----------->       0 18   19  0

 6    15                       0  9    18  0

                                 0  0    0   0      

 

2 x 2                4 x 4

 

*패딩 1 수행하니, 다시 원본 행렬 형태로 돌아왔다.

*패딩 1 ----->  +2, +2

 

 

 

 

문제257.

4x4 행렬에 3x3 필터를 적용해서 결과로 4x4 행렬이 출력되게 하려면

제로패딩을 해줘야하는가?

 

패딩공식: p234

 

 

       ( OH - 1 ) * S - H + FH

p = -----------------------------

                     2

 

입력크기를 (H, W), 필터크기를 (FH, FW)

출력크기를 (OH, OW), 패딩을 P, 스트라이드 S 라고 한다.

 

      (4-1) * 1 - 4 + 3       3 - 1

P = ------------------  =  ---------  =  1

                2                  2

 

*스트라이드 : 한칸씩 움직이는거 ! 스트라이드 1이면 한칸씩, 2이면 두칸씩.

*출력크기OH 패딩입혀서 나온 최종출력크기

 

 

 

문제258.

위의 패딩 공식을 구현하는 파이썬 함수를 생성하시오

 

def padding(H,S,OH,FH):

   

    p = ( (OH-1)*S - H+FH ) / 2

    return p

   

print(padding(4,1,4,3))

   

 

 

 

문제259.(마지막문제)

아래의 결과가 무엇인지 출력하시오 !

 

입력행렬에 제로패딩을 해서 출력층을 구현하는 것이다.

 

4x4 ----------> 6x6 3x3 ------->4x4

      패딩1                             

 

 

[[0 0 0 0 0 0]

 [0 1 2 3 0 0]

 [0 0 1 2 3 0]

 [0 3 0 1 2 0]

 [0 2 3 0 1 0]

 [0 0 0 0 0 0]]

 

 

[[10 15 13  5]

 [ 7 18 19 13]

 [13  9 18  9]

 [11 13  7  6]]

 

 

def padding(H,S,OH,FH):   

    p = ( (OH-1)*S - H+FH ) / 2

    return int(p)      # int 안씌우면 float 형태로 나와서 pad_width 적용안됨   

#print(padding(4,1,4,3))

 

import numpy as np

s=1

b=np.array( [ [ 3 ] ] )

a=np.array([ [1,2,3,0],[0,1,2,3],[3,0,1,2],[2,3,0,1] ])

a=np.pad(a, pad_width=padding(a.shape[0],s,a.shape[0],filter.shape[0]), \

         mode='constant', constant_values=0)

#print(a)

filter=np.array([[2,0,1],[0,1,2],[1,0,2]]) #뽑고자 하는 형태, 또는 필터

 

result=[]

 

for i in range(len(a)-len(filter)+1): #4-3+1 = 0

    for j in range(len(a)-len(filter)+1): # 4-3+1 = 0

        result.append( np.sum( a[i:3+i,j:3+j] * filter  ))

 

print(np.array(result).reshape(4,4) + b)

 

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

반장답:

import numpy as np

def padding(H,S,OH,FH):

    return int(( (OH -1)*S - H+FH ) / 2)

 

x = np.array([[1, 2, 3, 0], [0, 1, 2, 3], [3, 0, 1, 2], [2, 3, 0, 1]])

y = np.array([[2, 0, 1], [0, 1, 2], [1, 0, 2]])

b = np.array([3])

pad = padding(x.shape[1], 1, x.shape[1], y.shape[1])

 

x_pad = np.pad(x, pad_width = pad, mode = 'constant', constant_values=0)

 

gop = []

for i in range(x_pad.shape[0]-y.shape[0]+1):

    for j in range(x_pad.shape[1] - y.shape[1]+1):

        gop.append(np.sum(x_pad[i:y.shape[0]+i,j:y.shape[1]+j]*y))

 

res = np.array(gop).reshape(i+1,j+1)  #reshape(x_pad.shape[0], x_pad.shape[1] )

res = res+b

print(res)

 

 

 

 

사진을 사진 자체로 인식하게끔 컴퓨터에게 알려주는 방법이 CNN 이다

1. convolution 계층 ---> 이미지의 특징 잡아내는 역할

2. pooling 계층 -------> 흐릿한 이미지를 진하고 뚜렷하게 만들어주는 역할

 

 

 

3차원 합성곱(p 235)

 

이미지의 색깔이 보통은 흑백이 아니라 RGB 컬러이므로

RGB(Red Green Blue) 컬러에 합성곱을 해야 한다.

 

 

 

 

 

 

문제260.

레드벨벳의 아이린 사진을 3차원 행렬로 변환하시오

(jupyter notebook 이용)

from PIL import Image

import numpy as np

import matplotlib.pyplot as plt

import matplotlib.image as mpimg

 

##5.1. 원본 이미지 불러오기

 

img = Image.open('d://아이린.jpg')

img_pixel = np.array(img)  #이미지를 넘파이배열화

plt.imshow(img_pixel)     # 3차원 행렬을 이미지로 뽑아옴

print (img_pixel)    # 3차원 행렬값 출력

 

 

 red  green blue

         

[[[ 79  96 104]  픽셀 하나의 숫자가 0~255 사이로 나타낼 있는데
  [113 118 138]
     숫자가 수록 밝은색이다. (0= 검정색)
  [147 137 172]
  ...,
  [ 50  72  51]
  [ 50  72  51]
  [ 50  72  51]]

 

 

 

 

 

문제261.

아이린 사진의 넘파일 배열로 변환한 행렬에 shape 확인해보시오

print (img_pixel.shape)

(500, 500, 3)

        

가로 세로 색상

*색상: 0-> red

 1-> green

2->blue

 

 

 

 

 

문제262.

아이린 사진에서 red부분의 행렬만 출력하고 red부분만 이미지로 시각화 하시오

from PIL import Image

import numpy as np

import matplotlib.pyplot as plt

import matplotlib.image as mpimg

 

##5.1. 원본 이미지 불러오기

 

img = Image.open('d://아이린.jpg')

img_pixel = np.array(img)

plt.imshow(img_pixel[: , : , 0])

 

#print (img_pixel)

print (img_pixel[: , : , 0] )

 

 

[[[ 79  96 104] 
  [
113 118 138]    
  [
147 137 172]
  ...,
  [ 50  72  51]
  [ 50  72  51]
  [ 50  72  51]]

 

   ↓↓↓↓↓↓↓↓

[[ 79 113 147 ...,  50  50  50]
 [101 137 169 ...,  51  51  50]
 [116 152 181 ...,  49  49  49]

 

*red열만 가져온걸 있다.

**green, blue 값이 0 아니라서, 잔재한다.

 

 

 

 

 

문제263.

아이린 사진에 블루행렬을 시각화 하시오

 

img = Image.open('d://아이린.jpg')

img_pixel = np.array(img)

plt.imshow(img_pixel[:,:,2])

 

#print (img_pixel)

print (img_pixel[:,:,2] )

 

 

 

 

[[[ 79  96 104]
  [113 118
138]    
  [147 137
172]

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

 

[[104 138 172 ...,  51  51  51]
 [128 162 194 ...,  50  50  49]
 [147 181 208 ...,  48  48  48]

 

 

 

 

 

 

문제264.

아래의 3차원 행렬을 시각화 하시오

 

from PIL import Image

import numpy as np

import matplotlib.pyplot as plt

import matplotlib.image as mpimg

 

Filter = np.array([[[255,255,255],

                    [255,255,255],

                    [0,0,0],

                    [255,255,255],

                    [255,255,255]],

                   [[255,255,255],

                    [255,255,255],

                    [0,0,0],

                    [255,255,255],

                    [255,255,255]],

                   [[0,0,0],

                    [0,0,0],

                    [0,0,0],

                    [0,0,0],

                    [0,0,0]],

                   [[255,255,255],

                    [255,255,255],

                    [0,0,0],

                    [255,255,255],

                    [255,255,255]],

                   [[255,255,255],

                    [255,255,255],

                    [0,0,0],

                    [255,255,255],

                    [255,255,255]]], dtype=np.uint8)

 

 

print(Filter.shape)

 

plt.imshow(Filter)

 

(5,    5,    3)

        

가로,세로,색상

 

 

**T 처리 하면 이해가 훨씬 쉽다.

print(Filter.T)

(3, 5, 5)
[[[255 255   0 255 255]
  [255 255   0 255 255]
  [  0   0   0   0   0]
  [255 255   0 255 255]
  [255 255   0 255 255]]

[[255 255   0 255 255]
  [255 255   0 255 255]
  [  0   0   0   0   0]
  [255 255   0 255 255]
  [255 255   0 255 255]]

[[255 255   0 255 255]
  [255 255   0 255 255]
  [  0   0   0   0   0]
  [255 255   0 255 255]
  [255 255   0 255 255]]]

 

위에부터 Red, Green, Blue .

모두 255 더해지면 흰색이 나온다.

0 검은색이다.

 

 

 

 

문제265. 사진에서 red 출력하시오

 

print(Filter[:,:,0])

plt.imshow(Filter[:,:,0])

 

[[255 255   0 255 255]
 [255 255   0 255 255]
 [  0   0   0   0   0]
 [255 255   0 255 255]
 [255 255   0 255 255]]

 

 

 

 

 

문제266.

R,G,B 행렬을 이해하기 위한 아래의 numpy array 이해하시오

 

import numpy as np

 

data = np.array(

       [

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

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

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

          [1, 2, 1, 1, 1],    #  --->  Red

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

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

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

          [0, 0, 0, 0, 2],    # ---->  Green

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

          [2, 0, 2, 2, 2]],

         [[4, 2, 1, 2,2],

          [0, 1, 0, 4,1],      # ---->  Blue

          [3, 0, 6, 2,1],

          [4, 2, 4, 5,4],

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

       ])

print(data.shape)

(  3  ,   5  ,    5   )

              

 

      가로   세로

*이해를 위해 색이 앞으로 출력되게 하셨다함.

 

 

 

 

 

 

문제267.

위의 3차원 행렬의 이미지를 확인하시오

 

*색부터 나오게 해놔서 트랜스 시켜야 한다

 

plt.imshow(data.T)

 

RGB 섞어놔서 까맣게 나오는게 맞다.

 

 

 

 

 

문제268.

위의 3차원 행렬에서 RED 이미지만 출력하시오

print(data.T[:,:,0])

plt.imshow(data.T[:,:,0])

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

 

숫자 2 있는 부분은 밝고, 0 검다.

숫자가 커질수록 밝은색에 가까워진다.

 

 

 

 

 

문제269.

문제 265번에서 만든 filter 이미지 행렬을 이해하기 쉽도록

만든 문제 266 형태로 변경하시오

 

print(Filter.shape)

print(Filter.T.shape)

 

(5, 5, 3)

(3, 5, 5)

 

원래 가로,세로 먼저 나오게 했던것을

T 사용해서 (=3) 부터 나오게 .

 

 

 

문제270.

아래의 코드로 레드십자가를 출력하시오

 

from PIL import Image

import numpy as np

import matplotlib.pyplot as plt

import matplotlib.image as mpimg

 

Filter = np.array([[[255,0,0],

                    [255,0,0],

                    [0,0,0],

                    [255, 0, 0],

                    [255, 0, 0]],

                   [[255,0,0],

                    [255, 0, 0],

                    [0,0,0],

                    [255, 0, 0],

                    [255, 0, 0]],

                   [[0,0,0],

                    [0,0,0],

                    [0,0,0],

                    [0,0,0],

                    [0,0,0]],

                   [[255,0,0],

                    [255, 0, 0],

                    [0,0,0],

                    [255, 0, 0],

                    [255, 0, 0]],

                   [[255,0,0],

                    [255, 0, 0],

                    [0,0,0],

                    [255, 0, 0],

                    [255, 0, 0]]], dtype=np.uint8)

plt.imshow(Filter)

 

 

 

 

 

문제271.

위의 코드를 이용해서 이번에는 Red 아니라 Green 으로 십자가모양의

그림이 출력되게 하시오

from PIL import Image

import numpy as np

import matplotlib.pyplot as plt

import matplotlib.image as mpimg

 

Filter = np.array([[[255,0,0],

                    [255,0,0],

                    [0,0,0],

                    [255, 0, 0],

                    [255, 0, 0]],

                   [[255,0,0],

                    [255, 0, 0],

                    [0,0,0],

                    [255, 0, 0],

                    [255, 0, 0]],

                   [[0,0,0],

                    [0,0,0],

                    [0,0,0],

                    [0,0,0],

                    [0,0,0]],

                   [[255,0,0],

                    [255, 0, 0],

                    [0,0,0],

                    [255, 0, 0],

                    [255, 0, 0]],

                   [[255,0,0],

                    [255, 0, 0],

                    [0,0,0],

                    [255, 0, 0],

                    [255, 0, 0]]], dtype=np.uint8)

plt.imshow(Filter)

 

 

 

 

레드십자가의 원래 행렬값에서 전치시킨

[[[255 255   0 255 255]
  [255 255   0 255 255]
  [  0   0   0   0   0]
  [255 255   0 255 255]
  [255 255   0 255 255]]

[[  0   0   0   0   0]
  [  0   0   0   0   0]
  [  0   0   0   0   0]
  [  0   0   0   0   0]
  [  0   0   0   0   0]]

[[  0   0   0   0   0]
  [  0   0   0   0   0]
  [  0   0   0   0   0]
  [  0   0   0   0   0]
  [  0   0   0   0   0]]]

 

↓↓↓↓↓↓↓↓↓↓

print(Filter.T)

Filter.T[1]=Filter.T[0]

Filter.T[0]=Filter.T[2]

print(Filter.T)

 

plt.imshow(Filter)

↓↓↓↓↓↓↓↓↓↓

[[[  0   0   0   0   0]
  [  0   0   0   0   0]
  [  0   0   0   0   0]
  [  0   0   0   0   0]
  [  0   0   0   0   0]]

[[255 255   0 255 255]
  [255 255   0 255 255]
  [  0   0   0   0   0]
  [255 255   0 255 255]
  [255 255   0 255 255]]

[[  0   0   0   0   0]
  [  0   0   0   0   0]
  [  0   0   0   0   0]
  [  0   0   0   0   0]
  [  0   0   0   0   0]]]

plt.imshow(Filter)

 

우리의 이해를 위해, 간편한 작업을 위해  T처리 했으나

Plt 돌리려면 다시 가로x세로x색상 형태에서 plt.imshow 돌려야 한다.

 

 

 

 

 

문제272.

블루로 바꾸시오

Filter.T[2]=Filter.T[0]   # red=255, green=0, blue=255

Filter.T[0]=Filter.T[1]   # red=0, green=0, blue=255

print(Filter.T)

 

 

 

 

 

문제273.

아이린 사진의 Red 출력하시오!

 

아이린 사진의 Red 행렬만 그대로 두고

아이린 사진의 Green blue 0으로 변경해서 시각화 하시오

from PIL import Image

import numpy as np

import matplotlib.pyplot as plt

import matplotlib.image as mpimg

##5.1. 원본 이미지 불러오기

img = Image.open('d://아이린.jpg')  # 사진 불러오기

img_pixel = np.array(img)  # np 행렬

 

img_pixel.T[1]=0

img_pixel.T[2]=0

print (img_pixel.T)

plt.imshow(img_pixel)

 

 

 

 

 

문제274. 아래의 RGB 3차원 행렬을 zero 패딩 1을 한 결과를 출력하시오!

 

 

import numpy as np

 

data = np.array(

       [

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

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

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

          [1, 2, 1, 1, 1],    #  --->  Red

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

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

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

          [0, 0, 0, 0, 2],    # ---->  Green

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

          [2, 0, 2, 2, 2]],

         [[4, 2, 1, 2,2],

          [0, 1, 0, 4,1],      # ---->  Blue

          [3, 0, 6, 2,1],

          [4, 2, 4, 5,4],

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

       ])

 

print (data.shape)

 

:

data_pad = np.pad(data, pad_width=1, mode='constant',constant_values=0)[1:4]

print(data_pad)

 

[1:4] 해주는 이유는 3차원 행렬이라 구간지정없이 all 해주면

, 뒤로 패드만있는 행렬이 추가된다.

우리가 원하는건 2차원 행렬에 패드 입히는거라서 [1:4] 해준다.

 

[[[0 0 0 0 0 0 0]

  [0 2 2 1 1 0 0]

  [0 0 0 1 0 0 0]

  [0 0 2 0 0 1 0]

  [0 1 2 1 1 1 0] ----------red

  [0 1 0 1 0 1 0]

  [0 0 0 0 0 0 0]]

 

 [[0 0 0 0 0 0 0]

  [0 2 0 0 0 1 0]

  [0 0 2 2 0 1 0]

  [0 0 0 0 0 2 0]-----------green

  [0 0 1 2 0 1 0]

  [0 2 0 2 2 2 0]

  [0 0 0 0 0 0 0]]

 

 [[0 0 0 0 0 0 0]

  [0 4 2 1 2 2 0]

  [0 0 1 0 4 1 0]---------blue

  [0 3 0 6 2 1 0]

  [0 4 2 4 5 4 0]

  [0 0 1 2 0 1 0]

  [0 0 0 0 0 0 0]]]

 

 

 

 

 

문제275.

문제274 결과인 아래의 Red 행렬에서 아래의 행렬만 추출하시오

 

[[[0 0 0 0 0 0 0]

  [0 2 2 1 1 0 0]

  [0 0 0 1 0 0 0]

  [0 0 2 0 0 1 0]

  [0 1 2 1 1 1 0]

  [0 1 0 1 0 1 0]

  [0 0 0 0 0 0 0]]

   

[[0 0 0]

 [0 2 2]

 [0 0 0]]

 

print(data_pad[0][0:3,0:3])

print(data_pad[0, 0:3,0:3])

 

 

 

 

문제276.

문제 275번과 같은 방법으로 green , blue 추출하시오

 

결과:

[[0 0 0]

 [0 2 2]

 [0 0 0]]

[[0 0 0]

 [0 2 0]

 [0 0 2]]

[[0 0 0]

 [0 4 2]

 [0 0 1]]

 

print(data_pad[0][0:3,0:3])

print(data_pad[1][0:3,0:3])

print(data_pad[2][0:3,0:3])

 

print(data1[0,:3,:3])

print(data1[1,:3,:3])

print(data1[2,:3,:3])

 

 

 

문제277.

아래의 Filter 에서 Red 행렬만 추출하시오

 

Filter=np.array([[[1,1,-1,-1,0,0,1,1,0],   \

                  [-1,-1,0,0,-1,1,0,-1,0], \

                  [-1,1,1,-1,1,-1,0,0,-1]]]).reshape(3,3,3)

 

*Filter

[[[ 1  1 -1]

  [-1  0  0]

  [ 1  1  0]]

 

 [[-1 -1  0]

  [ 0 -1  1]

  [ 0 -1  0]]

 

 [[-1  1  1]

  [-1  1 -1]

  [ 0  0 -1]]]

 

 

print(Filter[0,:,:])

plt.imshow(Filter[0,:,:])

 

[[ 1  1 -1]

 [-1  0  0]

 [ 1  1  0]]

 

 

 

 

화면 캡처: 2019-01-29 오전 11:47

 

 

 

 

 

 

 

문제278.

위의 원본 이미지(data) 행렬 Red 행렬과 Filter Red 행렬과의 곱을

아래와 같이 수행하시오

 

[[0 0 0]

 [0 2 2]

 [0 0 0]]

   *

[[ 1  1 -1]

 [-1  0  0]

 [ 1  1  0]]

   ||

 

[[0 0 0]

 [0 0 0]

 [0 0 0]]

 

print( data_pad[0][:3,:3] * Filter[0,:,:] )

***0:3  으로 하면 값이 달라짐

print(data_pad[0,:3,:3]*Filter[0])

 

 

 

문제279.

아래의 원본 이미지 RGB 3개의 행렬과 아래의 필터 RGB 3개의 행렬을

각각 행렬 곱한 원소들을 합친 결과 숫자 하나를 출력하시오

(3차원 합성곱 연산)

 

결과:

[[0 0 0]

 [0 0 0]

 [0 0 0]]

[[ 0  0  0]

 [ 0 -2  0]

 [ 0  0  0]]

[[ 0  0  0]

 [ 0  4 -2]

 [ 0  0 -1]]

 

-1

 

print(data_pad[0,:3,:3]*Filter[0])

print(data_pad[1,:3,:3]*Filter[1])

print(data_pad[2,:3,:3]*Filter[2])

for문을 !

res=0

for i in range(len(data_pad)):

    res+=np.sum(data_pad[i,:3,:3]* Filter[i])

print(res)

 

*Filter[i] 어차피 필터는 3x3 이라서 Filter[0] 이라고 써도 된다.

 

 

 

 

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

위의 원본 이미지(RGB) Filter(RGB)와의 3차원 합성곱을 결과를

출력하시오!

 

스트라이드 = 1

 

[[ -1  -7 -10  -1  -3]

 [  5  -3  -4   7  -5]

 [  3 -13  -2  -1  -6]

 [  2  -2   2  -9  -6]

 [  2   3   7   0  -1]]

 

result=[]

res=[]

 

for i in range(data_pad.shape[1]-Filter.shape[1]  + 1):  # 7 - 3 + 1

   

    for j in range(data_pad.shape[2]-Filter.shape[2] + 1):  #정방형이 아닐경우도 있음

        hap=0

        for k in range(len(data_pad)):  # 0,1,2

            hap+=( np.sum( data_pad[k,i:Filter.shape[1]+i,j:Filter.shape[2]+j] * Filter[k] ) ) 

            #print(hap)

        res.append(hap)

 

res = np.array(res)

out = res.reshape(data.shape[1], data.shape[2])

print(out)

plt.imshow(out)

 

 

 

[[ -1  -7 -10  -1  -3]

 [  5  -3  -4   7  -5]

 [  3 -13  -2  -1  -6]

 [  2  -2   2  -9  -6]

 [  2   3   7   0  -1]]

 

 

다른 방법(for 2개로 해결 하는 방법)

 

 

hap=0

res=[]

for i in range(data_pad.shape[1]-Filter.shape[1] + 1):

   

    for j in range(data_pad.shape[2]-Filter.shape[2] +1):

        hap=np.sum( data_pad[:,i : Filter.shape[1]+i, j : Filter.shape[2]+j ] * Filter)

        res.append(hap)

out = np.array(res).reshape(data.shape[1], data.shape[2])

print(out)

 

 

(5, 5)

print(out.shape) 해보면 결과(feature map) shape

(5, 5) 이다.

입력할 행렬도 (5, 5) 였다.

 

                                        stride:1

        zero padding: 1

            

입력이미지 ------> convolution ------> feature map(output)

      5x5                               7x7 3x3                  5x5

 

 

입력할 때의 shape 5x5 똑같이 5x5 행렬로 출력 하려면

입력할 zero 패딩을 1 해줘야 한다.

 

 

OH = 높이

OW=넓이

 

컬러 부분을 공식 OH 적용시켜보면

 

          5 + 2x1 -3

OH= -------------   +  1   =   5

                1

 

공식으로 output feature map 값의 높이가 5 나오는걸 있다.

마찬가지로 OW 대입하면 넓이가 5 나오는것도 확인할 있다.

 

 

지금까지 내용 정리:

(패딩씌운)원본 이미지1 * 필터 50 ----> feature map 갯수(50)

       7x7                            3x3                       5x5

    

 

       

문제281.

아래와 같이 입력행렬과 필터행렬과 스트라이드와 패딩을 입력받아

출력행렬의 shape 출력하는 함수를 생성하시오 !

import numpy as np

 

def output_size( x, filter, stride, padding ):

    OH = ( x.shape[1] + 2*padding - Filter.shape[1] )/stride +1

    OW = ( x.shape[2] + 2*padding - Filter.shape[2] )/stride +1

    return OH, OW

 

x = np.array([[[2, 2, 1, 1, 0],

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

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

               [1, 2, 1, 1, 2],

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

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

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

               [0, 0, 0, 0, 2],

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

               [2, 0, 2, 2, 2]],

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

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

               [0, 2, 2, 0, 0],

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

               [1, 1, 2, 1, 1]]])

 

 

Filter=np.array([[[1,1,-1,-1,0,0,1,1,0],   \

                  [-1,-1,0,0,-1,1,0,-1,0], \

                  [-1,1,1,-1,1,-1,0,0,-1]]]).reshape(3,3,3)

   

stride = 1

padding = 1

 

                

print ( output_size( x , Filter, stride, padding ) )

 

 

 

 

블록으로 생각하기(p 237)

3차원 합성곱 연산은 데이터와 필터를 직육면체 블럭이라고 생각하면

쉽다.

*C = 채널 = RGB

블럭은 3차원 직육면체(채널  ,  높이  ,  너비) 구성됨.

                               C        H         W

 

필터의 채널(FC) , 필터의 높이(FH) , 필터의 너비(FW)

설명 : 아이린 사진 (RGB) RGB 필터 1 합성곱해서

2차원 출력행렬(feature map) 1장을 출력한 그림

    

위의 그림은 feature map 개가 나오고 있는데

실제로는 아이린 사진 장에 대해서 여러개의 feature map 필요하다.

그러면 여러개의 feature map 출력하려면 어떻게 해야 하는가?

   

"filter 갯수를 늘린다"

   

 

RGB 필터 FN 합성곱 시키는 그림이다.

 

 

문제282.

설현사진 50장과 아이린사진 50, 100장의 사진을

신경망에 입력해서 설현, 아이린을 구분(분류)하는 신경망을 만든다고 ,

RGB 필터를 30개를 사용하면 출력 feature map 일까?

 

100 ---> conv ---> (100*30=)3000

* 1장당 30개의 필터가 적용 되는 것이다 .

 

그림에서 편향을 더하면?

 

 

*편향은 필터랑 갯수가 같은데, 브로드캐스트 되서 3천개가 된다.

 

 

 

 

배치처리 (p 239)

그림은 이미지를 1장씩 집어넣어서 학습 시키므로 학습 속도가 느리다.

그래서 여러장의 이미지를 번에 입력해서 학습시키면(mini batch)

아래의 그림이 된다.

 

 

아이린 사진10 --> 필터의 갯수 100 --> (10*100, 5, 5)

                                                               

아이린 사진 1 만들어지는 100개의 feature map 10개가 생성

(100개씩 10= 1000)

 

그러면 결국 합성곱 계층을 구현할

흘러가는 행렬이 4차원 행렬 흘러가면서 연산이 것인데

그러면 문제가 연산 속도가 느리므로 행렬 계산을

행렬 연산을 빠르게 하려면 4차원이 아니라 2차원으로

차원축소가 필요하다.

 

그래서 필요한 함수?

" im2col 함수 "

    

4차원 ---> 2차원

 

im2col 함수 역할을 그림으로 표현(p 243)

 

 

문제283.

자료에 나온 아이린 사진 장의 3차원 행렬을 만드시오

(RGB 7x7 행렬 1)

 

import numpy as np

x1 = np.random.randn(1,3,7,7) # 1, RGB, 가로, 세로

print(x1)

print(x1.shape)

 

 

 

문제284.

im2col 함수를 이용해서 아래의 4차원을 2차원 행렬로 변경하시오

(필터는 5x5 RGB 행렬을 사용함)

 

def im2col(input_data, filter_h, filter_w, stride=1, pad=0):

    """다수의 이미지를 입력받아 2차원 배열로 변환한다(평탄화).

 

    Parameters

    ----------

    input_data : 4차원 배열 형태의 입력 데이터(이미지 수, 채널 수, 높이, 너비)

    filter_h : 필터의 높이

    filter_w : 필터의 너비

    stride : 스트라이드

    pad : 패딩

 

    Returns

    -------

    col : 2차원 배열

    """

    N, C, H, W = input_data.shape

    out_h = (H + 2 * pad - filter_h) // stride + 1

    out_w = (W + 2 * pad - filter_w) // stride + 1

 

    img = np.pad(input_data, [(0, 0), (0, 0), (pad, pad), (pad, pad)], 'constant')

    col = np.zeros((N, C, filter_h, filter_w, out_h, out_w))

 

    for y in range(filter_h):

        y_max = y + stride * out_h

        for x in range(filter_w):

            x_max = x + stride * out_w

            col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride]

 

    col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N * out_h * out_w, -1)

    return col

 

import numpy as np

x1 = np.random.randn(1,3,7,7) # if one photo

col = im2col(x1, 5,5,stride=1,pad=0)

print(col.shape)

 # 아이린 사진 1장을 5개의 윈도우로 1씩 스트라이드 하면  9, 75 가 나온다.

 

 

 

 

문제285.

아이린 사진 10장을 랜덤으로 생성하시오.

 

import numpy as np

x1 = np.random.randn(10,3,7,7) # if one photo

print(x1.shape)

 

 

 

 

문제286.

아이린 사진 10장을 im2col 함수에 넣어서 2차원 행렬로 변환 시키시오

(필터 :  5x5 RGB 행렬 사용)

 

  4차원 ----------------->2차원

(10,3,7,7)                    (90,75)

 

import numpy as np

x1 = np.random.randn(10,3,7,7) # if one photo

col = im2col(x1, 5,5,stride=1,pad=0)

print(col.shape) 

# 아이린 사진 10 5개의 윈도우로 1씩 스트라이드 하면 90,75가 나온다.

(90, 75)

 

 

 

필터 RGB 행렬을 2차원으로 푸는 방법

1. 원본 이미지를 필터 사이즈에 맞게 2차원으로 변경한 행렬

(10, 3, 7, 7) ---------------------->(90, 7)

                       im2col 함수

 

2. 4차원 필터 행렬을 2차원으로 변경

(10, 3, 5, 5) -------------------->(75, 10)

          reshape 함수의 -1 이용

 

 

문제287. 아래의 filter 생성하고 shape 확인하고서 전치시키시오

Filter = np.array([[[255,255,255],[255,255,255],[0,0,0],[255,255,255],[255,255,255]],

                   [[255,255,255],[255,255,255],[0,0,0],[255,255,255],[255,255,255]],

                   [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]],

                   [[255,255,255],[255,255,255],[0,0,0],[255,255,255],[255,255,255]],

                   [[255,255,255],[255,255,255],[0,0,0],[255,255,255],[255,255,255]]], dtype  = np.uint8)

 

print(Filter.shape)

print(Filter.T.shape)

(5, 5, 3)

(3, 5, 5)

 

 

 

문제288.

Filter(3,5,5) 행렬을 (3,25) 행렬로 변경하시오

 

a =Filter.T.reshape(3,-1) 

print(a.shape)

 

(3, 25)

*reshape -1 지정하면 다차원 배열의 원소 수가 변환 후에도

똑같이 유지되도록 절절히 묶어줍니다.

 

 

 

 

문제289. 아래의 4차원 행렬의 filter numpy random

         이용해서 만드시오 !

 

    (10,3,5,5)  <--- 4차원 행렬 ( RGB 5X5 필터 10)

 

import  numpy  as  np

filter_4dim = np.random.rand(10,3,5,5)

print (filter_4dim.shape)

 

 

 

문제290.

아래의 4차원 행렬을 3차원으로 변경하시오

(10, 3, 5, 5) ----------------------> (10, 3, 25)

   4차원 --------------------------->  3차원

 

import  numpy  as  np

filter_4dim = np.random.rand(10,3,5,5)

print (filter_4dim.shape)

 

filter_3dim = filter_4dim.reshape(10,3,-1)

print(filter_3dim.shape)

 

(10, 3, 5, 5)

(10, 3, 25)

 

 

 

 

 

문제291.

아래의 3차원 행렬을 2차원 행렬로 변경하시오

(10, 3, 25) ----------->(10, 75)

 3차원                2차원

 

 

import  numpy  as  np

filter_4dim = np.random.rand(10,3,5,5)

print (filter_4dim.shape)

 

filter_3dim = filter_4dim.reshape(10,3,-1)

print(filter_3dim.shape)

 

filter_2dim = filter_3dim.reshape(10,-1)

print(filter_2dim.shape)

(10, 3, 5, 5)

(10, 3, 25)

(10, 75)

 

 

 

 

문제292.

아래의 2차원을 1차원 행렬로 변경하시오 !

(10, 75) ----------->(750, )

 2차원             1차원

 

import  numpy  as  np

filter_4dim = np.random.rand(10,3,5,5)

print (filter_4dim.shape)

 

filter_3dim = filter_4dim.reshape(10,3,-1)

print(filter_3dim.shape)

 

filter_2dim = filter_3dim.reshape(10,-1)

print(filter_2dim.shape)

 

filter_1dim = filter_2dim.reshape(-1)

print(filter_1dim.shape)

 

 

(10, 3, 5, 5)

(10, 3, 25)

(10, 75)

(750,)

 

 

 

 

문제293.

문제 279번의 3차원 합성곱 코드를 2차원의 행렬 내적으로 수행해도

결과가 같은지 확인하시오

 

문제279.

아래의 원본 이미지 RGB 3개의 행렬과 아래의 필터 RGB 3개의 행렬을

각각 행렬 곱한 후 그 원소들을 다 합친 결과 숫자 하나를 출력하시오

(3차원 합성곱 연산)

 

결과:

[[0 0 0]

 [0 0 0]

 [0 0 0]]

[[ 0  0  0]

 [ 0 -2  0]

 [ 0  0  0]]

[[ 0  0  0]

 [ 0  4 -2]

 [ 0  0 -1]]

 

-1

 

print(data_pad[0,:3,:3]*Filter[0])

print(data_pad[1,:3,:3]*Filter[1])

print(data_pad[2,:3,:3]*Filter[2])

for문을 !

res=0

for i in range(len(data_pad)):

    res+=np.sum(data_pad[i,:3,:3]* Filter[i])

print(res)

 

 

 

1. 3차원 합성곱의 하나의 스트라이드의 합성곱을 구현

 

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

 [0 2 2]     *  -1  0  0  =  0  0  0

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

 

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

 [0 2 0]     *   0 -1  1  =  0 -2  0

 [0 0 2]]        0 -1  0     0  0  0

 

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

 [0 4 2]     *  -1  1 -1  =  0  4  -2

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

 

 

 

원본이미지를 1차원으로 변경한 행렬의 shape? (1 , 27)

[ 0 ,0 ,0 ,0 ,2 ,2 ,0 ,0 ,0 , 0 ,0 ,0 ,0 ,2 ,0 ,0 ,0 ,2 ,0 ,0 ,0 ,0 ,4 ,2 ,0 ,0  ,1  ] 

 

 

Filter 1차원으로 변경하면? (1 , 27)

[ 1, 1, -1, -1, 0, 0, 1, 1, 0, -1, -1, 0, 0, -1, 1, 0, -1, 0, -1,1,1,-1,1,- 1,0,0,-1]

 

내적 시키려면??

1x27 1x27  불가능! 그러면

전치(Trans) 시킨다 !

1x27 27x1

 

import numpy as np

origin=np.array( [ 0 ,0 ,0 ,0 ,2 ,2 ,0 ,0 ,0 , 0 ,0 ,0 ,0 ,2 ,0 ,0 ,0 ,2 ,0 ,0 ,0 ,0 ,4 ,2 ,0 ,0  ,1  ])

Filter =np.array([ 1, 1, -1, -1, 0, 0, 1, 1, 0, -1, -1, 0, 0, -1, 1, 0, -1, 0, -1,1,1,-1,1,- 1,0,0,-1])

print(np.dot(origin, Filter.T) )

-1

 

*우리가 예로 든건 1차원,1 배열이라 전치안시켜도 내적연산이 가능하다.

 

 

 

 

 

 

 

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

아래의 입력값과 Filter 행렬을 점심시간 문제로 3차원 합성곱을 했었다.

그래서 결과가 아래와 같이 나왔다.

그런데 이번에는 3차원 합성곱하지 말고 차원을 축소시켜서 아래의 결과를

출력하시오

 

결과:

[[ -1  -7 -10  -1  -3]

 [  5  -3  -4   7  -5]

 [  3 -13  -2  -1  -6]

 [  2  -2   2  -9  -6]

 [  2   3   7   0  -1]]

 

 

입력값과 필터값:

x = np.array([[[2, 2, 1, 1, 0],

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

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

               [1, 2, 1, 1, 2],

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

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

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

               [0, 0, 0, 0, 2],

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

               [2, 0, 2, 2, 2]],

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

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

               [0, 2, 2, 0, 0],

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

               [1, 1, 2, 1, 1]]])

 

 

Filter=np.array([[[1,1,-1,-1,0,0,1,1,0],   \

                  [-1,-1,0,0,-1,1,0,-1,0], \

                  [-1,1,1,-1,1,-1,0,0,-1]]]).reshape(3,3,3)

 

 

from PIL import Image

import numpy as np

import matplotlib.pyplot as plt

import matplotlib.image as mpimg

 

 

def im2col(input_data, filter_h, filter_w, stride=1, pad=0):

    """다수의 이미지를 입력받아 2차원 배열로 변환한다(평탄화).

 

    Parameters

    ----------

    input_data : 4차원 배열 형태의 입력 데이터(이미지 수, 채널 수, 높이, 너비)

    filter_h : 필터의 높이

    filter_w : 필터의 너비

    stride : 스트라이드

    pad : 패딩

 

    Returns

    -------

    col : 2차원 배열

    """

    N, C, H, W = input_data.shape

    out_h = (H + 2 * pad - filter_h) // stride + 1

    out_w = (W + 2 * pad - filter_w) // stride + 1

 

    img = np.pad(input_data, [(0, 0), (0, 0), (pad, pad), (pad, pad)], 'constant')

    col = np.zeros((N, C, filter_h, filter_w, out_h, out_w))

 

    for y in range(filter_h):

        y_max = y + stride * out_h

        for x in range(filter_w):

            x_max = x + stride * out_w

            col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride]

 

    col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N * out_h * out_w, -1)

    return col

 

 

data = np.array(

      [

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

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

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

        [1, 2, 1, 1, 1],    #  --->  Red

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

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

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

        [0, 0, 0, 0, 2],    # ---->  Green

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

        [2, 0, 2, 2, 2]],

       [[4, 2, 1, 2,2],

        [0, 1, 0, 4,1],      # ---->  Blue

        [3, 0, 6, 2,1],

        [4, 2, 4, 5,4],

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

      ])

 

#print (data_pad.shape)

#print(data.T.shape)

 

data_pad = np.pad(data, pad_width=1, mode='constant',constant_values=0)[1:4]

 

 

Filter=np.array([[[1,1,-1,-1,0,0,1,1,0],   \

                  [-1,-1,0,0,-1,1,0,-1,0], \

                  [-1,1,1,-1,1,-1,0,0,-1]]]).reshape(3,3,3)

 

col = im2col(data_pad.reshape(1,3,7,7), Filter.shape[1],Filter.shape[2],stride=1,pad=0)

print(col.shape) 

print( np.dot( col , Filter.reshape(-1).T).reshape(5,5) )

*reshape -1 하나만 하면 바로 1차원으로 처리된다

 

(25, 27)

[[ -1.  -7. -10.  -1.  -3.]

 [  5.  -3.  -4.   7.  -5.]

 [  3. -13.  -2.  -1.  -6.]

 [  2.  -2.   2.  -9.  -6.]

 [  2.   3.   7.   0.  -1.]]

 

im2col 함수 input 값이 4차원으로 정해져 있어서

우리의 input 값을 4차원으로 바꿔서 입력시켜야 한다.

 

 

 

convolution 클래스내에서 일어나는

1. 원본이미지를 im2col 2차원 행렬로 변경한다.

2. filter reshape -1 옵션을 이용해서 2차원 행렬로 변경한다.

3. 개의 2차원 행렬을 내적한다.

4. 내적한 결과 2차원 행렬을 다시 4차원으로 변경한다.

 

 

convolution 층의 역할? 이미지의 특징을 추출하는 feature map

여러개 만든다.

 

 

 

 

 

2차원을 4차원으로 배열

 

문제295.

어제 마지막 문제는 4차원 행렬 원본이미지와 4차원 행렬 필터를

2차원으로 차원 축소하여 내적한 결과이다

2차원 결과를 다시 4차원으로 변경하시오

 

(N=배치갯수 ,  출력행렬의 높이, 출력행렬의 너비, C=필터갯수)

 

out.reshape(배치갯수, 출력행렬의 높이, 출력행렬의 너비, -1)

    

feature map 갯수

(filter 갯수)

 

지엽코드:

import numpy as np

import matplotlib.pyplot as plt

data = np.array(

    [

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

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

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

         [1, 2, 1, 1, 1],    #  --->  Red

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

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

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

         [0, 0, 0, 0, 2],    # ---->  Green

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

         [2, 0, 2, 2, 2]],

        [[4, 2, 1, 2,2],

         [0, 1, 0, 4,1],      # ---->  Blue

         [3, 0, 6, 2,1],

         [4, 2, 4, 5,4],

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

    ])

Filter=np.array([[[1,1,-1,-1,0,0,1,1,0], \

                  [-1,-1,0,0,-1,1,0,-1,0], \

                  [-1,1,1,-1,1,-1,0,0,-1]]]).reshape(3,3,3)

data_pad=np.pad(data, pad_width=1, mode='constant', constant_values=0)[1:4]

# 0번째랑 4번째에 0으로만 채워진 게 있어서 [1:4]

 

# im2col 함수

def im2col(input_data, filter_h, filter_w, stride=1, pad=0):

    """다수의 이미지를 입력받아 2차원 배열로 변환한다(평탄화).

    Parameters

    ----------

    input_data : 4차원 배열 형태의 입력 데이터(이미지 수, 채널 수, 높이, 너비)

    filter_h : 필터의 높이

    filter_w : 필터의 너비

    stride : 스트라이드

    pad : 패딩

    Returns

    -------

    col : 2차원 배열

    """

    N, C, H, W = input_data.shape

    out_h = (H + 2 * pad - filter_h) // stride + 1

    out_w = (W + 2 * pad - filter_w) // stride + 1

    img = np.pad(input_data, [(0, 0), (0, 0), (pad, pad), (pad, pad)], 'constant')

    col = np.zeros((N, C, filter_h, filter_w, out_h, out_w))

    for y in range(filter_h):

        y_max = y + stride * out_h

        for x in range(filter_w):

            x_max = x + stride * out_w

            col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride]

    col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N * out_h * out_w, -1)

    return col

 

data_pad=data_pad.reshape(1,3,7,7)  # im2col 사용하기 위해 4차원으로 변경, 배치 사이즈 1

Filter=Filter.reshape(1,3,3,3).reshape(1,-1)  # 4차원 변경 후 2차원 변경

 

col=im2col(data_pad, 3, 3, stride=1,pad=0)  # 여기서 .이 찍히는데 실수 값 처리한듯.

temp=np.array( [np.dot(col, Filter.T)] )  # 내적한 결과값 리스트

 

temp2 = temp.reshape(   1   ,   5   ,   5   ,    -1    )

                                                         

                              N     H    W    C

 

# N: 갯수,   H: 높이,   W: 너비,   C: 채널

                               

print (temp2)

print(temp2.shape)

(1, 5, 5, 1)

 

[[[[ -1.]

   [ -7.]

   [-10.]

   [ -1.]

   [ -3.]]

 

  [[  5.]

   [ -3.]

   [ -4.]

   [  7.]

   [ -5.]]

 

  [[  3.]

   [-13.]

   [ -2.]

   [ -1.]

   [ -6.]]

 

  [[  2.]

   [ -2.]

   [  2.]

   [ -9.]

   [ -6.]]

 

  [[  2.]

   [  3.]

   [  7.]

   [  0.]

   [ -1.]]]]

 

 

 

-- 아이린 사진 한장

 import  numpy  as  np

 

 x1 = np.random.rand(   1   ,   3   ,   7   ,   7   )                                        

                      

                            N     C    H    W

 

 print (x1)

 print (x1.shape)

print (temp2)

   

*비교

 

temp2 = temp.reshape(   1   ,   5   ,   5   ,    -1    )

                                                         

                              N     H    W    C

 

# N: 갯수,   H: 높이,   W: 너비,   C: 채널

 

 

 

 

문제296.

문제295번의 4차원 결과를 아이린 사진과 같은 4차원 결과로 출력되게 하시오

(p.247)

 

-- 아이린 사진 한장

 import  numpy  as  np

 

 x1 = np.random.rand(   1   ,   3   ,   7   ,   7   )                                        

                      

                            N     C    H    W

 

 

temp2 = temp.reshape(   1   ,   5   ,   5   ,    -1    )

                                                         

                              N     H    W    C

 

temp2 = temp.reshape(1,5,5,-1).transpose(0,3,1,2)

(1, 1, 5, 5)

-1 FN 바뀔때마다 알아서 넣는다.

 

 

 

 

 

 

 

 

문제297.

246페이지에 나오는 Convolution 클래스를 생성하시오

class Convolution:

    def __init__(self, W, b, stride=1, pad=0):

        self.W = W

        self.b = b

        self.stride = stride

        self.pad = pad

       

    def forward(self, x):

        FN, C, FH, FW = self.W.shape

        N, C, H, W = x.shape

        out_h = int(1 + (H + 2*self.pad - FH)/self.stride)

        out_w = int(1 + (W + 2*self.pad - FW)/self.stirde)

       

        col = im2col(x, FH, FW, self.stride, self.pad)

        col_W = self.W.reshape(FN, -1).T  #필터전개

        out = np.dot(col, col_W) + self.b

       

        out = out.reshape(N, out_h, out_w, -1).transpose(0,3,1,2)

       

        return out

 

 

 

문제298.

책의 그림 아래의 그림 7-28 앞의 convolution 층을 통과한

결과의 feature map shape 출력하시오

 

 

 

                      #50176 = 224x224x3

x=np.arange(150528).reshape(1,3,224,224) #원본이미지

                      

                               #34848 = 96x11x11x3

filter = np.arange(34848).reshape(96,3,11,11) #filter  11x11 짜리 96

 

b1 = 1 # bias

conv1=Convolution(filter, b1, 4, 2)   #스트라이드=1, 패드=2

#패드값은 OH 공식을 통해 최종값 55 나오는지 확인해서

#소현이가 알아낸

fe_map = conv1.forward(x)

print("fe_map shape", fe_map.shape)

:

fe_map shape (1, 96, 55, 55)

 

 

 

 

화면 캡처: 2019-01-30 오전 11:12

 

 

 

 

풀링(pooling)층의 역할

convolution 층이 이미지의 특징을 잡아내는 역할을 한다면

pooling 층은 이미지를 선명하게 만드는 역할을 한다

" 그대로 출력값에서 일부분만 취하는 기능"

 

convolution 층이 이렇게 저렇게 망쳐놓은 그림들을 가지고

feature map 이미지의 부분에서 대표들을 뽑아 사이즈가 작은

이미지를 만드는 것이다.

 

마치 사진을 축소하면 해상도가 좋아지는 듯한 효과와 비슷하다.

 

 

*풀링(pooling) 종류 3가지

1. 최대풀링: convolution 데이터에서 가장 값을 대표값으로 선정(맥스풀링)

2. 평균폴링: convolution 데이터에서 모든값의 평균값을 대표값으로 선정

3. 확률적 풀링: convolution 데이터에서 임의 확률로 개를 선정

 

 

최대풀링(=맥스풀링, 아래그림-스트라이드 2)

 

최댓값만 취하면서 선명하게 만들어 준다.

 

 

 

 

문제299.

파이썬으로 아래의 행렬을 만들고 max pooling 시도해서

아래의 결과를 출력하시오

[[21  8  8 12]

 [12 19  9  7]

 [ 8 10  4  3]

 [18 12  9 10]]

 

코드:

import numpy as np

x=[21,8,8,12,12,19,9,7,8,10,4,3,18,12,9,10]

 

def max_pooling(x,stride):

   

    res=[]

    for i in range(0, len(x)-1, stride):

        for j in range(0, len(x)-1, stride):

            res.append( np.max(x[ i : i+stride , j : stride+j ])  )

    res = np.array(res)

    return res.reshape(stride,stride)

   

x= np.array(x)

x=x.reshape(4,4)

stride=2

 

print(max_pooling(x,stride))

 

결과:

[[21 12]

 [18 10]]

 

 

 

 

 

문제300.

아래의 입력 이미지 행렬(4x4) 4차원으로 변경한

im2col 함수에 입력해서 결과를 출력하시오

( stride = 2,  padding = 0 )

 

[[21  8  8 12]                            

 [12 19  9  7]

 [ 8 10  4  3]

 [18 12  9 10]]

  

[[21 12]

 [18 10]]

 

 

x = np.array([[[21,8,8,12],[12,19,9,7],[8,10,4,3],[18,12,9,10]],

              [[19,8,7,12],[1,19,9,7],[4,2,4,3],[4,12,9,10]],

              [[2,8,8,12],[10,19,9,7],[5,6,4,3],[1,12,9,12]]])

print(x)

 

x2 = x.reshape(1,3,4,4)

print(x2.shape)

(1, 3, 4, 4)  # 4차원으로 만들었음! im2col 적용 준비 !

 

[[[[21  8  8 12]

   [12 19  9  7]

   [ 8 10  4  3]

   [18 12  9 10]]

 

  [[19  8  7 12]

   [ 1 19  9  7]

   [ 4  2  4  3]

   [ 4 12  9 10]]

 

  [[ 2  8  8 12]

   [10 19  9  7]

   [ 5  6  4  3]

   [ 1 12  9 12]]]]

 

 

print( im2col(input_data=x2, filter_h=2, filter_w=2, stride=2, pad=0) )

                                                   

*filter_h filter_w pooling 가로, 세로값으로 적용시키자

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

 

[[ 21.   8.  12.  19.  19.   8.   1.  19.   2.   8.  10.  19.]  # RGB 순서로 풀어놓았다.

 [  8.  12.   9.   7.   7.  12.   9.   7.   8.  12.   9.   7.]

 [  8.  10.  18.  12.   4.   2.   4.  12.   5.   6.   1.  12.]

 [  4.   3.   9.  10.   4.   3.   9.  10.   4.   3.   9.  12.]]

 

*2차원 행렬로 변환된걸 있다.

 

근데

 

4x4 행렬의 max pooling 값을 찾아내려면 4x4 형태로 바꿔줘야 한다.

print( res.reshape(-1,4) )

행은 모르겠으니 -1. 알아서 하고, 열은 4 맞춰라

 

형태가 변환되었다

↓↓↓↓↓↓↓↓↓↓↓

 

[[ 21.   8.  12.  19.]

 [ 19.   8.   1.  19.]

 [  2.   8.  10.  19.]    ------------> red

 [  8.  12.   9.   7.]

 

 [  7.  12.   9.   7.]

 [  8.  12.   9.   7.]

 [  8.  10.  18.  12.] -------------> green

 [  4.   2.   4.  12.]

 

 [  5.   6.   1.  12.]

 [  4.   3.   9.  10.]

 [  4.   3.   9.  10.] --------------> blue

 [  4.   3.   9.  12.]]

 

 

그래서 위의 상태에서 행의 최대값을 가져오면 된다.

res2 = np.max(res1, axis=1)

print(res2)

[ 21.  19.  19.  12.  12.  12.  18.  12.  12.  10.  10.  12.]

 

 

 

 

원본이미지에서 maxpooing 한 결과를 아래와 같이 구현

 

 

[[[[21  8  8 12]

   [12 19  9  7]

   [ 8 10  4  3]     ---->   21  12

   [18 12  9 10]]            18  10

 

  [[19  8  7 12]    ---->    19  12 

   [ 1 19  9  7]                 12  10

   [ 4  2  4  3]

   [ 4 12  9 10]]

 

  [[ 2  8  8 12]    ---->   19  12

   [10 19  9  7]              12  12 

   [ 5  6  4  3]

   [ 1 12  9 12]]]]

 

 

 

 

 

문제303. 아래그림처럼 출력되게하시오 !

 

 

화면 캡처: 2019-01-30 오후 2:05

 

x = np.array([[[21,8,8,12],[12,19,9,7],[8,10,4,3],[18,12,9,10]],

              [[19,8,7,12],[1,19,9,7],[4,2,4,3],[4,12,9,10]],

              [[2,8,8,12],[10,19,9,7],[5,6,4,3],[1,12,9,12]]])

x2 = x.reshape(1,3,4,4)

print(x2)

 

res= im2col(input_data=x2, filter_h=2, filter_w=2, stride=2, pad=0)

 

res1 = res.reshape(-1,4)

print(res1)

res2 = np.max(res1, axis=1)

print(res2)

 

print(res2.reshape(   1   ,   2   ,   2   ,   -1   ))

                                             

                  사진1 풀링 풀링  res2(채널값_ 근데 알아서 해라)

                            가로  세로

[[[[ 21.  19.  19.]

   [ 12.  12.  12.]]

 

  [[ 18.  12.  12.]

   [ 10.  10.  12.]]]]

 

아래 행렬은 뒷블럭 .

 

정리

 

"""

res= im2col(input_data=x2, filter_h=2, filter_w=2, stride=2, pad=0)

res1 = res.reshape(-1,4)

print("im2col 나온2차원을 4열로 reshape\n",res1)

res2 = np.max(res1, axis=1)

print("reshape 행의 최대값\n",res2)

 

print("행최대값에 다시 reshape 1,2,2,-1\n",res2.reshape(1,2,2,-1))

 

res3 = res2.reshape(1,2,2,-1)

print("transpose 시킨 \n",res3.transpose(0,3,1,2))

"""

행렬:1,3,4,4

 [[[[21  8  8 12]

   [12 19  9  7]

   [ 8 10  4  3]

   [18 12  9 10]]

 

  [[19  8  7 12]

   [ 1 19  9  7]

   [ 4  2  4  3]

   [ 4 12  9 10]]

 

  [[ 2  8  8 12]

   [10 19  9  7]

   [ 5  6  4  3]

   [ 1 12  9 12]]]]

im2col 나온2차원을 4열로 reshape

 [[ 21.   8.  12.  19.]

 [ 19.   8.   1.  19.]

 [  2.   8.  10.  19.]

 [  8.  12.   9.   7.]

 [  7.  12.   9.   7.]

 [  8.  12.   9.   7.]

 [  8.  10.  18.  12.]

 [  4.   2.   4.  12.]

 [  5.   6.   1.  12.]

 [  4.   3.   9.  10.]

 [  4.   3.   9.  10.]

 [  4.   3.   9.  12.]]

reshape 행의 최대값

 [ 21.  19.  19.  12.  12.  12.  18.  12.  12.  10.  10.  12.]

행최대값에 다시 reshape 1,2,2,-1

 [[[[ 21.  19.  19.]

   [ 12.  12.  12.]]

 

  [[ 18.  12.  12.]

   [ 10.  10.  12.]]]]

 

 

 

문제304.

위의 결과로 아래의 결과를 출력하시오

( 249 pooling클래스)

[[[[ 21.  12.]

   [ 18.  10.]]

 

  [[ 19.  12.]

   [ 12.  10.]]

 

  [[ 19.  12.]

   [ 12.  12.]]]]

 

print("행최대값에 다시 reshape 1,2,2,-1\n",res2.reshape(1,2,2,-1))

res3 = res2.reshape(1,2,2,-1)

print("transpose 시킨 \n",res3.transpose(0,3,1,2))

 

N  H  W  C ---->  N  C  H  W

 

,

0 1 2

 

2 0 1

 

 

화면 캡처: 2019-01-30 오후 2:12

 

 

 

 

문제305.

위의 일련의 과정을 하나로 묶은 것이 249페이지의 pooling 클래스입니다

클래스 생성하시오.

 

class Pooling:

    def __init__(self, pool_h, pool_w, stride=1, pad=0):

        self.pool_h = pool_h

        self.pool_w = pool_w

        self.stride = stride

        self.pad = pad

       

    def forward(self, x):

        N, C, H, W = x.shape

        out_h = int(1 + ( H - self.pool_h ) / self.stride)

        out_w = int(1 + ( W - self.pool_w ) / self.stride)

       

        #전개(1)

        col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad)

        col = col.reshape(-1, self.pool_h * self.pool_w)

       

       

        #최댓값(2)

        out = np.max(col, axis=1)

       

       

        #성형(3)

        out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2)

       

        return out

 

 

 

 

문제306.

위에서 만든 pooling 클래스를 객체화 시켜서

아래의 원본 이미지의 maxpooling 결과를 출력하시오

 

x = np.array([[[21,8,8,12],[12,19,9,7],[8,10,4,3],[18,12,9,10]],

              [[19,8,7,12],[1,19,9,7],[4,2,4,3],[4,12,9,10]],

              [[2,8,8,12],[10,19,9,7],[5,6,4,3],[1,12,9,12]]])

x2 = x.reshape(1,3,4,4)

 

결과:

[[[[ 21.  12.]

   [ 18.  10.]]

 

  [[ 19.  12.]

   [ 12.  10.]]

 

  [[ 19.  12.]

   [ 12.  12.]]]]

 

코드:

# im2col 함수

def im2col(input_data, filter_h, filter_w, stride=1, pad=0):

    """다수의 이미지를 입력받아 2차원 배열로 변환한다(평탄화).

    Parameters

    ----------

    input_data : 4차원 배열 형태의 입력 데이터(이미지 수, 채널 수, 높이, 너비)

    filter_h : 필터의 높이

    filter_w : 필터의 너비

    stride : 스트라이드

    pad : 패딩

    Returns

    -------

    col : 2차원 배열

    """

    N, C, H, W = input_data.shape

    out_h = (H + 2 * pad - filter_h) // stride + 1

    out_w = (W + 2 * pad - filter_w) // stride + 1

    img = np.pad(input_data, [(0, 0), (0, 0), (pad, pad), (pad, pad)], 'constant')

    col = np.zeros((N, C, filter_h, filter_w, out_h, out_w))

    for y in range(filter_h):

        y_max = y + stride * out_h

        for x in range(filter_w):

            x_max = x + stride * out_w

            col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride]

    col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N * out_h * out_w, -1)

    return col

 

 

 

 

class Pooling:

    def __init__(self, pool_h, pool_w, stride=1, pad=0):

        self.pool_h = pool_h

        self.pool_w = pool_w

        self.stride = stride

        self.pad = pad

       

    def forward(self, x):

        N, C, H, W = x.shape

        out_h = int(1 + ( H - self.pool_h ) / self.stride)

        out_w = int(1 + ( W - self.pool_w ) / self.stride)

       

        #전개(1)

        col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad)

        col = col.reshape(-1, self.pool_h * self.pool_w)

       

       

        #최댓값(2)

        out = np.max(col, axis=1)

       

       

        #성형(3)

        out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2)

       

        return out

 

 

x = np.array([[[21,8,8,12],[12,19,9,7],[8,10,4,3],[18,12,9,10]],

              [[19,8,7,12],[1,19,9,7],[4,2,4,3],[4,12,9,10]],

              [[2,8,8,12],[10,19,9,7],[5,6,4,3],[1,12,9,12]]])

x2 = x.reshape(1,3,4,4)

 

pool=Pooling(2,2,2,0)

 

print( pool.forward(x2) )

 

 

 

문제307.

위의 코드를 이번에는 최대풀링이 아니라 평균풀링으로 구현하시오

 

pooling 클래스에서

#최댓값(2)

out = np.max(col, axis=1)

#최댓값(2)

out = np.mean(col, axis=1)

 

 

[[[[ 15.     9.  ]

   [ 12.     6.5 ]]

 

  [[ 11.75   8.75]

   [  5.5    6.5 ]]

 

  [[  9.75   9.  ]

   [  6.     7.  ]]]]

 

 

 

문제308.

위의 풀링을 이번에는 확률적 풀링으로 수행하시오

 

out = np.array([np.random.choice(i) for i in col])

pooling클래스에서 첫번째 out 값의 형태는

[[ 21.   8.  12.  19.]

 [ 19.   8.   1.  19.]

 [  2.   8.  10.  19.]    ------------> red

 [  8.  12.   9.   7.]

 

 [  7.  12.   9.   7.]

 [  8.  12.   9.   7.]

 [  8.  10.  18.  12.] -------------> green

 [  4.   2.   4.  12.]

 

 [  5.   6.   1.  12.]

 [  4.   3.   9.  10.]

 [  4.   3.   9.  10.] --------------> blue

 [  4.   3.   9.  12.]]

이렇게 나온다.

이게 col 형태인데 for 돌리면 행에서 랜덤으로 한개씩 뽑는다.

그게 [ 21, 8, 10, 7, ....  ] 이렇게 줄로 늘어지는데

두번째 out 에서 reshpae 해줘서

[[[[ 19.   7.]

   [  8.   3.]]

 

  [[ 19.  12.]

   [  4.  10.]]

 

  [[  2.   9.]

   [ 12.   4.]]]]

마지막에 이런 결과가 나온다.

 

 

 

 

CNN 구현하기(250페이지)

                                                                          (완전연결계층)

                     입력층                     1                           2                      3

                                          (필터=가중치1)

 

 

 

 

 

 

문제310.

그림처럼 코드를 수정하시오

 

# coding: utf-8

import sys, os

 

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

import pickle

import numpy as np

from collections import OrderedDict

from common.layers import *

from common.gradient import numerical_gradient

import matplotlib.pyplot as plt

from dataset.mnist import load_mnist

from common.trainer import Trainer

 

 

class SimpleConvNet:

    """단순한 합성곱 신경망

 

    conv - relu - pool - affine - relu - affine - softmax

 

    Parameters

    ----------

    input_size : 입력 크기(MNIST의 경우엔 784

    hidden_size_list : 은닉층의 뉴런 수를 담은 리스트(e.g. [100, 100, 100]

    output_size : 출력 크기(MNIST의 경우엔 10

    activation : 활성화 함수 - 'relu' 혹은 'sigmoid'

    weight_init_std : 가중치의 표준편차 지정(e.g. 0.01

        'relu' 'he'로 지정하면 'He 초깃값'으로 설정

        'sigmoid' 'xavier'로 지정하면 'Xavier 초깃값'으로 설정

    """

 

    def __init__(self, input_dim=(1, 28, 28),

                 conv_param={'filter_num': 32, 'filter_size': 5, 'pad': 2, 'stride': 1},

                 conv_param2={'filter_num': 64, 'filter_size': 5, 'pad': 2, 'stride': 1},

                 hidden_size=100, output_size=10, weight_init_std= 0.01):

#hidden_size 어파인2 에서 사용됨.

        filter_num = conv_param['filter_num']

        filter_size = conv_param['filter_size']

        filter_pad = conv_param['pad']

        filter_stride = conv_param['stride']             

        input_size = input_dim[1]

       

        filter_num2 = conv_param2['filter_num']

        filter_size2 = conv_param2['filter_size']

        filter_pad2 = conv_param2['pad']

        filter_stride2 = conv_param2['stride']             

        input_size2 = input_size/2

        conv_output_size = (input_size2 - filter_size2 + 2 * filter_pad2) / filter_stride2 + 1

        pool_output_size = int(filter_num2 * (conv_output_size / 2) * (conv_output_size / 2))

        #결국 64*7^2

 

 

 

        # 가중치 초기화

        self.params = {}

        self.params['W1'] = weight_init_std * \

                            np.random.randn(filter_num, input_dim[0], filter_size, filter_size)

# 1x5x5 32 생성( 32 , 1 , 5 , 5 )

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

       

        self.params['W2'] = weight_init_std * \

                            np.random.randn(filter_num2, filter_num , filter_size2, filter_size2)

# 32x5x5 64 생성( 64, 32, 5, 5 )

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

       

        self.params['W3'] = weight_init_std * \

                            np.random.randn(pool_output_size , output_size)

# Affine 넣기위한 1차원화

# pool_output_size = 7 x 7 x 64

# ( 3136 , 10 )

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

 

        # 계층 생성

        self.layers = OrderedDict()

        self.layers['Conv1'] = Convolution(self.params['W1'], self.params['b1'],

                                           conv_param['stride'], conv_param['pad'])

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

        self.layers['Pool1'] = Pooling(pool_h=2, pool_w=2, stride=2)

        self.layers['Conv2'] = Convolution(self.params['W2'], self.params['b2'],

                                           conv_param2['stride'], conv_param2['pad'])

        self.layers['Pool2'] = Pooling(pool_h=2, pool_w=2, stride=2)

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

        self.layers['Affine1'] = Affine(self.params['W3'], self.params['b3'])

 

        self.last_layer = SoftmaxWithLoss()

 

 

 

 

    def predict(self, x):

        for layer in self.layers.values():

            x = layer.forward(x)

 

        return x

 

 

 

 

    def loss(self, x, t):

        """손실 함수를 구한다.

 

        Parameters

        ----------

        x : 입력 데이터

        t : 정답 레이블

        """

        y = self.predict(x)

        return self.last_layer.forward(y, t)

 

 

 

 

    def accuracy(self, x, t, batch_size=100):

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

 

        acc = 0.0

 

        for i in range(int(x.shape[0] / batch_size)):

            tx = x[i * batch_size:(i + 1) * batch_size]

            tt = t[i * batch_size:(i + 1) * batch_size]

            y = self.predict(tx)

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

            acc += np.sum(y == tt)

 

        return acc / x.shape[0]

 

 

 

 

    def numerical_gradient(self, x, t):

        """기울기를 구한다(수치미분).

 

        Parameters

        ----------

        x : 입력 데이터

        t : 정답 레이블

 

        Returns

        -------

        층의 기울기를 담은 사전(dictionary) 변수

            grads['W1']grads['W2']... 각 층의 가중치

            grads['b1']grads['b2']... 각 층의 편향

        """

        loss_w = lambda w: self.loss(x, t)

 

        grads = {}

        for idx in (1, 2, 3):

            grads['W' + str(idx)] = numerical_gradient(loss_w, self.params['W' + str(idx)])

            grads['b' + str(idx)] = numerical_gradient(loss_w, self.params['b' + str(idx)])

 

        return grads

 

 

 

 

    def gradient(self, x, t):

        """기울기를 구한다(오차역전파법).

 

        Parameters

        ----------

        x : 입력 데이터

        t : 정답 레이블

 

        Returns

        -------

        층의 기울기를 담은 사전(dictionary) 변수

            grads['W1']grads['W2']... 각 층의 가중치

            grads['b1']grads['b2']... 각 층의 편향

        """

        # forward

        self.loss(x, t)

 

        # backward

        dout = 1

        dout = self.last_layer.backward(dout)

 

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

        layers.reverse()

        for layer in layers:

            dout = layer.backward(dout)

 

        # 결과 저장

        grads = {}

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

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

        grads['W3'], grads['b3'] = self.layers['Affine1'].dW, self.layers['Affine1'].db

 

        return grads

 

 

 

 

    def save_params(self, file_name="params.pkl"):

        params = {}

        for key, val in self.params.items():

            params[key] = val

        with open(file_name, 'wb') as f:

            pickle.dump(params, f)

 

 

 

 

    def load_params(self, file_name="params.pkl"):

        with open(file_name, 'rb') as f:

            params = pickle.load(f)

        for key, val in params.items():

            self.params[key] = val

 

        for i, key in enumerate(['Conv1', 'Conv2', 'Affine1']):

            self.layers[key].W = self.params['W' + str(i + 1)]

            self.layers[key].b = self.params['b' + str(i + 1)]

 

 

 

 

# 데이터 읽기

(x_train, t_train), (x_test, t_test) = load_mnist(flatten=False)

 

# 시간이 오래 걸릴 경우 데이터를 줄인다.

# x_train, t_train = x_train[:5000], t_train[:5000]

# x_test, t_test = x_test[:1000], t_test[:1000]

 

max_epochs = 20

 

network = SimpleConvNet(input_dim=(1, 28, 28),

                        conv_param={'filter_num': 32, 'filter_size': 5, 'pad': 2, 'stride': 1},

                        conv_param2={'filter_num': 64, 'filter_size': 5, 'pad': 2, 'stride': 1},

                        hidden_size=100, output_size=10, weight_init_std=0.01)

 

 

# 매개변수 보존

network.save_params("params.pkl")

print("Saved Network Parameters!")

 

 

# 하이퍼파라미터

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)

print(iter_per_epoch) # 600

 

for i in range(iters_num): # 10000

    # 미니배치 획득  # 랜덤으로 100개씩 뽑아서 10000번을 수행하니까 백만번

    batch_mask = np.random.choice(train_size, batch_size) # 100 씩 뽑아서 10000번 백만번

    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)

    # 매개변수 갱신

 

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

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

 

 

    # 학습 경과 기록

    loss = network.loss(x_batch, t_batch)

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

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

 

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

        print(x_train.shape) # 60000,784

        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')

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()

 

 

 

 

 

 

 

 

 

728x90
반응형