충분하지 않은 훈련 데이터로 이미지 분류기를 훈련하려면 사전훈련된 모델의 하위층을 사용하는 것이 좋다. 예를 들어 사전훈련된 Xception 모델을 사용해 꽃 이미지를 분류하는 모델을 훈련해보겠다.
import tensorflow_datasets as tfds
dataset,info=tfds.load('tf_flowers',as_supervised=True,with_info=True)
dataset_size=info.splits['train'].num_examples #3670
class_names=info.features['label'].names #['dandelion','daisy',...]
n_classes=info.features['label'].num_classes # 5
with_info=True로 지정하면 데이터셋에 대한 정보를 얻을 수 있다. 여기에서는 데이터셋의 크기와 클래스의 이름을 얻는다. 이 데이터셋에는 'train' 세트만 있고 테스트 세트나 검증 세트는 없다. 따라서 훈련 세트를 나누어야 한다. TF 데이터셋에는 이를 위한 API가 제공된다. 예를 들어 데이터셋의 처음 10%를 테스트 세트로 사용하고 다음 15%를 검증 세트, 나머지 75%를 훈련 세트로 나눈다.
test_set_raw, valid_set_raw, train_set_raw = tfds.load(
"tf_flowers",
split=["train[:10%]", "train[10%:25%]", "train[25%:]"],
as_supervised=True)
plt.figure(figsize=(12,10))
index=0
for image,label in train_set_raw.take(9):
index +=1
plt.subplot(3,3,index)
plt.imshow(image)
plt.title('Class: {}'.format(class_names[label]))
plt.axis('off')
plt.show()
그 다음 이미지를 전처리 해야한다. 이 CNN 모델은 224x224 크기 이미지를 기대하므로 크기를 조정해야 한다. 또한 xception에 패키지에 포함된 preprocess_input() 함수로 이미지를 전처리해야한다.
def preprocess(image,label):
resized_image=tf.image.resize(image,[224,224])
final_image=keras.applications.xception.preprocess_input(resized_image)
return final_image,label
훈련 세트를 섞은 다음 이 전처리 함수를 3개 데이터셋에 모두 적용한다. 그다음 배치 크기를 지정하고 프리패치를 적용한다.
batch_size=32
train_set=train_set_raw.shuffle(1000)
train_set=train_set.map(preprocess).batch(batch_size).prefetch(1)
valid_set=valid_set_raw.map(preprocess).batch(batch_size).prefetch(1)
test_set=valid_set_raw.map(preprocess).batch(batch_size).prefetch(1)
그다음 이미지넷에서 사전훈련된 Xception 모델을 로드한다. include_top=False로 지정하여 네트워크의 최상층에 해당하는 전역 평균 풀링 층과 밀집 출력 층을 제외시킨다. 이 기반 모델의 출력을 바탕으로 새로운 전역 평균 풀링 층을 추가하고 그 뒤에 클래스마다 하나의 유닛과 소프트맥스 활성화함수를 가진 밀집 출력층을 놓는다. 마지막으로 케라스의 Model 클래스 객체를 만든다.
base_model=keras.applications.xception.Xception(weights='imagenet',include_top=False)
avg=keras.layers.GlobalAveragePooling2D()(base_model.output)
output=keras.layers.Dense(n_classes,activation='softmax')(avg)
model=keras.Model(inputs=base_model.input,outputs=output)
훈련 초기에는 사전훈련된 층의 가중치를 동결하는 것이 좋다.
for layer in base_model.layers:
layer.trainable=False
optimizer=keras.optimizers.SGD(lr=0.2,momentum=0.9,decay=0.01)
model.compile(loss='sparse_categorical_crossentropy',optimizer=optimizer,
metrics=['accuracy'])
history=model.fit(train_set,epochs=5,validation_data=valid_set)
for layer in base_model.layers:
layer.trainable=True
early_stopping_cb=keras.callbacks.EarlyStopping(patience=20)
callbacks=[early_stopping_cb]
optimizer=keras.optimizers.SGD(lr=0.01,momentum=0.9,decay=0.001)
model.compile(loss='sparse_categorical_crossentropy',optimizer=optimizer,
metrics=['accuracy'])
history=model.fit(train_set,
epochs=100,validation_data=valid_set,callbacks=callbacks)
잠시 후에 이 모델이 테스트 세트에서 95%의 정확도를 달성할 것이다. 이런 식으로 훌룡한 이미지 분류기를 훈련할 수 있다.
'Computer Vision > Deep learning' 카테고리의 다른 글
26. 객체 탐지 (0) | 2021.06.15 |
---|---|
25. 분류와 위치 추정 (0) | 2021.06.15 |
23. 케라스를 사용해 ResNet-34 CNN 구현 (0) | 2021.06.13 |
22. ResNet, Xception (0) | 2021.06.12 |
21. LeNet-5, AlexNet, GoogleNet (0) | 2021.06.12 |