[AI ์คํฐ๋] Section 8 : CNN & LeNet5
CNN (Convolutional Neural Network) ์๊ฐ
์ด๋ฏธ์ง ํ์ต ๊ณผ์
1. Pixel ์ ๋ณด ์ธ์
- pixel : 0 ~ 255 ์ฌ์ด์ ์ ์๊ฐ์ผ๋ก ๋น์ ๊ฐ๋๋ฅผ ๋ํ๋ (black : 0)
- ์ปฌ๋ฌ์ด๋ฏธ์ง : ํ๋ฐฑ ์ด๋ฏธ์ง 3์ฅ์ผ๋ก RGB๋ก ๊ฒน์ณ์ ์์ ํํํ๊ฒ ๋จ
< NN (neural network)๋ฅผ ๊ฑฐ์น๋ฉด์ ์ด๋ฏธ์ง์ ํน์ฑ์ด ํ์ต๋จ>
2. Edge/Simple Shape ํน์ฑ ํ์ต
⇒ ์๋์ธต์ ๊ฑฐ์นจ : ๋จ์ํ ํน์ฑ(์ฌ์ , ์์ง์ ๋ฑ์ ํ
๋๋ฆฌ ๋ฑ์ ํ์ต)
3. Complex Shape ํน์ฑ ํ์ต
⇒ ์๋์ธต ๋จ๊ณ๊ฐ ๊น์ด์ง : ๋จ์ํ ํน์ฑ์ ์กฐํฉํ ๋ณต์กํ ์์
์ด ํ์ต๋จ
4. ์ผ๊ตด์ธ์์ ํ์ํ ํน์ฑ ํ์ต
⇒ ์ต์ข : ์ ์ฒด ์ธ์์ ํ์ํ ํน์ฑ์ ํ์ต
5. ์ผ๊ตด์ ๋ณด๊ณ ๋๊ตฌ์ธ์ง ๋ถ๋ฅ ๊ฐ๋ฅ
CNN ์ด์ ์ ์ด๋ฏธ์ง ์ฒ๋ฆฌ : 2์ฐจ์ ์ด๋ฏธ์ง๋ฅผ 1์ฐจ์ ๋ฒกํฐ conversion

- reshape(60000, 784) : 60000์ฅ์ ์ฌ์ง์ reshape
- ๋ฌธ์ ์
- ์ด๋ฏธ์ง์ ๊ณต๊ฐ์ , ์ง์ญ์ ํน์ฑ ์์ค
- fully connected์ด๋ฏ๋ก ๊ณ์ฐ๋ ๊ธ์ฆ
⇒ 100๋ง ํฝ์ ์ ๊ฒฝ์ฐ, 1000 x 1000 ์ฌ์ง
⇒ ์ปฌ๋ฌ๋ฉด, 3 x 1000 x 1000
⇒ ์ด ๊ณ์ฐ : 300๋ง ์ฐจ์ x Layer ์ x ๊ฐ Layer์ Neuron ์ - ํด๊ฒฐ : ์ด๋ฏธ์ง๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํ ํน๋ณํ ๊ตฌ์กฐ์ NN์ด ํ์ ⇒ CNN
CNN์ ํน๋ณํ ๋ ์ด์ด
Convolutional Layer (ํฉ์ฑ๊ณฑ์ธต)
01. ํน์ง
- Image ์ ๋ณด์ ๊ณต๊ฐ์ ์ง์ญ ํน์ฑ (Locality) ๋ณด์กด
⇒ ์ปค๋ ์ฌ์ด์ฆ ๋งํผ์ patch์ ์ธ์ ํฝ์ ๋ค์ ๋ํ ์๊ด๊ด๊ณ๋ฅผ ๋น์ ํ ํํฐ๋ฅผ ์ ์ฉํด Locality ์ถ์ถ
⇒ ์ฌ๋ฌ๊ฐ์ ํํฐ ์ ์ฉ์, ๋ค์ํ locality ์ถ์ถ ๊ฐ๋ฅ
( ํํฐ ๊ฐ๊ฐ์ ํน์ง์ ์ง์ ๋ถ์ฌํ๋๊ฒ ์๋๋ผ ์ญ์ ํ์ ์ํด ์๋์ผ๋ก ์ต์ ํ๋จ) - Filter (Kernel) ์ ์ด์ฉํ ์ด๋ฏธ์ง ํน์ฑ ์ถ์ถ
- Parameter Sharing
: ์ด๋ฏธ์ง์ ๋ชจ๋ ํจ์น๊ฐ ๋์ผํ ์ปค๋์ ์ ์ฉํ์ฌ ๋ค์ ๋ ์ด์ด์ output ์ถ๋ ฅํ๋ค.
⇒ ์ฅ์ : ํ๋ผ๋ฏธํฐ์ ๊ฐ์๊ฐ ํ๊ธฐ์ ์ผ๋ก ๊ฐ์ (ํ์ต๋๋๊ฒ์ ์ปค๋๋ฐ์ ์๊ธฐ ๋๋ฌธ)
02. Kernel : ์ค์ค๋ก ํ์ตํ๋ ํ๋ผ๋ฏธํฐ๋ก, Neural Network์ ๊ฒฝ์ฌํ๊ฐ๋ฒ๊ณผ ์ค์ฐจ์ญ์ ํ๋ก ํ์ต๋๋ค
03. Convolution (ํฉ์ฑ๊ณฑ)
(1) ๋ฐฉ๋ฒ

- ์ฒซ๋ฒ์งธ image patch ์์ฑ
→ kernel ์ฌ์ด์ฆ์ ๋ง๊ฒ input ์ด๋ฏธ์ง๋ฅผ ์ด๋ฏธ์ง ํจ์น๋ก ๋ง๋ ๊ฒ
→ ๊ฒฐ๊ณผ : 5 = 1x1 + 0x2 + 0x3 + 1x4 (ํ๋์ ) - ํ ํฝ์ ์ฎ๊ฒจ์, 2๋ฒ์งธ ์ด๋ฏธ์ง ํจ์น ์์ฑ
- ๋๊น์ง ๋๋ฌ์, ํํฝ์ ๋ด๋ ค๊ฐ์ ๋ค์ ์งํ
- ๋๊น์ง ์งํ
(2) Padding
: ํฉ์ฑ๊ณฑ ์งํ์, ์ธํ์ฌ์ด์ฆ๊ฐ ์ค์ด๋ค๊ฒ ๋๋๋ฐ ์ด๋ฅผ ๋ง๊ธฐ ์ํ ๋ฐฉ๋ฒ
- default = no padding
⇒ ์ด์ : ์ด๋ฏธ์ง์ ๋๋ถ๋ถ์ ๊ฐ์ด๋ฐ๊ฐ ์ค์ํ ๊ฒ - padding์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ (= padding = ”same”) : ์ค์ํ ๋ฐ์ดํฐ๊ฐ ๊ทํ์ด์ ์์ด ์ ๋ณด์์ค์ ๋ง์์ผํ๋ ๊ฒฝ์ฐ
- ๋ฐฉ๋ฒ : 4x4 ์ธํ์ ๊ฐ์ฅ์๋ฆฌ์ 0 ํฝ์ ์ ๋ฃ์ด 5x5๋ก ๋ง๋ ํ, ํฉ์ฑ๊ณฑ์ ์งํ
(3) Striding
: ์ด๋ฏธ์ง ํจ์น๋ฅผ ์์ฑํ ๋, ์์ง์ด๋ ์ ๋ (= ํํฐ๋ฅผ ์ธํ์์ ์์ง์ด๋ ๊ฐ๊ฒฉ์ ์ ๋)

- ํน์ง : stride๊ฐ ํด์๋ก ๊ณ์ฐ์ด ์ค๊ณ , ์๋๊ฐ ๋นจ๋ผ์ง๋, ์ ๋ณด๊ฐ ๋ง์ด ์์ค๋์ด ์ ํ๋๊ฐ ๋จ์ด์ง
- ์ฌ์ฉํ๋ ๊ฒฝ์ฐ : ์ ํ๋ ๋ณด๋จ, ์๋๋ฅผ ์ค์์ ํ๊ณ ์ถ์ ๊ฒฝ์ฐ / ์ด๋ฏธ์ง๊ฐ ๋๋ฌด ํฐ ๊ฒฝ์ฐ
- ์ผ๋ฐ์ ์ผ๋ก๋ 1๋ก ๋ง์ด ํจ
(4) ์ปฌ๋ฌ ์ด๋ฏธ์ง์์์ ํฉ์ฑ๊ณฑ

- R, G, B 3๊ฐ์ ์ฑ๋๋ก ๊ตฌ์ฑ๋ ์ฌ์ง์ ์ฑ๋ ๊ฐ๊ฐ์ ํํฐ๋ฅผ ์ ์ฉ
- 3๊ฐ์ ํฉ์ฑ๊ณฑ ๊ฒฐ๊ณผ๋ฅผ ๋ํ์ฌ ํ๋์ matrix๋ก ๋ง๋ญ
- ๋น์ ํ ํํฐ๋ฅผ ์ ์ฉํ๋ ๋จ๊ณ๋ก, relu(matrix + b)๋ฅผ ๊ฑฐ์ณ, output์ ์์ฑํ๋ค.
Pooling Layer (ํ๋ง์ธต)
01. ํน์ง
- Image data ์ ์ ๋ณด ์์ค ์๋ ์์ถ (์ ๋ณด ์์ค์ ์ต์ํ!) : ์ฌ์ด์ฆ ์ถ์๋จ
โ ๊ณ์ฐ๋ ๋ฐ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ์ถ์, ํ๋ผ๋ฏธํฐ์ ์ ๊ฐ์ (๊ณผ์ ํฉ ๋ฐฉ์ง → ์ผ๋ฐํ ๋ฅ๋ ฅ์ ๋์๋จ)
- ๋ด๋ฐ์ ๊ฐ์ค์น๊ฐ ์์
- positional Invariance : ํน์ ํฝ์ ์ ์ ํํ ํฌ์ง์ ์ ๋ฏผ๊ฐ๋๊ฐ ์ ์
โ ์ฌ๋ฌ๊ฐ์ ํ๋ง์ ๊ฑฐ์น๋ฉด, ๋์ ์์ญ์ ๊ฑธ์ณ์ ๊ฐ์ ํจ๊ณผ๊ฐ ๋ฐ์ํจ
โ ์ด์ : ํ๋ง์ ๊ฑฐ์น๋ฉด์ ์๋ ์ด๋ฏธ์ง์ ์ฌ๋ฌ ๊ฐ ํฝ์ ์ ํน์ฑ์ 1ํฝ์ ์ ๋ด๊ฒ ๋๊ธฐ ๋๋ฌธ
02. ์ญํ : image subsampling
โ ์ด๋ฏธ์ง ์ฌ์ด์ฆ๋ฅผ ์ค์ฌ๋, ์ ๋ณด ์์ค์ด ์ผ๋ง ๋์ง ์์์ ์ด์ฉํ ๊ฒ
03. ์ข ๋ฅ
- Average Pooling : ํ๊ท ๊ฐ์ ๋ด, ๊ทธ ๊ฐ์ ์ฌ์ฉํ๋ ๊ฒ
- Max Pooling : ์ต๋๊ฐ์ ๊ฐ์ ธ์จ ๊ฒ
โ ex) 2x2 max pooling with stride 2 : 2x2 ํฝ์ ์ ์ด๋ฏธ์ง์ ์ ์ฉํด, 4๊ฐ์ ํฝ์ ์ค ์ต๋๊ฐ 1๊ฐ์ฉ ๋ฝ์
04. Flattening

(1) ํ์ํ ์ด์ : ๋ง์ง๋ง์ ๊ผญ fully connected layer/Dense ๋ ์ด์ด๋ฅผ ๊ฑฐ์ณ์ผํ๋๋ฐ, ์ด๋ค์ ์ ๋ ฅ์ 1์ฐจ์์ผ๋ก๋ง ๋ฐ๊ธฐ ๋๋ฌธ์
(2) ๊ณผ์
- ์ด๋ฏธ์ง๋ฅผ Flattening ์ ํตํด 1์ฐจ์์ผ๋ก ๋ง๋ฌ
- fully connected ๋ ์ด์ด๋ก ์ฐ๊ฒฐ๋ ํ๋ ๋ ์ด์ด๋ฅผ ์ง๋จ
- softmax ํจ์๋ฅผ ์ง๋, ์ด ์ฌ์ง์ด ์ด๋ค ์ฌ์ง์ผ ํ๋ฅ ์ ์ถ๋ ฅ
- ๋ถ๋ฅ๋จ
๋ํ์ ์ธ CNN ๋ชจ๋ธ
| AlexNet | - 2012 ๋
ILSVRC ๋ํ ์ฐ์น - LeNet์ ํ์ฅํ |
| GoogleLeNet(Inception Net) | - 2014 ๋ ILSVRC ๋ํ ์ฐ์น |
| ResNet | - 2015 ๋
ILSVRC ๋ํ ์ฐ์น - 152๊ฐ์ ์ธต : ResNet ๋ถํฐ ๋ฅํด์ง๊ธฐ ์์ - skip connection์ ํตํด ์๋์ ์ ๋ณด๋ฅผ ์์ง ์๊ณ , ํ์ต์ ์ด์ด๋๊ฐ ์ ์์ |
| MobileNet | - 1000๊ฐ์ง ํด๋์ค๋ฅผ ๋ถ๋ฅํ ์ ์๋ ๊ฐ๋ฒผ์ด ๋ชจ๋ธ - mobile device ์ฉ pre-trained model ⇒ ์ ์ดํ์ต ๋ชจ๋ธ ⇒ ํ์ธํ๋ํด์ ์ฌ์ฉ ๊ฐ๋ฅ |
| VGG-16 | - Keras ๋ด์ฅ ์ฌ์ ํ์ต ๋ชจ๋ธ - (2014 ๋ , 16 layers) |
์ค์ต - Deeper CNN์ ์ด์ฉํ CIFAR-10 ๋ถ๋ฅ
๋ชจ๋ธ

GPU๊ฐ ์ฐ๊ฒฐ๋์๋์ง ํ์ธ + ํ ์ํ๋ก์ฐ ๋ฒ์
# GPU ์ฐ๊ฒฐ ํ์ธ
from tensorflow.python.client import device_lib
device_lib.list_local_devices()
# ํ
์ํ๋ก์ฐ ๋ฒ์
import tensorflow as tf
tf.__version__
๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ
import numpy as np
from tensorflow.keras.datasets import cifar10
# train, test split
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
# (50000, 32, 32, 3)
# (10000, 32, 32, 3)
# (50000, 1)
# (10000, 1)
# ํด๋์ค๋ณ ์ด๋ฆ
cifa10_classes = ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
# ํด๋์ค๋ณ ์ฌ์ง ์๊ฐํ
fig, axes = plt.subplots(2, 8, figsize=(15, 4))
axes = axes.ravel()
for i in range(16):
idx = np.random.randint(0, len(y_train))
axes[i].imshow(X_train[idx, :])
axes[i].set_xticks([])
axes[i].set_yticks([])
axes[i].set_title(cifa10_classes[y_train[idx, 0]])
# data normalization
X_train_scaled = X_train / 255.
X_test_scaled = X_test / 255.
# one-hot encoding of class labels
# categorical cross entryopy๋ฅผ ์ ์ฉํ๊ธฐ ์ํจ
y_train_onehot = utils.to_categorical(y_train)
y_test_onehot = utils.to_categorical(y_test)
print(y_train_onehot.shape)
print(y_test_onehot.shape)
# tf.data ๋ฅผ ์ด์ฉํ shuffling and batch ๊ตฌ์ฑ
# gpu์ ํจ์จ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฆฌ๊ธฐ ์ํด ์ฌ์ฉ (์ํด๋ ๋์ค์ ๋ณํ๊ณผ์ ์ ๊ฑฐ์ณ์ง
# ์ด๊ฑฐ ํ๊ธฐ ์ ์ numpy ๋ฐ์ดํฐ (GPU์์๋ ๋ชป๋์๊ฐ๋ ๋ฐ์ดํฐ ํ์
)
# ๊ทธ๋ฅ ์ถ๋ ฅํ๋ฉด ๋ญ๊ฐ ๋์ค์ง ์์
train_ds = tf.data.Dataset.from_tensor_slices((X_train_scaled, y_train_onehot)).shuffle(10000).batch(64)
test_ds = tf.data.Dataset.from_tensor_slices((X_test_scaled, y_test_onehot)).batch(64)
๋ชจ๋ธ ๊ตฌ์ฑ
from tensorflow.keras import utils
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Activation, Dropout
from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt
# model build
model = Sequential()
model.add(Conv2D(16, (3, 3), padding='same', input_shape=(32, 32, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D((2,2))) # strides ์ง์ ์ด ์๋ต๋จ => pool ์ฌ์ด์ฆ์ ๋์ผํ๊ฒ
model.add(Dropout(0.2)) # 20 % ๋ด๋ฐ deactivate
# ์ ๋ณด๋ค ํํฐ ์ฌ์ด์ฆ ๋๋ ค๊ฐ-> ๊ณ์ ๋๋ ค๊ฐ -> ์ฌ์ง ์ฌ์ด์ง๋ maxpooling ๋๋ฉฐ ์์์ง์ง๋ง, ๊ฐ์๋ ๋์ด๋๋๋ก
model.add(Conv2D(32, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D((2, 2)))
model.add(Dropout(0.2))
model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D((2,2)))
model.add(Dropout(0.2))
model.add(Flatten()) # Dense ๋ ์ด์ด์ ์ฐ๊ฒฐํ๊ธฐ ์ํด
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax')) # ์์ํ ๋ ์ด์ด์ ๋ฐ๋ก ์ด๊ฒฐ / ๋ค์ค๋ถ๋ฅ์ฌ์ softmax
# ๋ชจ๋ธ ์์ฝ
model.summary()
๋ชจ๋ธ ํ์ต
# model compile : ๋ค์ค๋ถ๋ฅ์ฌ์ categorical_crossentropy
# Adam์ ํจ์๋ก ๋ถ๋ฅด๊ฒ ๋๋ฉด ํ๋ผ๋ฏธํฐ๋ก ํ์ต๋ฅ ๋ฑ์ ์ง์ ๊ฐ๋ฅ
model.compile(loss='categorical_crossentropy', optimizer=Adam(learning_rate=0.001), metrics=['accuracy'])
# ๋ชจ๋ธ ํ์ต
model.fit(train_ds, epochs=5, validation_data=test_ds, verbose=1, shuffle=True)
๋ชจ๋ธ ์์ธก
# [0.9354581832885742, 0.6686000227928162]
model.evaluate(test_ds, verbose=0)
# ํ๋ฅ ๋ถํฌ๋ฅผ ๋ฐํํ๋ฏ๋ก argmax๋ฅผ ์ด์ฉํด, ๊ฐ์ฅ ํ๋ฅ ์ด ๋์ ์ธ๋ฑ์ค๊ฐ ๋ฐํํ๋๋ก
# => y_test์ ๋น๊ตํ ์ ์์
y_pred = model.predict(X_test_scaled).argmax(axis=-1)
# y_test๋ฅผ flatten : (10000,1) => (10000,)
y_true = y_test.ravel()
ํ๊ฐ ์งํ
cm = confusion_matrix(y_true, y_pred)
array([[734, 25, 51, 21, 5, 6, 10, 8, 93, 47],
[ 13, 830, 3, 6, 4, 2, 8, 2, 23, 109],
[ 99, 5, 536, 81, 74, 68, 77, 25, 27, 8],
[ 41, 14, 79, 478, 46, 162, 94, 29, 27, 30],
[ 38, 5, 137, 71, 509, 42, 93, 82, 16, 7],
[ 24, 7, 80, 215, 30, 527, 30, 56, 17, 14],
[ 10, 7, 50, 64, 34, 14, 797, 3, 9, 12],
[ 17, 1, 41, 48, 59, 79, 12, 707, 9, 27],
[ 72, 46, 14, 14, 3, 6, 5, 5, 807, 28],
[ 32, 118, 6, 14, 7, 3, 7, 15, 37, 761]], dtype=int64)
์ ๋์๋์ง ํ์ธ ์๊ฐํ : ๋ญ๋ก ์์ธกํ๋์ง ํ์ธ ๊ฐ๋ฅ
fig, axes = plt.subplots(2, 8, figsize=(15, 4))
axes = axes.ravel()
# 16๊ฐ์ ๋ฌด์์ ์ด๋ฏธ์ง๋ฅผ ์ ํํ์ฌ ํ์
for i in range(16):
idx = np.random.randint(0, len(y_test)) # ๋ฌด์์ ์ธ๋ฑ์ค ์์ฑ
axes[i].imshow(X_test[idx, :]) # ์ด๋ฏธ์ง ํ์
axes[i].set_xticks([]) # x์ถ ๋๊ธ ์ ๊ฑฐ
axes[i].set_yticks([]) # y์ถ ๋๊ธ ์ ๊ฑฐ
# ์ค์ ๋ผ๋ฒจ๊ณผ ์์ธก๋ ๋ผ๋ฒจ๋ก ์ ๋ชฉ ์ค์
axes[i].set_title("true={} \\npredicted={}".
format(cifa10_classes[y_true[idx]], cifa10_classes[y_pred[idx]]))
plt.tight_layout() # ์๋ธํ๋กฏ๋ค์ด ๊ฒน์น์ง ์๋๋ก ๋ ์ด์์ ์กฐ์
plt.show()

Heat Map
plt.figure(figsize=(10,8))
sns.heatmap(cm, annot=True)
plt.xticks(np.arange(10), cifa10_classes, rotation=45, fontsize=12)
plt.yticks(np.arange(10), cifa10_classes, rotation=45, fontsize=12)
plt.xlabel("true class")
plt.ylabel("predicted class")
plt.title('Confusion Matrix')
print('Test Accuracy :', accuracy_score(y_true, y_pred))

LesNet 5
01. ์๊ฐ
- 1998๋ Yan LeCunn์ด ์ ์ํ ์ต์ด์ CNN ๋ชจ๋ธ
02. ๊ตฌ์กฐ
- 2, 4, 7, 8, 9 : 5๊ฐ์ ์ธต์ ๊ฐ์ง (ํ์ต๋๋ ํ๋ผ๋ฏธํฐ๊ฐ ์๋ ์ธต)

- input image : 32x32์ ํ๋ฐฑ ์ด๋ฏธ์ง
- convolution filter : 5x5์ 6์ฅ์ ํํฐ ⇒ ๊ฒฐ๊ณผ : 28x28x6
- pooling : average pooling (2x2 / stride 2) ⇒ ๊ฒฐ๊ณผ : 14x14x6
- convolution filter : 5x5์ 16์ฅ์ ํํฐ ⇒ ๊ฒฐ๊ณผ : 10x10x16
- pooling : average pooling (2x2 / stride 2) ⇒ ๊ฒฐ๊ณผ : 5x5x16 (5x5 ์ฌ์ด์ฆ์ ์ฌ์ง 16)
- flattening : 400x1 ๋ฒก(1655=400)
- Dense layer : 120๊ฐ์ ๋ด๋ฐ ⇒ ๊ฒฐ๊ณผ : fully connected ๋ ์ด์ด ์์ฑ
- Dense layer : 84๊ฐ์ ๋ด๋ฐ
- output layer : 10๊ฐ์ ๋ด๋ฐ ⇒ ๊ฒฐ๊ณผ : 10๊ฐ ์ค ํ๋๋ก ๋ถ๋ฅํ๋ ๋ชจ๋ธ
03. ์ค์ต : MNIST ๋ฐ์ดํฐ์ ์ ์ด์ฉํ ๋ชจ๋ธ ๊ตฌ์ถ
๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ ๋ฐ ์ ์
from tensorflow.keras.datasets import mnist
# ์๋์ผ๋ก ํ์ด์ฌ์ ํํ ํํ๋ก ๋ฐ์ดํฐ๊ฐ ๋๋
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# ํด๋์ค ๋ณ ๊ทธ๋ฆผ
plt.figure(figsize=(5,5))
for i in range(9):
plt.subplot(3, 3, i+1)
plt.imshow(X_train[i], cmap='gray', interpolation='none') # default : color
plt.title("Class {}".format(y_train[i]))
plt.xticks([])
plt.yticks([])
plt.tight_layout()
plt.show()
# simple scailing : ์ต๋๊ฐ์ผ๋ก ๋๋ 0 ~ 1 ์ฌ์ด๋ก pixel ๊ฐ์ scale
X_train_scaled = X_train / 255.
X_test_scaled = X_test / 255.
X_train_scaled.shape, X_test_scaled.shape # ((60000, 28, 28), (10000, 28, 28))
# Conv2D layer ์ ์
๋ ฅ ์ฌ์์ ๋ง์ถ์ด 3 dimension ์ผ๋ก ์ฐจ์ ์ฆ๊ฐ : ํ๋ฐฑ์ด๋ฏ๋ก 1 (์ปฌ๋ฌ๋ฉด 3)
X_train_scaled = np.expand_dims(X_train_scaled, axis=3)
X_test_scaled = np.expand_dims(X_test_scaled, axis=3)
X_train_scaled.shape, X_test_scaled.shape # ((60000, 28, 28, 1), (10000, 28, 28, 1))
# ๋ ์ด๋ธ์ one hot encoding ํด์ค -> categorical cross entryopy๋ฅผ ์ ์ฉํ๊ธฐ ์ํจ
# (60000, 10) (10000, 10)
y_train_onehot = tf.keras.utils.to_categorical(y_train)
y_test_onehot = tf.keras.utils.to_categorical(y_test)
# tf.data ๋ฅผ ์ด์ฉํ shuffling and batch ๊ตฌ์ฑ
# gpu์ ํจ์จ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฆฌ๊ธฐ ์ํด ์ฌ์ฉ (์ํด๋ ๋์ค์ ๋ณํ๊ณผ์ ์ ๊ฑฐ์ณ์ง
# ์ด๊ฑฐ ํ๊ธฐ ์ ์ numpy ๋ฐ์ดํฐ (GPU์์๋ ๋ชป๋์๊ฐ๋ ๋ฐ์ดํฐ ํ์
)
# ๊ทธ๋ฅ ์ถ๋ ฅํ๋ฉด ๋ญ๊ฐ ๋์ค์ง ์์
train_ds = tf.data.Dataset.from_tensor_slices((X_train_scaled, y_train_onehot)).shuffle(10000).batch(128) # ํํ ํํ๋ก ์
๋ ฅํผ์ฒ, ๋ ์ด๋ธ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์
test_ds = tf.data.Dataset.from_tensor_slices((X_test_scaled, y_test_onehot)).batch(128) # shuffle ํ์ ์์ -> test์ ๊ตณ์ด,,,,!
# ์ถ๋ ฅ ๋ฐฉ๋ฒ : for๋ฌธ ์ฌ์ฉ
for x, y in train_ds :
print(X)

LeNet ๊ตฌ์ฑ
model = tf.keras.Sequential()
model.add(Conv2D(6, kernel_size=5, padding="same", input_shape=(28, 28, 1))) # ํจ๋ฉ ์ ์ฉ
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(Conv2D(16, kernel_size=5, padding="valid"))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(Flatten())
model.add(Dense(120))
model.add(Activation ('relu'))
model.add(Dense(84))
model.add(Activation ('relu'))
model.add(Dense(10))
model.add(Activation ('softmax')) # ๋ค์ค๋ถ๋ฅ์ด๋ฏ๋ก softmax
model.summary()
Model: "sequential_3"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_4 (Conv2D) (None, 28, 28, 6) 156
activation_4 (Activation) (None, 28, 28, 6) 0
max_pooling2d_2 (MaxPooling 2D) (None, 14, 14, 6) 0
conv2d_5 (Conv2D) (None, 10, 10, 16) 2416
activation_5 (Activation) (None, 10, 10, 16) 0
max_pooling2d_3 (MaxPooling 2D) (None, 5, 5, 16) 0
flatten_1 (Flatten) (None, 400) 0
dense_2 (Dense) (None, 120) 48120
activation_6 (Activation) (None, 120) 0
dense_3 (Dense) (None, 84) 10164
activation_7 (Activation) (None, 84) 0
dense_4 (Dense) (None, 10) 850
activation_8 (Activation) (None, 10) 0
=================================================================
Total params: 61,706
Trainable params: 61,706
Non-trainable params: 0
# ๋ชจ๋ธ ์ปดํ์ผ
model.compile(loss="categorical_crossentropy", optimizer='adam', metrics=['accuracy'])

๋ชจ๋ธ ํ๋ จ ๋ฐ ์์ธก
# ์์์ train_ds๋ฅผ ๊ตฌ์ฑํ๋ฉฐ ๋ฐฐ์น์ฌ์ด์ฆ ๋ฑ์ ๋ง์ถฐ๋์๊ธฐ ๋๋ฌธ์ ํ์์์
history = model.fit(train_ds, epochs=5, validation_data=test_ds)
score = model.evaluate(test_ds, verbose=0)
print("Test loss ", score[0]) # Test loss 0.037596870213747025
print("Test Accuracy ", score[1]) # Test Accuracy 0.9873999953269958
y_pred = model.predict(X_test_scaled).argmax(axis=1)
# ๋ชจ๋ธ ํ๋ จ ๊ฒฐ๊ณผ ์๊ฐํ : ๊ณผ์ ํฉ์ด ์ผ์ด๋ฌ๋์ง ํ์ธํ๊ธฐ ์ํจ
plt.figure(figsize=(12,4))
plt.subplot(1, 2, 1)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('model accuracy')
plt.xlabel('epoch')
plt.ylabel('accuracy')
plt.legend(['train', 'test'])
plt.subplot(1, 2, 2)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(['train', 'test']

์์ธก ๊ฒฐ๊ณผ ํ์ธ ๋ฐ ์๊ฐํ
from sklearn.metrics import confusion_matrix, accuracy_score
# Test Accuracy : 0.985
print('Test Accuracy :', accuracy_score(y_test, y_pred))
# ํผ๋ํ๋ ฌ ๊ทธ๋ฅ ์ถ๋ ฅ
print(confusion_matrix(y_test, y_pred))
# ํผ๋ํ๋ ฌ ์๊ฐํ
plt.figure(figsize=(7,6))
sns.heatmap(confusion_matrix(y_test, y_pred), annot=True, fmt='d')
plt.xticks(np.arange(10), list(range(10)), rotation=45, fontsize=12)
plt.yticks(np.arange(10), list(range(10)), rotation=45, fontsize=12)
plt.xlabel("predicted class")
plt.ylabel("true class")
plt.title('Confusion Matrix')

04. ์ค์ต : Fashion MNIST ๋ฐ์ดํฐ์ ์ ์ด์ฉํ ๋ชจ๋ธ ๊ตฌ์ถ
๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ ๋ฐ ์ ์
(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.fashion_mnist.load_data()
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress',
'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
# ๋ฐ์ดํฐ ์์ ์๊ฐํ
plt.figure(figsize=(10,10))
for i in range(25):
plt.subplot(5,5,i+1)
plt.imshow(train_images[i], cmap=plt.cm.binary)
plt.xlabel(class_names[train_labels[i]])
plt.xticks([])
plt.yticks([])
X_train = train_images / 255.0
X_test = test_images / 255.0
# Conv2D layer ์ ์
๋ ฅ ์ฌ์์ ๋ง์ถ์ด 3 dimension ์ผ๋ก ์ฐจ์ ์ฆ๊ฐ
X_train_scaled = np.expand_dims(X_train_scaled, axis=3)
X_test_scaled = np.expand_dims(X_test_scaled, axis=3)
X_train_scaled.shape, X_test_scaled.shape # ((60000, 28, 28, 1), (10000, 28, 28, 1))
# ๋ ์ด๋ธ์ one hot encoding : (60000, 10) (10000, 10)
y_train_onehot = tf.keras.utils.to_categorical(y_train)
y_test_onehot = tf.keras.utils.to_categorical(y_test)
# tf.data ๋ฅผ ์ด์ฉํ shuffling and batch ๊ตฌ์ฑ
train_ds = tf.data.Dataset.from_tensor_slices((X_train_scaled, y_train_onehot)).shuffle(10000).batch(128) # ํํ ํํ๋ก ์
๋ ฅํผ์ฒ, ๋ ์ด๋ธ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์
test_ds = tf.data.Dataset.from_tensor_slices((X_test_scaled, y_test_onehot)).batch(128) # shuffle ํ์ ์์ -> test์ ๊ตณ์ด,,,,!

๋ชจ๋ธ ๊ตฌ์ฑ
# LeNet model ๊ตฌ์ฑ
# kernel ์ฌ์ด์ฆ๋ฅผ ์ค์ด๊ณ convolution ์ธต ํ๋ฒ ๋ ๋๋ฆผ
model = tf.keras.Sequential()
model.add(Conv2D(6, kernel_size=3, padding="same", input_shape=(28, 28, 1))) # ํจ๋ฉ ์ ์ฉ
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(Conv2D(16, kernel_size=3, padding="valid"))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(Conv2D(32, kernel_size=3, padding="valid"))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(Flatten())
model.add(Dense(120))
model.add(Activation ('relu'))
model.add(Dense(84))
model.add(Activation ('relu'))
model.add(Dense(10))
model.add(Activation ('softmax')) # ๋ค์ค๋ถ๋ฅ์ด๋ฏ๋ก softmax
model.summary()
Model: "sequential_1"
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโณโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโณโโโโโโโโโโโโโโโโโโ
โ Layer (type) โ Output Shape โ Param # โ
โกโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฉ
โ conv2d (Conv2D) โ (None, 28, 28, 6) โ 60 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโค
โ activation (Activation) โ (None, 28, 28, 6) โ 0 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโค
โ max_pooling2d (MaxPooling2D) โ (None, 14, 14, 6) โ 0 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโค
โ conv2d_1 (Conv2D) โ (None, 12, 12, 16) โ 880 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโค
โ activation_1 (Activation) โ (None, 12, 12, 16) โ 0 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโค
โ max_pooling2d_1 (MaxPooling2D) โ (None, 6, 6, 16) โ 0 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโค
โ conv2d_2 (Conv2D) โ (None, 4, 4, 32) โ 4,640 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโค
โ activation_2 (Activation) โ (None, 4, 4, 32) โ 0 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโค
โ max_pooling2d_2 (MaxPooling2D) โ (None, 2, 2, 32) โ 0 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโค
โ flatten (Flatten) โ (None, 128) โ 0 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโค
โ dense (Dense) โ (None, 120) โ 15,480 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโค
โ activation_3 (Activation) โ (None, 120) โ 0 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโค
โ dense_1 (Dense) โ (None, 84) โ 10,164 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโค
โ activation_4 (Activation) โ (None, 84) โ 0 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโค
โ dense_2 (Dense) โ (None, 10) โ 850 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโค
โ activation_5 (Activation) โ (None, 10) โ 0 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโ
Total params: 32,074 (125.29 KB)
Trainable params: 32,074 (125.29 KB)
Non-trainable params: 0 (0.00 B)
# model compile
model.compile(loss="categorical_crossentropy", optimizer='adam', metrics=['accuracy'])
๋ชจ๋ธ ํ๋ จ ๋ฐ ์์ธก ๋ฐ ๊ฒฐ๊ณผ
# ๋ชจ๋ธ ํ์ต
history = model.fit(train_ds, epochs=5, validation_data=test_ds)
score = model.evaluate(test_ds, verbose=0)
print("Test loss ", score[0]) # Test loss
print("Test Accuracy ", score[1]) # Test Accuracy
y_pred = model.predict(X_test_scaled).argmax(axis=1)
# ๋ชจ๋ธ ํ๋ จ ๊ฒฐ๊ณผ ์๊ฐํ
plt.figure(figsize=(12,4))
plt.subplot(1, 2, 1)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('model accuracy')
plt.xlabel('epoch')
plt.ylabel('accuracy')
plt.legend(['train', 'test'])
plt.subplot(1, 2, 2)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(['train', 'test']

ํผ๋ํ๋ ฌ ์๊ฐํ
# confusion matrix ์๊ฐํ
cm = confusion_matrix(y_test, y_pred)
ax = sns.heatmap(cm, annot=True, fmt='d')
plt.figure(figsize=(7,6))
ax.set_xticklabels(class_names, rotation=45, fontsize=12)
ax.set_yticklabels(class_names, rotation=45, fontsize=12)
ax.set_xlabel("predicted class")
ax.set_ylabel("true class")
