본문 바로가기
ML | DL | Big data/DL

Fastai - X-ray 폐렴 검출 CNN 10분 컷

by 썽하 2020. 9. 2.

FastAi 딥러닝 라이브러리를 이용해 이미지 분류해보기

 

Fastai는 내가 tensorflow 이후 두 번째로 접했었던 딥러닝 라이브러리이다. 직장 동료로부터 이걸 소개받고는 적잖이 충격을 받았었는데, 너~무나도 간편했기 때문이다. 그동안 텐서플로로 삽질하면서 코딩을 했던 내게는 큰 신세계로 다가왔다.

 

Fastai는 PyTorch를 기반으로 한 라이브러리이다. 엄청 간단하고, 여기저기 우수한 튜토리얼 코드들이 많아서 일반인들도 천천히 따라온다면 AI 모델링을 단 몇 시간 안에 할 수 있을 정도로 간편하다. 실제로 코드 몇 줄만으로 모델을 만들 수 있다.

 

신경망의 각 부분에 대해서 학습 속도를 다르게 설정할 수도 있고, 대충 돌려보는 개인 사용자들을 위해서 transfer learning도 간편하게 제공한다.

 

이번 글에서는 Fastai의 사용법을 다뤄보자.

 


설치

Fastai를 설치하는 방법은 크게 두 가지가 있다.

  • conda나 pip를 이용해서 삽질하며 관련 모듈 전부를 설치하기
  • 세줄만에 도커 이미지 설치하기(설치가이드)

커 이미지를 사용할 예정이므로 전자의 설치 방법은 다루지 않는다.

 

데이터셋

데이터셋은 Kaggle에 공개된 제공하는 X-Ray 이미지를 사용한다. 데이터는 캐글 가입 후 아래 링크에서 받을 수 있다.

1GB가 약간 넘기에 크게 부담되는 용량은 아니다.

https://www.kaggle.com/paultimothymooney/chest-xray-pneumonia

 

 

모델링

모델링이라고 표현하긴 했지만 코드 몇 줄이면 끝나는 수준이라 '모델링'이라고 부르기도 민망하다.

 

1. 우선 fastai를 사용하기 위해서는 모듈을 임포트 해야 한다.

import fastai
from fastai.vision import *
defaults.device = torch.device('cuda') # gpu를 사용하는 경우만

import numpy as np
from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report

import warnings
warnings.filterwarnings('ignore')

print(fastai.__version__)

'''
1.0.61
'''

내 경우에는 1.0.61 버전의 fastai를 사용하는데 이 글을 따라 하는 분이라면 이것보다 크거나 같아야 하겠다.

 

2. 이후 데이터를 다운로드하고 압출을 푼 디렉터리 경로를 fastai.visionPath툴킷(클래스)으로 지정해준다.

path = Path('./chest_xray')
path.ls()

'''
[PosixPath('chest_xray/models'),
 PosixPath('chest_xray/chest_xray'),
 PosixPath('chest_xray/test'),
 PosixPath('chest_xray/val'),
 PosixPath('chest_xray/train'),
 PosixPath('chest_xray/__MACOSX')]
'''

다운로드한 데이터가 같고 경로를 잘 지정해주었다면 나와 동일한 형태로 path.ls()의 결과가 나와야 한다.

우리가 사용할 데이터는 'chest_xray/train', 'chest_xray/test'에 있다. val의 경우 4개밖에 없어서 너무 부족하다.

 

3. ImageDataBunch를 이용해 데이터를 생성해준다.

data = ImageDataBunch.from_folder(
    path, 
    train='train', # chest_xray 하위 train set 폴더명
    valid='test',  # chest_xray 하위 test set 폴더명
    ds_tfms=get_transforms(do_flip=False),  # 데이터셋 변형 함수
    size=224,  # 이미지 사이즈
    bs=64,     # 배치사이즈
    num_workers=8 # 워커 개수
)

여기서 get_transfroms 함수는 데이터를 좌우로 반전시키거나 밝기를 조절한다던가 회전시킨다던가 등의 역할을 한다. 나는 옵션을 flip은 비활성화시켰다.

 

4. 데이터를 확인해보자.

# 위 get_transforms() 함수로 변형된 이후의 이미지를 출력
data.show_batch()

# 클래스 명칭과 클래스 개수를 출력
print(data.classes, data.c)

# train과 valid 데이터 개수 확인
print(len(data.train_ds), len(data.valid_ds))

클래스는 NORMAL, PNEUMONIA 두 개가 있고

학습 데이터는 5216개 평가 데이터는 624개가 있는 것을 확인할 수 있다.

 

5. 모델을 생성해준다.

learn = cnn_learner(data, models.resnet34, metrics = [accuracy])

fastai에서는 모델을 learner라고 칭한다. 위와 같이 입력하면 이미 잘 학습된 resnet34 모델을 읽어와서 fc layer만 바꾼 후 사용하게 된다.

* 아직 resnet에 대한 이해가 없다면 지금은 fc layer가 무언지 건너뛰고 나중에 알아보자.

대충 다른 이미지를 분류하는 모델을 잘 갖고 와서 좋은 부분만 쓰겠다 라는 뜻이다.

 

pytorch 공홈에서 resnet 모델을 다운 받아오는 로그가 찍힌다.

 

6. 모델 학습시키기

learn.fit_one_cycle(10)

위와 같이 입력하면 이미 잘 학습된 모델에서 fc layer만 학습하게 된다.(이를 transfer learning이라고 한다.)

만약 모든 layer를 학습시키고 싶다면 학습 이전에 learn.unfreeze()를 입력해주면 된다.

다만 간단히 사용해보는 사용자들에게는 비추한다. 정말 오래 걸린다.

 

학습 결과는 다음과 같다.

overfit이 발생하긴 하지만 이번 글에서 이를 다루진 않는다.

 

7. 모델 저장과 로드는 다음과 같이 할 수 있다.

model_file_name = 'chest-xray-stage-1'
# 모델 저장
learn.save(model_file_name)
# 모델 로드
learn.load(model_file_name)

 

모델 평가하기

1. confusion matrix 그려보기

confusion matrix를 그리면 대략적으로 어떻게 분류가 되었는지 알 수 있다.

interp = ClassificationInterpretation.from_learner(learn)
interp.plot_confusion_matrix(figsize=(12,12), dpi=60)

 

2. most_confused case 출력해보기

이번 예제에서는 의미가 없다. 왜냐하면 틀린 경우가 두 종류 밖이기 때문이다. 

하지만 multi-class classification에서는 다음 함수가 빛을 발한다.

interp.most_confused()

잘못 분류한 case 수가 출력된다.

3. 가장 losses가 큰 이미지 출력해보기

interp.plot_top_losses(k=9)

의학적 지식이 없어서, 왜 잘못 분류된 건지는 잘 모르겠다. 정상인데 폐렴이라고 분류 경우가 9개 출력되었다.

여담) 예전에 코로나 관련 검사로 x-ray를 찍었는데 하얀 줄무늬가 많이 보이면 폐렴일 수 있다나 뭐라나 그러고 보니 이 이미지들이 그런 게 많아 보이기도 한다.

 

4. Testset 예측 결과 확인해보기

y_pred, y_true = learn.get_preds()
print(confusion_matrix(y_true, np.argmax(y_pred, axis=1)))
print(classification_report(y_true, np.argmax(y_pred, axis=1)))

'''
[[180  54]
 [  7 383]]
              precision    recall  f1-score   support

           0       0.96      0.77      0.86       234
           1       0.88      0.98      0.93       390

    accuracy                           0.90       624
   macro avg       0.92      0.88      0.89       624
weighted avg       0.91      0.90      0.90       624
'''

sklearn 라이브러리를 통해서 결과를 확인해 보았다.

 

마치며

길게 늘여 썼더니 엄청 오래 걸리지만  단순히 코드를 작성하고 학습하는 건 10분도 채 안 걸렸다.

확실히 fastai는 간단히 딥러닝을 사용하기에 매우 좋은 라이브러리인 것 같다.

댓글