커머스 산업에 관심이 많다보니, 커머스에서 사용할 수 있는 모델을 구상해보았고, 이미지를 통한 카테고리 분류를 한다면 하루에도 수많은 상품이 업데이트되는 커머스 플랫폼에선 자동화의 일환으로 사용할 수 있을 것이다.
from tensorflow.keras import datasets
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.layers import Dense, Conv2D, MaxPooling2D, Flatten
(train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data()
# Normalize pixel values to be between 0 and 1
train_images, test_images = train_images / 255.0, test_images / 255.0
# 라벨 설정
class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
'dog', 'frog', 'horse', 'ship', 'truck']
keras 제공 cifar10 데이터를 이용하기 위해 불러온 뒤, 정규화를 위해 255로 나눠준다.
기본적으로 cifar10 데이터는 10개의 라벨로 이뤄져있어, 해당 라벨을 분류할 수 있도록 모델 설계를 해주면 된다.
import matplotlib.pyplot as plt
plt.figure(figsize=(10,10))
for i in range(25):
plt.subplot(5,5,i+1)
plt.xticks([])
plt.yticks([])
plt.grid(False)
plt.imshow(train_images[i], cmap=plt.cm.binary)
# The CIFAR labels happen to be arrays,
# which is why you need the extra index
plt.xlabel(class_names[train_labels[i][0]])
plt.show()
train데이터 5만개 중 25개만 이미지를 띄워보면 위와같이 나온다. 위의 이미지를 학습하여 test 셋의 이미지를 맞추는지 실험해보도록 한다.
model = Sequential()
model.add(Conv2D(32, 3, activation = 'relu', input_shape=(32,32,3)))
model.add(MaxPooling2D(2,2))
model.add(Conv2D(64, 3, activation = 'relu'))
model.add(MaxPooling2D(2,2))
model.add(Conv2D(64, 3, activation = 'relu'))
model.add(Flatten())
model.add(Dense(64, activation='relu'))
model.add(Dense(10, activation='softmax'))
model.summary()
[output]
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 30, 30, 32) 896
max_pooling2d (MaxPooling2D (None, 15, 15, 32) 0
)
conv2d_1 (Conv2D) (None, 13, 13, 64) 18496
max_pooling2d_1 (MaxPooling (None, 6, 6, 64) 0
2D)
conv2d_2 (Conv2D) (None, 4, 4, 64) 36928
flatten (Flatten) (None, 1024) 0
dense (Dense) (None, 64) 65600
dense_1 (Dense) (None, 10) 650
=================================================================
Total params: 122,570
Trainable params: 122,570
Non-trainable params: 0
_________________________________________________________________
model.summary()를 통해 파라미터 수 변화, 인풋데이터의 shape 변화를 볼 수 있다.
위와같이 진행 후 컴파일을 해준다.
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(train_images, train_labels, epochs=10, validation_data=(test_images, test_labels))
[output]
Epoch 1/10
1563/1563 [==============================] - 11s 7ms/step - loss: 1.5798 - accuracy: 0.4221 - val_loss: 1.3096 - val_accuracy: 0.5288
Epoch 2/10
1563/1563 [==============================] - 9s 6ms/step - loss: 1.2251 - accuracy: 0.5639 - val_loss: 1.1692 - val_accuracy: 0.5920
Epoch 3/10
1563/1563 [==============================] - 10s 6ms/step - loss: 1.0634 - accuracy: 0.6261 - val_loss: 1.0515 - val_accuracy: 0.6330
Epoch 4/10
1563/1563 [==============================] - 10s 6ms/step - loss: 0.9634 - accuracy: 0.6622 - val_loss: 1.0322 - val_accuracy: 0.6387
Epoch 5/10
1563/1563 [==============================] - 10s 6ms/step - loss: 0.8922 - accuracy: 0.6886 - val_loss: 0.9355 - val_accuracy: 0.6719
Epoch 6/10
1563/1563 [==============================] - 10s 6ms/step - loss: 0.8331 - accuracy: 0.7113 - val_loss: 0.9039 - val_accuracy: 0.6864
Epoch 7/10
1563/1563 [==============================] - 9s 6ms/step - loss: 0.7868 - accuracy: 0.7243 - val_loss: 0.8952 - val_accuracy: 0.6916
Epoch 8/10
1563/1563 [==============================] - 9s 6ms/step - loss: 0.7464 - accuracy: 0.7376 - val_loss: 0.9186 - val_accuracy: 0.6839
Epoch 9/10
1563/1563 [==============================] - 9s 6ms/step - loss: 0.7063 - accuracy: 0.7518 - val_loss: 0.8898 - val_accuracy: 0.6986
Epoch 10/10
1563/1563 [==============================] - 9s 6ms/step - loss: 0.6677 - accuracy: 0.7668 - val_loss: 0.9407 - val_accuracy: 0.6927
# 수행
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
[output]
313/313 - 1s - loss: 0.9407 - accuracy: 0.6927 - 913ms/epoch - 3ms/step
val_accuracy가 높게 나오진 않았지만, 레이어를 늘리거나 학습을 더 하면 좀 더 높아진다.(과적합조심)
import matplotlib.pyplot as plt
plt.figure(figsize=(10,10))
for i in range(5):
plt.subplot(5,5,i+1)
plt.xticks([])
plt.yticks([])
plt.grid(False)
plt.imshow(test_images[i], cmap=plt.cm.binary)
# The CIFAR labels happen to be arrays,
# which is why you need the extra index
plt.xlabel(class_names[test_labels[i][0]])
plt.show()
위와같이 테스트 셋의 다섯개 이미지를 분류해본다.
plt.figure(figsize=(10,10))
for i in range(5):
x = np.expand_dims(test_images[i], axis=0) # 이미지의 차원을 맞추기 위해 늘려줘야한다.
predictions = model.predict(x) # 예측을 진행한다.
predicted_ids = np.argmax(predictions, axis=-1)
predicted_class_names = class_names[predicted_ids[0]]
plt.subplot(5,5,i+1)
plt.xticks([])
plt.yticks([])
plt.grid(False)
plt.imshow(test_images[i], cmap=plt.cm.binary)
plt.title(predicted_class_names)
결과를 보면 5개 모두 화질지 좋지 않음에도 잘 맞춘것을 볼 수 있다. 이러한 방식으로 상품이미지에 대한 카테고리 라벨을 학습시켜 이미지 특징으로 카테고리를 구분할 수 있는 인공지능을 만들어 봐야겠다.