본문 바로가기

카테고리 없음

Brain Tumor Classification (MRI) - Tumor Classification

https://www.kaggle.com/datasets/sartajbhuvaji/brain-tumor-classification-mri?resource=download&select=Testing 

 

Brain Tumor Classification (MRI)

Classify MRI images into four classes

www.kaggle.com

 

https://www.kaggle.com/code/rohandeysarkar/tumor-classification

 

Tumor Classification

Explore and run machine learning code with Kaggle Notebooks | Using data from Brain Tumor Classification (MRI)

www.kaggle.com

 

Brain Tumor Classification (MRI)

Classify MRI images into four classes

 

aim is to predict whether a patient has any kind of tumor or not based on a MRI scan of brain.

 

 

Steps Involved

  • Import all the necessary modules & load the data.
  • Observe the data and determine the number of output classes (4 in this case).
  • Define labels for each of the output class.
  • Read & save the images along with their respective labels.
  • Create Train and Test set.
  • Define the CNN model & set the number of output classes.
  • Train & observe the model, then tune hyperparams accordingly.
  • Predict & save our model.

 

Imports

import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import seaborn as sns
import cv2
from sklearn.model_selection import train_test_split
from tensorflow.keras.applications.mobilenet import MobileNet
from keras.applications.mobilenet_v2 import MobileNetV2
from keras.applications.vgg16 import VGG16
from keras.models import Sequential
from keras.callbacks import EarlyStopping
from keras.layers import Dropout, Dense, BatchNormalization
from tensorflow.keras.utils import to_categorical
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import EarlyStopping, ReduceLROnPlateau
from tqdm import tqdm
from sklearn.utils import shuffle

 

Checking available files/folders

path = "../input/brain-tumor-classification-mri"

 

 

 

Define labels of the output classes

labels = ['glioma_tumor','no_tumor','meningioma_tumor','pituitary_tumor']

class_map = {
    'no_tumor': 0,
    'glioma_tumor' :1,
    'meningioma_tumor' :2, 
    'pituitary_tumor' :3 
}

inverse_class_map = {
    0: 'no_tumor',
    1: 'glioma_tumor',
    2: 'meningioma_tumor',
    3: 'pituitary_tumor'
}

 

 

Set Hyperparameters

h, w = 224, 224
batch_size = 32
epochs = 100

 

 

Reading the image & saving as np.array, along with their respective labels

IMAGE = []
LABELS = []

for label in labels:
    folderPath = os.path.join('C:/input/brain-tumor-classification-mri/Training', label)
    for j in tqdm(os.listdir(folderPath)):
        img = cv2.imread(os.path.join(folderPath, j))
        img = cv2.resize(img,(h,w))
        IMAGE.append(img)
        LABELS.append(class_map[label])
        
for label in labels:
    forlderPath = os.path.join('C:/input/brain-tumor-classification-mri/Testing', label)
    for j in tqdm(os.listdir(folderPath)):
        img = cv2.imread(os.path.join(folderPath,j))
        img = cv2.resize(img,(h,w))
        IMAGE.append(img)
        LABELS.append(class_map[label])
        
        
X = np.array(IMAGE)   
y = np.array(LABELS)

 

Looking at different types of tumor

plt.figure(figsize=(16,12))

path = 'C:/input/brain-tumor-classification-mri/Training/'
fileNames = ['glioma_tumor/gg (10).jpg', 'meningioma_tumor/m (108).jpg', 'no_tumor/image (16).jpg', 'pituitary_tumor/p (12).jpg']

fileLabels = ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor']


for i in range(4):
    ax = plt.subplot(4,4,i+1)
    img = mpimg.imread(path + fileNames[i])
    img = cv2.resize(img, (h,w))
    plt.imshow(img)
    plt.title(fileLabels[i])
    plt.axis("off")

 

 

 

Create Train & Test sets

X, y = shuffle(X,y, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, to_categorical(y), test_size=0.1, random_state=42)

 


 ★ Q. to_categorical 함수를 이용하여 원-핫 인코딩을 하는 이유 ?

 to_categorical(y)

훈련 데이터의 개수가 n이고 클래스의 개수가 k일 때, to_categorical 함수는 입력받은 (n) 크기의 1차원 정수 배열을 (n, k) 크기의 2차원 배열로 변경합니다. 이 배열의 두 번째 차원의 인덱스가 클래스 값을 의미한다.

예를 들어 to_categorical([0, 2])는 [[1, 0, 0], [0, 0, 1]]을 반환한다.

 


 

Define CNN mode

# base_model = MobileNet(
#     input_shape=(h, w, 3), 
#     weights='imagenet',
#     include_top=False, 
#     pooling='avg'
# )


base_model = VGG16(
    input_shape=(h,w,3),weights='imagenet',include_top=False,pooling = 'max')

base_model.summary()

 


★ 전이학습 ★

 

딥러닝 모델 훈련을 위한 전이학습

전이학습은 하나의 작업을 위해 훈련된 모델을 유사 작업 수행 모델의 시작점으로 활용하는 딥러닝 접근법입니다. 일반적으로 신경망은 처음부터 새로 훈련하는 것보다 전이학습을 통해 업데이트하고 재훈련하는 편이 더 빠르고 간편합니다. 이 접근법은 여러 응용 분야 중에서도 특히 객체 검출, 영상 인식, 음성 인식 분야에 흔히 사용됩니다.

전이학습은 다음과 같은 이유로 널리 쓰입니다.

  • 대용량 데이터셋으로 이미 훈련된 널리 쓰이는 모델을 재사용함으로써 더 적은 레이블 지정 데이터를 사용하여 모델을 훈련할 수 있습니다.
  • 훈련 시간과 연산 리소스를 줄일 수 있습니다. 전이학습에서는 사전 훈련된 모델이 이전의 학습을 기반으로 이미 가중치를 학습했으므로 가중치가 처음부터 새로 학습되지 않습니다.
  • GoogLeNet과 ResNet처럼 널리 쓰이는 아키텍처를 포함해 딥러닝 연구 커뮤니티에서 개발되는 모델 아키텍처를 활용할 수 있습니다.

 

전이학습 응용 분야에 가장 적합한 모델

선택할 수 있는 전이학습 모델이 많은 만큼 각각의 장단점과 프로젝트의 전반적 목표를 염두에 두는 것이 중요합니다. 예를 들어 정확도가 비교적 낮은 신경망이라도 새로운 딥러닝 작업에는 완벽하게 잘 맞을 수 있습니다. 바람직한 접근법은 다양한 모델을 시험하여 원하는 응용 분야에 가장 잘 맞는 모델을 찾는 것입니다.

시작하는 데 적합한 단순한 모델. AlexNet, GoogLeNet, VGG-16, VGG-19와 같은 단순한 모델을 사용하면 빠르게 반복하면서 다양한 데이터 전처리 단계와 훈련 옵션을 실험할 수 있습니다. 어떤 설정이 효과적인지 파악한 다음에는 더 정확한 신경망을 시험해 보면서 결과가 개선되는지 확인할 수 있습니다.

가볍고 연산적으로 효율적인 모델. 배포 환경에서 모델 크기가 제한되는 경우에는 SqueezeNet, MobileNet-v2 및 ShuffleNet을 사용하는 것이 좋습니다.

심층 신경망 디자이너를 사용하여 다양한 사전 훈련된 모델이 프로젝트에 맞는지 신속히 평가하고 서로 다른 모델 아키텍처의 장단점을 더 정확히 파악할 수 있습니다.

 

 

https://dodonam.tistory.com/347

https://kr.mathworks.com/discovery/transfer-learning.html


Set the no. of output class of the model

base_model.trainable = False  # layer.trainable =False : 모든 레이어의 가중치 훈련 불가능 설정

output_class = 4

model = Sequential([
    base_model,
    Dropout(rate=0.5),
    Dense(output_class, activation='softmax')
])


model.compile(loss='categorical_crossentropy',optimizer='adam', metrics=['accuracy'])
model.summary()

 

Defining Callbacks

조기종료(early stopping)은 Neural Network가 과적합을 회피하도록 만드는 정칙화(regularization) 기법 중 하나이다[1]. 훈련 데이터와는 별도로 검증 데이터(validation data)를 준비하고, 매 epoch 마다 검증 데이터에 대한 오류(validation loss)를 측정하여 모델의 훈련 종료를 제어한다. 구체적으로, 과적합이 발생하기 전 까지 training loss와 validaion loss 둘다 감소하지만, 과적합이 일어나면 training loss는 감소하는 반면에 validation loss는 증가한다. 그래서 early stopping은 validation loss가 증가하는 시점에서 훈련을 멈추도록 조종한다.

 

TensorFlow 1.12에 포함된 Keras에서, EarlyStopping은 두 개의 파라미터를 입력받는다. monitor는 어떤 값을 기준으로 하여 훈련 종료를 결정할 것인지를 입력받고, patience는 기준되는 값이 연속으로 몇 번 이상 향상되지 않을 때 종료시킬 것인지를 나타낸다. 위 예제로 보면 early stopping은 validation loss를 기준으로 훈련을 제어할 것이다. 이 때 validaion loss가 이전 epoch보다 증가되었다고 하여 바로 중지하지는 않고, 5번 연속으로 validaion loss가 낮아지지 않는 경우에 종료하도록 설정하였다. 즉, patience는 모델이 아직 더 향상될 수 있지만, 우연히 validation loss가 낮게 나와버려서 훈련이 종료되버리는 상황을 피하기 위한 옐로우 카드라고 생각하면 된다.

  • monitor : 어떤 값을 기준으로 하여 훈련 종료를 결정할 것인가
  • patience : 기준이 되는 값이 연속으로 몇 번 이상 향상되지 않을 때 종료

 

earlystop = EarlyStopping(monitor = 'val_loss', patience=5)
# early stopping은 validation loss를 기준으로 훈련을 제어
# 5번 연속으로 validation loss 가 낮아지지 않는 경우에 종료

learning_rate_reduction = ReduceLROnPlateau(monitor='val_acc',
                                           patience=2,
                                           verbose=1,
                                           factor=0.5,
                                           min_lr=0.00001)

callbacks = [earlystop, learning_rate_reduction]

 

Image Augmentation

datagen = ImageDataGenerator(rescale=1./255,shear_range=0.2,zoom_range=0.2,horizontal_flip=True)

 

 

Training our model

history = model.fit(datagen.flow(X_train,y_train,batch_size=batch_size), validation_data=(X_test,y_test),
                   steps_per_epoch = len(X_train) / batch_size , epochs = epochs, callbacks = callbacks)

 

 

Checking model performance

Predicting with our model

 

Checking prediction accuracy with confusion matrix

 

Converting labels to their respective class names