2024 DSWU 소프트웨어 전공 강의 [딥러닝플랫폼실습] 기말 과제 리포지토리
목차
- 주제: 김장철 주요 작물 질병 탐지 모델 학습 및 성능 향상
- 최근 김장철을 앞두고 배추, 고추 등 김장에 필요한 주요 작물들의 가격이 급등하며 문제로 떠오르고 있다. 특히 배추의 경우 폭염과 작물 질병이 겹쳐 생산량에 큰 영향을 미쳤다[1]. 이러한 상황에서, 질병에 신속히 대처할 수 있는 기술적 지원이 필요하다. 본 프로젝트는 AI-Hub의 "노지 작물 질병 진단 이미지" 데이터를 활용하여 주요 작물의 질병 분류 모델을 구축하는 것을 목표로 한다. CNN 기반 모델을 통해 작물 질병을 자동으로 판별하고, 빠른 대처가 가능하도록 지원함으로써 농가의 피해를 최소화하고자 한다.
- 본 프로젝트는 김장철 주요 작물의 질병 분류 모델을 개발하여, 농가가 질병을 조기에 탐지하고 신속히 대응할 수 있도록 지원하는 시스템을 구축하는 것을 목표로 한다. 이를 통해 농작물의 품질을 유지하고, 질병 확산을 예방함으로써 농가의 피해를 최소화할 수 있다. 또한, AI 기반의 자동화된 질병 진단 시스템을 제공함으로써, 기존의 육안 검사에 의존한 방법을 대체하고, 농업의 생산성을 향상시킬 수 있다. 이를 통해 농업 관리의 효율성을 높이고, 향후 다른 작물과 질병 또는 해충에 대한 추가적인 연구 및 시스템 적용의 기초 자료를 마련할 수 있다.
- 정상 데이터셋 작물별 300장씩 총 1,500장, 질병 데이터셋 각 클래스별 1,200개씩 총 13,200장 구축 - 총 데이터셋 개수: 14,700장
- 바운딩 박스(
save_crop_data.ipynb
)- 바운딩 박스 내부 데이터만 사용해도 충분함 (작물 전체를 바운딩 박스 처리함)
- 크롭 과정
- 바운딩 박스의 중심(대각선의 교차점)을 찾음
- 바운딩 박스의 가로와 세로의 평균값을 찾음
- 박스의 중심을 유지하고 평균값을 한 면의 길이로 하는 정사각형으로 크롭
- 증강 처리(
save_transform_data.ipynb
)torchvision.transforms
모듈을 활용하여 학습 및 테스트 데이터를 각각 전처리- 학습 데이터(
train_transform
): 데이터 증강을 포함한 다양한 변환 적용 및 정규화- Resize: 이미지를
(224, 224)
로 크기 조정 - RandomResizedCrop: 이미지를 무작위로 크롭하고 크기를
(224, 224)
로 조정 - RandomHorizontalFlip: 수평(좌우) 방향으로 랜덤 반전(p=0.5)
- RandomVerticalFlip: 수직(상하) 방향으로 랜덤 반전(p=0.5)
- RandomRotation: 이미지 각도를 미리 지정한 각도 범위에서 랜덤으로 회전
- Resize: 이미지를
- 이미지에 대해 질병 분류 번호로 라벨링
- 이 과정을 위해 Training, Test, Validation 폴더 내부에서도 질병 번호로 폴더가 존재
- 정상 클래스의 경우 여러 작물이 섞여 있음
- 전부 0으로 라벨링
- 모든 데이터셋을 클래스 구분 없이 Training, Test, Validation 폴더 내부에 넣고 전처리 과정에서 라벨링
- 이미지 파일명에 작물 종류, 질병 종류 등의 정보가 있음
- 순회하면서 각각의 이미지에 대한 작물 종류과 질병 종류 라벨링 진행
- 합성곱 계층 추가
- 세 개의 합성곱 계층을 사용하여 특징 추출 진행
- 커널 크기 3, 패딩 1
- 첫 번째 합성곱 계층: 입력 채널 3, 출력 채널 32
- 두 번째 합성곱 계층: 출력 채널 64
- 세 번째 합성곱 계층: 출력 채널 128
- 각 계층의 출력은
MaxPooling
을 통해 크기를 절반으로 줄임 - 합성곱 계층의 출력은 배치 정규화(Batch Normalization)와 ReLU 활성화 함수를 사용하여 성능 개선
- 세 개의 합성곱 계층을 사용하여 특징 추출 진행
- 배치 정규화 (Batch Normalization) 적용
- 각 합성곱 계층 뒤에 배치 정규화를 적용하여 학습 속도 향상 및 과적합 방지
BatchNorm2d
사용하여 2차원 이미지 데이터에 적합하게 설정
- 드롭아웃 (Dropout) 적용
- 합성곱 계층의 출력에 드롭아웃(
Dropout2d
)을 적용하여 과적합 방지 - 드롭아웃 확률은 0.3으로 설정
- 합성곱 계층의 출력에 드롭아웃(
- 완전 연결 계층 (Fully Connected Layer)
- 첫 번째 완전 연결 계층: 입력 크기 128 * 28 * 28, 출력 크기 512
- 두 번째 완전 연결 계층: 출력 크기 2 (클래스가 두 개)
- 완전 연결 계층에도 드롭아웃 적용 (
Dropout
), 확률 0.5
- 활성화 함수
- 각 계층에서 ReLU 활성화 함수 사용하여 비선형성 부여
- 분류 성능 향상 및 계산 효율성
- 7x7 커널, 스트라이드 2, 패딩 3 설정으로 초기 합성곱 계층을 구성하여 입력 이미지의 특징을 추출
- 입력 채널은 3(RGB 이미지), 출력 채널은 64로 설정하여 다양한 특징을 추출
- 배치 정규화(
BatchNorm2d
)와 ReLU 활성화 함수 적용 MaxPooling
(커널 크기 3, 스트라이드 2, 패딩 1)을 통해 특징 맵 크기를 절반으로 줄임
- 병목 블록(BottleneckBlock)을 통한 잔차 학습 계층 구성
BottleneckBlock
클래스를 사용하여 높은 차원의 입력을 더 작은 차원으로 축소한 뒤 복원하는 방식으로 잔차 학습을 수행- 각 BottleneckBlock은 세 개의 합성곱 계층과 배치 정규화를 포함하며,
ReLU
활성화 함수를 사용해 비선형성을 부여함 - 스킵 연결(skip connection) 사용: 입력과 출력이 차원 일치하지 않을 경우, 1x1 합성곱을 통해 차원을 맞춘 뒤 더해줌
- 첫 번째 합성곱 계층(
conv1
): 1x1 커널로 차원을 축소하여 연산 비용을 줄임 - 두 번째 합성곱 계층(
conv2
): 3x3 커널로 공간적 특징을 추출하고, 설정된 스트라이드로 다운샘플링 가능 - 세 번째 합성곱 계층(
conv3
): 1x1 커널로 차원을 원래대로 복원
- 첫 번째 합성곱 계층(
- 레이어 별 특징:
- Layer1: 64 채널, BottleneckBlock 2개 사용
- Layer2: 128 채널, BottleneckBlock 2개 사용, 스트라이드 2로 설정하여 다운샘플링
- Layer3: 256 채널, BottleneckBlock 2개 사용, 스트라이드 2로 설정하여 다운샘플링
- Layer4: 512 채널, BottleneckBlock 2개 사용, 스트라이드 2로 설정하여 다운샘플링
- 잔차 학습과 스킵 연결
- 각
BottleneckBlock
에서 입력을 그대로 다음 계층에 전달하는 스킵 연결을 적용해 정보 손실을 줄이고, 깊은 네트워크에서도 효과적으로 학습 가능 - 스킵 연결의 차원 불일치가 발생하는 경우 1x1 합성곱을 통해 맞춰줌으로써 모델 안정성 유지
- 각
- 평균 풀링 및 완전 연결 계층
- 마지막 특징 맵을
AdaptiveAvgPool2d
로 입력의 크기와 상관없이 1x1로 축소 - 특징을
Linear
완전 연결 계층에 전달해 최종 출력 크기num_classes=2
로 이진 분류 수행
- 마지막 특징 맵을
- 활성화 함수와 출력
- 각 합성곱 계층 뒤에
ReLU
활성화 함수 적용해 비선형성 추가 - 최종 완전 연결 계층의 출력을 통해 각 클래스에 대한 예측 확률 산출
- 각 합성곱 계층 뒤에
-
공유 백본(Backbone): ResNet-34
- ResNet-34: 34개의 계층으로 구성된 잔차 네트워크(Residual Network)
- 사전 학습된 모델(
ResNet34_Weights.DEFAULT
)을 사용하여 초기화 - 마지막 Fully Connected(FC) Layer를 제외한 모든 계층을 공유
- 다중 태스크를 위해 마지막 Fully Connected(FC) Layer, 즉 분류기를 제거
- ResNet-34의 마지막 풀링 계층에서 추출된 특징은 512개의 차원(feature dimension)을 가지고 있음
-
태스크별 출력층(Task-Specific Heads)
- 작물 분류와 질병 분류를 진행
- 각 분류기의 구조는 다음과 같음
-
Crop Head (작물 분류기)
- 입력 특징을 활용하여 5개 작물 클래스를 분류
- 출력 노드: 5개
- 활성화 함수: Softmax 함수
- 손실 함수: CrossEntropyLoss
-
Disease Head (질병 분류기)
- 입력 특징을 활용하여 12개 질병 클래스를 분류
- 출력 노드: 12개
- 활성화 함수: Softmax 함수
- 손실 함수: CrossEntropyLoss
-
손실함수 계산 비율(작물:질병) | 테스트 정확도(작물) | 테스트 정확도(질병) | 정밀도 (Precision) | 재현율 (Recall) |
---|---|---|---|---|
0.3:0.7 (B모델) | 95.97 | 91.58 | 0.95 | 0.89 |
0.5:0.5 (A모델) | 98.53 | 94.02 | 0.93 | 0.89 |
1) 0.5:0.5 (작물:질병)
가중치 비율 적용 여부 | 테스트 정확도(작물) | 테스트 정확도(질병) | 정밀도 (Precision) | 재현율 (Recall) |
---|---|---|---|---|
O | 98.53 | 92.55 | 0.91 | 0.90 |
X (A모델) | 98.53 | 94.02 | 0.93 | 0.89 |
2) 0.3:0.7 (작물:질병)
가중치 비율 적용 여부 | 테스트 정확도(작물) | 테스트 정확도(질병) | 정밀도 (Precision) | 재현율 (Recall) |
---|---|---|---|---|
O | 97.56 | 87.06 | 0.92 | 0.91 |
X (B모델) | 95.97 | 91.58 | 0.95 | 0.89 |
- 손실함수 적용 비율은 동일한 비율(0.5)
- 가중치 비율 적용
- A 모델만 가중치 적용X
- 나머지는 가중치 적용O
배치 사이즈 | 에폭 | 테스트 정확도(작물) | 테스트 정확도(질병) | 정밀도 (Precision) | 재현율 (Recall) |
---|---|---|---|---|---|
32 (A모델) | 10 | 98.53 | 94.02 | 0.93 | 0.89 |
32 | 20 | 98.90 | 93.53 | 0.62 | 0.63 |
64 (C모델) | 10 | 99.15 | 92.92 | 0.91 | 0.92 |
64 | 20 | 97.92 | 91.94 | 0.91 | 0.90 |
모델 | 배치 사이즈 | 에폭 | 가중치 비율 적용 | 손실함수 비율 | 테스트 정확도(질병) | 정밀도 (Precision) | 재현율 (Recall) |
---|---|---|---|---|---|---|---|
CNN | 32 | 10 | - | - | 41.15 | 0.41 | 0.39 |
ResNet | 32 | 10 | - | - | 83.88 | 0.79 | 0.80 |
A | 32 | 10 | X | 0.5:0.5 | 94.02 | 0.93 | 0.89 |
B | 32 | 10 | X | 0.3:0.7 | 91.58 | 0.95 | 0.89 |
C | 64 | 10 | O | 0.5:0.5 | 92.92 | 0.91 | 0.92 |
- 질병 분류 모델이기 때문에 질병 정확도만 비교
- A 모델이 테스트 정확도가 가장 높으며 C 모델이 모델의 재현율이 제일 높음
- 뿐만 아니라 전반적인 성능 또한 두 모델이 가장 우수함
- Python 버전: 3.9.20
- CUDA 버전: 11.8
- 사용 도구: Visual Studio Code, Jupyter Notebook
- 사용 폰트(혼동행렬): 맑은고딕
- GPU 사용
- 학습을 진행하기 위해서는 반드시 GPU를 사용해야 합니다.
- 특히 MTL 모델 학습의 경우 GPU를 사용하지 않을 시 학습이 진행되지 않습니다.
- check_cuda 폴더 내의 cuda 사용 여부 코드를 사용하여 GPU를 사용중인지 확인해주세요.
- 과제를 진행하는 과정에서 주피터 노트북 파일에서는 GPU를 사용할 수 없어 파이썬 파일로 학습을 진행하였습니다.
- 과정 가시화를 위해 주피터 노트북 파일을 첨부하나 실제 학습 진행은 파이썬 파일로 진행하여 실행 결과가 저장되지 않았음을 유의해주세요.
- 학습을 진행하기 위해서는 반드시 GPU를 사용해야 합니다.
- Tensorboard 사용
- 학습 시 텐서보드 저장 위치를 항상 바꿔주세요.
- 기존의 경로를 사용할 경우, 이전 학습 정확도와 현재 학습 정확도가 섞여 문제가 생깁니다.
- 아래 링크에서 데이터셋과 모델 파일을 다운로드 및 압축 해제
- 깃허브 클론을 통해 로컬에 폴더를 생성
- 로컬에 생성된 파일에 맞게 다운로드한 데이터셋 및 모델 파일을 저장
- 예를 들어, CNN 데이터셋 및 모델 파일이라면, "cnn_code/"에 저장
- 다른 경로로 저장하고 싶다면 코드에서 경로 변경 필요
- 필요한 코드를 실행
- 학습은 파이썬(.py) 파일을 사용하는 것을 권장
코드 및 폴더 설명
- 데이터셋 전처리 코드(dataset_preprocess_code)
dataset_preprocess_code
폴더는 데이터셋 전처리 코드(전처리 이전 코드는 너무 용량이 커서 제출하지 않았습니다. 참고만 해주세요.)check_data_count.ipynb
: 데이터의 클래스별 개수를 확인하는 코드check_data_crop.ipynb
: 바운딩 박스만큼 크롭했을 때 데이터 상태를 확인하는 코드(확인 후 크롭을 결정했음)save_crop_data.ipynb
: 바운딩 박스를 사용하여 이미지를 크롭하고 저장하는 코드class_data.ipynb
: 학습 데이터에서 일부를 테스트 데이터로 분류save_transform_data.ipynb
: 데이터 증강 처리 이후 데이터를 저장하는 코드
- cnn 모델 코드(cnn_code)
cnn_model.ipynb
: CNN 기본 모델 구축 및 학습 코드resnet_model.ipynb
: ResNet 기본 모델 구축 및 학습 코드
- mtl 모델 코드(mtl_code)
basic_mtl_model.py(ipynb)
: MTL 기본 모델 구축 및 학습 코드weight_mtl_model.py(ipynb)
: 가중치 반영 비율이 적용된 MTL 모델 구축 및 학습 코드
use_model.ipynb
: 저장된 모델 파일을 테스트 하는 코드use_tensorboard.ipynb
: 학습 과정을 기록한 텐서보드 확인 코드- 기본적으로 모델 전체 코드(
resnet_model.ipynb
,basic_mtl_model.ipynb
,basic_mtl_model.py
등)에 학습, 테스트, 시각화 과정이 포함되어 있습니다.