์ด๋ฏธ์ง ๋ถ๋ฅ ๋ฌธ์ ์ ์ฃผ๋ก ์ฌ์ฉ๋๋ CNN์ ๋ํด์ ์์๋ณด์!
๊ฐ์ฅ ๋ณดํธํ๋ CNN์ ๊ตฌ์กฐ๋ผ๊ณ ํ ์ ์๋ค.
Convolution Layer์์ ํน์ง์ ์ ์ถ์ถํ ์ ์๋๋กํ๋ kernel์ ๊ฐ์ค์น(weight)๊ฐ ํ์ต๋๋ค.
์ปค๋์ด๋ ์ปจ๋ณผ๋ฃจ์
๋ ์ด์ด๊ฐ ํ์ต๋ ๋ ์ฌ์ฉ๋๋ ํ๋์ ํ๊ณผ ๊ฐ๋ค.
๋ฏธ๋ฆฌ ๋ณด์๋ฉด ์ด๋ฏธ์ง์ ๋ปฅ ๋ซ๋ฆฐ ์ ์ฌ๊ฐํ์ด ์ปค๋์ด๋ค.
์ปค๋์ด ์ด๋ฏธ์ง๋ฅผ ์ด๋ํ๋ฉฐ ์ปค๋๊ณผ feature๋งต ๊ฐ์ ์ฐ์ฐ์ด ์ด๋ฃจ์ด์ง๋ค.
์ปจ๋ณผ๋ฃจ์
์ฐ์ฐ์ ํต๊ณผํ์ ๋, ๋์ค๊ฒ๋๋ ์ถ์ถ๋ ํน์ง map์ด๋ค.
์ด๋ฌํ feature map์ ๊ฐ์๋ ์ปจ๋ณผ๋ฃจ์
layer์์์ ์ปค๋์ ๊ฐ์์ ๋ฐ๋ผ์ ๋ฌ๋ผ์ง๊ฒ ๋๋ค.
ํด๋น ์ปค๋ ํ๋๋น ์๋ก์ด feature map์ด ํ๋์ฉ ์์ฑ๋๋ ๊ฒ.
์ด๋ฌํ feature map์ ๋ง์ ์์ฑ์ผ๋ก ์ธํด ๊ณผ์ ํฉ ๋ฐ ๋ง์ ์ฐ์ฐ๋์ด ์๊ธธ ์ ์๋๋ฐ, ์ด๋ฅผ ํด๊ฒฐํ๋ ๊ฒ์ด ๋ฐ๋ก Conv2D
์ดํ ์งํํ๋ Maxpooling2D
๊ณผ ๊ฐ์ ๊ณผ์ ์ด๋ค.
RGB 3๊ฐ์ ๊ฐ์ ๊ฐ์ง๋ ์ด๋ฏธ์ง๊ฐ ์๋ค๊ณ ํ์. (7x7x3)
์ด๋ฌํ ์ด๋ฏธ์ง๋ 3depth๋ฅผ ๊ฐ์ง๋ค. (๊น์ด๊ฐ ์ด RGB๋ก 3์ด๋ผ๋ ๋ป)
์ด๋ ๊ฐ๊ฐ์ ์ฑ๋์ ๋ํด์ ๋ค๋ฅธ ์ปค๋์ ์ ์ฉํด๋ ๋๊ณ , ๊ฐ์ ์ปค๋์ ์ ์ฉํด๋ ๋ ๊ฒ์ด๋ค.
์ฌ๊ธฐ์๋ ํ๋์ ์ปค๋์ ๊ฐ๊ฐ ๋ค๋ฅด๊ฒ ํ์ ๊ต์ฒด๋ง์ ํตํด ์ฌ์ฉํ์ผ๋ฏ๋ก, ๊ฒฐ๊ณผ์ ์ผ๋ก ๋จ ํ๊ฐ์ ์ปค๋๋ง์ ์ฌ์ฉํ๋ค.
์ปค๋์ ์ฌ์ฉ๊ฐ์ = ์ดํ ์์ฑ๋๋ feature map์ ๊ฐ์ ์ด๋ฏ๋ก ํด๋น ๊ฒฐ๊ณผ๋ (5x5x1)์ ๊ฒฐ๊ณผ๊ฐ ๋์ค๊ฒ ๋๋ค.
dept๋ 1์ธ๊ฒ์ ์๊ฒ ๋๋ฐ, ์ด๋ฏธ์ง์ ํฌ๊ธฐ๋ ์ ์ค์์๊น? ์๋์ ๋์ค๋ padding๊ณผ stride์ ๊ด๋ จ๋ ๋ด์ฉ์ด๋ค.
๋จ์ํ๊ฒ ๋ฏธ๋ฆฌ ๋งํ์๋ฉด ํฉ์ฑ๊ณฑ ์ ๊ฒฝ๋ง(Convolution Layer)๋ฅผ ํต๊ณผํ๋ ๊ณผ์ ์์ 3x3 ์ปค๋์ด ์ฌ์ฉ๋์๋ค. ์ด ๋, ์ด๋ฌํ ์ปค๋์ด ์ด๋ฏธ์ง ์์์ ์์ง์ฌ๊ฐ๋ฉฐ ํฉ์ฑ๊ณฑ์ฐ์ฐ์ด ์ด๋ฃจ์ด์ง๊ฒ ๋๋๋ฐ ๋งจ ๊ฐ์ชฝ์ ์๋ edge(๊ฒฝ๊ณ)์์ญ์ ํฝ์ ์๋ ์์ ๊ณต๊ฐ์ด ์๊ธฐ์ ์ปค๋์ด ์ฌ๋ผ๊ฐ์ง ๋ชปํด ํฉ์ฑ๊ณฑ ์ฐ์ฐ์ ์งํํ ์ ์๋ค. ๋ฐ๋ผ์ ์ฐ์ฐ์ด ๋์ง์์ผ๋ฏ๋ก ํด๋น ๋ถ๋ถ๋งํผ ์ด๋ฏธ์ง์ ํฌ๊ธฐ๊ฐ ๊ฐ์ํ๋ ๊ฒ์ด๋ค.
์ฐธ๊ณ ๋ก Tensorflow์์์ ํจ์๋
Conv2D(1,(3, 3),input_shape = (7,7,3), activation = 'relu')
์ด๋ฌํ ํจ์๊ฐ ๋์ํ๋ค๋ ๊ฒ์ ์ ์ ์๋ค.
๊ฐ์ฅ์๋ฆฌ์์ ์ปจ๋ณผ๋ฃจ์ ์ฐ์ฐ์ด ์ด๋ฃจ์ด ์ง๋ ๊ฒ์ ๋ง๊ธฐ์ํด Image์ ๊ฐ์์ ํฝ์ ์ ์ฑ์ ๊ฐ์ฅ์๋ฆฌ ์์ญ๋ํ ์ปจ๋ณผ๋ฃจ์ ์ฐ์ฐ์ด ์ด๋ฃจ์ด์ง๋๋ก ํ๋ ๊ฒ์ด๋ค.
ํ์ฌ ๊ทธ๋ฆผ์์๋ 5x5 input image์ ๋ํด์ padding์ ์ ์ฉํ์๊ธฐ์ ๊ฒฐ๊ณผ๊ฐ 5x5 ํฌ๊ธฐ๊ทธ๋๋ก ๋์จ๋ค.
padding์ ํ๋ ๋ฐฉ์์๋ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์๋๋ฐ ์์ ํฝ์
์ ๊ฐ์ ๋ณต์ฌํ๋ ๋ฐฉ๋ฒ, ๊ทธ๋ฅ 0์ผ๋ก ์ฑ์ฐ๋ ๋ฐฉ๋ฒ(zero padding)๋ฑ์ด ์๋ค.
์์์ฒ๋ฆฌ ํํธ์์ ์ด๊ฒ์ ๋ํด์ ์ ๋๋ก ๋ค์ ๋ค๋ค๋ณด๋๋ก ํ๊ฒ ๋ค.
์ปค๋์ ์์ง์ด๋ ๋ณดํญ size๋ฅผ ๋ปํ๋ค.
์์ง์ด๋ ๋ณดํญ์ 2์นธ์ฉ ์ด๋ํ๋ ๋น์ฐํ ์ค๊ฐ์์ ์ฐ์ฐ์ด ์๋๋ ๋ถ๋ถ์ด ์๊ธด๋ค.
์ฐ์ฐ์ด ๋์ง์์ผ๋ฉด ๊ฒฐ๊ณผ ์์์ ํฌํจ๋์ง ์์ผ๋ฏ๋ก, padding์ ํ๋๋ผ๋ ํฌ๊ธฐ๊ฐ ์ค์ด๋๋ ๊ฒฐ๊ณผ๋ฅผ ํ์ธ ํ ์ ์๋ค.
padding์ ํ๋ค๊ณ ํด์ ๋ฐ๋ผ์ ์์์ด ํญ์ ์ค์ด๋ค์ง ์๋๋ก ํ๋ ๊ฒ์ ์๋๋ค. stride๊ฐ = 2 ์ด์์ผ๋ก ์ ์ฉ๋ ์, ๋ค์๊ณผ ๊ฐ์ด padding ์์๋ ์์์ ํฌ๊ธฐ๊ฐ ์ค์ด๋ ๋ค.
์ซ์๋ ์์๋ก ํ๊ธฐํ ๊ฒ์ด๋ฏ๋ก ์ซ์๋ ๋ฐ๋ก ํฌ๊ฒ ๊ณ์ฐํ์ง ์๊ธธ ๋ฐ๋๋ค.
+1 ๋ค์๊ณผ ๊ฐ์ ์์์ผ๋ก ๊ตฌํ ์ ์๋ค.
ํ์ต๋๋ ํ๋ผ๋ฏธํฐ์ ์๋ ๊ธฐ๋ณธ์ ์ผ๋ก "์ปค๋" ์ด ํ์ต๋๋ ๊ฒ์ ์ ์ํ๋ฉฐ ๊ตฌํ๋ฉด ์ฝ๋ค.
(7x7)์ปค๋์ 64๊ฐ ์ฌ์ฉํ๊ณ input_shape๊ฐ (5x5x1) ์ด๋ผ๊ณ ๊ฐ์ ํ์.
(์ปค๋ ๊ฐ๋ก) x (์ปค๋ ์ธ๋ก) x (์ปค๋์ ์) x (input shape์ depth) + ํด๋น ์ปค๋์ bias ์
7 x 7 x 64 x 1 + 64 = 3,200
์ฌ๊ธฐ์ ์ปค๋์ด ํ์ต๋๋ ์ปค๋์ ์ด 3x3๊ฐ์ ๊ฐ ๊ทธ๋ฆฌ๊ณ ์ด๋ฌํ ์ปค๋์ด ์ด 32๊ฐ
depth๊ฐ 1๊น์ง๋ ์ฌ์ด๋ฐ, bias๋ ๋ฌด์์ผ๊น?
bias๋ ์ปค๋๋ง๋ค ํ๋์ฉ ๋ถ๋ ํธํฅ์น ๊ฐ์ด๋ค.
๋ฐ๋ผ์ ์ปค๋์ด ์ด 32๊ฐ ํ์ต๋๋ฏ๋ก ์ต์ข
๊ฐ์ 32๋ฅผ ๋ํด์ฃผ๋ฉด ๋๋ค.
์ปค๋์ด ํ์ต๋๋ฏ๋ก ์ด๋ฏธ์ง์ ํฌ๊ธฐ(28x28)๋ param์ ๋ค์ด๊ฐ์ง ์๋๋ค๋ ์ ์ ์ฃผ์ํ์.
ํด๋น ์์ ์ 2๋ฒ์ฌ Conv2D ์ฐ์ฐ์ ๋ณด์.
์ปค๋์ด 3X3, ์ปค๋์ ์ 64, input์ผ๋ก ๋ค์ด์ค๋ depth๋ 32๊ฐ ๋๋ค.
๋ฐ๋ผ์ 3 x 3 x 64 x 32 = 18,432 ๊ฐ์ param์ด ๋๋ค.
์ฌ๊ธฐ์ ์ปค๋์ ์ ๋งํผ bias๊ฐ ์กด์ฌํ๋ฏ๋ก 64๋ฅผ ๋ํด์ค๋ค๋ฉด?
์ต์ข
์ ์ผ๋ก 18,496์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์๋ค.
๊ทธ๋ผ ์ข ๋ ์๋์ชฝ flatten์ ๋ณด์
flatten์ ๊ฐ๋จํ ํ์ฌ ์ด๋ฏธ์ง๋ฅผ 1์ฐจ์ ์ด๋ฒกํฐ๋ก ๋ณ๊ฒฝํ๋ ๊ฒ์ด๋ฏ๋ก ๊ฐ๋กx์ธ๋กxdept๋ฅผ ๊ณฑํ๋ฉด ๋๋ค.
12x12x64 = 9,216
์ดํ dense๋ฅผ ์ดํด๋ณด๋ฉด 128๊ฐ์ ๋ ธ๋๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค.
FC์๋ Conv2D๋ ๊ตฌํด์ง๋ ๊ฒ์ด ์ฝ๊ฐ ๋ค๋ฅด๋ค. ํ์ง๋ง ์๊ฐํด๋ณด๋ฉด ์ฝ๋ค.
FC๋ ๋ค์ด์ค๋ ์ธต์ ๋
ธ๋์ ๊ฐ์ X ํ์ฌ ์ธต์ ๋
ธ๋ ๊ฐ์ + bias์ ์๋ก ๊ตฌํด์ง๋ค.
์ฌ๊ธฐ์์ bias๋ ์ปค๋์ ์์ ๊ฐ์ด ํด๋น dense layer์์์ ๋
ธ๋ ์์ ๊ฐ๋ค.
๋ฐ๋ผ์ 9216 x 128 + 128(node๋ณ bias์ ๊ฐ์)๋ฅผ ํตํด 1,179,776์ ๊ฐ์ ์ป์ ์ ์๋ค.
์ฌ์ค 9216 + 1 x 128๊ณผ ๊ฐ์ ์ฐ์ฐ๊ฒฐ๊ณผ๊ฐ ๋์ค๋, ์์ ์ดํดํ๊ธฐ์๋ ์ ๋ ๊ฒ ์ฐ๋ ๊ฒ์ด ํจ์ฌ ์ฝ๋ค๊ณ ์๊ฐํ๋ค.
์ธํ x ์์ ํ(ํ์ฌ ๊ฐ์) + ํ์ฌ ์ธต์ bias ์
- 60 x 24 + 24 = 1464
- 24 x 10 + 10 = 250
- 10 x 1 + 1 = 11
๋ถ๋ฅ๋ฅผ ์ ์ํํ ์ ์๋๋ก ์
๋ ฅ feature map์ ํฌ๊ธฐ๋ฅผ ์ค์ธ๋ค.
์ฆ, ์ถ์ถ๋ feature์ค์์ ์ค์ํ ๊ฒ๋ง ์ถ์ถํ๊ฒ ๋ค.
(์ด๋ฅผ ํตํด ์์์ ์ฐ์ฐ๋๋ํ ๊ฐ์ํ๋ ํจ๊ณผ๋ํ ๊ฐ์ง๋ค.)
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy
import os
from keras.datasets import mnist
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPooling2D
from keras.callbacks import ModelCheckpoint,EarlyStopping
# seed ๊ณ ์
seed = 0
numpy.random.seed(seed)
tf.random.set_seed(3)
# ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ / ๋๋๊ธฐ
(X_train, Y_train), (X_test, Y_test) = mnist.load_data()
X_train = X_train.reshape(X_train.shape[0], 28, 28, 1).astype('float32') / 255
X_test = X_test.reshape(X_test.shape[0], 28, 28, 1).astype('float32') / 255
Y_train = np_utils.to_categorical(Y_train)
Y_test = np_utils.to_categorical(Y_test)
# ์ปจ๋ณผ๋ฃจ์
์ ๊ฒฝ๋ง(ํฉ์ฑ๊ณฑ ์ ๊ฒฝ๋ง) ์ค์
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3), input_shape=(28, 28, 1), activation='relu'))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=2))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax'))
model.compile(loss='categorical_crossentropyโ, optimizer='adamโ, metrics=['accuracy'])
# ๋ชจ๋ธ ์ต์ ํ ์ค์
MODEL_DIR = './model/'
if not os.path.exists(MODEL_DIR):
os.mkdir(MODEL_DIR)
modelpath="./model/{epoch:02d}-{val_loss:.4f}.hdf5"
checkpointer = ModelCheckpoint(filepath=modelpath, monitor='val_loss', verbose=1,
save_best_only=True)
early_stopping_callback = EarlyStopping(monitor='val_loss', patience=10)
# ๋ชจ๋ธ ์คํ
history = model.fit(X_train, Y_train, validation_data=(X_test, Y_test), epochs=30,
batch_size=200, verbose=0, callbacks=[early_stopping_callback,checkpointer])
# ํ
์คํธ ๋ฐ์ดํฐ ์ธํธ ์ ํ๋ ์ถ๋ ฅ
print("\n Test Accuracy: %.4f" % (model.evaluate(X_test, Y_test)[1]))
# ๊ทธ๋ํ๋ก ํํ
y_loss = history.history['loss']
y_vloss = history.history['val_loss']
# ๊ทธ๋ํ์ ๊ทธ๋ฆฌ๋๋ฅผ ์ฃผ๊ณ ๋ ์ด๋ธ์ ํ์
x_len = numpy.arange(len(y_loss))
plt.plot(x_len, y_vloss, marker='.', c="red", label='Testset_loss')
plt.plot(x_len, y_loss, marker='.', c="blue", label='Trainset_loss')
#
plt.legend(loc='upper right')
plt.grid()
plt.xlabel('epoch')
plt.ylabel('loss')
plt.show()