# 드디어 합성곱
# 이미지 처리에 탁월한 성능을 보이는 신경망
# 마치 입력 데이터에 도장을 찍어서 유용한 특성만 드러나게 하는것으로 비유할수 있음
# 합성곱에서는 뉴런이 입력 위를 이동하면서 출력을 만들기 때문에 이런 식으로 표현하기가 어렵다. 
# 합성곱에서는 완전 연결 신경망와 달리 뉴런을 필터 혹은 커널이라고 부름
# 합성곱 연산 = 커널 또는 필터라는 n x m 크기의 행렬로 높이 x 너비 크기의 이미지를 처음부터 끝까지 겹치며 훑으면서 n x m크기의 겹쳐지는 부분의 각 이미지와 커널의 원소 값을 곱해서 모두 더한 값을 출력으로 하는것
# 이를 통해 얻은 출력을 특성맵이라함

# 케라스 합성곱 층 
# 케라스의 층은 모두 keras.layers 패키지 아래 클래스로 구현되어있음 합성곱 층도 마찬가지이다
# 특성맵은 활성화 함수를 적용하기 후 
# 커널의 크기는 하이퍼파라미터라 여러가지 값을 시도해봐야 하지만 보통 3,3 5,5 크기가 권장
# 입력 배열의 주위를 가상의 원소로 채우는 것을 패딩이라고한다 
# 입력과 특성 맵의 크기를 동일하게 만들기 위해 입력 주위에 0으로 패딩하는것을 세임 패딩 ( 합성곱 신경망에서는 세임 패딩이 많이 사용)
# 패딩 없이 순수한 입력 배열에서만 합성곱을 하여 특성 맵을 만드는 경우를 벨리드 패딩 ( 벨리드 패딩은 특성 맵의 크기가 줄어들 수밖에 없음)

from tensorflow import keras
keras.layers.Conv2D(10, kernel_size=(3,3), activation='relu')
# Conv2D 크래스의 첫 번째 매개변수는 필터의 개수  
# Kenel_size 매개변수는 필터에 사용할 커널의 크기를 지정 필터의 개수와 커널의 크기는 반드시 지정해야 하는 매개변수

keras.layers.Conv2D(10, kernel_size=(3,3), activation='relu', padding='same')

#%% 
keras.layers.Conv2D(10, kernel_size=(3,3), activation='relu', padding='same', stride=1)
# stride 매개변수는 오른쪽으로 이동하는 크기와 아래쪽으로 이동하는 크기를 (1,1)과 같이 튜플을 사용해 각각 지정할수 있음
# 하지만 커널의 이동 크기를 가로세로 방향으로 다르게 지정하는 경우는 거의 없음 또 1보다 큰 스트라이드를 사용하는 경우도 드뭄 
# 이로인해 strides 매개변수는 잘이용하지않음

# 폴링 = 합성곱 층에서 만든 특성 맵의 가로세로 크기를 줄이는 역활을 함
# 하지만 특성 맵의 개수를 줄이지 않음
