강의영상

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 [==============================] - 2s 1ms/step - loss: 1.2243 - accuracy: 0.7894
Epoch 2/5
1875/1875 [==============================] - 2s 1ms/step - loss: 0.4534 - accuracy: 0.8388
Epoch 3/5
1875/1875 [==============================] - 2s 1ms/step - loss: 0.4161 - accuracy: 0.8502
Epoch 4/5
1875/1875 [==============================] - 2s 907us/step - loss: 0.4019 - accuracy: 0.8569
Epoch 5/5
1875/1875 [==============================] - 2s 973us/step - loss: 0.3873 - accuracy: 0.8622
<keras.callbacks.History at 0x7f38111302b0>
net1.evaluate(XX,yy)
313/313 [==============================] - 0s 835us/step - loss: 0.4163 - accuracy: 0.8504
[0.41634100675582886, 0.8503999710083008]
net1.summary()
Model: "sequential_6"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 flatten_6 (Flatten)         (None, 784)               0         
                                                                 
 dense_22 (Dense)            (None, 500)               392500    
                                                                 
 dense_23 (Dense)            (None, 500)               250500    
                                                                 
 dense_24 (Dense)            (None, 500)               250500    
                                                                 
 dense_25 (Dense)            (None, 500)               250500    
                                                                 
 dense_26 (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 [==============================] - 2s 1ms/step - loss: 0.8787 - accuracy: 0.8044
Epoch 2/5
1875/1875 [==============================] - 2s 994us/step - loss: 0.3843 - accuracy: 0.8618
Epoch 3/5
1875/1875 [==============================] - 2s 994us/step - loss: 0.3454 - accuracy: 0.8755
Epoch 4/5
1875/1875 [==============================] - 2s 989us/step - loss: 0.3217 - accuracy: 0.8838
Epoch 5/5
1875/1875 [==============================] - 2s 901us/step - loss: 0.3053 - accuracy: 0.8878
<keras.callbacks.History at 0x7f3234110fd0>
net2.evaluate(XX,yy)
313/313 [==============================] - 0s 837us/step - loss: 0.3438 - accuracy: 0.8736
[0.3437994122505188, 0.8736000061035156]
net2.summary()
Model: "sequential_8"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv2d_2 (Conv2D)           (None, 27, 27, 30)        150       
                                                                 
 max_pooling2d_2 (MaxPooling  (None, 13, 13, 30)       0         
 2D)                                                             
                                                                 
 conv2d_3 (Conv2D)           (None, 12, 12, 30)        3630      
                                                                 
 max_pooling2d_3 (MaxPooling  (None, 6, 6, 30)         0         
 2D)                                                             
                                                                 
 flatten_8 (Flatten)         (None, 1080)              0         
                                                                 
 dense_28 (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
print(X.shape) # 입력이미지 = 2D 
print(c1(X).shape) #2D 
print(m1(c1(X)).shape)  #2D
print(c2(m1(c1(X))).shape) #2D
print(m2(c2(m1(c1(X)))).shape) #2D
print(flttn(m2(c2(m1(c1(X))))).shape)# 1D
print(dns(flttn(m2(c2(m1(c1(X)))))).shape)# 1D
(60000, 28, 28, 1)
(60000, 27, 27, 30)
(60000, 13, 13, 30)
(60000, 12, 12, 30)
(60000, 6, 6, 30)
(60000, 1080)
(60000, 10)

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([[[ 4.0450797,  5.7349434,  7.4248075],
        [10.804535 , 12.494399 , 14.184262 ],
        [17.56399  , 19.253855 , 20.943718 ]]], 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

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([[[1.7157198, 2.9689512, 2.7728844],
        [2.4162836, 1.8230928, 2.9890852],
        [1.9408667, 1.2231059, 2.2712555]]], dtype=float32)>
cnv.weights[0]
<tf.Variable 'conv2d_13/kernel:0' shape=(3, 3, 1, 1) dtype=float32, numpy=
array([[[[ 0.28270614]],

        [[-0.13318631]],

        [[ 0.21818542]]],


       [[[ 0.23769057]],

        [[ 0.40044254]],

        [[ 0.38520074]]],


       [[[ 0.15709132]],

        [[ 0.48156905]],

        [[-0.25362712]]]], 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_27/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.6207629 , -0.25241536, -0.7710641 ]]]],
      dtype=float32)>
cnv.weights[0] # (2,2) 커널의 크기 // 1은 XXX의 채널수 // 4는 conv(XXX)의 채널수 
<tf.Variable 'conv2d_24/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_33/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