ํ•ฉ์„ฑ๊ณฑ ์‹ ๊ฒฝ๋ง์„ ์‚ฌ์šฉํ•œ ์ด๋ฏธ์ง€ ๋ถ„๋ฅ˜

  • ํ•ฉ์„ฑ๊ณฑ, ํ•„ํ„ฐ, ํŒจ๋”ฉ, ์ŠคํŠธ๋ผ์ด๋“œ, ํ’€๋ง ๋“ฑ์˜ ๊ฐœ๋… -> ํ…์„œํ”Œ๋กœ ์‚ฌ์šฉ ์‹œ ์ง์ ‘ ๊ณ„์‚ฐํ•  ํ•„์š” ์—†์Œ
  • ๋ณต์žกํ•œ ๊ณ„์‚ฐ์€ keras์— ๋งก๊ธฐ๊ณ  ์‚ฌ์šฉ์ž๋Š” ์ง๊ด€์ ์œผ๋กœ ์‹ ๊ฒฝ๋ง ์„ค๊ณ„ ๊ฐ€๋Šฅ

ํŒจ์…˜ MNIST ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

  • keras API๋ฅผ ์‚ฌ์šฉํ•ด ํŒจ์…˜ MNIST ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๊ณ  ์ „์ฒ˜๋ฆฌ -> ๋ฐ์ดํ„ฐ ์Šค์ผ€์ผ 0 ~ 255 ์‚ฌ์ด์—์„œ 0 ~ 1 ์‚ฌ์ด๋กœ ๋ฐ”๊พธ๊ณ  ํ›ˆ๋ จ์„ธํŠธ์™€ ๊ฒ€์ฆ์„ธํŠธ๋กœ ๋‚˜๋ˆ”
  • ํ•ฉ์„ฑ๊ณฑ ์‹ ๊ฒฝ๋ง์€ 2์ฐจ์› ์ด๋ฏธ์ง€๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ผ๋ ฌ๋กœ ํŽผ์น˜์ง€ ์•Š๋Š”๋‹ค
  • ์ž…๋ ฅ ์ด๋ฏธ์ง€๋Š” ํ•ญ์ƒ ๊นŠ์ด (์ฑ„๋„) ์ฐจ์›์ด ์žˆ์–ด์•ผํ•จ
  • ํ‘๋ฐฑ ์ด๋ฏธ์ง€์˜ ๊ฒฝ์šฐ ์ฑ„๋„์ฐจ์›์ด ์—†๋Š” 2์ฐจ์› ๋ฐฐ์—ด์ด์ง€๋งŒ Conv2D ์ธต์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์ด ์ฑ„๋„ ์ฐจ์›์„ ๋งˆ์ง€๋ง‰์— ์ถ”๊ฐ€ํ•ด์•ผํ•จ
  • ๋„˜ํŒŒ์ด reshape() ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ ์ „์ฒด ๋ฐฐ์—ด ์ฐจ์›์„ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•˜๋ฉด์„œ ๋งˆ์ง€๋ง‰์— ์ฐจ์› ๊ฐ„๋‹จํžˆ ์ถ”๊ฐ€ ๊ฐ€๋Šฅ
from tensorflow import keras
from sklearn.model_selection import train_test_split
(train_input, train_target), (test_input, test_target) = keras.datasets.fashion_mnist.load_data()
train_scaled = train_input.reshape(-1, 28, 28, 1)/255.0
train_scaled, val_scaled, train_target, val_target = train_test_split(train_scaled, train_target, test_size=0.2, random_state=42)

png

png

ํ•ฉ์„ฑ๊ณฑ ์‹ ๊ฒฝ๋ง ๋งŒ๋“ค๊ธฐ

  • ํ•ฉ์„ฑ๊ณฑ ์‹ ๊ฒฝ๋ง์˜ ๊ตฌ์กฐ : ํ•ฉ์„ฑ๊ณฑ ์ธต์œผ๋กœ ์ด๋ฏธ์ง€์—์„œ ํŠน์ง• ๊ฐ์ง€ -> ๋ฐ€์ง‘์ธต์œผ๋กœ ํด๋ž˜์Šค์— ๋”ฐ๋ฅธ ๋ถ„๋ฅ˜ ํ™•๋ฅ  ๊ณ„์‚ฐ
  • ์ผ€๋ผ์Šค์˜ Sequential ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ตฌ์กฐ ์ •์˜ ๊ฐ€๋Šฅ

1) ๊ฐ์ฒด ์ƒ์„ฑ ํ›„ ํ•ฉ์„ฑ๊ณฑ ์ธต ์ถ”๊ฐ€

  • Sequential ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  ์ฒซ ๋ฒˆ์งธ ํ•ฉ์„ฑ๊ณฑ ์ธต์ธ Conv2D ์ถ”๊ฐ€.
  • keras.layers ํŒจํ‚ค์ง€ ์•„๋ž˜์— ์žˆ๋Š” ํด๋ž˜์Šค.
model = keras.Sequential()
model.add(keras.layers.Conv2D(32, kernel_size=3, activation='relu', padding='same', input_shape=(28,28,1)))

2) ํ’€๋ง ์ธต ์ถ”๊ฐ€

  • keras.layers ํŒจํ‚ค์ง€์—์„œ MaxPooling2D(์ตœ๋Œ€ ํ’€๋ง)์™€ AveragePooling2D(ํ‰๊ท  ํ’€๋ง) ํด๋ž˜์Šค ์ œ๊ณต
  • (2,2) ์ตœ๋Œ€ ํ’€๋ง ์‚ฌ์šฉ
model.add(keras.layers.MaxPooling2D(2))

3) ๋‘๋ฒˆ์งธ ํ•ฉ์„ฑ๊ณฑ ์ธต ์ถ”๊ฐ€

  • ์ฒซ๋ฒˆ์งธ ํ•ฉ์„ฑ๊ณฑ์ธต๊ณผ ๊ฑฐ์˜ ๋™์ผํ•˜๋ฉฐ ํ•„ํ„ฐ์˜ ๊ฐœ์ˆ˜๊ฐ€ 64๊ฐœ๋กœ ๋Š˜์–ด๋‚จ
model.add(keras.layers.Conv2D(64, kernel_size=3, activation='relu', padding='same'))

4) ๋‘๋ฒˆ์งธ ํ’€๋ง ์ธต ์ถ”๊ฐ€

  • ์œ„์˜ ๋‘ ํ•ฉ์„ฑ๊ณฑ ์ธต์€ ์„ธ์ž„ ํŒจ๋”ฉ์„ ์‚ฌ์šฉ -> ์ž…๋ ฅ์˜ ๊ฐ€๋กœ ์„ธ๋กœ ํฌ๊ธฐ๋ฅผ ์ค„์ด์ง€ ์•Š์Œ
  • ํ’€๋ง ์ธต์—์„œ ์ด ํฌ๊ธฐ๋ฅผ ์ ˆ๋ฐ˜์œผ๋กœ ์ค„์ž„
  • 64๊ฐœ์˜ ํ•„ํ„ฐ๋ฅผ ์‚ฌ์šฉํ–ˆ์œผ๋ฏ€๋กœ ์ตœ์ข…์ ์œผ๋กœ ๋งŒ๋“ค์–ด์ง€๋Š” ํŠน์„ฑ ๋งต์˜ ํฌ๊ธฐ๋Š” (7,7,64)
model.add(keras.layers.MaxPooling2D(2))

5) 3์ฐจ์› ํŠน์„ฑ ๋งต ์ผ๋ ฌ๋กœ ํŽผ์น˜๊ธฐ

  • ๋งˆ์ง€๋ง‰์— 10๊ฐœ์˜ ๋‰ด๋Ÿฐ์„ ๊ฐ€์ง„ (๋ฐ€์ง‘)์ถœ๋ ฅ์ธต์—์„œ ํ™•๋ฅ  ๊ณ„์‚ฐํ•˜๊ธฐ ๋•Œ๋ฌธ
  • ์—ฌ๊ธฐ์„œ๋Š” ํŠน์„ฑ ๋งต์„ ์ผ๋ ฌ๋กœ ํŽผ์ณ์„œ ๋ฐ”๋กœ ์ถœ๋ ฅ์ธต์— ์ „๋‹ฌํ•˜์ง€ ์•Š๊ณ  ์ค‘๊ฐ„์— ํ•˜๋‚˜์˜ ๋ฐ€์ง‘ ์€๋‹‰์ธต์„ ๋” ๋‘ 
  • Flatten -> Dense ์€๋‹‰์ธต -> Dense ์ถœ๋ ฅ์ธต
  • ์€๋‹‰์ธต๊ณผ ์ถœ๋ ฅ์ธต ์‚ฌ์ด์— dropout ์ธต์ด ์€๋‹‰์ธต์˜ ๊ณผ๋Œ€์ ํ•ฉ์„ ๋ง‰์•„ ์„ฑ๋Šฅ์„ ์ข€ ๋” ๊ฐœ์„ ํ•ด์คŒ
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(100, activation='relu'))
model.add(keras.layers.Dropout(0.4))
model.add(keras.layers.Dense(10,activation='softmax'))

6) ๋ชจ๋ธ ๊ตฌ์กฐ ์ถœ๋ ฅ

  • ์ฒซ๋ฒˆ์งธ ํ•ฉ์„ฑ๊ณฑ ์ธต์„ ํ†ต๊ณผํ•˜๋ฉด์„œ ํŠน์„ฑ ๋งต์˜ ๊นŠ์ด๋Š” 32๊ฐ€ ๋˜๊ณ  ๋‘๋ฒˆ์งธ ํ•ฉ์„ฑ๊ณฑ์—์„œ ํŠน์„ฑ ๋งต์˜ ํฌ๊ธฐ๊ฐ€ 64๋กœ ๋Š˜์–ด๋‚จ
  • ํŠน์„ฑ๋งต์˜ ๊ฐ€๋กœ์„ธ๋กœ ํฌ๊ธฐ๋Š” ์ฒซ ๋ฒˆ์งธ ํ’€๋ง ์ธต์—์„œ ์ ˆ๋ฐ˜์œผ๋กœ ์ค„์–ด๋“ค๊ณ  ๋‘ ๋ฒˆ์งธ ํ’€๋ง ์ธต์—์„œ ๋‹ค์‹œ ์ ˆ๋ฐ˜์œผ๋กœ ๋” ์ค„์–ด๋“ฌ
  • ๋”ฐ๋ผ์„œ ์ตœ์ข… ํŠน์„ฑ ๋งต์˜ ํฌ๊ธฐ๋Š” (7,7,64)
model.summary()

png

  • ๋ชจ๋ธ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐœ์ˆ˜ ๊ณ„์‚ฐ
    • ์ฒซ ๋ฒˆ์งธ ํ•ฉ์„ฑ๊ณฑ ์ธต -> 32๊ฐœ ํ•„ํ„ฐ, ํฌ๊ธฐ (3,3), ๊ฐš์ด 1, ํ•„ํ„ฐ๋งˆ๋‹ค ํ•˜๋‚˜์˜ ์ ˆํŽธ -> 3 * 3 * 1 * 32 + 32 = 320๊ฐœ
    • ๋‘ ๋ฒˆ์งธ ํ•ฉ์„ฑ๊ณฑ ์ธต -> 64๊ฐœ ํ•„ํ„ฐ, ํฌ๊ธฐ (3,3), ๊นŠ์ด 32, ํ•„ํ„ฐ๋งˆ๋‹ค ํ•˜๋‚˜์˜ ์ ˆํŽธ -> 3 * 3 * 32 * 64 + 64 = 18496๊ฐœ
    • ์€๋‹‰์ธต -> (7,7,64) ํŠน์„ฑ ๋งต 1์ฐจ์› ๋ฐฐ์—ด๋กœ ํŽผ์น˜๋ฉด (3136,). ์ด๋ฅผ 100๊ฐœ์˜ ๋‰ด๋Ÿฐ๊ณผ ์™„์ „ํžˆ ์—ฐ๊ฒฐํ•ด์•ผํ•จ -> 3136 * 100 + 100 = 313700๊ฐœ
    • ์ถœ๋ ฅ์ธต -> (100, ) ์‚ฌ์ด์ฆˆ์˜ 1์ฐจ์› ๋ฐฐ์—ด. ์ด๋ฅผ 10๊ฐœ์˜ ๋‰ด๋Ÿฐ๊ณผ ์™„์ „ํžˆ ์—ฐ๊ฒฐํ•ด์•ผํ•จ -> 100 * 10 + 10 = 1010๊ฐœ

png

keras.utils.plot_model(model)

png

keras.utils.plot_model(model, show_shapes=True, to_file='cnn-architecture.png', dpi=300)

png

๋ชจ๋ธ ์ปดํŒŒ์ผ๊ณผ ํ›ˆ๋ จ

  • ์ผ€๋ผ์Šค์˜ ์žฅ์  : ๋”ฅ๋Ÿฌ๋‹ ๋ชจ๋ธ์˜ ์ข…๋ฅ˜๋‚˜ ๊ตฌ์„ฑ ๋ฐฉ์‹์— ์ƒ๊ด€์—†์ด ์ปดํŒŒ์ผ๊ณผ ํ›ˆ๋ จ ๊ณผ์ •์ด ๊ฐ™๋‹ค
  • Adam ์˜ตํ‹ฐ๋งˆ์ด์ €๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ModelCheckpoint ์ฝœ๋ฐฑ๊ณผ EarlyStopping ์ฝœ๋ฐฑ์„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ด์„œ ์กฐ๊ธฐ ์ข…๋ฃŒ ๊ธฐ๋ฒ• ๊ตฌํ˜„
  • EarlyStopping ํด๋ž˜์Šค์—์„œ restore_best_weights ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ true๋กœ ์ง€์ • -> ํ˜„์žฌ model ๊ฐ์ฒด๊ฐ€ ์ตœ์ ์˜ ๋ชจ๋ธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ณต์›๋˜์–ด ์žˆ์Œ.
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics='accuracy')
checkpoint_cb = keras.callbacks.ModelCheckpoint('best-cnn-model.h5')
early_stopping_cb= keras.callbacks.EarlyStopping(patience=2, restore_best_weights=True)
history = model.fit(train_scaled, train_target, epochs=20, validation_data=(val_scaled, val_target),
                   callbacks=[checkpoint_cb, early_stopping_cb])

png

์„ฑ๋Šฅ ํ‰๊ฐ€

  • ์„ธํŠธ์— ๋Œ€ํ•œ ์„ฑ๋Šฅ
  • fit() ๋ฉ”์„œ๋“œ์˜ ์ถœ๋ ฅ ์ค‘ 9๋ฒˆ์งธ ์—ํฌํฌ์˜ ์ถœ๋ ฅ๊ณผ ๋™์ผ
import matplotlib.pyplot as plt
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(['train','val'])
plt.show()

png

model.evaluate(val_scaled, val_target)

png

  • ์ฒซ ๋ฒˆ์งธ ์ƒ˜ํ”Œ ์ด๋ฏธ์ง€ ํ™•์ธ
  • matplotlib์—์„œ๋Š” ํ‘๋ฐฑ ์ด๋ฏธ์ง€์— ๊นŠ์ด ์ฐจ์› ์—†์Œ. (28,28,1) ํฌ๊ธฐ๋ฅผ (28,28)๋กœ ๋ฐ”๊พธ์–ด ์ถœ๋ ฅํ•ด์•ผํ•จ
plt.imshow(val_scaled[0].reshape(28,28),cmap='gray_r')
<matplotlib.image.AxesImage at 0x1fb104bd8c8>

png

preds = model.predict(val_scaled[:1])
print(preds)

png

plt.bar(range(1,11), preds[0])
plt.xlabel('class')
plt.ylabel('prob.')
plt.show()

png

  • 9๋ฒˆ์งธ ๊ฐ’์ด 1์ด๊ณ  ๋‹ค๋ฅธ ๊ฐ’์€ ๊ฑฐ์˜ 0์— ๊ฐ€๊นŒ์›€

  • fashion MNIST dataset ์— ์ •์˜๋œ ๋ ˆ์ด๋ธ”
  • ๊ฐ ์ด๋ฏธ์ง€๋Š” ํ•˜๋‚˜์˜ ๋ ˆ์ด๋ธ”์— ๋งคํ•‘๋˜์–ด ์žˆ์Œ
  • ๋ฐ์ดํ„ฐ์…‹์— ํด๋ž˜์Šค ์ด๋ฆ„์ด ๋“ค์–ด์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฏธ์ง€๋ฅผ ์ถœ๋ ฅํ•  ๋•Œ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋ณ„๋„์˜ ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์ €์žฅ

png

classes = ['T-shirt','Trouser','Pullover','Dress','Coat','Sandal','Shirt','Sneaker','Bag','Ankle boot']
import numpy as np
print(classes[np.argmax(preds)])
Bag

ํ…Œ์ŠคํŠธ์„ธํŠธ ํ‰๊ฐ€

  • ํ›ˆ๋ จ์„ธํŠธ์™€ ๊ฒ€์ฆ์„ธํŠธ์—์„œ ํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ ํ”ฝ์…€๊ฐ’์˜ ๋ฒ”์œ„๋ฅผ 0 ~ 1 ์‚ฌ์ด๋กœ ๋ฐ”๊พธ๊ณ  ์ด๋ฏธ์ง€ ํฌ๊ธฐ (28,28)์—์„œ (28,28,1)๋กœ ๋ฐ”๊ฟˆ
  • evaluate() ํ•จ์ˆ˜๋กœ ํ…Œ์ŠคํŠธ ์„ธํŠธ์— ๋Œ€ํ•œ ์„ฑ๋Šฅ ์ธก์ •
test_scaled = test_input.reshape(-1, 28, 28, 1)/255.0
model.evaluate(test_scaled, test_target)

png