프로그래밍/Python

Python-23) 합성곱 : 파이썬 합성곱, 컨볼루션 연산, python Convolution

LeeSeunghyuk 2020. 12. 25. 11:29
반응형

※ 합성곱(Convolution) ? 

 

   

     이미지의 형상을 무시하지 않고 이미지를 그대로 인공 신경망이 학습할 있게 해주는 수학 행렬 연산입니다.

     

     합성곱에서 원본 이미지는 학습해야할 사진 데이터(행렬로 변환)

     필터(filter) 원본 이미지에서 특징을 잡아내는데 사용되는 행렬입니다.

     특징을 잡아서 feature map 생성해 원본이미지의 형태를 이해하는 것입니다.

 

     즉, 이미지의 특징을 추출하는 것으로 생각하시면 됩니다.

 

     행렬곱 연산입니다.

 

     위의 예시에서 크게 4번 이루어집니다.

 

     색깔 별 구역의 (3x3) 행렬과 필터가 각각 연산되어 15 , 16 , 6 , 15 라는 결과로 (2x2) 행렬이 만들어집니다.

     4x4 의 행렬이 2x2 행렬로 크기가 작아지고, 4x4 행렬의 특징을 가지고 있습니다.

     이는 나중에 CNN 학습 시 속도 개선에 도움이 되는 부분입니다.

 

   ※ 컨벌루션 연산이 계속되면 데이터가 작아지면서 정보가 유실 될 수 있습니다.

      빈 가장자리를 채우는 것을 padding이라고 합니다.

 

   ※ 필터의 이동 간격은 stride라고 합니다.

 

 

     위의 예제를 파이썬으로 구현한 코드입니다.

import numpy as np
m=np.array([[1,2,3,0],[0,1,2,3],[3,0,1,2],[2,3,0,1]])  
f=np.array([[2,0,1],[0,1,2],[1,0,2]])
result=[]

mx,my=np.shape(m)
fx,fy=np.shape(f)

for i in range(mx-fx+1): 
    for j in range(my-fy+1): 
        result.append((m[i:i+fy,j:j+fy]*f).sum())

result=np.array(result).reshape(2,2)
print(result)

 

    위의 코드에서는 패딩도 무시하고, 스트라이도 직접 계산해버려 하드코딩한 소스입니다.

   

* 합성곱 가능 여부 구하기

    (입력 크기 - 필터 크기) % Stride == 0

          &

    (입력 크기 - 필터 크기) % Stride == 0

 

* output size 구하기

 

* 패딩 크기 구하기

 

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

     예제) ((4 - 1 ) * 1 - 4 + 3 ) / 2 = 1

 

    P : 패딩

    H : 입력 데이터의 높이 ( )

    OH : 출력 데이터의 높이 ( )

    FH : 필터의 높이 ( )

    S : stride

 

함수로 만들어 보았습니다.

def convolution(m,f,s=1):
    import numpy as np
    mx,my=np.shape(m)
    fx,fy=np.shape(f)
    if (mx-fx)%s==0 and (my-fy)%s==0:
        print('convolution 연산 가능')
    else:
        print('convolution 연산 불가능')
        print('(mx-fx)%s=',(mx-fx)%s)
        print('(my-fy)%s=',(my-fy)%s)
        return
    o=[]

    for i in range(0,mx-fx+1,s): 
        for j in range(0,my-fy+1,s): 
            o.append((m[i:i+fx,j:j+fy]*f).sum())
    ow=int((mx-fx)/s)+1
    oh=int((my-fy)/s)+1
    print('ouptput 크기=(%s,%s)'%(ow,oh))
    o=np.array(o).reshape(oh,ow)
    return o

data=np.array([[1,2,3,0,-1],[0,1,2,3,-1],[3,0,1,2,-1],[2,3,0,1,-1],[2,3,0,1,-1],[2,3,0,1,-1]])  
f=np.array([[2,0,9],[0,1,8],[1,0,7]])
print('--data--\n',data)
print('\n--filter--\n',f,'\n')
print(convolution(data,f,s=1))
convolution(data,f,s=2)

반응형