2023.06.13

개인 기록용 입니다 :) 오타, 수정 등 피드백 환영


CUDA, cuDNN 설치하기 앞선 링크에서 GPU 활용을 위해 CUDA, cuDNN 설치와 tensorflow 등 각각에 맞는 버전을 활용하여 GPU 세팅을 마쳤다 여기에 이어 머신러닝 학습을 위해 GPU를 활용하려면 딥러닝 Pytorch 적용도 필요하다 Pytorch 적용에 꽤나 애를 먹었기 때문에 기록하여 나에게 맞는 버전 등을 기록해두려 한다 1. 본인 사양에 맞는 Pytorch 확인하기 NVIDIA Geforce 3060 Ti Python 3.9 CUDA 11.2.2 cuDNN 8.1.1 tensorflow 2.8 필자의 경우 위와 같이 진행을 하였고 이 버전들의 기준에는 NVIDIA Geforce 3060 Ti 그래픽 카드가 우선적이었다 3060과 호환되는 CUDA 그리고 CUDA에 호환되는 cuDNN 그것을 지원하는 PyTorch 버전을 찾아야한다 pytorch.org/get-started/previous-versions 위 링크를 살펴보면 각 버전에 맞게 어떤 PyTorch 를 써야 하고 어떻게 설치를 해야하는지 설명을 해주는데 필자의 경우 11.2 버전을 써야 하는데 거기에 맞는 PyTorch에 대한 설명이 없다 이럴땐 11.1 로 버전을 낮추면 적용시킬 수 있다 따라서 CUDA 11.1 에 맞는 버전을 찾아 해당하는 명령어로 설치를 진행해준다 * 진행 도중 pip install 과 conda install 이 있는데 처음엔 pip install 로 했으나 적용되지 않아 conda install 로 적용시켰다 # CUDA 11.1 conda install pytorch==1.8.0 torchvision==0.9.0 torchaudio==0.8.0 cudatoolkit=11.1 -c pytorch -c conda-forge ​ 그리고 확인을 위해 파이썬 코드로 작성 후 테스트 from tensorflow.python.client import device_lib print(device_lib.list_local_devices()) GPU 를 잡아주는지 확인 후 import torch print(torch.cuda.get_device_name(0)) print(torch.cuda.is_available()) 위 명령어를 실행하면 본인의 디바이스 이름과 CUDA와 호환되는 여부를 True 로 반환해준다 만일 torch.cuda.is_available() 이 False 로 반환된다면 어딘가 잘못된 것이니 다시 잡아주어야 하며, 이 과정에서 NVIDIA 그래픽 드라이버 여부, CUDA 와 cuDNN 버전 호환 여부 등 여러가지 확인을 해보아야 한다 2. YOLO v8 설치 이어서 yolo v8 로 학습을 위한 환경 세팅을 진행한다 yolo 설치에는 두가지 방식이 있다 1) git clone 을 활용하여 github 의 파일을 가져오기 2) pip install 필자는 pip install 을 활용했으며 그와 같은 방법을 안내한다 conda 를 활용해 가상환경을 만들었으며 Python 3.9 버전을 활용했다 (conda 가상환경)pip install ultralytics 위 명령어로 yolo v8 설치를 하면 (conda 가상환경)pip list # 혹은 아래 경로 C:\Users\User\anaconda3\envs\가상환경명\Lib\site-packages\ultralytics 에 설치된 것을 확인할 수 있다 3. bbox labeling yolo 학습을 위해선 yolo 에 맞게 데이터를 구성해 주어야 한다 yolo 는 bbox 라 해서 Bounding Box 즉, 네모난 박스로 label 처리를 한 객체의 좌표가 필요하다 이 데이터는 0 0.3132440476190476 0.0375 0.03869047619047619 0.017105263157894738 이런 형태로 된 txt 파일인데 어디서 라벨링을 어떻게 하느냐에 따라 달라질 수 있다 띄어쓰기를 기준으로 처음 0 : 클래스 넘버 두번째 : bbox 의 가운데 x좌표 세번째 : bbox 의 가운데 y좌표 네번째 : bbox 의 넓이 다섯번째 : bbox 의 높이 위와 같이 구성이 되어 있다 필자는 현재 진행중인 프로젝트의 내용에 따라 AI hub 에 제공되어 있는 데이터를 받아서 활용중이다 다만 AI hub 에 제공되어 있는 데이터는 모두 json 형태였으며, bbox가 아닌 polygon 형태로 라벨링을 진행한 데이터였다 json 파일 안에 polygon 데이터가 있고 이 polygon 데이터의 좌표의 x값의 최소, 최대 y값의 최소, 최대를 구하면 bbox 를 구할 수 있을 것 같아 수천개의 데이터를 정제할 수 있게 코드를 구성했다 단일 객체이기 때문에 클래스는 모두 0이고 각 객체들이 위치하고 있는 bbox를 뽑아내어 txt 파일로 만든 파일이다 이 라벨링 과정은 ROBOFLOW 라는것을 통해 쉽게 할 수 있다 하지만 해당 사이트에서는 장수에 제한을 두고 있기 때문에 직접 정제하고 싶어 이런식으로 진행했다 (데이터가 수만장이기 때문도 있음)

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# yolo to json.py
 
import os
import json
import glob
 
def convert(size, box):
    dw = 1./size[0]
    dh = 1./size[1]
    x = (box[0+ box[2])/2.0
    y = (box[1+ box[3])/2.0
    w = abs(box[2- box[0])
    h = abs(box[3- box[1])
    x = x*dw
    w = w*dw
    y = y*dh
    h = h*dh
    return [x,y,w,h]
 
def convert_annotation(json_path, output_path):
    with open(json_path, 'r'as json_file:
        data = json.load(json_file)
        image_name = os.path.splitext(data['META']['Image File Name'])[0]
        width = data['META']['Image Width MAGNITUDE']                   # 이미지 넓이 키값 위치 지정
        height = data['META']['Image Height MAGNITUDE']                 # 이미지 높이 키값 위치 지정
 
        try :
            annotations = data['ANNOTATION']['Anntation Regions']       # ANNOTATION 키 값이 'Anntation Regions'일 경우(제공된 데이터 내 오타 존재 때문)
        except KeyError:
            annotations = data['ANNOTATION']['Annotation Regions']      # ANNOTATION 키 값이 'Annotation Regions'일 경우
 
        with open(os.path.join(output_path, f'{image_name}.txt'), 'w'as outfile:
            for annotation in annotations:
                category_id = 0  
                x_coordinates = annotation['Polygon X Coordinate']
                y_coordinates = annotation['Polygon Y Coordinate']
                bbox = [min(x_coordinates), min(y_coordinates), max(x_coordinates), max(y_coordinates)] 
                bb = convert((width,height), bbox)
 
                if any([coord > 1 or coord < 0 for coord in bb]):
                    print(f"이상한 좌표값 발견: {bb}, 파일: {json_path}")
 
                outfile.write(f"{category_id} {bb[0]} {bb[1]} {bb[2]} {bb[3]}\n")
 
# json 파일 위치 경로 입력
json_paths = glob.glob('C:/Users/User/Desktop/InsectData/Data/Training/labelData/TL1/PtecticusTenebrifer/Caterpillar/Cam2/*.json')  
# 저장될 위치 경로 입력
output_path = 'C:/Users/User/Desktop/InsectData/ConvertData/Cam2' 
 
os.makedirs(output_path, exist_ok=True)
 
for json_path in json_paths:
    convert_annotation(json_path, output_path)
cs

4. yaml 파일 생성

data.yaml

1
2
3
4
5
6
7
train: C:/Users/User/Desktop/InsectData/ConvertData/Cam2_data/images/train (학습시킬 이미지 train data 경로)
val: C:/Users/User/Desktop/InsectData/ConvertData/Cam2_data/images/val (학습시킬 이미지 validation data 경로)
test: []
 
nc: 1
names: ['bug']
cs

나는 단일 객체를 인식할 준비만 하기 때문에 nc(number of class) 는 1개고 해당 클래스에 지정할 이름(names)은 'bug' 이다 보통 train, val 의 구성은 8:2 로 진행하나 7:3 혹은 검증 데이터셋까지 7:2:1 로 진행하는 경우가 일반적이다 따라서 학습할 데이터들의 비율은 본인의 비율에 맞추어 데이터를 이동해두는 식으로 구성하고 아래 코드로 학습을 진행한다 5. 학습 실시 from ultralytics import YOLO as yolo model = yolo('yolov8n.pt') model.train(data='yaml 파일의 경로', epochs=학습돌릴 횟수) ​ 여기서 시간이 많이 걸린 오류가 발생하는데 바로 train, val 데이터셋을 불러오기까지 시간이 좀 걸리더니 val 데이터셋을 읽고 나서 학습을 진행하지 않았다 하지만 셀은 계속해서 돌아가고 아무런 반응이 없고 셀을 중단시키자 커널이 죽으면서 다시 시작해달란 말이 반복됐다 이는 GPU memory 부족이나 데이터가 잘못 되었거나 충돌이 일어났거나 중 하나라고 한다 GPU를 활성화해서 돌리는 코드인데 CPU도 같이 돌리면서 인식을 못한 상황인듯 했다 model.train 속성에 workers=0 으로 활용할 CPU 를 0으로 돌려주자 기적같이 학습을 시작했고 아래와 같이 GPU가 잡힌 모습도 보여줬다 이렇게 학습을 마치면 그 결과가 어디에 저장되었는지 알려주는데 라이브러리가 설치된 ultralytics 폴더 안에 혹은 test를 진행한 파일이 위치한 폴더 안에 runs / detect / train(번호) 로 위치하게 된다 해당 위치로 가보면 이런식으로 결과가 어떻게 되었는지 알려주는 모습들을 볼 수 있다 그리고 weights 폴더 안의 best.pt 를 통해 predict 까지 진행할 수 있다

1
2
3
4
5
# best.pt 를 모델로 활용
model = yolo('C:/Users/User/Desktop/InsectData/runs/detect/train36/weights/best.pt')    
 
# source 에는 예측을 원하는 파일 경로
model.predict(source="C:/Users/User/Desktop/InsectData/Data/Training/rawData/TS1/PtecticusTenebrifer/Caterpillar/HighDefinition/Capture_20211115_15_27_37.jpg", save=True, conf=0.5, show=True)
cs

해당 셀이 실행된 후 이렇게 어떤 폴더에 저장됐는지까지 알려준다 가서 확인해보면 이렇게 인식을 시도한 그림을 확인할 수 있다 데이터도 많고 시간이 좀 걸릴듯 하여 epochs 를 10밖에 안주었더니 어느정도밖에 인식을 하지 못한다 추후 더 시간을 들여 학습을 시키고 프로젝트에 적용시키도록 할 예정이다