nan + nan = 2nan

[인턴] Data Cleansing 및 Undersampling, Modeling 본문

Statistics/Machine Learning

[인턴] Data Cleansing 및 Undersampling, Modeling

2nan 2022. 4. 27. 16:03
728x90

지난번 시설작물, 노지작물, 노지해충 3가지의 데이터셋에 대해 EDA를 진행한 바 있다.

생각보다 시설작물의 경우 데이터 상태가 좋지 않았다.

대부분 회사에 입사하면 Raw data는 AIhub의 데이터보다 훨씬 지저분하고 정제하는데 오래 걸린다고 하는데,

아직은 AIhub의 데이터셋, 혹은 교육 당시 이용했던 kaggle 데이터셋 밖에 이용해 보지 않아서 결측치나 노이즈도 거의 없었고, 오류 데이터가 거의 존재하지 않았다.

아무튼, 서버에 올릴 수 있는 용량이 2TB까지 밖에 안 됐기 때문에 시설작물과 노지작물, 즉 질병 데이터를 우선적으로 정제하고 모델링에 투입하고 해충 데이터는 따로 하는 방향으로 결정되었다.

시설작물 질병 데이터 정제 대상내용

정제 종류

정제 방법

중복 데이터

  • 제거 완료 ( 건)

질병 - 피해 정도 오류 데이터

(Valid data 제거해야 될 지 논의 - 포도의 경우 train data에 없기 때문에 검증 시 신뢰도를 저하시킬 우려는 없는지에 대한 고민)
  • Valid data
    • 토마토 - 고추 마일드 (10건) 제거 요망
      •  
    • 포도 - 정상 데이터 제거 요망
      • 포도(12)_정상(0)_정상(0)': 4304건


  • Train data
  • '가지(1)_참외노균병(16)_정상(0)',
    '가지(1)_포도노균병(20)_정상(0)',
    '가지(1)_딸기잿빛곰팡이병(7)_중기(2)',
    '고추(2)_가지흰가루병(2)_정상(0)',
    '고추(2)_정상(0)_초기(1)',
    '고추(2)_수박탄저병(11)_초기(1)',
    '고추(2)_정상(0)_중기(2)',
    '상추(5)_가지흰가루병(2)_정상(0)',
    '상추(5)_딸기잿빛곰팡이병(7)_초기(1)',
    '수박(6)_단호박흰가루병(6)_중기(2)',
    '애호박(7)_가지흰가루병(2)_정상(0)',
    '애호박(7)_딸기잿빛곰팡이병(7)_정상(0)',
    '오이(8)_딸기흰가루병(8)_정상(0)',
    '쥬키니호박(9)_단호박흰가루병(6)_정상(0)',
    '쥬키니호박(9)_고추마일드모틀바이러스병(3)_정상(0)',
    '쥬키니호박(9)_상추균핵병(9)_정상(0)',
    '쥬키니호박(9)_가지흰가루병(2)_정상(0)',
    '참외(10)_포도노균병(20)_정상(0)',
    '토마토(11)_수박탄저병(11)_정상(0)',
    '토마토(11)_가지잎곰팡이병(1)_초기(1)',
    '토마토(11)_고추마일드모틀바이러스병(3)_초기(1)',
    '토마토(11)_쥬키니호박 오이녹반모자이크바이러스(15)_말기(3)',
    '포도(12)_수박흰가루병(12)_정상(0)
    • 작물과 질병 간 연결이 잘못되었다고 생각하는 데이터 제거 (169건)


  • '쥬키니호박(9)_쥬키니호박 오이녹반모자이크바이러스(15)_중기(2)': 11
    • 해당 데이터의 경우 작물과 질병의 연결은 올바르지만, 쥬키니호박의 경우 대부분 클래스가 그냥 오이녹반모자이크바이러스로 연결되어 있고, 해당 질병에 해당하는 클래스 수가 11개 밖에 없어 Undersampling에 있어 차질을 빚을 것으로 예상되기 때문에 삭제하는 것이 맞다고 판단
    • 질병이 있지만 피해 정도가 정상으로 분류되는 각 데이터들 삭제
  • 쥬키니호박 / 상추균핵, 노균병 제거 후 데이터 개수
    • 180,119개

촬영 부위 클래스

  • 잎 / 열매 이외 나머지 부위 삭제

작물 클래스

  • 딸기, 수박, 참외는 일단 제외

작물-질병 오류

  • 오이 / 쥬키니호박의 질병이 서로 바뀐 듯한 양상
  • 해당 이미지 데이터를 살펴보고, 어노테이션만 변경하면 된다 싶으면 작업 시 해당 어노테이션만 서로 변경해주는 작업 필요

 

이렇게 크게 5가지로 나눌 수 있었다. 

1. 중복 데이터

- 중복 데이터의 경우, 처음 데이터를 살펴보고 시각화를 진행할 때는 몰랐는데, 모델링 과정에서 데이터를 input 할 때 중복 데이터가 어느 정도 있다는 오류 때문에 인지를 하게 되었다. 

해당 문제를 인식한 후에 이미지 데이터를 살펴보았을 때, 증강 데이터에서 주로 문제가 많았다. 예를 들어 양배추 증강 데이터로 분류가 되어있는데 실제 폴더 내 이미지는 고추 증강 이미지와 동일했고, 라벨링도 고추 증강 데이터의 것이었다. 이러한 데이터들은 일괄적으로 삭제를 해주었다.

2. 질병 - 피해 정도 오류 데이터

- 질병으로 분류가 되었는데, 해당 피해 정도가 정상으로 분류되었던 데이터들이 꽤 있었다. 질병이 있는데 피해정도가 나타나지 않은 데이터는 사실상 정상 데이터와 비교했을 때, 무슨 차이점이 있는지 모르겠어서 삭제를 했다.

3. 촬영부위 클래스 삭제

- 대부분의 질병이 잎(80%가량)에서 나타나고, 특정 작물이 아니라면 이외 부위에서 발병되는 질병이 거의 없었기에 데이터셋을 일단 축소하는 목적에서 잎과 열매를 제외한 나머지 데이터에 대해 전부 삭제를 했다.

4. 작물 클래스 삭제

- 우리의 타깃이 주말 농장이고, 작물에 대한 이해도가 부족한 시민들이라는 점에서 재배하기 어려운 작물의 경우 수요가 낮을 것으로 생각했기 때문에 딸기, 수박, 참외 등은 일단 제외했다.

5. 작물 - 질병 오류 데이터

- 오이와 쥬키니 호박의 질병이 서로 바뀌어있는 양상이 나타났다. 보통 오이녹반 모자이크바이러스라고 하는 질병이 두 작물 모두에서 나타나고 있긴한데, 어노테이션을 살펴 보았을 때 오이는 쥬키니호박 오이녹반모자이크바이러스 질병으로만 분류가 되었고, 쥬키니 호박은 오이녹반 모자이크바이러스로 분류가 되었다. 해당 부분은 모델링 이후 App에 나타낼 때 라벨링을 직접 해주면 되는 부분이기 때문에 일단은 인지만 해두었다.

 

노지 작물 데이터의 경우, 시설 작물 데이터보다 건드릴게 별로 없었고 비슷한 양상으로 나타나는 오류, 클래스를 제거했다.

 

노지작물 질병 데이터 제거 대상 내용

정제 종류

정제 방법

중복 데이터

  • 수량 - ()
  • 시설 작물과 겹치는 고추 / 잎 / 정상 데이터의 경우 삭제
  • 고추 / 열매 / 정상의 경우 disease code를 44번으로 변경
    • 과제번호로 시설 작물과 노지 작물의 데이터를 구분하면 되기 때문에 사실상 의미는 없었지만, 어쨌든 분류
    • RUS를 거치면 노지 작물 클래스 최소 데이터(약 1,200건)로 언더 샘플링 될 것으로 예상. 노지 작물과 시설 작물 데이터를 병합하고 모델링

질병 - 피해 정도 오류 데이터

  • 양배추균핵병 - 정상(16건)으로 분류된 데이터 제거

촬영 부위 클래스

  • 잎 / 열매 이외 나머지 부위 삭제

작물 클래스

-

 

1. 중복 데이터

- 해당 제거는 시설 작물의 내용과 비슷하다. 다만, 고추의 경우 잎과 열매 부위 정상 데이터가 함께 존재하는데 노지작물 데이터와 병합할 경우 잎 부위의 정상 데이터는 굳이 없어도 될 것이라는 판단 하에 잎 부위를 삭제하고, 열매 부위는 병합하기 이전에 기존 고추-잎-정상 데이터와 구분을 해주기 위해서 질병 코드를 변경해주었다. 사실, 과제 번호라는 annotation이 존재하기 때문에 해당 작업이 나중에는 굳이 필요하지 않았다는 생각이 들었지만. 이런 부분도 시행착오라고 생각한다.

2. 질병 - 피해 정도 오류 데이터

- 질병이 있는데 피해 정도가 정상으로 분류되어 있는 소량의 데이터를 제거했다.

3. 촬영 부위 클래스 제거

- 잎, 열매 이외 나머지 부위는 제거해주었다.

 

이렇게 개략적으로 모델링을 테스트하기 위한 데이터를 정제했고, 데이터 클래스 불균형 문제를 해결하기 위해 Undersampling을 진행했다.

Oversampling과 Undersampling 2가지를 함께 고민해보았는데, 아무래도 개별 클래스 중 가장 많은 데이터 수가 2만 개가 넘고 이것을 Oversampling을 해주었을 때 서버의 용량 문제 등 고려해줄 부분이 많았다.

데이터의 손실을 감수하고서라도, Undersampling을 진행하는 것이 맞지 않겠냐는 여론이 우세했다. 최소 데이터 수가 1,200개가량 있었기 때문에 너무 적지 않을 것이라는 판단이었다.

이를 위해 Random Undersampling을 사용했다.

다른 Undersampling 기법들도 알아보고 적용해보기 위한 노력을 기울였지만, 파라미터 조정이 문제였는지 제대로 클래스 수가 맞게 나오지 않는다던지, 클래스 수 자체를 줄여버리던지 하는 문제들이 발생했다. 이러한 부분들은 나중에 데이터 불균형 해소 기법들을 따로 정리하면서 피드백해봐야겠다.

각 데이터 셋에 맞는 기법을 사용하는 것이 옳겠다는 생각이 들었고, 가장 간단하면서도 따로 파라미터 조정을 많이 해줄 필요가 없는 RUS(Random UnderSampling) 기법을 사용했다.

 

from imblearn.under_sampling import *

X_sam_rus, y_sam_rus = RandomUnderSampler(random_state=0).fit_resample(X, y)
count_and_plot(y_sam_rus)

 

시설 작물과 노지작물 데이터를 함께 합쳐 Undersampling을 진행한 결과, 대략 10만 건의 데이터로 축소할 수 있었다. 최초 데이터셋의 합이 75만 건 가량 되었다는 것을 생각했을 때 어느 정도 모델링을 위해 정제를 했다고 생각이 든다. 

해당 데이터를 가지고 Yolov5에 적용시키기 위해 노력 중이다. 특히 딥러닝 모델 부분은 아직 거의 경험이 없어서, 사전 훈련된 모델을 어떻게 활용할 지에 대한 지식도 별로 없다. Yolo 이외에도 Efficientdet 등 2~3개의 모델을 적용 후, 가장 성능이 좋은 모델을 쓰고 싶어서 Efficinetdet에 대한 Reference를 찾아보는 중인데 이마저도 쉽지가 않다..  Input 할 데이터의 양식이라든지, 파라미터 설정 부분에 있어서도 너무 신경 써야 할 부분이 많아서 쉽지 않을 것이라는 생각이 든다.

https://medium.com/data-science-at-microsoft/training-efficientdet-on-custom-data-with-pytorch-lightning-using-an-efficientnetv2-backbone-1cdf3bd7921f

 

Training EfficientDet on custom data with PyTorch-Lightning (using an EfficientNetv2 backbone)

A clean and clear starting point for anyone wishing to experiment with EfficientDet using PyTorch-Lightning

medium.com

 

잘 정리된 블로그가 있긴 한데, 해당 커스텀 데이터는 단순히 BoundingBox 정보만 주고 해당 객체를 감지하는 것만 학습시키는 것 같다. 우리는 추가적으로 해당 BoundingBox 내 이미지에 대해 질병, 작물 등 라벨 데이터를 Input 하고 도출해야 하는데 모델링 코드에서 어딜 손봐야 할지 아직 잘 모르겠다..

 

 

모델링 부분도 그렇고, 데이터 정제를 하면서 반복문 등 코딩을 더욱 간결하게 하거나 능숙하게 하는 것이 아직은 쉽지가 않다. List Comprehension이나 lambda 식 보다는 그냥 for 문만 이용해서 해결하는 경우가 많은데 경험을 쌓으면서 성능을 높이고, 간결하게 코딩할 수 있는 실력을 쌓아야 하는 중요성을 실감하고 있다.

Comments