Fly ai 4기 2주차 day 10 : 딥러닝(classification, object detection)

이성원·2024년 1월 1일
0

10일차

오전: 고양이, 개 분류하기
오후: 객체 탐지 기초

1. 여러 모델로 고양이, 개 분류

1.1 파이프라인 작성

압축 풀고 train, test loader 설정

import zipfile
import os
from sklearn.model_selection import train_test_split

zip_file_path = '/content/drive/MyDrive/cat_dog.zip'

# 압축 해제할 폴더 경로
extracted_folder_path = '/content/drive/MyDrive/cat_dog_extracted'

# 압축 해제
with zipfile.ZipFile(zip_file_path, 'r') as zip_ref:
    zip_ref.extractall(extracted_folder_path)
    
    
    from tensorflow.keras.preprocessing.image import ImageDataGenerator

# 이미지 데이터 생성기 설정
datagen = ImageDataGenerator(rescale=1./255, validation_split=0.2)

# 훈련 데이터셋 생성
train_generator = datagen.flow_from_directory(
    '/content/drive/MyDrive/cat_dog_extracted/PetImages',
    target_size=(224, 224),  # 이미지 크기 조절
    batch_size=32,
    class_mode='binary',  # 이진 분류인 경우 'binary'
    subset='training'  # 훈련 데이터 설정
)

# 테스트 데이터셋 생성
test_generator = datagen.flow_from_directory(
    '/content/drive/MyDrive/cat_dog_extracted/PetImages',
    target_size=(224, 224),
    batch_size=32,
    class_mode='binary',
    subset='validation'  # 검증 데이터 설정
)




Found 20032 images belonging to 2 classes.
Found 5007 images belonging to 2 classes.

데이터셋 확인


import matplotlib.pyplot as plt

images, labels = next(train_generator)

# 가져온 배치의 첫 번째 이미지와 라벨 시각화
plt.figure(figsize=(10, 10))
for i in range(min(9, len(images))):  # 처음 9장의 이미지만 표시
    plt.subplot(3, 3, i+1)
    plt.imshow(images[i])
    plt.title(f"Label: {int(labels[i])}")
    plt.axis("off")

plt.show()

1.2 직접 모델 구현 후 학습

import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense

# Sequential 모델 생성
model = Sequential()

model.add(Conv2D(32, (3, 3), input_shape=(224, 224, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(128, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Flatten())

model.add(Dense(256, activation='relu'))
model.add(Dense(1, activation='sigmoid'))  # 2 클래스 이진 분류

model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

history_cnn = model.fit(train_generator, epochs=5, validation_data=test_generator)

cnn 정확도: 0.97%

1.3 vgg16에 전이학습

from tensorflow.keras.applications import VGG16

# VGG16 모델 가져오기 (include_top=False로 설정하여 fully connected layers를 포함하지 않도록 설정)
base_model = VGG16(weights='imagenet', include_top=False, input_shape=(224, 224, 3))

model = Sequential()

model.add(base_model)

model.add(Flatten())
model.add(Dense(256, activation='relu'))

model.add(Dense(1, activation='sigmoid'))  # 2 클래스(고양이, 개) 이진 분류의 경우

# 기존 모델의 가중치를 동결하여 훈련하지 않도록 설정
for layer in base_model.layers:
    layer.trainable = False

# 모델 컴파일
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])


# 모델 훈련
history_vgg = model.fit(train_generator, epochs=5, validation_data=test_generator)

vgg16 정확도: 98.30%

1.4 resnet50에 전이학습

from tensorflow.keras.applications import ResNet50

# RESNET50 모델 가져오기 (include_top=False로 설정하여 fully connected layers를 포함하지 않도록 설정)
base_model = ResNet50(weights='imagenet', include_top=False, input_shape=(224, 224, 3))

model3 = Sequential()

model3.add(base_model)

model3.add(Flatten())
model3.add(Dense(256, activation='relu'))

model3.add(Dense(1, activation='sigmoid'))  # 2 클래스(고양이, 개) 이진 분류의 경우

# 기존 모델의 가중치를 동결하여 훈련하지 않도록 설정
for layer in base_model.layers:
    layer.trainable = False

# 모델 컴파일
model3.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])


# 모델 훈련
history_res = model3.fit(train_generator, epochs=15, validation_data=test_generator)

resnet50 정확도: 77.30%

1.5 비교 결과

다른 팀원들의 코드를 봤을때 차이가 전혀 없었음에도 RESNET의 정확도가 매우 높게 나왔다.

왜그런지 계속 파라미터를 바꿔보다가 IMAGE_SIZE를 (224, 224)에서 (150, 150)으로 변경하였더니 정확도가 올라갔다.

모든 경우에서 적용되진 않겠지만 여러가지 실험을 해봐야겠다.

2. 객체 탐지 연습

2.1 캐글 데이터셋 가져오기

!git clone https://github.com/Pseudo-Lab/Tutorial-Book-Utils
!mkdir -p ~/.kaggle
!cp kaggle.json ~/.kaggle
!chmod 600 ~/.kaggle/kaggle.json
!kaggle datasets download -d andrewmvd/face-mask-detection
!unzip -q /content/face-mask-detection.zip
import os
import glob
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import matplotlib.patches as patches
from bs4 import BeautifulSoup

img_path = '/content/images'
label_path = '/content/annotations'

img_list = sorted(glob.glob(img_path+'/*'))
annot_list = sorted(glob.glob(label_path+'/*'))

print(len(img_list))
print(len(annot_list))

853
853

2.2 image, label 시각화

## 바운딩 박스 시각화 함수 정의

def generate_box(obj):

    xmin = float(obj.find('xmin').text)
    ymin = float(obj.find('ymin').text)
    xmax = float(obj.find('xmax').text)
    ymax = float(obj.find('ymax').text)

    return [xmin, ymin, xmax, ymax]

def generate_label(obj):
    if obj.find('name').text == "with_mask":
        return 1
    elif obj.find('name').text == "mask_weared_incorrect":
        return 2
    return 0

def generate_target(file):
    with open(file) as f:
        data = f.read()
        soup = BeautifulSoup(data, "html.parser")
        objects = soup.find_all("object")

        num_objs = len(objects)

        boxes = []
        labels = []
        for i in objects:
            boxes.append(generate_box(i))
            labels.append(generate_label(i))

        target = {}
        target["boxes"] = boxes
        target["labels"] = labels

        return target

def plot_image(img_path, annotation):

    img = mpimg.imread(img_path)

    fig,ax = plt.subplots(1)
    ax.imshow(img)


    for idx in range(len(annotation["boxes"])):
        xmin, ymin, xmax, ymax = annotation["boxes"][idx]

        if annotation['labels'][idx] == 0 :
            rect = patches.Rectangle((xmin,ymin),(xmax-xmin),(ymax-ymin),linewidth=1,edgecolor='r',facecolor='none')

        elif annotation['labels'][idx] == 1 :

            rect = patches.Rectangle((xmin,ymin),(xmax-xmin),(ymax-ymin),linewidth=1,edgecolor='g',facecolor='none')

        else :

            rect = patches.Rectangle((xmin,ymin),(xmax-xmin),(ymax-ymin),linewidth=1,edgecolor='orange',facecolor='none')

        ax.add_patch(rect)

    plt.show()
img_list.index(img_path+'/maksssksksss307.png')
bbox = generate_target(annot_list[232])
plot_image(img_list[232], bbox)

profile
개발자

0개의 댓글