1. Cat and Dogs
1.1 Cat and Dgos
- PCA 할때 사용했던 데이터. https://hmkim312.github.io/posts/강아지와_고양이_분류기_on_PCA/
- kaggle : https://www.kaggle.com/c/dogs-vs-cats/data
- 위의 링크에서 Donwload all 버튼을 눌러 dogs-vs-cats를 받으면 된다.
- 압축을 2번 풀어 train과 test1 폴더를 구한다.
- 용량이 약 900메가정도되는 개와 고양이 이미지 데이터이다.
- rian에는 강아지 사진 12500장, 고양이 사진 12500장이 있으며, test1데이터에는 고양이와 강아지 사진이 12500장 있다.
2. 실습
2.1 Data Load
1
2
3
4
import os
path = './data/dogs-vs-cats/train/'
os.listdir(path)[:5]
1
2
3
4
5
['dog.8011.jpg',
'cat.5077.jpg',
'dog.7322.jpg',
'cat.2718.jpg',
'cat.10151.jpg']
- 고양이와 개 사진의 데이터.
- jpg 파일로 되어있음
2.2 라벨과 id로 나눔
1
2
3
full_name = os.listdir(path)
labels = [each.split('.')[0] for each in full_name]
file_id = [each.split('.')[1] for each in full_name]
1
set(labels), len(file_id)
1
({'cat', 'dog'}, 25000)
- Cat와 Dog로 라벨을 나누고, 총 파일은 25000개.
2.3 데이터 보기
1
2
3
4
5
6
7
8
9
import random
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
sample = random.choice(full_name)
image = mpimg.imread(path + sample)
plt.imshow(image)
plt.title(sample)
plt.show()
- Dog 라벨인데, 6725번은 사람과 개가.. 이런 사진이 있다.
2.4 사진의 크기
1
2
3
4
5
6
sample = random.choice(full_name)
image = mpimg.imread(path + sample)
print(image.shape)
sample = random.choice(full_name)
image = mpimg.imread(path + sample)
print(image.shape)
1
2
(132, 249, 3)
(500, 320, 3)
- 각각의 사진의 크기가 다름
1
2
3
4
5
6
7
8
9
10
11
12
13
from skimage.transform import resize
resized = resize(image, (128, 128, 3))
fig, axes = plt.subplots(1, 2, figsize=(8, 4))
ax = axes.ravel()
ax[0].imshow(image, cmap = plt.cm.gray)
ax[0].set_title('image')
ax[1].imshow(resized, cmap = plt.cm.gray)
ax[1].set_title('Resized')
fig.tight_layout()
plt.show()
- 사이즈를 128 x 128로 리사이즈를 하였음
2.5 Resized
1
2
3
4
5
6
7
8
9
from skimage.color import rgb2gray
import numpy as np
images = []
bar_total = full_name
for file in bar_total:
image = mpimg.imread(path + file)
images.append(resize(image, (128, 128, 3)))
images = np.array(images)
- 총 25000개의 데이터를 모두 128 x 128 x 3으로 리사이즈함
1
images.shape, labels[:3]
1
((25000, 128, 128, 3), ['dog', 'cat', 'dog'])
- 총 25000개의 데이터가 128 x 128 x 3의 사이즈이고, dog, cat으로 라벨링 되어있음
2.6 Label 인코딩
1
2
3
4
5
6
from sklearn.preprocessing import LabelEncoder
encoder = LabelEncoder()
encoder.fit(labels)
labels_encoded = encoder.transform(labels)
labels_encoded[:3], encoder.classes_
1
(array([1, 0, 1]), array(['cat', 'dog'], dtype='<U3'))
- Label 인코딩하고 (dog = 1, cat = 0)
2.7 Data 나누기
1
2
3
4
5
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(images, labels_encoded, test_size = 0.2, random_state = 13, stratify = labels_encoded)
X_train.shape, X_test.shape
1
((20000, 128, 128, 3), (5000, 128, 128, 3))
- 총 2만개의 학습용 데이터와 5천개의 테스트 데이터
2.8 이미지 확인
1
2
3
4
5
6
7
8
9
10
samples = random.choices(population = range(0,20000),k=8)
plt.figure(figsize = (14,12))
for idx, n in enumerate(samples):
plt.subplot(2,4, idx+1)
plt.imshow(X_train[n], cmap = 'Greys', interpolation = 'nearest')
plt.title(y_train[n])
plt.tight_layout()
plt.show()
- 욕조에 들어간 고양이도있고.. 이미지가 제각각임
2.9 CNN 모델 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from tensorflow.keras import layers, models
model = models.Sequential([
layers.Conv2D(32, (3, 3), activation='relu', input_shape = (128, 128, 3)),
layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2)),
layers.Dropout(0.25),
layers.Conv2D(64, (3, 3), activation='relu', padding='same'),
layers.MaxPooling2D(pool_size=(2, 2)),
layers.Dropout(0.25),
layers.Conv2D(64, (3, 3), activation='relu', padding='same'),
layers.MaxPooling2D(pool_size=(2, 2)),
layers.Dropout(0.25),
layers.Flatten(),
layers.Dense(512, activation='relu'),
layers.Dropout(0.25),
layers.Dense(2, activation='softmax')
])
model.summary()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 126, 126, 32) 896
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 63, 63, 32) 0
_________________________________________________________________
dropout (Dropout) (None, 63, 63, 32) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 63, 63, 64) 18496
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 31, 31, 64) 0
_________________________________________________________________
dropout_1 (Dropout) (None, 31, 31, 64) 0
_________________________________________________________________
conv2d_2 (Conv2D) (None, 31, 31, 64) 36928
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 15, 15, 64) 0
_________________________________________________________________
dropout_2 (Dropout) (None, 15, 15, 64) 0
_________________________________________________________________
flatten (Flatten) (None, 14400) 0
_________________________________________________________________
dense (Dense) (None, 512) 7373312
_________________________________________________________________
dropout_3 (Dropout) (None, 512) 0
_________________________________________________________________
dense_1 (Dense) (None, 2) 1026
=================================================================
Total params: 7,430,658
Trainable params: 7,430,658
Non-trainable params: 0
_________________________________________________________________
2.10 Fit
1
2
3
4
5
6
7
8
9
import time
model.compile(
optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
start_time = time.time()
hist = model.fit(X_train.reshape(20000, 128, 128, 3), y_train, epochs = 5, verbose=1, validation_data= (X_test.reshape(5000, 128,128,3), y_test))
print(f'Fit Time : {time.time() - start_time}')
1
2
3
4
5
6
7
8
9
10
11
Epoch 1/5
625/625 [==============================] - 143s 229ms/step - loss: 0.6912 - accuracy: 0.5497 - val_loss: 0.6332 - val_accuracy: 0.6434
Epoch 2/5
625/625 [==============================] - 141s 225ms/step - loss: 0.5874 - accuracy: 0.6835 - val_loss: 0.5333 - val_accuracy: 0.7388
Epoch 3/5
625/625 [==============================] - 134s 215ms/step - loss: 0.5083 - accuracy: 0.7490 - val_loss: 0.4638 - val_accuracy: 0.7764
Epoch 4/5
625/625 [==============================] - 134s 214ms/step - loss: 0.4518 - accuracy: 0.7847 - val_loss: 0.4352 - val_accuracy: 0.8002
Epoch 5/5
625/625 [==============================] - 134s 215ms/step - loss: 0.4071 - accuracy: 0.8144 - val_loss: 0.4200 - val_accuracy: 0.8084
Fit Time : 689.2392101287842
- 시간도 오래걸림..
2.11 학습 상황
1
2
3
4
5
6
7
8
9
plot_target = ['loss', 'val_loss', 'accuracy', 'val_accuracy']
plt.figure(figsize = (12,8))
for each in plot_target:
plt.plot(hist.history[each], label = each)
plt.legend()
plt.grid()
plt.show()
- loss도 떨어지고, accuracy도 올라가는데 어느정도 지나면 두개가 역전이 된다 오버피팅을 의심해볼만함
2.12 점수 확인
1
2
3
score = model.evaluate(X_test, y_test)
print(f'Test Loss : {score[0]}')
print(f'Test Accuracy : {score[1]}')
1
2
3
157/157 [==============================] - 6s 37ms/step - loss: 0.4200 - accuracy: 0.8084
Test Loss : 0.42004361748695374
Test Accuracy : 0.8083999752998352
- Accuracy가 0.8.. 데이터가 그렇게 좋지 않아서 그런듯 하다
2.13 예측
1
2
3
predicted_result = model.predict(X_test)
predicted_labels = np.argmax(predicted_result, axis=1)
predicted_labels
1
array([0, 1, 0, ..., 0, 1, 1])
- np.argmax : 가장 최대값을 가지는 인덱스 가져옴
2.14 틀린데이터 확인
1
2
3
4
5
6
wrong_result = []
for n in range(0, len(y_test)):
if predicted_labels[n] != y_test[n]:
wrong_result.append(n)
len(wrong_result)
1
958
- 총 5000개 데이터 중에 958개 틀림
2.15 그중 16개만 그려보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import random
samples = random.choices(population=wrong_result, k=16)
plt.figure(figsize=(14, 12))
for idx, n in enumerate(samples):
plt.subplot(4, 4, idx + 1)
plt.imshow(X_test[n].reshape(128, 128, 3),
cmap='Greys', interpolation='nearest')
plt.title('Label ' + str(y_test[n]) +
', Predict ' + str(predicted_labels[n]))
plt.axis('off')
plt.show()
- 이상한 이미지도 보이고, 그렇다.. (0 : Cat, 1 : Dog)
2.16 이미지 하나 넣고 확인
1
2
3
4
5
6
7
8
9
import cv2
import matplotlib.pyplot as plt
image_bgr = cv2.imread("./data/dogs-vs-cats/cat_test.jpeg")
test_image = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)
test_image = resize(test_image, (128, 128, 3))
plt.imshow(test_image)
plt.title('cat')
plt.show()
- 집에서 키우는 반려묘의 사진을 집어넣기로 했음.
- 데이터를 opencv로 불러오고, 이미지 사이즈를 128 x 128 x 3 으로 리 사이즈함
2.17 예측
1
2
3
4
if np.argmax(model.predict(test_image.reshape(1, 128, 128, 3))) == 0:
print('Cat')
else :
print('Dos')
1
Cat
- 고양이 사진을 넣고, 예측하기를 고양이로 해주었다.
3. 요약
3.1 요약
- CNN을 이용하여 강아지, 고양이 구별하는 모델을 생성
- 데이터에 다른 사람이나 기타 사물이 같이 찍혀있어서, 예측이 너무 안되긴 한다.
- 정제가 잘 안된데이터를 넣으면 예측모델도 좋지 않다는 한 예인듯하다.
- 그래도 집에서 키우는 반려묘의 사진을 넣고 고양이로 예측해줘서 다행이다..