Tensorflow 개발자 자격증 준비하기(6)

Tensorflow 개발자 자격증 준비하기(6)

Image Classification : Tensorflow dataset

3번 유형의 문제를 몇개 더 찾아보았다. 개/고양이 사진을 분류하는 문제를 풀어보았다.

1. 문제

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
# using the Cats v Dogs dataset from TFDS.
# The testing infrastructre will resize all images to 224x224
# with 3 bytes of color depth. Make sure your input layer trains
# images to that specification, or the tests will fail.
import tensorflow_datasets as tfds
import tensorflow as tf


dataset_name = 'cats_vs_dogs'
dataset, info = tfds.load(name=dataset_name, split=tfds.Split.TRAIN, with_info=True)

def preprocess(features):
# YOUR CODE HERE

def solution_model():
train_dataset = dataset.map(preprocess).batch(32)

model = # YOUR CODE HERE, BUT MAKE SURE YOUR LAST LAYER HAS 2 NEURONS ACTIVATED BY SOFTMAX
tf.keras.layers.Dense(2, activation='softmax')
])

return model

if __name__ == '__main__':
model = solution_model()
model.save("mymodel.h5")
  • tensorflow dataset 클래스의 개/고양이 컬러사진 데이터를 모델 학습에 사용한다.
  • 최종 레이어는 softmax로 2개 종류로 분류하는 Dense layer
    • label값은 0 or 1인 1차원 텐서다
    • label을 one hot encoding 하면 categorical cross entropy, 안하면 sparse categorical crossentropy를 사용하자.

2. 데이터 전처리

아.. 일단 데이터 다운로드 받는 것 부터가 난관이었다ㅋㅋ 오랜 고군분투 끝에 알아낸 방법은 아래와 같다.

1
2
3
4

test_dataset, train_dataset = tfds.load(name='cats_vs_dogs'
, split=('train[:35%]', 'train[20%:]')
, as_supervised=True)
  • with_info 옵션을 주면 데이터셋의 정보를 같이 반환한다.
  • split 옵션설정을 통해 데이터를 앞에서부터 30%, 나머지 80%로 분할해서 반환하도록 했다.
  • as_supervised 옵션을 True로 주면 데이터가 튜플로 반환된다. False일 경우 dictionary 형태로 반환된다. => default 값은 False.

받아온 데이터를 전처리한다. 별건 없고 일단은 그냥 (1)이미지 값을 0-1 사이로 조정하고, (2)이미지 사이즈를 (224, 224)로 줄인다.

간단한 전처리 함수는 아래와 같다.

1
2
3
4
5
6
def preprocess(img, lbl):
_img = tf.cast(img, tf.float32)
_img = tf.divide(_img, 255)
_img = tf.image.resize(_img, (224, 224)) # 이미지 사이즈를 얜 224, 아래는 244로 해둬서 한참해멤...ㅋㅋ

return _img, lbl

이제 전처리된 데이터셋으로 배치를 생성한다.

1
2
train_databatch = train_dataset.map(preprocess).batch(BATCH_SZ).repeat()
test_databatch = test_dataset.map(preprocess).batch(BATCH_SZ).repeat()
  1. map() : 데이터셋의 모든 원소에 preprocess 함수로 지정한 변환을 한다
  2. batch(BATCH_SZ) : BATCH_SZ개씩 원소를 가져와서 데이터셋에 저장한다.
    데이터셋 원소 개수는 데이터셋원소개수/BATCH_SZ(나머지있으면 +1)이다.
  3. repeat() : 이걸 넣어줘야 반복적으로 데이터셋의 모든 데이터에 대해 배치가 생긴다.

3. 모델 구성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

model = Sequential([
Conv2D(16, (3, 3), padding='same', activation='relu', input_shape=(224, 224, 3)),
MaxPooling2D(2, 2),
Conv2D(16, (3, 3), padding='same', activation='relu'),
MaxPooling2D(2, 2),
Conv2D(32, (3, 3), padding='same', activation='relu'),
MaxPooling2D(2, 2),
Conv2D(32, (3, 3), padding='same', activation='relu'),
MaxPooling2D(2, 2),
Conv2D(64, (3, 3), padding='same', activation='relu'),
MaxPooling2D(2, 2),
Flatten(),
Dropout(0.5),
Dense(128, activation='relu'),
Dense(2, activation='softmax'),
])

model.compile(optimizer='rmsprop', loss='sparse_categorical_crossentropy', metrics=['acc'])

4. 모델 학습

1
2
3
4
5
6
7
8
9
10
11
12
13
14
checkpointPath = 'catDogBest.ckpt'
mc = ModelCheckpoint(checkpointPath,
monitor = 'val_loss',
verbose = 1,
save_weights_only=True,
save_best_only = True)

model.fit(
train_databatch,
steps_per_epoch=(train_len/BATCH_SZ),
epochs=50,
validation_data=(test_databatch),
validation_steps=(test_len/BATCH_SZ),
callbacks=[mc])
1
2
Epoch 00028: val_loss improved from 0.16154 to 0.14961, saving model to catDogBest.ckpt
582/581 [==============================] - 25s 43ms/step - loss: 0.1320 - acc: 0.9513 - val_loss: 0.1496 - val_acc: 0.9445

+ 알게된 점

  • train_dataset과 test_dataset의 비율을 조정하는 것 만으로도 모델의 성능을 높일 수 있다.

  • 기존에 train_data랑 test_data를 걍 암생각없이 2 : 8로 나눴는데, 이를 3.5 : 8로 비율 조정한 것 만으로 모델 성능이 확 올라갔다.

댓글