본문 바로가기

KAIROS 2기

[카이로스2기] 딥러닝 심화 교육1 : 전이학습, YOLO v8 with CV2

이번주는 딥러닝의 마지막 강의, 딥러닝 심화 교육을 진행하였다.
PLC 이전에 진행했던 딥러닝 기초 강의에 대한 간단한 복습과 이어서, 아래와 같이 전이학습과 YOLO를 메인으로 심화 과정을 배웠다.🥰

1. 데이터 전처리
2. 전이학습 & Fine Tuning
3. YOLO v8 (with cv2)
4. Labelling (Roboflow)

 

1. 데이터 전처리

본격 학습에 앞서서, 이번 주에는 데이터 전처리에 대한 내용을 많이 배울 수 있었다.
주어진 데이터로 학습하는 MNIST 같은 경우와 다르게, 실제 데이터는 당연히 모델이 학습하기에 그리 적합하지 않은 상태로 받아오게 될 것이다.
이를 잘 활용할 수 있게 하는 작업을 먼저 진행해야하는데, 이를 전처리 작업이라고 한다.
보기에 따라 귀찮고 불필요한 과정처럼 느껴질 수도 있으나, 개인적으로는 이 부분을 세세하게 배울 수 있어서 좋았다.🥹
 
전처리 과정으로는 크게 X_data(Input)와 Label(Output) 두 개에 대해서 처리해주었다.
Input(이미지)에 대해서는 제일 중요한 shape 맞추기(크기, 차원 등), 잘못된 데이터 예외처리를 진행해주었고, Output(라벨)에 대해서는 라벨링 작업, 원핫인코딩을 해주었다.
 
1) X_data (Image)
Input 데이터는 img_preprocessing 함수를 만들어 전처리를 진행해주었다.
- load_img(경로, target_size) : 이미지 데이터 크기를 전이학습 기준인 (224, 224)로 맞추기
- img_to_array : 이미지를 numpy 배열로 변환
- np.expand_dims : 개수 쌓기위해 차원 추가 (224, 224, 3)-> (1, 224, 224, 3)
- preprocess_input : vgg16에서 사용하였던 정규화 기준으로 학습할 데이터 scaling 진행
- 이미지 오류가 있는 데이터들은 None 값으로 처리 (except UnidentifiedImageError:)
- np.concatenate : 전처리 완료된 이미지를 한 더미로 쌓아주기 : (76, 224, 224, 3)
 


2) Label
정답인 라벨 값 생성은 비교적 간단한 편이다.
- def label(path) if '' in path: return 0/1/2 : 경로에 해당 라벨값 이름이 있는지에 따라 0/1/2 숫자값으로 반환
- one hot encoding : to_categorical : [1, 0, 0] 형식으로 원 핫 인코딩 진행
- train_test_split : 생성된 X_data, y_data를 섞기 및 학습용/검증용으로 분리(sklearn.model_selection)

이렇게 하면 새로운 데이터를 모델에 사용할 준비 완료!😉
 

2. 전이학습 & Fine Tuning

지난 수업의 전이학습에 이어, 이번 수업에는 Feature Extract와 Fine Tuning으로 사용하는 법을 배웠다.
기본적으로 전이학습은 이미 학습이 된 모델을 가져와서 우리 모델의 베이스 모델로 사용한다.
이 과정에서 해당 모델을 완전히 그대로 사용할 것인지, 출력층만 사용하지 않을 것인지, n개 레이어는 사용하지 않을 것인지에 따라 Feature Extract, Fine Tuning으로 구분된다.
출력층을 사용하지 않을 것인지는 include_top 속성을 True(사용함)/False(사용안함)으로 지정한다.
나머지 층에 대해서는 base_model.trainable 속성을 True(변경함)/False(변경안함)으로 각 레이어를 지정할 수 있다.😮

from tensorflow.keras.applications import VGG16
# 1. base model 그대로 사용
base_model = VGG16(include_top=True, weights='imagenet', input_shape=(224, 224, 3))

# 2. Feature Extract 마지막 output 레이어만 변경
base_model = VGG16(include_top=False, weights='imagenet', input_shape=(224, 224, 3))
base_model.trainable = False

# 3. Fine Tuning 일부 레이어 변경
base_model.trainable = False
for layer in base_model.layers[-3:]:
  layer.trainable = True

베이스 모델을 완료했으면, 원하는대로 추가 레이어를 붙일 수 있다.
전이학습 때에는 Sequential 대신 Model을 사용해서 생성해야 Shape 연결 문제가 발생하지 않는다고 한다.🧐
모델 레이어끼리 연결하기 위해서는 Flatten()(x) 과 같은 형식을 사용하여 레이어끼리 연결되도록 할 수 있다.

inputs = base_model.input
x = base_model.output
x = Flatten()(x)
x = Dense(32, activation='relu')(x)
outputs = Dense(3, activation='softmax')(x)
model = Model(inputs=inputs, outputs=outputs)

해당 모델을 사용해서 알파카, 호랑이, 코끼리를 구분하였다.
데이터가 직접 simple_image_download를 통해 다운받은 이미지들인데도 잘 적용되는 것을 볼 수 있다.

 

3. YOLO v8

요즘 딥러닝에서 빼놓을 수 없는 압도적인 편리성, 활용도, 정확성을 자랑한다는 YOLO를 드디어 배웠다!🥳
YOLO는 you only live once를 변형한(?)듯한 You Only Look Once의 줄임말로, Object Detection 영역에서 가장 많이 사용되는 모델이다.

1) Single Image Detection
YOLO는 물체를 탐지하여 네모 박스를 그려주는 detection과 픽셀 단위로 구분해주는 segmentation까지도 제공하지만, 우리는 박스를 기준으로 먼저 진행하였다.
기본적인 YOLO의 detection결과는 아래 왼쪽 그림과 같고, 오른쪽은 내가 cat에 대해서만 박스를 따로 그려본 이미지이다!😸

 
2) result 값 풀어보기
YOLO가 제공하는 결과를 사용하기 위해서는, 반환값인 result를 해체하여 내가 원하는 데이터를 잘 가져와 사용할 수 있어야 한다.
개인적으로는 web API와 비슷하게 느껴져서 정말 재미있었다.🌟
single image 기준으로는 results 배열 안에 한 개의 값만 들어있기 때문에, results[0]을 사용하였고, 그 안의 boxes에 아래 이미지와 같은 메인 데이터가 있다.
- boxes.cls : detect한 classes의 값들로, 16, 15에 해당하는 실제 클래스명은 results[0].names에 정의되어있다.
- boxes.conf : 각 클래스들에 대한 confidence값
- boxes.xyxy : 각 클래스들에 대한 박스의 좌표 값. 다양한 방식으로 사용할 수 있지만, 나는 직관적으로 xyxy를 사용하였다.
약간 주의할 점은, 반환되는 값은 tensor 형식이므로, cv2와 사용하기 위해서는 float(), int()등 형변환을 적절하게 사용해주자.😎

 
3) Live Detection
이미지에 대한 detection을 진행했다면, 이제는 실제 라이브 영상에 적용해볼 차례이다.
colab에서 학습완료된 모델을 다운로드하여 vscode환경에서 불러온 후, cv2 실시간 영상의 frame을 모델에 넣어 결과를 받아올 수 있다.
한 프레임 안에서도 여러개의 물체를 탐지할 수 있기 때문에, boxes의 길이만큼 순회하며 인덱싱을 통해 아래와 같이 보여주도록 구현해보았다.🐣
교실 환경에서는 person, chair가 다수 감지되었다 ㅎㅎㅎ 네이버 이미지를 통해 cat도 알아보는 것을 볼 수 있었다.

    boxes = results[0].boxes
    for i in range(len(boxes)):
        cls = boxes.cls[i]
        xyxy = boxes.xyxy[i]
        conf = boxes.conf[i]
        
        print(f'i: {i}, cls: {cls}, xyxy: {xyxy}')   
        x1, y1, x2, y2 = map(int, (xyxy[0], xyxy[1], xyxy[2], xyxy[3]))
        cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 255), 2)
        cv2.putText(frame, full_names[int(cls)], (x1, y1-50),  cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 255), 1)
        cv2.putText(frame, str(round(float(conf), 4)), (x1, y1-20),  cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0), 1)

 
 

4. Labelling

다시 전처리로 조금 돌아와서, 학습시킬 이미지들이 준비되었다면, 각 이미지가 어떤 정답을 가지고 있는지 라벨링 작업이 필요하다.
이전 1번 항목에서는 단순히 해당 이미지의 정답 값이 어떤 물체인지만 넣어주었지만, 이미지의 어떤 부분이 해당 물체인지를 지정해주면 당연히 학습의 정확도가 올라갈 것이다.
이렇게 특정 영역에 대해서 라벨링을 쉽게 작업할 수 있는 툴로 labellmg과 roboflow를 배워보았다.
아래 이미지처럼 영역을 드래그해서 라벨을 붙여주는 방식으로 작업을 진행하면 된다. (초큼 노가다성😇)

 
우리는 주로 roboflow를 사용하였는데, 웹 기반으로 이미지 업로드, 라벨링과 전처리와 train test split까지도 쉽게 진행할 수 있어서 매우 편리한 사이트였다.
다만 무료 버전으로는 프로젝트당 이미지 제한 수가 있으니 참고하자..

이번 학습의 예제로는 가위, 바위, 보 이미지를 학습시켜서 실제 영상으로 이를 구분하도록 하고자 했다.
강사님께서 제공해주신 이미지 중 가위바위보를 각 30여장 하여 총 90장 정도를 라벨링해보았다.👊✌️🖐️
Train, Validation, Test 비중을 정해서 나눠주고, 각 분류별로 images/labels를 넣어준다.

 

 
라벨링 완료 후, roboflow에서는 Auto-Orient(이미지 조작)나 Resize도 쉽게 할 수 있도록 기능도 제공하고 있다.
정말 이런 서비스들은 누가 이렇게 앞서서 잘 만들어주는 것인지 감탄스러운 부분..

 
그럼 이제 라벨링된 데이터를 가지고 학습을 진행해보자.
roboflow에서는 API 사용 snippet을 제공하여 완료된 데이터를 쉽게 다운로드 받아갈 수 있도록 하고 있다.
받아온 데이터는 train>images/lables 등으로 파일구조가 잘 나누어져 들어오게 되어있어서 매우 편리하다! 🤗
이를 모델에 활용하기 위해서는 yaml 파일이 중요한데, 여기에 어떤 데이터를 사용하면 되는지를 정의해주면, yolo에서 해당 경로에 있는 이미지들을 사용하여 학습/검증을 진행한다.
학습할 때는 기본 yolov8s 모델을 다운하여 사용하고, 학습이 완료되면 train>weights 폴더에 best.pt 모델 파일이 생성되는데, 이 ‘가장 잘 학습된 모델’을 사용하여 검증을 진행하고, 추후 live detection에도 사용하면 된다.

# 학습: 기본 yolov8s 모델 다운하여 사용
!yolo detect train model=yolov8s.pt data=/content/RockPaperScissors-1/data.yaml epochs=10
# Validation : train 완료된 best.pt 사용
!yolo detect mode=val model=/content/runs/detect/train/weights/best.pt data=/content/RockPaperScissors-1/data.yaml

 
confusion matrix를 확인해보면, 2건 외에는 모두 잘 정답을 맞추고 있음을 확인할 수 있다.

 
이제 다시 vscode 환경에서 cv2를 이용한 실시간 detect를 진행해본다.
아무래도 데이터 수량이 많지 않았다보니 앞선 모델보다 정확도가 좀 떨어졌지만, 가위바위보를 인식하는 것을 확인할 수 있었다.

 
+) 번외로 우리반 인기 키티인형은 YOLO 모델에서 Teddy Bear로 잘(?) 분류되는 것을 확인했다😍

 
 
딥러닝 심화 학습 후기👀
- 이전 포스팅에서 정제되지 않은 데이터에 대한 학습은 어떻게 할지도 알고싶다고 적었는데, 그 부분에 대한 전처리를 자세히 배울 수 있어서 좋았다! 아무래도 shape를 맞추는 것이 은근히 까다로워서 연습이 필요할 것 같다.
- 라벨링을 실제로 어떻게 할까 했는데, 단순히 이미지에 번호를 붙이는 것을 넘어서 어떤 영역이 해당 물체인지까지 부여할 수 있는 방법을 알게 되어서 프로젝트 시에도 사용할 수 있겠다는 생각을 했다.
- 경사하강법과 역전파에 대해 간단히 배웠는데, 편미분이라는 정보 외에 사실 구체적인 원리까지 이해하기에는 시간이 부족했던 것 같다. 이런 부분은 수학적인 지식과 더불어 스스로 더 공부할 영역으로 잊지 않고 노력해야겠다.😵
 
🌱카이로스 2기에서 배운 딥러닝 기초 교육이 궁금하다면?
https://bagjo2884.tistory.com/m/18

 

[카이로스2기] 딥러닝 기초 흐름 이해하기 : 고양이 사진을 인식해보자!

아두이노를 잠시 뒤로하고, AI 로봇을 만들기 위한 딥러닝 기초 교육을 받았다.이번 게시물에서는 어렵지만 정말 흥미로웠던 딥러닝 교육 후기를 작성해보고자 한다.😸 딥러닝을 이해함에 있

bagjo2884.tistory.com


다음주에는 6축 로봇! myCobot과 딥러닝의 콜라보 내용으로 만나요🕊