11주차-5월 16일
빅데이터분석특강
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)
net1.evaluate(XX,yy)
net1.summary()
-
두번째 시도
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)
net2.evaluate(XX,yy)
net2.summary()
14590/ 1149010
c1, m1, c2, m2, flttn, dns = net2.layers
-
레이어생성
m=tf.keras.layers.MaxPool2D()
-
입력데이터
XXX = tnp.arange(1*4*4*1).reshape(1,4,4,1)
XXX.reshape(1,4,4)
-
입력데이터가 레이어를 통과한 모습
m(XXX).reshape(1,2,2)
-
MaxPool2D layer의 역할: (2,2)윈도우를 만들고 (2,2)윈도우에서 max를 뽑아 값을 기록, 윈도우를 움직이면서 반복
XXX = tnp.arange(1*6*6*1).reshape(1,6,6,1)
XXX.reshape(1,6,6)
m(XXX).reshape(1,3,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)
m(XXX).reshape(1,2,2)
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)
m(XXX).reshape(1,2,2)
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)
m(XXX).reshape(1,3,3)
XXX = tnp.arange(2*4*4*1).reshape(2,4,4,1)
XXX.reshape(2,4,4)
m(XXX).reshape(2,2,2)
XXX = tnp.arange(1*4*4*3).reshape(1,4,4,3)
XXX[...,0]
m(XXX)[...,0]
-
레이어생성
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)
cnv(XXX).reshape(1,3,3)
- 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))
-
conv연산 추론
tf.reshape(cnv.weights[0],(2,2))
0 * -0.13014299 + 1 * -0.23927206 + 4 * -0.20175874 + 5 * -0.6158894 + 0
-
내가 정의한 weights를 대입하여 conv 연산 확인
cnv.get_weights()[0].shape
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)
cnv(XXX).reshape(1,3,3)
np.mean([0,1,4,5])+3, np.mean([1,2,5,6])+3, np.mean([2,3,6,7])+3
-
요약
(1) size=(2,2)인 윈도우를 만듬.
(2) XXX에 윈도우를 통과시켜서 (2,2)크기의 sub XXX 를 얻음. sub XXX의 각 원소에 conv2d.weights[0]의 각 원소를 element-wise하게 곱한다.
(3) (2)의 결과를 모두 더한다. 그리고 그 결과에 다시 conv2d.weights[1]을 수행
(4) 윈도우를 이동시키면서 반복!
-
레이어와 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.reshape(cnv.weights[0],(3,3)) ## 커널의 가중치
cnv(XXX).reshape(1,3,3) ## 출력: conv(XXX)
tf.reduce_sum(XXX.reshape(1,5,5)[0,:3,:3] * tf.reshape(cnv.weights[0],(3,3)))
![](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)
cnv = tf.keras.layers.Conv2D(1,(3,3))
cnv.weights
cnv(XXX).reshape(1,3,3)
cnv.weights[0]
_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.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))
np.mean([0,1,5,6])+3,np.mean([25,26,30,31])+3,
-
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))
cnv(XXX)
cnv.weights[0] # (2,2) 커널의 크기 // 1은 XXX의 채널수 // 4는 conv(XXX)의 채널수
cnv.weights[0][...,0].reshape(2,2) ## conv(XXX)의 첫번째채널 출력을 얻기 위해 곱해지는 w
tf.reduce_sum(XXX.reshape(1,2,2) * cnv.weights[0][...,0].reshape(2,2)) ### conv(XXX)의 첫번째 채널 출력결과
-
계산결과를 확인하기 쉽게 하기 위한 약간의 트릭
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))
- 이렇게 XXX를 설정하면 cnv(XXX)의 결과는 단지 cnv의 weight들의 sum이 된다.
cnv(XXX)
cnv.weights[0] # (2,2) 커널의 크기 // 1은 XXX의 채널수 // 4는 conv(XXX)의 채널수
cnv.weights[0][...,0].reshape(2,2) ## conv(XXX)의 첫번째채널 출력을 얻기 위해 곱해지는 w
tf.reduce_sum(cnv.weights[0][...,0])
#tf.reduce_sum(XXX.reshape(1,2,2) * cnv.weights[0][...,0].reshape(2,2)) ### conv(XXX)의 첫번째 채널 출력결과
-
결과확인을 쉽게하기 위해서 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)
cnv.weights[0] ## (2,2)는 커널의 사이즈 // 3은 XXX의채널 // 4는 cnv(XXX)의 채널
cnv.weights[0][...,0] ## cnv(XXX)의 첫번째 채널결과를 얻기 위해서 사용하는 w
tf.reduce_sum(cnv.weights[0][...,0]) ### cnv(XXX)의 첫번째 채널의 결과
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)의 결과
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)의 첫채널 출력결과
아래와 같은 흑백이미지가 있다고 하자.
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)
cnv(XXX).reshape(1,5,5)
cnv.weights[0]
_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
cnv(XXX).reshape(1,5,5)