A.I
Linear, Convolution layer 본문
Linear 레이어¶
import tensorflow as tf
batch_size = 64
boxes = tf.zeros((batch_size, 4, 2)) # Tensorflow는 Batch를 기반으로 동작하기에,
# 우리는 사각형 2개 세트를 batch_size개만큼
# 만든 후 처리를 하게 됩니다.
print("1단계 연산 준비:", boxes.shape)
first_linear = tf.keras.layers.Dense(units=1, use_bias=False)
# units은 출력 차원 수를 의미합니다.
# Weight 행렬 속 실수를 인간의 뇌 속 하나의 뉴런 '유닛' 취급을 하는 거죠!
first_out = first_linear(boxes)
first_out = tf.squeeze(first_out, axis=-1) # (4, 1)을 (4,)로 변환해줍니다.
# (불필요한 차원 축소)
print("1단계 연산 결과:", first_out.shape)
print("1단계 Linear Layer의 Weight 형태:", first_linear.weights[0].shape)
print("\n2단계 연산 준비:", first_out.shape)
second_linear = tf.keras.layers.Dense(units=1, use_bias=False)
second_out = second_linear(first_out)
second_out = tf.squeeze(second_out, axis=-1)
print("2단계 연산 결과:", second_out.shape)
print("2단계 Linear Layer의 Weight 형태:", second_linear.weights[0].shape)
1단계 연산 준비: (64, 4, 2) 1단계 연산 결과: (64, 4) 1단계 Linear Layer의 Weight 형태: (2, 1) 2단계 연산 준비: (64, 4) 2단계 연산 결과: (64,) 2단계 Linear Layer의 Weight 형태: (4, 1)
- #### 1차원으로 줄여 데이터를 집약시켰다
- #### 각 사각형에 대해 독립적인 정보가 생겨나면서 데이터가 풍부해졌다.
import tensorflow as tf
batch_size = 64
boxes = tf.zeros((batch_size, 4, 2))
print("1단계 연산 준비:", boxes.shape)
########
# Step 1: (4,2)차원인 boxes를 (4,3)으로 확장시키는 Linear Layer를 활용하세요.
first_linear = tf.keras.layers.Dense(units=3, use_bias=False)
first_out = first_linear(boxes)
########
print("1단계 연산 결과:", first_out.shape)
print("1단계 Linear Layer의 Weight 형태:", first_linear.weights[0].shape)
print("\n2단계 연산 준비:", first_out.shape)
# Dense = Linear
second_linear = tf.keras.layers.Dense(units=1, use_bias=False)
second_out = second_linear(first_out)
second_out = tf.squeeze(second_out, axis=-1)
print("2단계 연산 결과:", second_out.shape)
print("2단계 Linear Layer의 Weight 형태:", second_linear.weights[0].shape)
print("\n3단계 연산 준비:", second_out.shape)
########
# Step 2: 4차원인 second_out을 하나의 실수으로 집약시키는 Linear Layer를 활용하세요.
third_linear = tf.keras.layers.Dense(units=1, use_bias=False)
third_out = third_linear(second_out)
third_out = tf.squeeze(third_out, axis=-1)
########
print("3단계 연산 결과:", third_out.shape)
print("3단계 Linear Layer의 Weight 형태:", third_linear.weights[0].shape)
########
# Step 3: 모든 params를 더하여 total_parmams를 구하세요.
total_params = first_linear.count_params() + second_linear.count_params() + third_linear.count_params()
print("총 Parameters:", total_params)
1단계 연산 준비: (64, 4, 2) 1단계 연산 결과: (64, 4, 3) 1단계 Linear Layer의 Weight 형태: (2, 3) 2단계 연산 준비: (64, 4, 3) 2단계 연산 결과: (64, 4) 2단계 Linear Layer의 Weight 형태: (3, 1) 3단계 연산 준비: (64, 4) 3단계 연산 결과: (64,) 3단계 Linear Layer의 Weight 형태: (4, 1) 총 Parameters: 13
Convolution 레이어¶
- 이러한 필터를 수십개를 중첩시켜 훈련 하는 레이어
- Convolution 레이어는 입력의 정보를 집약시키는 효과가 뛰어나기 때문에 여러 겹의 레이어를 중첩하는 것이 일반적
- 중첩할수록 최종 Linear 레이어는 작아지게 되어 입력에서 중요한 부분을 뽑아내는 데에 최적화
import tensorflow as tf
batch_size = 64
pic = tf.zeros((batch_size, 1920, 1080, 3))
print("입력 이미지 데이터:", pic.shape)
conv_layer = tf.keras.layers.Conv2D(filters=16,
kernel_size=(5, 5),
strides=5,
use_bias=False)
conv_out = conv_layer(pic)
print("\nConvolution 결과:", conv_out.shape)
print("Convolution Layer의 Parameter 수:", conv_layer.count_params())
flatten_out = tf.keras.layers.Flatten()(conv_out)
print("\n1차원으로 펼친 데이터:", flatten_out.shape)
linear_layer = tf.keras.layers.Dense(units=1, use_bias=False)
linear_out = linear_layer(flatten_out)
print("\nLinear 결과:", linear_out.shape)
print("Linear Layer의 Parameter 수:", linear_layer.count_params())
입력 이미지 데이터: (64, 1920, 1080, 3) Convolution 결과: (64, 384, 216, 16) Convolution Layer의 Parameter 수: 1200 1차원으로 펼친 데이터: (64, 1327104) Linear 결과: (64, 1) Linear Layer의 Parameter 수: 1327104
Pooling 레이어 - 핵심을 추려서 넓게 만듦¶
Receptive Field 개념¶
- Neural Network의 출력부가 충분한 정보를 얻기 위해 커버하는 입력 데이터의 Receptive Field가 충분히 커서 그 안에 detect해야 할 object의 특성이 충분히 포함되어있어야함.
위 그림은 7 X 7의 이미지에 3 X 3의 필터로 Convolution한 결과를 도식화한 것입니다. Convolution 레이어를 한번 통과한 후 Output의 빨간색 포인트는 원본 이미지의 좌상단 3 X 3만큼의 입력만을 수용하게 됩니다. 그 결과 이 포인트의 Receptive Field의 크기는 Filter size와 정확히 같습니다.
Max Pooling 레이어의 효과¶
translational invariance 효과
이미지는 약간의 상하좌우 시프트가 생긴다고 해도 내용상 동일한 특징이 있는데, Max Pooling을 통해 인접한 영역 중 가장 특징이 두드러진 영역 하나를 뽑는 것은 오히려 약간의 시프트 효과에도 불구하고 동일한 특징을 안정적으로 잡아낼 수 있는 긍정적 효과가 있어서 오히려 object 위치에 대한 오버피팅을 방지하고 안정적인 특징 추출 효과를 가져온다고 합니다.Non-linear 함수와 동일한 피처 추출 효과
Relu와 같은 Non-linear 함수도 마찬가지로 많은 하위 레이어의 연산 결과를 무시하는 효과를 발생시키지만, 그 결과 중요한 피처만을 상위 레이어로 추출해서 올려줌으로써 결과적으로 분류기의 성능을 증진시키는 효과를 가집니다. Min/Max Pooling도 이와 동일한 효과를 가지게 됩니다.Receptive Field 극대화 효과
Max Pooling이 없이도 Receptive Field를 크게 하려면 Convolutional 레이어를 아주 많이 쌓아야 합니다. 그 결과 큰 파라미터 사이즈로 인한 오버피팅, 연산량 증가, Gradient Vanishing 등의 문제를 감수해야 합니다. 이런 문제를 효과적으로 해결하는 방법으로 꼽히는 두 가지 중 하나가 Max Pooling 레이어 사용입니다. 다른 하나로는 Dilated Convolution이 있습니다.
- 패키지 임포트 및 MNIST 데이터셋 로딩
- AutoEncoder 모델 구성
- AutoEncoder 모델 훈련
- AutoEncoder Reconstruction Test
import numpy as np
from tensorflow.python.keras.layers import Input, Dense, Conv2D, MaxPooling2D, UpSampling2D
from tensorflow.python.keras.models import Model
from tensorflow.python.keras.datasets import mnist
import json
import matplotlib.pyplot as plt #for plotting
# MNIST 데이터 로딩
(x_train, _), (x_test, _) = mnist.load_data() # y_train, y_test는 사용하지 않습니다.
# AutoEncoder가 수행하는 Image Reconstruction Task는 x_train의 라벨이 바로 x_train 자신이기때문이다.
x_train = np.expand_dims(x_train, axis=3)
x_test = np.expand_dims(x_test, axis=3)
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
# AutoEncoder 모델 구성 - Input 부분
input_shape = x_train.shape[1:]
input_img = Input(shape=input_shape)
# AutoEncoder 모델 구성 - Encoder 부분
# Conv2D 레이어는 shape를 변화시키지않는다. Output shape를 변화시키는 것은 오롯이 MaxPooling2D 레이어의 역할
encode_conv_layer_1 = Conv2D(16, (3, 3), activation='relu', padding='same')
encode_pool_layer_1 = MaxPooling2D((2, 2), padding='same')
encode_conv_layer_2 = Conv2D(8, (3, 3), activation='relu', padding='same')
encode_pool_layer_2 = MaxPooling2D((2, 2), padding='same')
encode_conv_layer_3 = Conv2D(4, (3, 3), activation='relu', padding='same')
encode_pool_layer_3 = MaxPooling2D((2, 2), padding='same')
encoded = encode_conv_layer_1(input_img)
encoded = encode_pool_layer_1(encoded)
encoded = encode_conv_layer_2(encoded)
encoded = encode_pool_layer_2(encoded)
encoded = encode_conv_layer_3(encoded)
encoded = encode_pool_layer_3(encoded)
# AutoEncoder 모델 구성 - Decoder 부분
# Shape의 변형은 upsample 레이어
decode_conv_layer_1 = Conv2D(4, (3, 3), activation='relu', padding='same')
decode_upsample_layer_1 = UpSampling2D((2, 2))
decode_conv_layer_2 = Conv2D(8, (3, 3), activation='relu', padding='same')
decode_upsample_layer_2 = UpSampling2D((2, 2))
decode_conv_layer_3 = Conv2D(16, (3, 3), activation='relu')
decode_upsample_layer_3 = UpSampling2D((2, 2))
decode_conv_layer_4 = Conv2D(1, (3, 3), activation='sigmoid', padding='same')
decoded = decode_conv_layer_1(encoded) # Decoder는 Encoder의 출력을 입력으로 받습니다.
decoded = decode_upsample_layer_1(decoded)
decoded = decode_conv_layer_2(decoded)
decoded = decode_upsample_layer_2(decoded)
decoded = decode_conv_layer_3(decoded)
decoded = decode_upsample_layer_3(decoded)
decoded = decode_conv_layer_4(decoded)
# AutoEncoder 모델 정의
autoencoder=Model(input_img, decoded)
autoencoder.summary()
Model: "model" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_1 (InputLayer) [(None, 28, 28, 1)] 0 _________________________________________________________________ conv2d_1 (Conv2D) (None, 28, 28, 16) 160 _________________________________________________________________ max_pooling2d (MaxPooling2D) (None, 14, 14, 16) 0 _________________________________________________________________ conv2d_2 (Conv2D) (None, 14, 14, 8) 1160 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 7, 7, 8) 0 _________________________________________________________________ conv2d_3 (Conv2D) (None, 7, 7, 4) 292 _________________________________________________________________ max_pooling2d_2 (MaxPooling2 (None, 4, 4, 4) 0 _________________________________________________________________ conv2d_4 (Conv2D) (None, 4, 4, 4) 148 _________________________________________________________________ up_sampling2d (UpSampling2D) (None, 8, 8, 4) 0 _________________________________________________________________ conv2d_5 (Conv2D) (None, 8, 8, 8) 296 _________________________________________________________________ up_sampling2d_1 (UpSampling2 (None, 16, 16, 8) 0 _________________________________________________________________ conv2d_6 (Conv2D) (None, 14, 14, 16) 1168 _________________________________________________________________ up_sampling2d_2 (UpSampling2 (None, 28, 28, 16) 0 _________________________________________________________________ conv2d_7 (Conv2D) (None, 28, 28, 1) 145 ================================================================= Total params: 3,369 Trainable params: 3,369 Non-trainable params: 0 _________________________________________________________________
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')
autoencoder.fit(x_train, x_train,
epochs=50,
batch_size=256,
shuffle=True,
validation_data=(x_test, x_test))
Epoch 1/50 235/235 [==============================] - 20s 81ms/step - loss: 0.6961 - val_loss: 0.6948 Epoch 2/50 235/235 [==============================] - 18s 78ms/step - loss: 0.6942 - val_loss: 0.6927 Epoch 3/50 235/235 [==============================] - 18s 76ms/step - loss: 0.6921 - val_loss: 0.6903 Epoch 4/50 235/235 [==============================] - 18s 78ms/step - loss: 0.6896 - val_loss: 0.6876 Epoch 5/50 235/235 [==============================] - 18s 79ms/step - loss: 0.6869 - val_loss: 0.6846 Epoch 6/50 235/235 [==============================] - 19s 81ms/step - loss: 0.6837 - val_loss: 0.6810 Epoch 7/50 235/235 [==============================] - 19s 79ms/step - loss: 0.6800 - val_loss: 0.6766 Epoch 8/50 235/235 [==============================] - 19s 79ms/step - loss: 0.6753 - val_loss: 0.6709 Epoch 9/50 235/235 [==============================] - 19s 79ms/step - loss: 0.6691 - val_loss: 0.6630 Epoch 10/50 235/235 [==============================] - 19s 80ms/step - loss: 0.6602 - val_loss: 0.6505 Epoch 11/50 235/235 [==============================] - 19s 80ms/step - loss: 0.6459 - val_loss: 0.6285 Epoch 12/50 235/235 [==============================] - 19s 80ms/step - loss: 0.6196 - val_loss: 0.5861 Epoch 13/50 235/235 [==============================] - 18s 79ms/step - loss: 0.5699 - val_loss: 0.5215 Epoch 14/50 235/235 [==============================] - 19s 80ms/step - loss: 0.5080 - val_loss: 0.4878 Epoch 15/50 235/235 [==============================] - 19s 81ms/step - loss: 0.4825 - val_loss: 0.4795 Epoch 16/50 235/235 [==============================] - 19s 79ms/step - loss: 0.4744 - val_loss: 0.4731 Epoch 17/50 235/235 [==============================] - 18s 77ms/step - loss: 0.4679 - val_loss: 0.4668 Epoch 18/50 235/235 [==============================] - 18s 77ms/step - loss: 0.4623 - val_loss: 0.4603 Epoch 19/50 235/235 [==============================] - 18s 78ms/step - loss: 0.4564 - val_loss: 0.4537 Epoch 20/50 235/235 [==============================] - 18s 76ms/step - loss: 0.4489 - val_loss: 0.4471 Epoch 21/50 235/235 [==============================] - 18s 77ms/step - loss: 0.4419 - val_loss: 0.4404 Epoch 22/50 235/235 [==============================] - 18s 77ms/step - loss: 0.4352 - val_loss: 0.4335 Epoch 23/50 235/235 [==============================] - 18s 77ms/step - loss: 0.4285 - val_loss: 0.4262 Epoch 24/50 235/235 [==============================] - 18s 77ms/step - loss: 0.4217 - val_loss: 0.4185 Epoch 25/50 235/235 [==============================] - 18s 76ms/step - loss: 0.4137 - val_loss: 0.4104 Epoch 26/50 235/235 [==============================] - 18s 77ms/step - loss: 0.4055 - val_loss: 0.4021 Epoch 27/50 235/235 [==============================] - 18s 77ms/step - loss: 0.3972 - val_loss: 0.3934 Epoch 28/50 235/235 [==============================] - 18s 77ms/step - loss: 0.3879 - val_loss: 0.3842 Epoch 29/50 235/235 [==============================] - 18s 77ms/step - loss: 0.3795 - val_loss: 0.3747 Epoch 30/50 235/235 [==============================] - 18s 77ms/step - loss: 0.3699 - val_loss: 0.3653 Epoch 31/50 235/235 [==============================] - 18s 77ms/step - loss: 0.3607 - val_loss: 0.3562 Epoch 32/50 235/235 [==============================] - 18s 77ms/step - loss: 0.3512 - val_loss: 0.3471 Epoch 33/50 235/235 [==============================] - 18s 77ms/step - loss: 0.3426 - val_loss: 0.3382 Epoch 34/50 235/235 [==============================] - 18s 77ms/step - loss: 0.3340 - val_loss: 0.3295 Epoch 35/50 235/235 [==============================] - 18s 76ms/step - loss: 0.3253 - val_loss: 0.3211 Epoch 36/50 235/235 [==============================] - 18s 77ms/step - loss: 0.3174 - val_loss: 0.3132 Epoch 37/50 235/235 [==============================] - 18s 76ms/step - loss: 0.3094 - val_loss: 0.3060 Epoch 38/50 235/235 [==============================] - 18s 77ms/step - loss: 0.3022 - val_loss: 0.2996 Epoch 39/50 235/235 [==============================] - 18s 77ms/step - loss: 0.2965 - val_loss: 0.2941 Epoch 40/50 235/235 [==============================] - 18s 77ms/step - loss: 0.2919 - val_loss: 0.2896 Epoch 41/50 235/235 [==============================] - 18s 77ms/step - loss: 0.2867 - val_loss: 0.2857 Epoch 42/50 235/235 [==============================] - 18s 77ms/step - loss: 0.2838 - val_loss: 0.2825 Epoch 43/50 235/235 [==============================] - 18s 77ms/step - loss: 0.2807 - val_loss: 0.2798 Epoch 44/50 235/235 [==============================] - 18s 77ms/step - loss: 0.2781 - val_loss: 0.2774 Epoch 45/50 235/235 [==============================] - 18s 77ms/step - loss: 0.2758 - val_loss: 0.2753 Epoch 46/50 235/235 [==============================] - 18s 77ms/step - loss: 0.2733 - val_loss: 0.2734 Epoch 47/50 235/235 [==============================] - 18s 77ms/step - loss: 0.2720 - val_loss: 0.2717 Epoch 48/50 235/235 [==============================] - 18s 77ms/step - loss: 0.2704 - val_loss: 0.2701 Epoch 49/50 235/235 [==============================] - 18s 77ms/step - loss: 0.2690 - val_loss: 0.2686 Epoch 50/50 235/235 [==============================] - 18s 77ms/step - loss: 0.2675 - val_loss: 0.2672
<tensorflow.python.keras.callbacks.History at 0x7f84a03bb290>
x_test_10 = x_test[:10] # 테스트 데이터셋에서 10개만 골라서
x_test_hat = autoencoder.predict(x_test_10) # AutoEncoder 모델의 이미지 복원생성
x_test_imgs = x_test_10.reshape(-1, 28, 28)
x_test_hat_imgs = x_test_hat.reshape(-1, 28, 28)
plt.figure(figsize=(12,5)) # 이미지 사이즈 지정
for i in range(10):
# 원본이미지 출력
plt.subplot(2, 10, i+1)
plt.imshow(x_test_imgs[i])
# 생성된 이미지 출력
plt.subplot(2, 10, i+11)
plt.imshow(x_test_hat_imgs[i])
Decoder Layers for Reconstruction¶
from tensorflow.python.keras.layers import Conv2DTranspose
# Conv2DTranspose를 활용한 AutoEncoder 모델
# AutoEncoder 모델 구성 - Input 부분
input_shape = x_train.shape[1:]
input_img = Input(shape=input_shape)
# AutoEncoder 모델 구성 - Encoder 부분
encode_conv_layer_1 = Conv2D(16, (3, 3), activation='relu')
encode_pool_layer_1 = MaxPooling2D((2, 2))
encode_conv_layer_2 = Conv2D(8, (3, 3), activation='relu')
encode_pool_layer_2 = MaxPooling2D((2, 2))
encode_conv_layer_3 = Conv2D(4, (3, 3), activation='relu')
encoded = encode_conv_layer_1(input_img)
encoded = encode_pool_layer_1(encoded)
encoded = encode_conv_layer_2(encoded)
encoded = encode_pool_layer_2(encoded)
encoded = encode_conv_layer_3(encoded)
# AutoEncoder 모델 구성 - Decoder 부분 -
decode_conv_layer_1 = Conv2DTranspose(4, (3, 3), activation='relu', padding='same')
decode_upsample_layer_1 = UpSampling2D((2, 2))
decode_conv_layer_2 = Conv2DTranspose(8, (3, 3), activation='relu', padding='same')
decode_upsample_layer_2 = UpSampling2D((2, 2))
decode_conv_layer_3 = Conv2DTranspose(16, (3, 3), activation='relu')
decode_upsample_layer_3 = UpSampling2D((2, 2))
decode_conv_layer_4 = Conv2DTranspose(1, (3, 3), activation='sigmoid', padding='same')
decoded = decode_conv_layer_1(encoded) # Decoder는 Encoder의 출력을 입력으로 받습니다.
decoded = decode_upsample_layer_1(decoded)
decoded = decode_conv_layer_2(decoded)
decoded = decode_upsample_layer_2(decoded)
decoded = decode_conv_layer_3(decoded)
decoded = decode_upsample_layer_3(decoded)
decoded = decode_conv_layer_4(decoded)
# AutoEncoder 모델 정의
autoencoder=Model(input_img, decoded)
autoencoder.summary()
Model: "model_1" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_2 (InputLayer) [(None, 28, 28, 1)] 0 _________________________________________________________________ conv2d_8 (Conv2D) (None, 26, 26, 16) 160 _________________________________________________________________ max_pooling2d_3 (MaxPooling2 (None, 13, 13, 16) 0 _________________________________________________________________ conv2d_9 (Conv2D) (None, 11, 11, 8) 1160 _________________________________________________________________ max_pooling2d_4 (MaxPooling2 (None, 5, 5, 8) 0 _________________________________________________________________ conv2d_10 (Conv2D) (None, 3, 3, 4) 292 _________________________________________________________________ conv2d_transpose (Conv2DTran (None, 3, 3, 4) 148 _________________________________________________________________ up_sampling2d_3 (UpSampling2 (None, 6, 6, 4) 0 _________________________________________________________________ conv2d_transpose_1 (Conv2DTr (None, 6, 6, 8) 296 _________________________________________________________________ up_sampling2d_4 (UpSampling2 (None, 12, 12, 8) 0 _________________________________________________________________ conv2d_transpose_2 (Conv2DTr (None, 14, 14, 16) 1168 _________________________________________________________________ up_sampling2d_5 (UpSampling2 (None, 28, 28, 16) 0 _________________________________________________________________ conv2d_transpose_3 (Conv2DTr (None, 28, 28, 1) 145 ================================================================= Total params: 3,369 Trainable params: 3,369 Non-trainable params: 0 _________________________________________________________________
회고¶
- Convolution레이어에 대한 것은 DeepML시간에도 접하여 어느정도 이해를 할 수 있었으나 AutoEncoder 부분은 몇번 다시 읽어봐야할 것 같다.
'파이썬 & AI 학습' 카테고리의 다른 글
딥러닝 레이어에 대한 이해 (0) | 2021.03.12 |
---|---|
Hadoop & Spark (0) | 2021.03.10 |
MapReduce 원리 (0) | 2021.03.04 |
TensorFlow v2 다뤄보기 (0) | 2021.02.26 |
파이썬으로 DB 다루기 (0) | 2021.02.24 |