이번 시각지능 딥러닝 프로젝트는 5일간 진행되었습니다.
프로젝트개요
주제 | 이미지 데이터 모델링 얼굴 인식 (Face Recognition) |
데이터 | 다른 사람 얼굴 데이터, 개인 얼굴 데이터 |
데이터 출처 | Kaggle, Roboflow Universe |
1. 데이터에 대한 적절한 전처리 및 keras를 이용한 학습 및 추론 2. 데이터에 대한 적절한 전처리 및 YOLO를 이용한 학습 및 추론 |
데이터 셋
keras 데이터
다른 사람 얼굴 이미지 데이터 | LFW dataset | 5750개의 폴더, 13223개의 이미지 |
개인 얼굴 이미지 데이터 | 내가 수집하기 | 최소 2500장 |
YOLO 데이터
다른 사람 얼굴 이미지 데이터 | Face Recognition1 | 5979개의 이미지, 5979의 텍스트 |
Face Recognition 2 | 4983개의 이미지, 4983개의 텍스트 | |
개인 얼굴 이미지 데이터 | 내가 수집하기 | 최소 2500장 |
[1일차] FaceNet 모델
1일차에는 개인 얼굴 이미지 데이터 셋을 수집하고 , FaceNet 모델을 생성했다.
데이터 수집
OpenCV 를 사용해 내 얼굴 이미지를 수집했다.
좋은 모델을 위해 다양한 각도와 표정으로 찍었다.
데이터 전처리
데이터 셋 분할
tf.keras.preprocessing.image_dataset_from_directory | TensorFlow v2.16.1
keras의 image_dataset_from_directory 을 사용하기 위해선 데이터 구조를 다음과 같이 해야한다.
main_directory/
...class_a/
......a_image_1.jpg
......a_image_2.jpg
...class_b/
......b_image_1.jpg
......b_image_2.jpg
class_a와 class_b 하위 디렉토리에서 이미지를 배치 단위로 가져오고, 함께 0과 1의 라벨도 제공한다.
여기서 0은 class_a에, 1은 class_b에 해당
위와 같이 0.2 비율로 데이터 분할을 했다.
image_dataset_from_directory 함수 사용
## Training set 데이터 폴더를 데이터셋화
## 이 과정에서 Validation set도 생성
tr_idfd, val_idfd = image_dataset_from_directory(tr_data, ## Training 폴더 경로
class_names=['other','my'], ## 클래스 순서 지정
batch_size=32, ## 이미지 덩어리 단위
image_size=(160,160), ## 이미지 리사이즈
shuffle=True, ## 섞어야 올바르게 분할됨
seed=2024, ## 재현성
validation_split=0.3, ## 데이터 스플릿 비율
subset='both', ## 데이터셋 나눔 방식
)
1. other 클래스는 라벨 0, my 클래스는 라벨 1로 매핑
2. 데이터를 한 번에 처리하는 배치 크기를 지정 (한 번에 32개의 이미지를 로드)
3. 모델의 입력 크기에 맞추기 위해 160x160 크기로 리사이즈
4. 데이터셋을 섞지 않으면 클래스별로 정렬된 상태로 불러올 가능성이 있으므로, Training-Validation 분할이 올바르게 되지 않을 수 있다. ->shuffle
5.이미지의 70%를 훈련에 사용하고 30%를 유효성 검사에 사용
스케일링
def rescale(image, label) :
image = image / 255
return image, label
tr_idfd_rescale = tr_idfd.map(rescale)
val_idfd_rescale = val_idfd.map(rescale)
te_idfd_rescale = te_idfd.map(rescale)
픽셀 값을 0~1 범위로 정규화
입력 이미지는 일반적으로 0~255 범위의 정수값을 가지는데, 이를 255로 나눠서 부동소수점 값으로 변환한다.
FaceNet 모델
[1503.03832] FaceNet: A Unified Embedding for Face Recognition and Clustering
[2일차] YOLO-cls 모델
2일차에는 YOLO-cls를 사용했다.
데이터수집
1일차에 수집한 데이터를 그대로 사용했다.
데이터 전처리
데이터 셋 분할
이미지 분류 데이터 세트 개요 - Ultralytics YOLO 문서
YOLO-cls 을 사용하기 위해선 데이터 구조를 다음과 같이 해야한다.
cifar-10-/
|
|-- train/
| |-- airplane/
| | |-- 10008_airplane.png
| | |-- 10009_airplane.png
| | |-- ...
| |
| |-- automobile/
| | |-- 1000_automobile.png
| | |-- 1001_automobile.png
| | |-- ...
| |
|
|-- test/
| |-- airplane/
| | |-- 10_airplane.png
| | |-- 11_airplane.png
| | |-- ...
| |
| |-- automobile/
| | |-- 100_automobile.png
| | |-- 101_automobile.png
| | |-- ...
| |
|
|-- val/ (optional)
| |-- airplane/
| | |-- 105_airplane.png
| | |-- 106_airplane.png
| | |-- ...
| |
| |-- automobile/
| | |-- 102_automobile.png
| | |-- 103_automobile.png
| | |-- ...
| |
YOLO-cls 모델
from ultralytics import YOLO
# Load a model
model = YOLO("yolo11n-cls.pt") # load a pretrained model (recommended for training)
n이 가장 빠르다 해서 yolo11n 을 사용했다.
[3일차] Annotation
3일차엔 데이터 수집 및 정제,Annotation 작업을 했다.
- 온라인에서작업: Roboflow, CVAT 등
- 로컬에서작업: Ybat-master 등
나는 roboflow를 활용하여 annotation과 augmentation을 진행했다.
Roboflow: Computer vision tools for developers and enterprises
roboflow에선 객체에 bounding box를 그려 직접 labeling 까지 할 수 있다.
Train, Valid, Test 비율을 설정 해주고 나눈 후 내가 원하는 방식으로 이미지 증강도 된다.
[4일차] YOLO 모델
3일차에 정제한 데이터를 사용해 yolo 모델 학습을 진행했다.
yolo 와 yolo-cls 의 차이는 다음과 같다.
YOLO | YOLO-cls | |
목적 | 객체 탐지 (위치 + 클래스 예측) | 이미지 분류 (클래스만 예측) |
입력 | 이미지 | 이미지 |
출력 | Bounding Box + 클래스 | 클래스 |
적용 범위 | 다중 객체 탐지, 복잡한 이미지 | 단일 객체 분류, 단순 이미지 |
속도 및 경량성 | 탐지 연산으로 다소 무거움 | 경량화되어 더 빠름 |
데이터 전처리
Label 파일의 클래스 값 변경
Face Recognition1, Face Recognition2 데이터 라벨 정제
- 여러 클래스로 구분되어 있는 것을 하나로 통일
- 이것은 다른 사람의 얼굴에 대해 전처리하는 작업
## txt 전체 파일을 리스트화
txt_list = sorted(glob.glob( os.path.join('/content/temp_dataset/labels', '*.txt')) )
for txt_file in txt_list :
with open(txt_file, 'r') as f :
lines = f.readlines()
new_lines = []
for line in lines :
parts = line.strip().split()
if not int(parts[0]) == 0 :
new_line = f'{0} ' + ' '.join( parts[1:] )
# new_line = f'{1} ' + ' '.join( parts[1:] ) ## 클래스 1로 변경 테스트
new_lines.append( new_line )
print('클래스 1으로 변경 : ', new_line)
else :
new_line = ' '.join( parts[0:] )
new_lines.append( new_line )
print('클래스 그대로 유지 : ', new_line)
with open(txt_file, 'w') as f :
f.write('\n'.join(new_lines) + '\n')
print(f'파일 {txt_file} 처리 완료')
데이터 셋 분할
## 원본 폴더 경로들
source_folders = {'images': '/content/temp_dataset/images',
'labels': '/content/temp_dataset/labels'
}
## 타겟 폴더 경로들
target_folders = {'images':{'train':'/content/Datasets/images/train',
'val':'/content/Datasets/images/val',
# 'test':'/content/Datasets/images/test',
},
'labels':{'train':'/content/Datasets/labels/train',
'val':'/content/Datasets/labels/val',
# 'test':'/content/Datasets/labels/test',
}
}
- 폴더 생성: /content/Datasets 아래에 필요한 폴더 구조를 생성.
## 데이터 스플릿 비율
split_size = 0.8
## images, labels 파일을 정렬하여 리스트화
image_list = sorted(glob.glob(os.path.join(source_folders['images'], '*')))
label_list = sorted(glob.glob(os.path.join(source_folders['labels'], '*')))
## 묶고 섞고 다시 리스트화
combined = list(zip(image_list, label_list))
random.shuffle(combined)
image_list, label_list = zip(*combined)
## 총 파일 수 계산
total_files = len(image_list)
tr_val_split = int(total_files * split_size)
print('전체 파일 수 : ', total_files)
print('training set 파일 수 : ', tr_val_split)
print('validation set 파일 수 : ', total_files - tr_val_split)
## train / val로 분리
tr_images, tr_labels = image_list[ : tr_val_split], label_list[ : tr_val_split]
val_images, val_labels = image_list[tr_val_split : ], label_list[tr_val_split : ]
print( 'training set 이미지 수 : ', len(tr_images), ' training set 라벨 수 : ', len(tr_labels) )
print( 'validation set 이미지 수 : ', len(val_images), 'validation set 라벨 수 : ', len(val_labels) )
- 데이터 분리: 랜덤하게 데이터를 Training(80%)과 Validation(20%)으로 나눔.
Yolo 모델
model = YOLO('yolo11n.pt')
어제 학습했던 모델보다 더 성능이 떨어지는 것을 알 수 있다.
과도한 augmentation이 학습에 악영향을 미치는 것 같아 이미지 증강을 적절히 하는 것이 중요하다.
[5일차] 로컬Cam에서의 실성능확인
Keras로 학습한 모델/ YOLO-cls로 학습한 모델/ YOLO로 학습한 모델
세가지의 모델을 개선하여 로컬Cam에서 실성능을 확인했다.
느낀 점
정확도가 떨어져 아쉬움이 많이 남는 프로젝트였다. 제한된 시간안에서 팀원들과 효율적으로 프로젝트를 진행하는 것이 중요하다는 것을 알게되었다. 세 모델을 전부다 손보기 어려웠고, 각 모델마다 접근 방법이 달랐기 때문에 역할을 나누어 튜닝했으면 더 좋은 성능의 모델을 뽑아낼 수 있었을 것 같다.
결국 모델링이란 데이터가 좋아야 좋은 모델이 나온다는 것을 알게 되었다. 따라서 데이터의 질을 높이는 것에 시간을 많이 투자해야하고, 이미지 증강을 신중히 해야한다.
다음 프로젝트엔 프로젝트의 큰 흐름을 파악하고 역할분담을 더 신중히 할 것이다. 또한 더 좋은 데이터를 얻기 위해 노력할 것이다.
'대외활동 > 에이블스쿨' 카테고리의 다른 글
[에이블 스쿨] 2차 코딩마스터스 | 1일 1코딩 리뷰 이벤트 (2) | 2024.11.28 |
---|---|
[에이블 스쿨] 5차 미니프로젝트 | ASSO 대비 (1) | 2024.11.26 |
[에이블 스쿨] 3차 미니프로젝트 | DL 모델링 (3) | 2024.11.07 |
[에이블 스쿨] KES 2024, 한국 전자전 후기 | 스터디 활동 (2) | 2024.10.29 |
[에이블 스쿨] 1차 코딩마스터스 | 기록 방법, 꿀팁 (2) | 2024.10.11 |