수색…


소개

2D 컨볼 루션은 1D 컨볼 루션을 계산하는 것과 비슷한 방식으로 계산됩니다. 커널을 입력 위에 밀어 넣고 요소 별 곱셈을 계산하여 합계합니다. 그러나 여러분의 커널 / 입력이 배열이 아닌, 여기서는 행렬입니다.

패딩 없음, 스트라이드 = 1

이것은 가장 쉬운 계산법과 함께 가장 기본적인 예제입니다. inputkernel 이 다음과 kernel 가정 해 보겠습니다. 여기에 이미지 설명을 입력하십시오.

커널을 컴파일하면 다음과 같은 결과를 얻게됩니다 : 여기에 이미지 설명을 입력하십시오. 이는 다음과 같은 방식으로 계산됩니다.

  • 14 = 4 * 1 + 3 * 0 + 1 * 1 + 2 * 2 + 1 * 1 + 0 * 0 + 1 * 0 + 2 * 0 + 4 * 1
  • 6 = 3 * 1 + 1 * 0 + 0 * 1 + 1 * 2 + 0 * 1 + 1 * 0 + 2 * 0 + 4 * 0 + 1 * 1
  • 6 = 2 * 1 + 1 * 0 + 0 * 1 + 1 * 2 + 2 * 1 + 4 * 0 + 3 * 0 + 1 * 0 + 0 * 1
  • 12 = 1 * 1 + 0 * 0 + 1 * 1 + 2 * 2 + 4 * 1 + 1 * 0 + 1 * 0 + 0 * 0 + 2 * 1

TF의 conv2d 함수는 일괄 처리로 회선을 계산하고 약간 다른 형식을 사용합니다. 입력의 경우 커널의 [batch, in_height, in_width, in_channels][filter_height, filter_width, in_channels, out_channels] 입니다. 따라서 올바른 형식으로 데이터를 제공해야합니다.

import tensorflow as tf
k = tf.constant([
    [1, 0, 1],
    [2, 1, 0],
    [0, 0, 1]
], dtype=tf.float32, name='k')
i = tf.constant([
    [4, 3, 1, 0],
    [2, 1, 0, 1],
    [1, 2, 4, 1],
    [3, 1, 0, 2]
], dtype=tf.float32, name='i')
kernel = tf.reshape(k, [3, 3, 1, 1], name='kernel')
image  = tf.reshape(i, [1, 4, 4, 1], name='image')

그 후에 컨볼 루션은 다음과 같이 계산됩니다.

res = tf.squeeze(tf.nn.conv2d(image, kernel, [1, 1, 1, 1], "VALID"))
# VALID means no padding
with tf.Session() as sess:
   print sess.run(res)

우리가 손으로 계산 한 것과 동등합니다.

일부 패딩, 스트라이드 = 1

패딩은 말하기의 단지 멋진 이름입니다. 입력 행렬을 일정하게 둘러싸십시오. 대부분의 경우 상수는 0이므로 사람들이 0으로 채우는 이유입니다. 따라서 원래 입력에서 1의 패딩을 사용하려면 ( padding=0, strides=1 첫 번째 예제를 확인하십시오.) 행렬은 다음과 같습니다.

여기에 이미지 설명을 입력하십시오.

회선의 값을 계산하려면 동일한 슬라이딩을 수행하십시오. 이 경우 중간에있는 많은 값을 다시 계산할 필요가 없습니다 (이전 예제와 동일 할 것입니다. 아이디어는 간단하므로 여기에 모든 계산을 표시하지 않습니다.) 결과는 다음과 같습니다.

여기에 이미지 설명을 입력하십시오.

어디에

  • 5 = 0 * 1 + 0 * 0 + 0 * 1 + 0 * 2 + 4 * 1 + 3 * 0 + 0 * 0 + 0 * 1 + 1 * 1
  • ...
  • 6 = 4 * 1 + 1 * 0 + 0 * 1 + 0 * 2 + 2 * 1 + 0 * 0 + 0 * 0 + 0 * 0 + 0 * 1

TF는 conv2d 함수에서 임의의 패딩을 지원하지 않으므로 지원되지 않는 패딩이 필요한 경우 tf.pad ()를 사용 하십시오 . 운좋게도 우리의 입력에 대해 패딩 'SAME'은 패딩 = 1과 같을 것입니다. 따라서 이전 예제에서 거의 변경하지 않아도됩니다.

res = tf.squeeze(tf.nn.conv2d(image, kernel, [1, 1, 1, 1], "SAME"))
# 'SAME' makes sure that our output has the same size as input and 
# uses appropriate padding. In our case it is 1.
with tf.Session() as sess:
   print sess.run(res)

답은 손으로 계산 한 것과 같은지 확인할 수 있습니다.

패딩과 스트라이드 (가장 일반적인 경우)

이제 우리는 이전에 설명한 패딩 된 예제에 strided convolution을 적용하고 p = 1, s = 2 컨볼 루션을 계산할 것입니다.

여기에 이미지 설명을 입력하십시오.

이전에 strides = 1 을 사용했을 때 우리의 슬라이딩 윈도우는 1 위치 씩 움직였습니다. strides = ss 위치만큼 이동합니다 ( s^2 요소를 더 적게 계산해야합니다. 그러나 우리의 경우에는 바로 가기를 취할 수 있고 우리는 이미 s = 1 대한 값을 계산했기 때문에 우리의 경우 두 번째 요소를 잡을 수 있습니다.

따라서 해가 s = 1 경우

여기에 이미지 설명을 입력하십시오.

s = 2 경우 다음과 같습니다.

여기에 이미지 설명을 입력하십시오.

이전 행렬에서 값 14, 2, 12, 6의 위치를 ​​확인하십시오. 코드에서 수행해야 할 유일한 변경 사항은 폭과 높이 치수 (2-nd, 3-rd)에 대해 strides를 1에서 2로 변경하는 것입니다.

res = tf.squeeze(tf.nn.conv2d(image, kernel, [1, 2, 2, 1], "SAME"))
with tf.Session() as sess:
   print sess.run(res)

그건 그렇고, 우리가 다른 차원에서 다른 진보를 사용하는 것을 막을 수있는 방법은 없습니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow