imports

import tensorflow as tf 
import tensorflow.experimental.numpy as tnp 
import numpy as np 
import matplotlib.pyplot as plt
tnp.experimental_enable_numpy_behavior()
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.fashion_mnist.load_data()
X = tf.constant(x_train.reshape(-1,28,28,1),dtype=tf.float64)
y = tf.keras.utils.to_categorical(y_train)
XX = tf.constant(x_test.reshape(-1,28,28,1),dtype=tf.float64)
yy = tf.keras.utils.to_categorical(y_test)

- 첫시도

net1 = tf.keras.Sequential()
net1.add(tf.keras.layers.Flatten())
net1.add(tf.keras.layers.Dense(500,activation='relu'))
net1.add(tf.keras.layers.Dense(500,activation='relu'))
net1.add(tf.keras.layers.Dense(500,activation='relu'))
net1.add(tf.keras.layers.Dense(500,activation='relu'))
net1.add(tf.keras.layers.Dense(10,activation='softmax'))
net1.compile(optimizer='adam', loss=tf.losses.categorical_crossentropy,metrics='accuracy')
net1.fit(X,y,epochs=5)
Epoch 1/5
1875/1875 [==============================] - 3s 2ms/step - loss: 1.0565 - accuracy: 0.7923
Epoch 2/5
1875/1875 [==============================] - 3s 1ms/step - loss: 0.4495 - accuracy: 0.8389
Epoch 3/5
1875/1875 [==============================] - 3s 2ms/step - loss: 0.4135 - accuracy: 0.8525
Epoch 4/5
1875/1875 [==============================] - 3s 2ms/step - loss: 0.4001 - accuracy: 0.8579
Epoch 5/5
1875/1875 [==============================] - 3s 2ms/step - loss: 0.3753 - accuracy: 0.8673
<keras.callbacks.History at 0x7f55d055a8c0>
net1.evaluate(XX,yy)
313/313 [==============================] - 1s 2ms/step - loss: 0.4420 - accuracy: 0.8570
[0.4419509172439575, 0.8569999933242798]
net1.summary()
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 flatten (Flatten)           (None, 784)               0         
                                                                 
 dense (Dense)               (None, 500)               392500    
                                                                 
 dense_1 (Dense)             (None, 500)               250500    
                                                                 
 dense_2 (Dense)             (None, 500)               250500    
                                                                 
 dense_3 (Dense)             (None, 500)               250500    
                                                                 
 dense_4 (Dense)             (None, 10)                5010      
                                                                 
=================================================================
Total params: 1,149,010
Trainable params: 1,149,010
Non-trainable params: 0
_________________________________________________________________

- 두번째 시도

net2 = tf.keras.Sequential()
net2.add(tf.keras.layers.Conv2D(30,(2,2),activation='relu'))
net2.add(tf.keras.layers.MaxPool2D()) 
net2.add(tf.keras.layers.Conv2D(30,(2,2),activation='relu'))
net2.add(tf.keras.layers.MaxPool2D()) 
net2.add(tf.keras.layers.Flatten())
#net2.add(tf.keras.layers.Dense(500,activation='relu'))
net2.add(tf.keras.layers.Dense(10,activation='softmax'))
net2.compile(optimizer='adam', loss=tf.losses.categorical_crossentropy,metrics='accuracy')
net2.fit(X,y,epochs=5)
Epoch 1/5
1875/1875 [==============================] - 3s 1ms/step - loss: 0.7357 - accuracy: 0.8065
Epoch 2/5
1875/1875 [==============================] - 3s 2ms/step - loss: 0.3728 - accuracy: 0.8676
Epoch 3/5
1875/1875 [==============================] - 3s 2ms/step - loss: 0.3346 - accuracy: 0.8798
Epoch 4/5
1875/1875 [==============================] - 3s 1ms/step - loss: 0.3110 - accuracy: 0.8875
Epoch 5/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.2929 - accuracy: 0.8925
<keras.callbacks.History at 0x7f55d055be50>
net2.evaluate(XX,yy)
313/313 [==============================] - 1s 1ms/step - loss: 0.3280 - accuracy: 0.8807
[0.32795271277427673, 0.8806999921798706]
net2.summary()
Model: "sequential_1"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv2d (Conv2D)             (None, 27, 27, 30)        150       
                                                                 
 max_pooling2d (MaxPooling2D  (None, 13, 13, 30)       0         
 )                                                               
                                                                 
 conv2d_1 (Conv2D)           (None, 12, 12, 30)        3630      
                                                                 
 max_pooling2d_1 (MaxPooling  (None, 6, 6, 30)         0         
 2D)                                                             
                                                                 
 flatten_1 (Flatten)         (None, 1080)              0         
                                                                 
 dense_5 (Dense)             (None, 10)                10810     
                                                                 
=================================================================
Total params: 14,590
Trainable params: 14,590
Non-trainable params: 0
_________________________________________________________________
14590/ 1149010
0.012697887746842934
c1, m1, c2, m2, flttn, dns = net2.layers

MaxPool2D

테스트1

- 레이어생성

m=tf.keras.layers.MaxPool2D()

- 입력데이터

XXX = tnp.arange(1*4*4*1).reshape(1,4,4,1)
XXX.reshape(1,4,4)
<tf.Tensor: shape=(1, 4, 4), dtype=int64, numpy=
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11],
        [12, 13, 14, 15]]])>

- 입력데이터가 레이어를 통과한 모습

m(XXX).reshape(1,2,2)
<tf.Tensor: shape=(1, 2, 2), dtype=int64, numpy=
array([[[ 5,  7],
        [13, 15]]])>

- MaxPool2D layer의 역할: (2,2)윈도우를 만들고 (2,2)윈도우에서 max를 뽑아 값을 기록, 윈도우를 움직이면서 반복

테스트2

XXX = tnp.arange(1*6*6*1).reshape(1,6,6,1)
XXX.reshape(1,6,6)
<tf.Tensor: shape=(1, 6, 6), dtype=int64, numpy=
array([[[ 0,  1,  2,  3,  4,  5],
        [ 6,  7,  8,  9, 10, 11],
        [12, 13, 14, 15, 16, 17],
        [18, 19, 20, 21, 22, 23],
        [24, 25, 26, 27, 28, 29],
        [30, 31, 32, 33, 34, 35]]])>
m(XXX).reshape(1,3,3)
<tf.Tensor: shape=(1, 3, 3), dtype=int64, numpy=
array([[[ 7,  9, 11],
        [19, 21, 23],
        [31, 33, 35]]])>

테스트3

m=tf.keras.layers.MaxPool2D(pool_size=(3, 3))
XXX = tnp.arange(1*6*6*1).reshape(1,6,6,1)
XXX.reshape(1,6,6)
<tf.Tensor: shape=(1, 6, 6), dtype=int64, numpy=
array([[[ 0,  1,  2,  3,  4,  5],
        [ 6,  7,  8,  9, 10, 11],
        [12, 13, 14, 15, 16, 17],
        [18, 19, 20, 21, 22, 23],
        [24, 25, 26, 27, 28, 29],
        [30, 31, 32, 33, 34, 35]]])>
m(XXX).reshape(1,2,2)
<tf.Tensor: shape=(1, 2, 2), dtype=int64, numpy=
array([[[14, 17],
        [32, 35]]])>

테스트4

m=tf.keras.layers.MaxPool2D(pool_size=(2, 2))
XXX = tnp.arange(1*5*5*1).reshape(1,5,5,1)
XXX.reshape(1,5,5)
<tf.Tensor: shape=(1, 5, 5), dtype=int64, numpy=
array([[[ 0,  1,  2,  3,  4],
        [ 5,  6,  7,  8,  9],
        [10, 11, 12, 13, 14],
        [15, 16, 17, 18, 19],
        [20, 21, 22, 23, 24]]])>
m(XXX).reshape(1,2,2)
<tf.Tensor: shape=(1, 2, 2), dtype=int64, numpy=
array([[[ 6,  8],
        [16, 18]]])>
m=tf.keras.layers.MaxPool2D(pool_size=(2, 2),padding="same")
XXX = tnp.arange(1*5*5*1).reshape(1,5,5,1)
XXX.reshape(1,5,5)
<tf.Tensor: shape=(1, 5, 5), dtype=int64, numpy=
array([[[ 0,  1,  2,  3,  4],
        [ 5,  6,  7,  8,  9],
        [10, 11, 12, 13, 14],
        [15, 16, 17, 18, 19],
        [20, 21, 22, 23, 24]]])>
m(XXX).reshape(1,3,3)
<tf.Tensor: shape=(1, 3, 3), dtype=int64, numpy=
array([[[ 6,  8,  9],
        [16, 18, 19],
        [21, 23, 24]]])>

테스트5

XXX = tnp.arange(2*4*4*1).reshape(2,4,4,1)
XXX.reshape(2,4,4)
<tf.Tensor: shape=(2, 4, 4), dtype=int64, numpy=
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11],
        [12, 13, 14, 15]],

       [[16, 17, 18, 19],
        [20, 21, 22, 23],
        [24, 25, 26, 27],
        [28, 29, 30, 31]]])>
m(XXX).reshape(2,2,2)
<tf.Tensor: shape=(2, 2, 2), dtype=int64, numpy=
array([[[ 5,  7],
        [13, 15]],

       [[21, 23],
        [29, 31]]])>

테스트6

XXX = tnp.arange(1*4*4*3).reshape(1,4,4,3)
XXX[...,0]
<tf.Tensor: shape=(1, 4, 4), dtype=int64, numpy=
array([[[ 0,  3,  6,  9],
        [12, 15, 18, 21],
        [24, 27, 30, 33],
        [36, 39, 42, 45]]])>
m(XXX)[...,0]
<tf.Tensor: shape=(1, 2, 2), dtype=int64, numpy=
array([[[15, 21],
        [39, 45]]])>

Conv2D

테스트1

- 레이어생성

cnv = tf.keras.layers.Conv2D(1,(2,2))

- XXX생성

XXX = tnp.arange(1*4*4*1,dtype=tf.float64).reshape(1,4,4,1)
XXX.reshape(1,4,4)
<tf.Tensor: shape=(1, 4, 4), dtype=float64, numpy=
array([[[ 0.,  1.,  2.,  3.],
        [ 4.,  5.,  6.,  7.],
        [ 8.,  9., 10., 11.],
        [12., 13., 14., 15.]]])>
cnv(XXX).reshape(1,3,3)
<tf.Tensor: shape=(1, 3, 3), dtype=float32, numpy=
array([[[-2.8128474, -3.2847993, -3.756751 ],
        [-4.7006545, -5.172607 , -5.6445584],
        [-6.588462 , -7.060414 , -7.532366 ]]], dtype=float32)>
  • XXX에서 cnv(XXX)로 가는 맵핑을 찾는건 쉽지 않아보인다.
  • 심지어 랜덤으로 결정되는 부분도 있어보임

- 코드정리 + 시드통일

tf.random.set_seed(43052)
cnv = tf.keras.layers.Conv2D(1,(2,2))
XXX = tnp.arange(1*4*4*1,dtype=tf.float64).reshape(1,4,4,1)

- conv의 입출력

print(XXX.reshape(1,4,4))
print(cnv(XXX).reshape(1,3,3))
tf.Tensor(
[[[ 0.  1.  2.  3.]
  [ 4.  5.  6.  7.]
  [ 8.  9. 10. 11.]
  [12. 13. 14. 15.]]], shape=(1, 4, 4), dtype=float64)
tf.Tensor(
[[[ -4.125754   -5.312817   -6.4998803]
  [ -8.874006  -10.0610695 -11.248133 ]
  [-13.622259  -14.809322  -15.996386 ]]], shape=(1, 3, 3), dtype=float32)

- conv연산 추론

tf.reshape(cnv.weights[0],(2,2))
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[-0.13014299, -0.23927206],
       [-0.20175874, -0.6158894 ]], dtype=float32)>
0 * -0.13014299 + 1 * -0.23927206 + 4 * -0.20175874 + 5 * -0.6158894 + 0
-4.1257540200000005

- 내가 정의한 weights를 대입하여 conv 연산 확인

cnv.get_weights()[0].shape
(2, 2, 1, 1)
w = np.array([1/4,1/4,1/4,1/4],dtype=np.float32).reshape(2, 2, 1, 1)
b = np.array([3],dtype=np.float32)
cnv.set_weights([w,b])
XXX.reshape(1,4,4)
<tf.Tensor: shape=(1, 4, 4), dtype=float64, numpy=
array([[[ 0.,  1.,  2.,  3.],
        [ 4.,  5.,  6.,  7.],
        [ 8.,  9., 10., 11.],
        [12., 13., 14., 15.]]])>
cnv(XXX).reshape(1,3,3)
<tf.Tensor: shape=(1, 3, 3), dtype=float32, numpy=
array([[[ 5.5,  6.5,  7.5],
        [ 9.5, 10.5, 11.5],
        [13.5, 14.5, 15.5]]], dtype=float32)>
np.mean([0,1,4,5])+3, np.mean([1,2,5,6])+3, np.mean([2,3,6,7])+3
(5.5, 6.5, 7.5)

tf.keras.layers.Conv2D(1,kernel_size=(2,2)) 요약

- 요약

(1) size=(2,2)인 윈도우를 만듬.

(2) XXX에 윈도우를 통과시켜서 (2,2)크기의 sub XXX 를 얻음. sub XXX의 각 원소에 conv2d.weights[0]의 각 원소를 element-wise하게 곱한다.

(3) (2)의 결과를 모두 더한다. 그리고 그 결과에 다시 conv2d.weights[1]을 수행

(4) 윈도우를 이동시키면서 반복!

테스트2

- 레이어와 XXX생성

tf.random.set_seed(43052)
cnv = tf.keras.layers.Conv2D(1,(3,3))
XXX = tnp.arange(1*5*5*1,dtype=tf.float64).reshape(1,5,5,1)
XXX.reshape(1,5,5) ## 입력: XXX
<tf.Tensor: shape=(1, 5, 5), dtype=float64, numpy=
array([[[ 0.,  1.,  2.,  3.,  4.],
        [ 5.,  6.,  7.,  8.,  9.],
        [10., 11., 12., 13., 14.],
        [15., 16., 17., 18., 19.],
        [20., 21., 22., 23., 24.]]])>
tf.reshape(cnv.weights[0],(3,3)) ## 커널의 가중치
<tf.Tensor: shape=(3, 3), dtype=float32, numpy=
array([[-0.08676198, -0.1595147 , -0.13450584],
       [-0.4105929 , -0.38366908,  0.07744962],
       [-0.09255642,  0.4915564 ,  0.20828158]], dtype=float32)>
cnv(XXX).reshape(1,3,3) ## 출력: conv(XXX)
<tf.Tensor: shape=(1, 3, 3), dtype=float32, numpy=
array([[[ 2.7395768 ,  2.2492635 ,  1.7589504 ],
        [ 0.28801066, -0.20230258, -0.6926158 ],
        [-2.1635566 , -2.6538715 , -3.1441827 ]]], dtype=float32)>
tf.reduce_sum(XXX.reshape(1,5,5)[0,:3,:3] * tf.reshape(cnv.weights[0],(3,3)))
<tf.Tensor: shape=(), dtype=float64, numpy=2.739577144384384>

테스트3

![](https://github.com/guebin/2021BDA/blob/master/_notebooks/2021-11-04-conv.png?raw=true)
/bin/bash: -c: line 0: syntax error near unexpected token `https://github.com/guebin/2021BDA/blob/master/_notebooks/2021-11-04-conv.png?raw=true'
/bin/bash: -c: line 0: `[](https://github.com/guebin/2021BDA/blob/master/_notebooks/2021-11-04-conv.png?raw=true)'
XXX = tf.constant([[3,3,2,1,0],[0,0,1,3,1],[3,1,2,2,3],[2,0,0,2,2],[2,0,0,0,1]],dtype=tf.float64).reshape(1,5,5,1)
XXX.reshape(1,5,5)
<tf.Tensor: shape=(1, 5, 5), dtype=float64, numpy=
array([[[3., 3., 2., 1., 0.],
        [0., 0., 1., 3., 1.],
        [3., 1., 2., 2., 3.],
        [2., 0., 0., 2., 2.],
        [2., 0., 0., 0., 1.]]])>
cnv = tf.keras.layers.Conv2D(1,(3,3))
cnv.weights
[]
cnv(XXX).reshape(1,3,3)
<tf.Tensor: shape=(1, 3, 3), dtype=float32, numpy=
array([[[-0.6065799 , -0.69143724, -1.1179221 ],
        [ 2.2352955 ,  1.5314975 ,  1.8658445 ],
        [ 0.7364182 ,  1.4419123 ,  1.2381717 ]]], dtype=float32)>
cnv.weights[0]
<tf.Variable 'conv2d_6/kernel:0' shape=(3, 3, 1, 1) dtype=float32, numpy=
array([[[[-0.3444655 ]],

        [[ 0.4521824 ]],

        [[ 0.236296  ]]],


       [[[ 0.54707503]],

        [[ 0.19746327]],

        [[ 0.20471048]]],


       [[[-0.1245549 ]],

        [[-0.25237298]],

        [[-0.4904977 ]]]], dtype=float32)>
_w = tf.constant([[0,1,2],[2,2,0],[0,1,2]],dtype=tf.float64).reshape(3,3,1,1)
_b = tf.constant([0],dtype=tf.float64)
cnv.set_weights([_w,_b])
cnv(XXX).reshape(1,3,3)
<tf.Tensor: shape=(1, 3, 3), dtype=float32, numpy=
array([[[12., 12., 17.],
        [10., 17., 19.],
        [ 9.,  6., 14.]]], dtype=float32)>

테스트4

tf.random.set_seed(43052)
cnv = tf.keras.layers.Conv2D(1,(2,2))
XXX = tnp.arange(2*5*5*1,dtype=tf.float64).reshape(2,5,5,1)
print(XXX.reshape(2,5,5))
cnv(XXX) # weights를 초기화 시키기 위해서 레이어를 1회 통과 
cnv.set_weights([w,b])
print(cnv(XXX).reshape(2,4,4))
tf.Tensor(
[[[ 0.  1.  2.  3.  4.]
  [ 5.  6.  7.  8.  9.]
  [10. 11. 12. 13. 14.]
  [15. 16. 17. 18. 19.]
  [20. 21. 22. 23. 24.]]

 [[25. 26. 27. 28. 29.]
  [30. 31. 32. 33. 34.]
  [35. 36. 37. 38. 39.]
  [40. 41. 42. 43. 44.]
  [45. 46. 47. 48. 49.]]], shape=(2, 5, 5), dtype=float64)
tf.Tensor(
[[[ 6.  7.  8.  9.]
  [11. 12. 13. 14.]
  [16. 17. 18. 19.]
  [21. 22. 23. 24.]]

 [[31. 32. 33. 34.]
  [36. 37. 38. 39.]
  [41. 42. 43. 44.]
  [46. 47. 48. 49.]]], shape=(2, 4, 4), dtype=float32)
np.mean([0,1,5,6])+3,np.mean([25,26,30,31])+3,
(6.0, 31.0)

테스트5

-

tf.random.set_seed(43052)
cnv = tf.keras.layers.Conv2D(4,(2,2),activation='relu')
XXX = tnp.arange(1*2*2*1,dtype=tf.float64).reshape(1,2,2,1)
print(XXX.reshape(1,2,2))
tf.Tensor(
[[[0. 1.]
  [2. 3.]]], shape=(1, 2, 2), dtype=float64)
cnv(XXX)
<tf.Tensor: shape=(1, 1, 1, 4), dtype=float32, numpy=array([[[[1.048703, 0.      , 0.      , 0.      ]]]], dtype=float32)>
cnv.weights[0] # (2,2) 커널의 크기 // 1은 XXX의 채널수 // 4는 conv(XXX)의 채널수
<tf.Variable 'conv2d_8/kernel:0' shape=(2, 2, 1, 4) dtype=float32, numpy=
array([[[[-0.08230966, -0.15132892, -0.12760344, -0.38952267]],

        [[-0.36398047,  0.07347518, -0.08780673,  0.46633136]]],


       [[[ 0.19759327, -0.46042526, -0.15406173, -0.34838456]],

        [[ 0.33916563, -0.08248386,  0.11705655, -0.49948823]]]],
      dtype=float32)>
cnv.weights[0][...,0].reshape(2,2) ## conv(XXX)의 첫번째채널 출력을 얻기 위해 곱해지는 w
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[-0.08230966, -0.36398047],
       [ 0.19759327,  0.33916563]], dtype=float32)>
tf.reduce_sum(XXX.reshape(1,2,2) * cnv.weights[0][...,0].reshape(2,2)) ### conv(XXX)의 첫번째 채널 출력결과
<tf.Tensor: shape=(), dtype=float64, numpy=1.0487029552459717>

- 계산결과를 확인하기 쉽게 하기 위한 약간의 트릭

tf.random.set_seed(43052)
cnv = tf.keras.layers.Conv2D(4,(2,2))
XXX = tnp.array([1]*1*2*2*1,dtype=tf.float64).reshape(1,2,2,1)
print(XXX.reshape(1,2,2))
tf.Tensor(
[[[1. 1.]
  [1. 1.]]], shape=(1, 2, 2), dtype=float64)
  • 이렇게 XXX를 설정하면 cnv(XXX)의 결과는 단지 cnv의 weight들의 sum이 된다.
cnv(XXX)
<tf.Tensor: shape=(1, 1, 1, 4), dtype=float32, numpy=
array([[[[ 0.09046876, -0.6207628 , -0.25241536, -0.7710641 ]]]],
      dtype=float32)>
cnv.weights[0] # (2,2) 커널의 크기 // 1은 XXX의 채널수 // 4는 conv(XXX)의 채널수
<tf.Variable 'conv2d_9/kernel:0' shape=(2, 2, 1, 4) dtype=float32, numpy=
array([[[[-0.08230966, -0.15132892, -0.12760344, -0.38952267]],

        [[-0.36398047,  0.07347518, -0.08780673,  0.46633136]]],


       [[[ 0.19759327, -0.46042526, -0.15406173, -0.34838456]],

        [[ 0.33916563, -0.08248386,  0.11705655, -0.49948823]]]],
      dtype=float32)>
cnv.weights[0][...,0].reshape(2,2) ## conv(XXX)의 첫번째채널 출력을 얻기 위해 곱해지는 w
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[-0.08230966, -0.36398047],
       [ 0.19759327,  0.33916563]], dtype=float32)>
tf.reduce_sum(cnv.weights[0][...,0])
#tf.reduce_sum(XXX.reshape(1,2,2) * cnv.weights[0][...,0].reshape(2,2)) ### conv(XXX)의 첫번째 채널 출력결과
<tf.Tensor: shape=(), dtype=float32, numpy=0.090468764>

테스트6

- 결과확인을 쉽게하기 위해서 XXX를 1로 통일

tf.random.set_seed(43052)
cnv = tf.keras.layers.Conv2D(4,(2,2))
XXX = tnp.array([1]*1*2*2*3,dtype=tf.float64).reshape(1,2,2,3)
cnv(XXX)
<tf.Tensor: shape=(1, 1, 1, 4), dtype=float32, numpy=
array([[[[ 0.3297621, -0.4498347, -1.0487393, -1.580095 ]]]],
      dtype=float32)>
cnv.weights[0] ## (2,2)는 커널의 사이즈 // 3은 XXX의채널 // 4는 cnv(XXX)의 채널
<tf.Variable 'conv2d_10/kernel:0' shape=(2, 2, 3, 4) dtype=float32, numpy=
array([[[[-0.06956434, -0.12789628, -0.10784459, -0.32920673],
         [-0.30761963,  0.06209785, -0.07421023,  0.3941219 ],
         [ 0.16699678, -0.38913035, -0.13020593, -0.29443866]],

        [[ 0.28664726, -0.0697116 ,  0.09893084, -0.4221446 ],
         [-0.23161241, -0.16410837, -0.36420006,  0.12424195],
         [-0.14245945,  0.36286396, -0.10751781,  0.1733647 ]]],


       [[[ 0.02764335,  0.15547717, -0.42024496, -0.31893867],
         [ 0.22414821,  0.3619454 , -0.00282967, -0.3503708 ],
         [ 0.4610079 , -0.17417148,  0.00401336, -0.29777044]],

        [[-0.1620284 , -0.42066965, -0.01578814, -0.4240524 ],
         [ 0.37925082,  0.24236053,  0.3949356 , -0.20996472],
         [-0.30264795, -0.28889188, -0.3237777 ,  0.37506342]]]],
      dtype=float32)>
cnv.weights[0][...,0] ## cnv(XXX)의 첫번째 채널결과를 얻기 위해서 사용하는 w
<tf.Tensor: shape=(2, 2, 3), dtype=float32, numpy=
array([[[-0.06956434, -0.30761963,  0.16699678],
        [ 0.28664726, -0.23161241, -0.14245945]],

       [[ 0.02764335,  0.22414821,  0.4610079 ],
        [-0.1620284 ,  0.37925082, -0.30264795]]], dtype=float32)>
tf.reduce_sum(cnv.weights[0][...,0]) ### cnv(XXX)의 첫번째 채널의 결과
<tf.Tensor: shape=(), dtype=float32, numpy=0.32976213>
print(tf.reduce_sum(cnv.weights[0][...,0]))
print(tf.reduce_sum(cnv.weights[0][...,1]))
print(tf.reduce_sum(cnv.weights[0][...,2]))
print(tf.reduce_sum(cnv.weights[0][...,3])) ### cnv(XXX)의 결과
tf.Tensor(0.32976213, shape=(), dtype=float32)
tf.Tensor(-0.44983464, shape=(), dtype=float32)
tf.Tensor(-1.0487392, shape=(), dtype=float32)
tf.Tensor(-1.5800952, shape=(), dtype=float32)
w_red = cnv.weights[0][...,0][...,0] 
w_green = cnv.weights[0][...,0][...,1] 
w_blue = cnv.weights[0][...,0][...,2]
tf.reduce_sum(XXX[...,0] * w_red + XXX[...,1] * w_green + XXX[...,2] * w_blue) ## cnv(XXX)의 첫채널 출력결과
<tf.Tensor: shape=(), dtype=float64, numpy=0.32976213097572327>

hw

아래와 같은 흑백이미지가 있다고 하자.

0 0 0 1 1 1 
0 0 0 1 1 1 
0 0 0 1 1 1 
0 0 0 1 1 1 
0 0 0 1 1 1
0 0 0 1 1 1

위의 이미지에 아래와 같은 weight를 가진 필터를 적용하여 convolution한 결과를 계산하라. (bias는 0으로 가정한다)

-1 1 
-1 1
cnv = tf.keras.layers.Conv2D(1,(2,2))
XXX = tf.constant([[0,0,0,1,1,1],[0,0,0,1,1,1],[0,0,0,1,1,1],[0,0,0,1,1,1],[0,0,0,1,1,1],[0,0,0,1,1,1]],dtype=tf.float64).reshape(1,6,6,1)
XXX.reshape(1,6,6)
<tf.Tensor: shape=(1, 6, 6), dtype=float64, numpy=
array([[[0., 0., 0., 1., 1., 1.],
        [0., 0., 0., 1., 1., 1.],
        [0., 0., 0., 1., 1., 1.],
        [0., 0., 0., 1., 1., 1.],
        [0., 0., 0., 1., 1., 1.],
        [0., 0., 0., 1., 1., 1.]]])>
cnv(XXX).reshape(1,5,5)
<tf.Tensor: shape=(1, 5, 5), dtype=float32, numpy=
array([[[0.       , 0.       , 1.4988861, 1.336632 , 1.336632 ],
        [0.       , 0.       , 1.4988861, 1.336632 , 1.336632 ],
        [0.       , 0.       , 1.4988861, 1.336632 , 1.336632 ],
        [0.       , 0.       , 1.4988861, 1.336632 , 1.336632 ],
        [0.       , 0.       , 1.4988861, 1.336632 , 1.336632 ]]],
      dtype=float32)>
cnv.weights[0]
<tf.Variable 'conv2d_11/kernel:0' shape=(2, 2, 1, 1) dtype=float32, numpy=
array([[[[-0.51669824]],

        [[ 0.6782736 ]]],


       [[[ 0.3544441 ]],

        [[ 0.8206125 ]]]], dtype=float32)>
_w = tf.constant([[-1,1],[-1,1]],dtype=tf.float64).reshape(2,2,1,1)
_b = tf.constant([0],dtype=tf.float64)
cnv.set_weights([_w,_b])
cnv.weights
[<tf.Variable 'conv2d_11/kernel:0' shape=(2, 2, 1, 1) dtype=float32, numpy=
 array([[[[-1.]],
 
         [[ 1.]]],
 
 
        [[[-1.]],
 
         [[ 1.]]]], dtype=float32)>,
 <tf.Variable 'conv2d_11/bias:0' shape=(1,) dtype=float32, numpy=array([0.], dtype=float32)>]
cnv(XXX).reshape(1,5,5)
<tf.Tensor: shape=(1, 5, 5), dtype=float32, numpy=
array([[[0., 0., 2., 0., 0.],
        [0., 0., 2., 0., 0.],
        [0., 0., 2., 0., 0.],
        [0., 0., 2., 0., 0.],
        [0., 0., 2., 0., 0.]]], dtype=float32)>