ํฉ์ฑ๊ณฑ ์ ๊ฒฝ๋ง์ ์ฌ์ฉํ ์ด๋ฏธ์ง ๋ถ๋ฅ
- ํฉ์ฑ๊ณฑ, ํํฐ, ํจ๋ฉ, ์คํธ๋ผ์ด๋, ํ๋ง ๋ฑ์ ๊ฐ๋ -> ํ ์ํ๋ก ์ฌ์ฉ ์ ์ง์ ๊ณ์ฐํ ํ์ ์์
- ๋ณต์กํ ๊ณ์ฐ์ 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)
ํฉ์ฑ๊ณฑ ์ ๊ฒฝ๋ง ๋ง๋ค๊ธฐ
- ํฉ์ฑ๊ณฑ ์ ๊ฒฝ๋ง์ ๊ตฌ์กฐ : ํฉ์ฑ๊ณฑ ์ธต์ผ๋ก ์ด๋ฏธ์ง์์ ํน์ง ๊ฐ์ง -> ๋ฐ์ง์ธต์ผ๋ก ํด๋์ค์ ๋ฐ๋ฅธ ๋ถ๋ฅ ํ๋ฅ ๊ณ์ฐ
- ์ผ๋ผ์ค์ 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()
- ๋ชจ๋ธ ํ๋ผ๋ฏธํฐ ๊ฐ์ ๊ณ์ฐ
- ์ฒซ ๋ฒ์งธ ํฉ์ฑ๊ณฑ ์ธต -> 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๊ฐ
keras.utils.plot_model(model)
keras.utils.plot_model(model, show_shapes=True, to_file='cnn-architecture.png', dpi=300)
๋ชจ๋ธ ์ปดํ์ผ๊ณผ ํ๋ จ
- ์ผ๋ผ์ค์ ์ฅ์ : ๋ฅ๋ฌ๋ ๋ชจ๋ธ์ ์ข ๋ฅ๋ ๊ตฌ์ฑ ๋ฐฉ์์ ์๊ด์์ด ์ปดํ์ผ๊ณผ ํ๋ จ ๊ณผ์ ์ด ๊ฐ๋ค
- 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])
์ฑ๋ฅ ํ๊ฐ
- ์ธํธ์ ๋ํ ์ฑ๋ฅ
- 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()
model.evaluate(val_scaled, val_target)
- ์ฒซ ๋ฒ์งธ ์ํ ์ด๋ฏธ์ง ํ์ธ
- matplotlib์์๋ ํ๋ฐฑ ์ด๋ฏธ์ง์ ๊น์ด ์ฐจ์ ์์. (28,28,1) ํฌ๊ธฐ๋ฅผ (28,28)๋ก ๋ฐ๊พธ์ด ์ถ๋ ฅํด์ผํจ
plt.imshow(val_scaled[0].reshape(28,28),cmap='gray_r')
<matplotlib.image.AxesImage at 0x1fb104bd8c8>
preds = model.predict(val_scaled[:1])
print(preds)
plt.bar(range(1,11), preds[0])
plt.xlabel('class')
plt.ylabel('prob.')
plt.show()
-
9๋ฒ์งธ ๊ฐ์ด 1์ด๊ณ ๋ค๋ฅธ ๊ฐ์ ๊ฑฐ์ 0์ ๊ฐ๊น์
- fashion MNIST dataset ์ ์ ์๋ ๋ ์ด๋ธ
- ๊ฐ ์ด๋ฏธ์ง๋ ํ๋์ ๋ ์ด๋ธ์ ๋งคํ๋์ด ์์
- ๋ฐ์ดํฐ์ ์ ํด๋์ค ์ด๋ฆ์ด ๋ค์ด์์ง ์๊ธฐ ๋๋ฌธ์ ์ด๋ฏธ์ง๋ฅผ ์ถ๋ ฅํ ๋ ์ฌ์ฉํ๊ธฐ ์ํด ๋ณ๋์ ๋ณ์๋ฅผ ๋ง๋ค์ด ์ ์ฅ
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)