Chest X-Ray Medical Diagnosis with Deep Learning - ⑤ Prediction and Evaluation 

start

BioinformaticsAndMe

 

 


Chest X-Ray Medical Diagnosis with Deep Learning

     ① Import Packages and Function
     ② Load the Datasets
     ③ Model Development
     ④ Training
    ⑤ Prediction and Evaluation 

 

 

 

 

⑤ Prediction and Evaluation


: 테스트셋을 사용하여 모델을 평가

predicted_vals = model.predict(test_generator, steps = len(test_generator))

 

 

 

5.1 ROC Curve and AUROC


: ROC(Receiver Operating Characteristic) 곡선에서 AUC(Area Under the Curve)를 계산

: 곡선이 좌상단에 있을수록, 더 많은 면적이 갖고, 모델이 더 잘 수행되고 있음을 의미함

: util.py에서 제공하는 util.get_roc_curve 함수를 사용

auc_rocs = util.get_roc_curve(labels, predicted_vals, test_generator)

 

 

 

5.2 Visualizing Learning with GradCAM


: GradCAM 기술을 사용하여 병리학적 상태를 예측하기 위해, 이미지의 중요한 영역을 강조하는 히트맵을 생성

: 먼저 작은 Training 셋을 로드하고, 앞서 AUC 측정값이 가장 높은 4개의 클래스를 살펴볼 것

df = pd.read_csv("drive/MyDrive/nih/train-small.csv")
IMAGE_DIR = "drive/MyDrive/nih/images-small/"

# only show the lables with top 4 AUC
labels_to_show = np.take(labels, np.argsort(auc_rocs)[::-1])[:4]

: 몇 가지 특정 이미지들을 확인

util.compute_gradcam(model, '00008270_015.png', IMAGE_DIR, df, labels, labels_to_show)
# Expected output
Loading original image
Generating gradcam for class Cardiomegaly
Generating gradcam for class Mass
Generating gradcam for class Pneumothorax
Generating gradcam for class Edema

util.compute_gradcam(model, '00011355_002.png', IMAGE_DIR, df, labels, labels_to_show)

util.compute_gradcam(model, '00029855_001.png', IMAGE_DIR, df, labels, labels_to_show)

: P 값은 정답 클래스의 softmax probability를 의미함

 

 

 

 

#Reference

1) www.coursera.org/learn/ai-for-medical-diagnosis

2) github.com/vishrutskaushik/Chest-X-Ray-Medical-Diagnosis

 

 

 

 

Chest X-Ray Medical Diagnosis with Deep Learning - ⑤ Prediction and Evaluation

end

BioinformaticsAndMe

 

 

 

Chest X-Ray Medical Diagnosis with Deep Learning - ④ Training

start

BioinformaticsAndMe

 

 


Chest X-Ray Medical Diagnosis with Deep Learning

     ① Import Packages and Function
     ② Load the Datasets
     ③ Model Development
     ④ Training
    ⑤ Prediction and Evaluation 

 

 

 

 

④ Training


: Keras의 model.fit 함수를 사용하여 모델을 훈련

: 현재, 데이터셋의 작은 부분 집합(~1%)에 대해 Training 하고 있음

: 전체 데이터셋의 Training에는 상당한 시간이 소요되므로 여기에서 모델을 교육하지 않음

: 다음 섹션에서 사전 교육된 모델을 로드할 예정

: 그러나 아래 코드를 사용하여 Colab에서 로컬로 모델 학습을 연습 할 수 있음

history = model.fit_generator(train_generator, 
                              validation_data=valid_generator,
                              steps_per_epoch=100, 
                              validation_steps=25, 
                              epochs = 3)
 
plt.plot(history.history['loss'])
plt.ylabel("loss")
plt.xlabel("epoch")
plt.title("Training Loss Curve")
plt.show()

: 사전 훈련된 가중치를 모델에 로드

model.load_weights("drive/MyDrive/nih/pretrained_model.h5")

 

 

 

다음 분석

Chest X-Ray Medical Diagnosis with Deep Learning

    ⑤ Prediction and Evaluation

 

 

 

#Reference

1) www.coursera.org/learn/ai-for-medical-diagnosis

2) github.com/vishrutskaushik/Chest-X-Ray-Medical-Diagnosis

 

 

 

Chest X-Ray Medical Diagnosis with Deep Learning - ④ Training

end

BioinformaticsAndMe

 

 

 

Chest X-Ray Medical Diagnosis with Deep Learning - ③ Model Development

start

BioinformaticsAndMe

 

 


Chest X-Ray Medical Diagnosis with Deep Learning

     ① Import Packages and Function
     ② Load the Datasets
     ③ Model Development
     ④ Training
    ⑤ Prediction and Evaluation 

 

 

 

 

③ Model Development


: 이제 Model 교육 및 개발을 수행

: 하지만 실제로 신경망을 훈련하기 전에, class 불균형을 해소해야 함

plt.xticks(rotation=90)
plt.bar(x=labels, height=np.mean(train_generator.labels, axis=0))
plt.title("Frequency of Each Class")
plt.show()

: 위 그림에서 여러 병리에 따라 양성 사례의 유병률이 크게 다르다는 것을 알 수 있음

  →이러한 경향은 전체 데이터셋의 경향도 반영함

: 이상적으로는 균형 잡힌 데이터셋으로 모델을 훈련시켜, positive 및 negative 사례가 손실에 동등하게 기여하도록 함

 

 

 

Exercise 2 - Computing Class Frequencies


: 아래 함수를 통해, 각 데이터셋의 라벨에 대한 빈도를 계산

def compute_class_freqs(labels):
    """
    Compute positive and negative frequences for each class.

    Args:
        labels (np.array): matrix of labels, size (num_examples, num_classes)
    Returns:
        positive_frequencies (np.array): array of positive frequences for each
                                         class, size (num_classes)
        negative_frequencies (np.array): array of negative frequences for each
                                         class, size (num_classes)
    """    
    
    # total number of patients (rows)
    N = labels.shape[0]
    
    positive_frequencies = np.sum(labels, axis=0) / labels.shape[0]
    negative_frequencies = 1 - positive_frequencies

    return positive_frequencies, negative_frequencies

: 예제 테스트

labels_matrix = np.array(
    [[1, 0, 0],
     [0, 1, 1],
     [1, 0, 1],
     [1, 1, 1],
     [1, 0, 1]]
)
print("labels:")
print(labels_matrix)

test_pos_freqs, test_neg_freqs = compute_class_freqs(labels_matrix)

print(f"pos freqs: {test_pos_freqs}")

print(f"neg freqs: {test_neg_freqs}")

: 결과 출력

# Expected output
labels:
[[1 0 0]
 [0 1 1]
 [1 0 1]
 [1 1 1]
 [1 0 1]]
pos freqs: [0.8 0.4 0.8]
neg freqs: [0.2 0.6 0.2]

: 이제 training 데이터셋에 대한 빈도를 계산

freq_pos, freq_neg = compute_class_freqs(train_generator.labels)
freq_pos

# Expected output
array([0.02 , 0.013, 0.128, 0.002, 0.175, 0.045, 0.054, 0.106, 0.038,
       0.021, 0.01 , 0.014, 0.016, 0.033])

: 각 병리에 대하여, positive 또는 negative의 기여 비율을 나란히 시각화

data = pd.DataFrame({"Class": labels, "Label": "Positive", "Value": freq_pos})
data = data.append([{"Class": labels[l], "Label": "Negative", "Value": v} for l,v in enumerate(freq_neg)], ignore_index=True)
plt.xticks(rotation=90)
f = sns.barplot(x="Class", y="Value", hue="Label" ,data=data)

: 위 그림에서 보듯이, 양성 사례의 기여도는 음성 사례의 기여도보다 현저히 낮음

: 기여도가 동일하도록 수행하는 방법은 각 클래스별 가중치인 Wpos 및 Wneg를 곱하여, 전체 기여도가 동일하게함

pos_weights = freq_neg
neg_weights = freq_pos
pos_contribution = freq_pos * pos_weights 
neg_contribution = freq_neg * neg_weights

 

: positive, negative 기여도를 다시 그래프로 확인

data = pd.DataFrame({"Class": labels, "Label": "Positive", "Value": pos_contribution})
data = data.append([{"Class": labels[l], "Label": "Negative", "Value": v} 
                        for l,v in enumerate(neg_contribution)], ignore_index=True)
plt.xticks(rotation=90)
sns.barplot(x="Class", y="Value", hue="Label" ,data=data);

: 위 그림에서처럼 가중치를 적용되어, 각 클래스의 양수/음수 레이블이 손실 함수에 대해 동일한 기여도를 갖게됨

 

 

 

Exercise 3 - Weighted Loss


: 아래 weighted_loss 함수를 작성하여 각 배치의 가중 손실을 계산하는 손실 함수를 반환

: 다중 클래스 손실의 경우 각 개별 클래스의 평균 손실을 합산

def get_weighted_loss(pos_weights, neg_weights, epsilon=1e-7):
    """
    Return weighted loss function given negative weights and positive weights.

    Args:
      pos_weights (np.array): array of positive weights for each class, size (num_classes)
      neg_weights (np.array): array of negative weights for each class, size (num_classes)
    
    Returns:
      weighted_loss (function): weighted loss function
    """
    def weighted_loss(y_true, y_pred):
        """
        Return weighted loss value. 

        Args:
            y_true (Tensor): Tensor of true labels, size is (num_examples, num_classes)
            y_pred (Tensor): Tensor of predicted labels, size is (num_examples, num_classes)
        Returns:
            loss (Tensor): overall scalar loss summed across all classes
        """
        # initialize loss to zero
        loss = 0.0
                
        for i in range(len(pos_weights)):
            # for each class, add average weighted loss for that class 
            loss += -(K.mean( pos_weights[i] * y_true[:,i] * K.log(y_pred[:,i] + epsilon) + \
                                neg_weights[i] * (1 - y_true[:,i]) * K.log(1 - y_pred[:,i] + epsilon), axis = 0))
        return loss
    
       
    return weighted_loss

: 예제 테스트

sess = K.get_session()
with sess.as_default() as sess:
    print("Test example:\n")
    y_true = K.constant(np.array(
        [[1, 1, 1],
         [1, 1, 0],
         [0, 1, 0],
         [1, 0, 1]]
    ))
    print("y_true:\n")
    print(y_true.eval())

    w_p = np.array([0.25, 0.25, 0.5])
    w_n = np.array([0.75, 0.75, 0.5])
    print("\nw_p:\n")
    print(w_p)

    print("\nw_n:\n")
    print(w_n)

    y_pred_1 = K.constant(0.7*np.ones(y_true.shape))
    print("\ny_pred_1:\n")
    print(y_pred_1.eval())

    y_pred_2 = K.constant(0.3*np.ones(y_true.shape))
    print("\ny_pred_2:\n")
    print(y_pred_2.eval())

    # test with a large epsilon in order to catch errors
    L = get_weighted_loss(w_p, w_n, epsilon=1)

    print("\nIf we weighted them correctly, we expect the two losses to be the same.")
    L1 = L(y_true, y_pred_1).eval()
    L2 = L(y_true, y_pred_2).eval()
    print(f"\nL(y_pred_1)= {L1:.4f}, L(y_pred_2)= {L2:.4f}")
    print(f"Difference is L1 - L2 = {L1 - L2:.4f}")
# Expected output
Test example:

y_true:

[[1. 1. 1.]
 [1. 1. 0.]
 [0. 1. 0.]
 [1. 0. 1.]]

w_p:

[0.25 0.25 0.5 ]

w_n:

[0.75 0.75 0.5 ]

y_pred_1:

[[0.7 0.7 0.7]
 [0.7 0.7 0.7]
 [0.7 0.7 0.7]
 [0.7 0.7 0.7]]

y_pred_2:

[[0.3 0.3 0.3]
 [0.3 0.3 0.3]
 [0.3 0.3 0.3]
 [0.3 0.3 0.3]]

If we weighted them correctly, we expect the two losses to be the same.

L(y_pred_1)= -0.4956, L(y_pred_2)= -0.4956
Difference is L1 - L2 = 0.0000

 

 

 

3.3 DenseNet121


: 다음으로 Keras에서 로드한 후, 두 개의 레이어를 추가 할 수 있는 DenseNet121 모델을 사용

  *GlobalAveragePooling2D - DenseNet121에서 마지막 convolution 레이어의 평균을 얻음

  *Dense - 각 클래스에 대한 예측 logit을 얻기 위한 sigmoid 기능이 있는 layer

: compile 함수에서 loss 매개 변수를 지정하여, 모델에 대한 사용자 정의 손실 함수를 설정할 수 있음

# create the base pre-trained model
base_model = DenseNet121(weights='drive/MyDrive/nih/densenet.hdf5', include_top=False)

x = base_model.output

# add a global spatial average pooling layer
x = GlobalAveragePooling2D()(x)

# and a logistic layer
predictions = Dense(len(labels), activation="sigmoid")(x)

model = Model(inputs=base_model.input, outputs=predictions)
model.compile(optimizer='adam', loss=get_weighted_loss(pos_weights, neg_weights))

 

 

 

 

 

다음 분석

Chest X-Ray Medical Diagnosis with Deep Learning

    ④ Training

 

 

 

#Reference

1) www.coursera.org/learn/ai-for-medical-diagnosis

2) github.com/vishrutskaushik/Chest-X-Ray-Medical-Diagnosis

 

 

 

Chest X-Ray Medical Diagnosis with Deep Learning - ③ Model Development

end

BioinformaticsAndMe

 

 

 

Chest X-Ray Medical Diagnosis with Deep Learning - ② Load the Datasets

start

BioinformaticsAndMe

 

 


Chest X-Ray Medical Diagnosis with Deep Learning

     ① Import Packages and Function
     ② Load the Datasets
     ③ Model Development
     ④ Training
    ⑤ Prediction and Evaluation 

 

 

 

 

② Load the Datasets


: 환자 32,717명의 108,948개 frontal-view X-ray 이미지가 포함된 ChestX-ray8 데이터셋을 사용

    데이터셋의 각 이미지에는 14개의 병리학적 상태를 식별하는 여러 텍스트 마이닝 레이블이 포함됨

          *의사는 이 결과를 통해, 8가지 질병을 진단하는데 사용할 수 있음

    이 데이터에 기반하여 14개의 레이블이 지정된 병리 상태에 대한 분류 모델을 개발할 것

          *각 병리에 대해 '양성' 또는 '음성'을 예측

: Link 에서 전체 데이터셋을 다운로드할 수 있음

: 분석 실습은 축소된 아래 3개의 파일을 사용 (github.com/vishrutskaushik/Chest-X-Ray-Medical-Diagnosis)

  • nih/train-small.csv: 875 images from our dataset to be used for training.
  • nih/valid-small.csv: 109 images from our dataset to be used for validation.
  • nih/test.csv: 420 images from our dataset to be used for testing.

: 이 데이터셋은 14개 병리 상태 중에서 아래 5개에 대해, 방사선과의사가 합의하여 주석을 달았음

  • Consolidation
  • Edema
  • Effusion
  • Cardiomegaly
  • Atelectasis

#pandas 라이브러리로 데이터 로딩

#구글드라이브에 'nih' 폴더 업로드 후, 마운트
from google.colab import drive
drive.mount('/content/drive')

#데이터 로딩
train_df = pd.read_csv("drive/MyDrive/nih/train-small.csv")
valid_df = pd.read_csv("drive/MyDrive/nih/valid-small.csv")
test_df = pd.read_csv("drive/MyDrive/nih/test.csv")

#데이터 확인
train_df.head()

labels = ['Cardiomegaly', 
          'Emphysema', 
          'Effusion', 
          'Hernia', 
          'Infiltration', 
          'Mass', 
          'Nodule', 
          'Atelectasis',
          'Pneumothorax',
          'Pleural_Thickening', 
          'Pneumonia', 
          'Fibrosis', 
          'Edema', 
          'Consolidation']

 

 

 

2.1 Preventing Data Leakage


: 데이터셋에 각 환자에 대해 여러 이미지가 포함되어 있음

: 예를 들어, 환자가 병원 방문 중 여러 다른 시간에 X-ray 이미지를 촬영한 경우가 이에 해당

: Train, Validation,, Test 데이터셋 사이에 Leakage가 없도록, 데이터 분할이 수행됨

 

Exercise 1 - Checking Data Leakage
: 아래 셀에서 두 데이터셋 사이에 누출이 있는지 확인하는 함수가 작성됨

def check_for_leakage(df1, df2, patient_col):
    """
    Return True if there any patients are in both df1 and df2.

    Args:
        df1 (dataframe): dataframe describing first dataset
        df2 (dataframe): dataframe describing second dataset
        patient_col (str): string name of column with patient IDs
    
    Returns:
        leakage (bool): True if there is leakage, otherwise False
    """
    
    df1_patients_unique = set(df1[patient_col].unique().tolist())
    df2_patients_unique = set(df2[patient_col].unique().tolist())
    
    patients_in_both_groups = df1_patients_unique.intersection(df2_patients_unique)

    # leakage contains true if there is patient overlap, otherwise false.
    leakage = len(patients_in_both_groups) >= 1 # boolean (true if there is at least 1 patient in both groups)
    
    
    return leakage

: 예제 테스트

print("test case 1")
df1 = pd.DataFrame({'patient_id': [0, 1, 2]})
df2 = pd.DataFrame({'patient_id': [2, 3, 4]})
print("df1")
print(df1)
print("df2")
print(df2)
print(f"leakage output: {check_for_leakage(df1, df2, 'patient_id')}")
print("-------------------------------------")
print("test case 2")
df1 = pd.DataFrame({'patient_id': [0, 1, 2]})
df2 = pd.DataFrame({'patient_id': [3, 4, 5]})
print("df1:")
print(df1)
print("df2:")
print(df2)

print(f"leakage output: {check_for_leakage(df1, df2, 'patient_id')}")

: 결과 출력

# Expected output
test case 1
df1
   patient_id
0           0
1           1
2           2
df2
   patient_id
0           2
1           3
2           4
leakage output: True
-------------------------------------
test case 2
df1:
   patient_id
0           0
1           1
2           2
df2:
   patient_id
0           3
1           4
2           5
leakage output: False

: 다음 셀을 실행하여 train, valid, test 데이터셋에 공통된 환자가 있는지 확인

print("leakage between train and test: {}".format(check_for_leakage(train_df, test_df, 'PatientId')))
print("leakage between valid and test: {}".format(check_for_leakage(valid_df, test_df, 'PatientId')))

# Expected output
leakage between train and test: False
leakage between valid and test: False

: 두 가지 모두에 대해 'False'가 출력되면, training을 위한 데이터셋 준비가 완료

 

 

 

2.2 Preparing Images


: 데이터셋 분할이 준비됐으므로, 이를 사용하도록 모델 설정을 진행할 수 있음

: 이를 위해, Keras의 ImageDataGenerator를 사용하여 데이터프레임에 지정된 이미지에 대한 'generator'를 빌드

: generator로 각 배치의 값을 변환하여 평균이 0, 표준 편차가 1이 되도록 표준화 함

: 또한, 단일채널 X-ray 이미지 (회색조)를 3채널 형식으로 변환

: 이미지 크기를 320x320 픽셀로 설정

def get_train_generator(df, image_dir, x_col, y_cols, shuffle=True, batch_size=8, seed=1, target_w = 320, target_h = 320):
    """
    Return generator for training set, normalizing using batch
    statistics.

    Args:
      train_df (dataframe): dataframe specifying training data.
      image_dir (str): directory where image files are held.
      x_col (str): name of column in df that holds filenames.
      y_cols (list): list of strings that hold y labels for images.
      sample_size (int): size of sample to use for normalization statistics.
      batch_size (int): images per batch to be fed into model during training.
      seed (int): random seed.
      target_w (int): final width of input images.
      target_h (int): final height of input images.
    
    Returns:
        train_generator (DataFrameIterator): iterator over training set
    """        
    print("getting train generator...") 
    # normalize images
    image_generator = ImageDataGenerator(
        samplewise_center=True,
        samplewise_std_normalization= True)
    
    # flow from directory with specified batch size
    # and target image size
    generator = image_generator.flow_from_dataframe(
            dataframe=df,
            directory=image_dir,
            x_col=x_col,
            y_col=y_cols,
            class_mode="raw",
            batch_size=batch_size,
            shuffle=shuffle,
            seed=seed,
            target_size=(target_w,target_h))
    
    return generator

 

Valid 및 Test 셋을 위한 별도의 생성기 구축

: 이제 데이터 validaiton 및 testing을 위한 새로운 생성기를 구축해야함

: Training 데이터와 동일한 generator를 사용할 수 없는 이유

   -Training에서는 배치마다 각 이미지를 정규화하므로 배치 통계를 사용함

   -실제 분석에서는 들어오는 이미지를 한 번에 일괄 처리하지 않음 (한번에 하나의 이미지를 처리)

   -Training 모델에는 test 데이터셋에 대한 정보가 없어야 함

: 우리가 해야 할 일은 training 셋에서 계산된 통계를 사용하여, 들어오는 test 셋을 정규화하는 것

   -아래 함수에서 이를 구현함

   -이상적으로는 전체 training 셋을 사용하여 표본 평균과 표준 편차를 계산하고자 할 것

     *그러나 이것은 매우 크기 때문에 시간이 많이 소요

   -시간을 고려하여 데이터셋의 무작위 샘플을 취하고, 샘플 평균과 샘플 표준 편차를 계산함

def get_test_and_valid_generator(valid_df, test_df, train_df, image_dir, x_col, y_cols, sample_size=100, batch_size=8, seed=1, target_w = 320, target_h = 320):
    """
    Return generator for validation set and test test set using 
    normalization statistics from training set.

    Args:
      valid_df (dataframe): dataframe specifying validation data.
      test_df (dataframe): dataframe specifying test data.
      train_df (dataframe): dataframe specifying training data.
      image_dir (str): directory where image files are held.
      x_col (str): name of column in df that holds filenames.
      y_cols (list): list of strings that hold y labels for images.
      sample_size (int): size of sample to use for normalization statistics.
      batch_size (int): images per batch to be fed into model during training.
      seed (int): random seed.
      target_w (int): final width of input images.
      target_h (int): final height of input images.
    
    Returns:
        test_generator (DataFrameIterator) and valid_generator: iterators over test set and validation set respectively
    """
    print("getting train and valid generators...")
    # get generator to sample dataset
    raw_train_generator = ImageDataGenerator().flow_from_dataframe(
        dataframe=train_df, 
        directory=IMAGE_DIR, 
        x_col="Image", 
        y_col=labels, 
        class_mode="raw", 
        batch_size=sample_size, 
        shuffle=True, 
        target_size=(target_w, target_h))
    
    # get data sample
    batch = raw_train_generator.next()
    data_sample = batch[0]

    # use sample to fit mean and std for test set generator
    image_generator = ImageDataGenerator(
        featurewise_center=True,
        featurewise_std_normalization= True)
    
    # fit generator to sample from training data
    image_generator.fit(data_sample)

    # get test generator
    valid_generator = image_generator.flow_from_dataframe(
            dataframe=valid_df,
            directory=image_dir,
            x_col=x_col,
            y_col=y_cols,
            class_mode="raw",
            batch_size=batch_size,
            shuffle=False,
            seed=seed,
            target_size=(target_w,target_h))

    test_generator = image_generator.flow_from_dataframe(
            dataframe=test_df,
            directory=image_dir,
            x_col=x_col,
            y_col=y_cols,
            class_mode="raw",
            batch_size=batch_size,
            shuffle=False,
            seed=seed,
            target_size=(target_w,target_h))
    return valid_generator, test_generator

: generator 함수가 준비 되었으면 training, validation, testing 데이터셋을 각각 하나씩 생성해봄

IMAGE_DIR = "./drive/MyDrive/nih/images-small/"
train_generator = get_train_generator(train_df, IMAGE_DIR, "Image", labels)
valid_generator, test_generator= get_test_and_valid_generator(valid_df, test_df, train_df, IMAGE_DIR, "Image", labels)
# Expected output
getting train generator...
Found 1000 validated image filenames.
getting train and valid generators...
Found 1000 validated image filenames.
Found 200 validated image filenames.
Found 420 validated image filenames.

: '__get_item __ (index)' 함수를 호출하여, generator가 모델에 제공하는 내용을 살펴봄

x, y = train_generator.__getitem__(0)
plt.imshow(x[0]);

# Expected output
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).

 

 

 

 

다음 분석

Chest X-Ray Medical Diagnosis with Deep Learning

    ③ Model Development

 

 

 

#Reference

1) www.coursera.org/learn/ai-for-medical-diagnosis

2) github.com/vishrutskaushik/Chest-X-Ray-Medical-Diagnosis

 

 

 

Chest X-Ray Medical Diagnosis with Deep Learning - ② Load the Datasets

end

BioinformaticsAndMe

 

 

 

Chest X-Ray Medical Diagnosis with Deep Learning - ① Import Packages and Function

start

BioinformaticsAndMe

 

 

 

Chest X-Ray Medical Diagnosis with Deep Learning

     ① Import Packages and Function
     ② Load the Datasets
     ③ Model Development
     ④ Training
    ⑤ Prediction and Evaluation 

 

 

 

 

Chest X-Ray Medical Diagnosis with Deep Learning 시작


: Keras를 사용하여 흉부 X-ray classifier 딥러닝 모델을 생성하여, 의료 영상 진단에 사용해보는 학습 과정

: 모든 분석 과정은 google colab에서 수행되었음

: 실제 X-ray 데이터 전처리부터 모델 평가까지 아래의 과정을 수행

  • Data preparation
    • Visualizing data
    • Preventing data leakage
  • Model Development
    • Addressing class imbalance
    • Leveraging pre-trained models using transfer learning
  • Evaluation
    • AUC and ROC curves

 

 

 

 

① Import Packages and Function


: numpy, pandas - 데이터 전처리, 가공

: matplotlib.pyplot, seaborn - 결과 플롯팅으로 시각화

: util - 로컬로 정의된 유틸리티 기능 제공

: keras - 딥러닝 모델 구축

util.py
0.00MB

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

from keras.preprocessing.image import ImageDataGenerator
from keras.applications.densenet import DenseNet121
from keras.layers import Dense, GlobalAveragePooling2D
from keras.models import Model
from tensorflow.compat.v1.keras import backend as K

from keras.models import load_model

# 아래 코드를 실행하여 util.py을 업로드
from google.colab import files
src = list(files.upload().values())[0]
open('util.py','wb').write(src)
import util

 

 

 

다음 분석

Chest X-Ray Medical Diagnosis with Deep Learning

    ② Load the Datasets

 

 

 

#Reference

1) www.coursera.org/learn/ai-for-medical-diagnosis

 

 

 

 

Chest X-Ray Medical Diagnosis with Deep Learning - ① Import Packages and Function

end

BioinformaticsAndMe

 

 

 

AUC-ROC 커브 Start

BioinformaticsAndMe







1. AUC - ROC Curve?


: AUC-ROC 곡선은 다양한 임계값에서 모델의 분류 성능에 대한 측정 그래프임

*ROC(Receiver Operating Characteristic) = 모든 임계값에서 분류 모델의 성능을 보여주는 그래프

*AUC(Area Under the Curve) = ROC 곡선 아래 영역

: AUC가 높다는 사실은 클래스를 구별하는 모델의 성능이 훌륭하다는 것을 의미

: 임상에서 AUC-ROC 곡선은 정상인 및 환자 클래스를 구분하는 모델(ex. 특정 유전자군)의 성능 평가로 흔하게 사용됨

: ROC 곡선은 TPR(=민감도)이 y축에 있고, FPR(=1-specificity)이 x축으로 그려짐






2. AUC - ROC Curve 용어 정리


: Confusion Matrix의 분류 모델 성능에 대한 지표 (TP, FP, TN, FN)

: 사용되는 통계량

ㄱ) Sensitivity(민감도) = 실제로 질병이 있을 때, 검사 결과가 양성인 경우 (true positive rate) = a / (a+b)


ㄴ) Specificity(특이도) = 실제로 질병이 없을 때, 검사 결과가 음성인 경우 (false positive rate) = d / (c+d)


ㄷ) Positive likelihood ratio(양성우도비) = 질병이 있을 때 검사 결과가 양성 확률과 질병이 없을 때 검사 결과가 양성 확률 사이의 비율 = True positive rate / False positive rate = Sensitivity / (1-Specificity)


ㄹ) Negative likelihood ratio(음성우도비) = 질병이 있을 때 검사 결과가 음성 확률과 질병이 없을 때 검사 결과가 음성 확률 사이의 비율 = False negative rate / True negative rate = (1-Sensitivity) / Specificity


ㅁ) Positive predictive value(양성예측도) = 검사 결과가 양성일 때, 질병이 실제로 존재할 확률 = a / (a+c)


ㅅ) Negative predictive value(음성예측도) = 검사 결과가 음성일 때, 질병이 실제로 없을 확률 = d  / (b+d)







3. 모델의 성능을 측정하는 방법


: 우수한 분류 모델은 AUC 값이 1에 가깝고, 클래스를 분류하는 성능이 뛰어남을 의미

: 반대로, 불량한 분류 모델은 AUC 값이 0에 가깝고, 클래스를 분류하는 성능이 떨어짐을 의미

*실제로는 AUC의 최소값은 0.5으로, 이 경우에 모델의 클래스 분리 능력이 전혀 없음을 뜻함

: ROC는 확률곡선의 형태로, 아래 그래프에서 적색은 양성클래스(질병o), 녹색은 음성클래스(질병x)로 표현했음


1) AUC = 1

- 두 개의 곡선이 전혀 겹치지 않는 경우 모델은 이상적인 분류 성능을 보임

- 양성 클래스와 음성 클래스를 완벽하게 구별 할 수 있음



2) AUC = 0.7

- 두 분포가 겹치면 'type 1 error' 및 'type 2 error'가 발생

- 설정한 threshold에 따라, 위에 오류값들을 최소화 또는 최대화 할 수 있음

- AUC 값이 0.7이면, 해당 분류 모델이 양성 클래스와 음성 클래스를 구별 할 수 있는 확률은 70%임을 의미



3) AUC = 0.5

- 분류 모델의 성능이 최악인 상황

- AUC가 0.5 정도인 경우, 해당 분류 모델은 양성 클래스와 음성 클래스를 구분할 수 있는 능력이 없음







4. Sensitivity, Specificity, FPR, Threshold 관계


: Sensitivity(민감도)와 Specificity(특이성)은 서로 반비례

*Sensitivity를 높이면 Specificity가 감소, Sensitivity를 낮추면 Specificity가 증가

: FPR(False Positive Rate) = 1 - Specificity

*TPR(True Positive Rate)을 올리면 FPR도 증가함

: Threshold(임계값)을 줄이면, positive rate이 높아져 Sensitivity ↑, Specificity ↓

: Threshold(임계값)을 높이면, negative rate이 높아져 Specificity ↑,  Sensitivity ↓







5. AUC-ROC을 쉽게 설명한 영상 소개










#Reference

1) https://towardsdatascience.com/understanding-auc-roc-curve-68b2303cc9c5

2) https://www.medcalc.org/manual/roc-curves.php

3) https://developers.google.com/machine-learning/crash-course/classification/roc-and-auc

4) https://link.springer.com/article/10.1007/s10115-017-1022-8

5) https://www.youtube.com/watch?v=4jRBRDbJemM





AUC-ROC 커브 End

BioinformaticsAndMe

Support Vector Machine (SVM) Start

BioinformaticsAndMe






1. Support Vector Machine (SVM;서포트 벡터 머신)


: 지도학습 모델인 SVM은 'Non-linear problem'을 'Linear problem'으로 바꾸어, 분류와 회귀 분석에 사용됨

: 주요 목적은 두 클래스 사이의 Margin(마진)을 최대화하는 '최적의 분리경계인 Hyperplane(초평면)'을 찾는 것

*(2차원 → Line), (3차원 → Plane), (3차원초과 → Hyperplane)

: 아래의 경우는 두 클래스인 늑대와 토끼를 분리하기 위해, 최적의 분리 경계를 찾고 있는 상황

: Hyperplane을 지지하는(걸쳐있는) 관측치들을 Support Vector라 부름





2. Kernel function (커널함수)


: SVM은 두 클래스를 선형 분리할 수 있도록, 커널함수를 이용해 데이터를 높은 차원 공간으로 변환시킴

: 아래 그림은 데이터를 3차원 공간으로 변환하여, 간단한 평면으로 두 클래스를 분리함

: 다양한 커널함수가 존재함 (RBF가 일반적으로 널리 사용됨)
ㄱ) linear → u'*v
ㄴ) polynomial → (gamma*u'*v + coef0)^degree
ㄷ) radial basis(RBF)  exp(-gamma*|u-v|^2)
ㄹ) sigmoid  tanh(gamma*u'*v + coef0)




3. SVM 알고리즘 과정


1) 마진을 극대화하는 최적의 Hyperplane을 선택

2) 잘못된 분류에 대한 페널티를 더함으로써 SVM 손실 함수를 조정

3) 선형으로 분리되지 않는 데이터인 경우에, 선형으로 쉽게 분류할 수 있는 고차원 공간으로 데이터를 변환 (Kernel Trick)





4. SVM 장점


: 비선형 분리 데이터를 커널트릭을 사용하여 분류 모델링 가능

: 고차원 공간에서 원활하게 작동함 (예측 변수가 많은 경우)

: 텍스트 분류 및 이미지 분류에 효과적임

: Multicollinearity problem(다중공선성 문제)를 회피함




5. SVM 단점


: 대용량 데이터셋 처리에는 많은 시간이 소요

: 확률 추정치를 직접적으로 반환하지 않음

: 선형 커널은 선형의 분리 가능한 데이터인 경우 로지스틱 회귀분석과 거의 유사함







#서포트 벡터 머신 알고리즘 설명 영상





#Reference

1) https://www.listendata.com/2017/01/support-vector-machine-in-r-tutorial.html

2) https://www.edureka.co/blog/support-vector-machine-in-r/#Support%20Vector%20Machine%20Demo

3) https://www.datacamp.com/community/tutorials/support-vector-machines-r

4) https://rischanlab.github.io/SVM.html

5) https://ko.wikipedia.org/wiki/%EC%84%9C%ED%8F%AC%ED%8A%B8_%EB%B2%A1%ED%84%B0_%EB%A8%B8%EC%8B%A0

6) https://lamfo-unb.github.io/2017/07/13/svm-en/

7) https://www.youtube.com/watch?v=1NxnPkZM9bc





Support Vector Machine (SVM) End

BioinformaticsAndMe

딥러닝 서버 PC 구축 Start

BioinformaticsAndMe






딥러닝 서버 컴퓨터 구축


: 딥러닝 서버 컴퓨터의 구축은 아래 제시된 사양으로 약 3000달러 정도가 소요 (2019년 4월 기준)

▶CPU: AMD Threadripper 1920x 12-core ($356)

▶CPU Cooler: Fractal S24 ($114)

▶Motherboard: MSI X399 Gaming Pro Carbon AC ($305)

▶GPU: EVGA RTX 2080 Ti XC Ultra ($1,187)

▶Memory: Corsair Vengeance LPX DDR4 4x16Gb ($399)

▶Hard-drive: Samsung 1TB Evo SSD M.2 PCIe ($241)

▶Power: EVGA SuperNOVA P2 Platinum 1200W ($249)

▶Case: Lian-Li PC-O11AIR ($114)

: 위 정보는 PCPartPicker 사이트에서 확인 가능 (해당 사이트는 컴퓨터 구성 부품의 상호 호환을 고려하며 최소 가격을 산정)

*참고로 국내는 다나와 사이트에도 조립 pc 견적을 확인할 수 있음

: 위 하드웨어 세팅으로 Tensorflow, Keras, PyTorch 등의 여러 딥러닝 프레임워크를 사용 가능




1. CPU


: CPU는 일반적으로 Intel과 AMD의 두가지 선택지가 있음 (Intel이 AMD보다 두배 비쌈)

: 딥러닝 머신에서는 CPU보다 GPU의 성능이 더 중요함

: AMD의 Ryzen 라인이 높은 가성비로 사용자들로부터 좋은 평을 받고 있음
▶CPU: AMD Threadripper 1920x 12-core ($356)




2. CPU Cooler


: AMD CPU는 발열이 매우 심하므로 액체 냉각기가 필요함

: 2개의 팬을 가진 Fractal S24을 사용

▶CPU Cooler: Fractal S24 ($114)




3. Motherboard


: 메인보드의 주요한 선택지는 바로 칩셋

: AMD Threadripper에는 X399 칩셋을 사용

: MSI X399 Gaming Pro Carbon AC에는 딥러닝에 필요한 모든 것을 갖춤

▶Motherboard: MSI X399 Gaming Pro Carbon AC ($305)




4. GPU


: 딥러닝 시스템의 핵심인 GPU는 Nvidia 제품을 사용하며, 최소 권장 사양은 GTX 1080 Ti

: EVGA RTX 2080 Ti XC Ultra는 듀얼 에어 쿨러를 가졌으며, GPU 과열 방지에 효과적임

▶GPU: EVGA RTX 2080 Ti XC Ultra ($1,187)




5. Memory


: 현재까지 구성에서 최선의 메모리 선택은 DDR4

: 64Gb를 맞추기 위해, 4x16Gb Corsair Vengeance LPX DDR4을 선택

▶Memory: Corsair Vengeance LPX DDR4 4x16Gb ($399)




6. Hard-Drive


: M.2 방식의 SSD는 월등하게 빠른 속도를 지니며, 메인보드의 PCIe 슬롯에 바로 연결됨

▶Hard-drive: Samsung 1TB Evo SSD M.2 PCIe ($241)




7. Power


: PCPartPicker 사이트는 앞서 구성된 시스템에 충분한 전원 공급 장치를 선택하도록 함

: 1개의 GPU는 1,000W여도 충분하지만, 2개의 GPU는 1,200W가 안전함

▶Power: EVGA SuperNOVA P2 Platinum 1200W ($249)




8. Case


: 모든 구성 요소를 넣을 수 있는 충분히 큰 케이스를 선택하는 것이 유리

: 내부의 공기 순환이 잘되고 냉각이 용이한 제품을 선택

▶Case: Lian-Li PC-O11AIR ($114)







#Reference

1) https://towardsdatascience.com/building-your-own-deep-learning-computer-and-saving-money-on-cloud-services-c9797261077d

2) https://pcpartpicker.com/

3) http://shop.danawa.com/shopmain/?logger_kw=TOP_dnwpc_main





딥러닝 서버 PC 구축 End

BioinformaticsAndMe

'Machine Learning' 카테고리의 다른 글

AUC-ROC 커브  (3) 2020.08.04
Support Vector Machine (SVM)  (0) 2020.02.05
유전 알고리즘 (Genetic algorithm)  (1) 2020.01.15
구글 어시스턴트(Google Assistant)  (0) 2020.01.06
가짜얼굴 (This person does not exist)  (0) 2019.12.30

유전 알고리즘 (Genetic algorithm) Start

BioinformaticsAndMe








유전 알고리즘 (Genetic Algorithm)


: 유전 알고리즘(GA)은 존 홀랜드(John Holland)가 다윈 진화론의 적자생존에 기반하여 개발한 최적화 연산 방법(1975)

*진화론에서 언급되는 최종적으로 살아남는 종은 변화에 가장 발빠르게 적응하는 종

*https://bioinformaticsandme.tistory.com/52

: 생물의 진화를 모방한 진화 연산의 대표적인 기법 (탐색 알고리즘의 일종)

1) 문제에 대한 가능한 해(유전자)들을 나열

2) 유전자들을 변화시켜 높은 정확도를 가진 해들을 생성

3) 이런 유전자들의 변형으로 좋은 해를 얻는 것을 진화라 봄

: 실제 진화 연구에서 사용되는 여러 용어들을 사용 중

*세대(Generation), 인구(Population), 변이(Mutation), 교차(Crossover) 등









#Reference

1) https://www.youtube.com/watch?v=Yr_nRnqeDp0&list=PLHyv9ND8t5M2bDh9jjOiIewVf77bglZ2y&index=9

2) https://namu.wiki/w/%EC%9C%A0%EC%A0%84%20%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98

3) https://ko.wikipedia.org/wiki/%EC%9C%A0%EC%A0%84_%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98

4) https://www.youtube.com/watch?v=7ZDvt4to7vU&list=PLHyv9ND8t5M2bDh9jjOiIewVf77bglZ2y&index=10





유전 알고리즘 (Genetic algorithm) End

BioinformaticsAndMe

'Machine Learning' 카테고리의 다른 글

Support Vector Machine (SVM)  (0) 2020.02.05
딥러닝 서버 PC 구축  (0) 2020.01.22
구글 어시스턴트(Google Assistant)  (0) 2020.01.06
가짜얼굴 (This person does not exist)  (0) 2019.12.30
[TensorFlow] 심장질환 예측  (2) 2019.12.19

구글 어시스턴트(Google Assistant) Start

BioinformaticsAndMe







구글 어시스턴트(Google Assistant)


: 구글 어시스턴트는 2016년, 구글에서 개발한 인공지능 양방향 대화 서비스

: 한국어를 지원하며, Android 및 iOS 운영체제와 호환됨

: 'OK Google' 또는 'Hey Google'로 구글 어시스턴트 실행

사람과 매우 흡사한 억양과 목소리 톤을 구사하여, 혼자서 미용실 예약을 해냄 (2018년 구글 I/O 개발자 컨퍼런스)








#Reference

1) https://www.youtube.com/watch?v=wMWdo8cVZ_U

2) https://namu.wiki/w/%EA%B5%AC%EA%B8%80%20%EC%96%B4%EC%8B%9C%EC%8A%A4%ED%84%B4%ED%8A%B8

3) https://www.maketecheasier.com/turn-off-ok-google-assistant-android/

4) https://www.youtube.com/watch?v=_GdvyWH5q2U





구글 어시스턴트(Google Assistant) End

BioinformaticsAndMe

+ Recent posts