医用画像における YoloV3 アーキテクチャの結果の分析

この記事はMediumオリジナル記事のレビューです(一部条件を変更して実験)。





医学におけるニューラル ネットワークの応用分野は急速に発展しています。この分野では、医師の仕事を容易にする課題が解決されています。特に、この領域で要求されるタスクの 1 つは、医用画像内のオブジェクトの検出です (これは、四角形が画像に重ねられている場合であり、オブジェクトが存在すると思われる領域を制限します)。そのような画像の例を以下に示します。





https://github.com/ultralytics/yolov3
https://github.com/ultralytics/yolov3

https://github.com/ultralytics/yolov3





, - . person tie. ( person 0.59, tie - 0.62). (, , , , ..), , , , , . ( , "person 0.59". , person - - 0.59). , - , 0 1.





, , . , , .





, . , 20 . 2019- ( 2,6 ). . - , . .





, , .





, , ( - ) , ( ).





.





YOLOv3. ? , =) .





YOLOv3 , YOLO (You Only Look Once). , CNN (Convolutional Neural Network) ( ). YOLOv3 106- . , YOLOv3 ( 3), . YOLOv3:





https://www.researchgate.net/figure/The-framework-of-YOLOv3-neural-network-for-ship-detection_fig2_335228064
https://www.researchgate.net/figure/The-framework-of-YOLOv3-neural-network-for-ship-detection_fig2_335228064

https://www.researchgate.net/figure/The-framework-of-YOLOv3-neural-network-for-ship-detection_fig2_335228064





YOLO 13 13. ? , bounding box' ( ) , . (, ) confidence value ( ). , , (, ). YOLOv3.





https://medium.com/nerd-for-tech/a-real-time-object-detection-model-using-yolov3-algorithm-for-non-gpu-computers-8941a20b445
https://medium.com/nerd-for-tech/a-real-time-object-detection-model-using-yolov3-algorithm-for-non-gpu-computers-8941a20b445

https://medium.com/nerd-for-tech/a-real-time-object-detection-model-using-yolov3-algorithm-for-non-gpu-computers-8941a20b445





, YOLO , anchor boxes ( ). Medium. ( ) . , anchor boxes ( ) bounding box' COCO k-.





YOLOv3 .





, . ? , . Kaggle, . .





. stage_2_train_images.zip stage_2_test_images.zip. , , . ( ) 26684 . DICOM 1024 1024. .





Class





Target





Patients





Lung Opacity





1





9555





No Lung Opacity / Not Normal





0





11821





Normal





0





8851





DICOM. JPG .





import pydicom as dicom
import os
from tqdm import tqdm
import numpy as np
import cv2
import pandas as pd

 dicom  jpg
def dicom_to_jpg(source_folder,destination_folder,labels):
    images_path = os.listdir(source_folder)
    image_dirs_label = {'image_dir':[],'Target':[]}
    for n, image in tqdm(enumerate(images_path)):
        ds = dicom.dcmread(os.path.join(source_folder, image))
        pixel_array_numpy = ds.pixel_array
        image = image.replace('.dcm', '.jpg')
        cv2.imwrite(os.path.join(destination_folder, image), pixel_array_numpy)
        image_dirs_label['image_dir'].append(os.path.join(destination_folder, image))
        image_dirs_label['Target'].append(train_labels[train_labels.patientId== image.split('.')[0]].Target.values[0])
    print('{} dicom files converted to jpg!'.format(len(images_path)))
    return pd.DataFrame(image_dirs_label)
      
      



3 , : Normal — 0, No Lung Opacity / Not Normal — 0, Lung Opacity — 1. Class, Target Patients, , . .





, (positive Lung Opacity). (negative) 1:4 ( , ).





クラスの不均衡





( , ). (positive) — . Albumentations. .





import albumentations as A
import pandas as pd
import cv2
import os
transformer
transform = A.Compose([
        A.RandomRotate90(),
        A.Flip(),
        A.Transpose(),
        A.OneOf([
            A.IAAAdditiveGaussianNoise(),
            A.GaussNoise(),
        ], p=0.2),
        A.OneOf([
            A.MotionBlur(p=.2),
            A.MedianBlur(blur_limit=3, p=0.1),
            A.Blur(blur_limit=3, p=0.1),
        ], p=0.2),
        A.ShiftScaleRotate(shift_limit=0.0625, scale_limit=0.2, rotate_limit=45, p=0.2),
        A.OneOf([
            A.OpticalDistortion(p=0.3),
            A.GridDistortion(p=.1),
            A.IAAPiecewiseAffine(p=0.3),
        ], p=0.2),
        A.OneOf([
            A.CLAHE(clip_limit=2),
            A.IAASharpen(),
            A.IAAEmboss(),
            A.RandomBrightnessContrast(),        ], p=0.3),
        A.HueSaturationValue(p=0.3),
    ])
      
      



( " ", , )





"". JPG DICOM YOLOv3 (backbone') DarkNet. DarkNet . YOLOv3 ( Darknet) CheXNet. CheXNet 121- , , . CheXNet. 14 , , CheXNet 2- (negative — positive — ). TensorFlow, DenseNet121. .





#  CheXNet   classifier_weights.hdf5,    
https://drive.google.com/file/d/1Bd50DpRWorGMDuEZ3-VHgndpJZwUGTAr/view
from absl import flags
from absl.flags import FLAGS
import numpy as np
import tensorflow as tf
from tensorflow.keras import Model
from tensorflow.keras.applications import DenseNet121
from tensorflow.keras.layers import (
    Add,
    Concatenate,
    Conv2D,
    Input,
    Lambda,
    LeakyReLU,
    MaxPool2D,
    UpSampling2D,
    ZeroPadding2D,
    BatchNormalization,
    Dense
)
def base_model(chexnet_weights=None,size=None):
    dense_net_121 = DenseNet121(input_shape = [size,size,3], include_top = False,pooling = 'avg')
    base_model_output = Dense(units = 14, activation = 'relu')(dense_net_121.output)
    base_model = Model(inputs = dense_net_121.input,outputs = base_model_output)
    output_layer = Dense(1, activation = 'sigmoid')(base_model.layers[-2].output)
    model = Model(inputs = base_model.inputs, outputs = output_layer)
    if chexnet_weights:
        model.load_weights(chexnet_weights)
    final_base_model = Model(inputs = model.inputs, outputs = model.layers[-3].output)
    return final_base_model
def ChexNet(name=None, chexnet_weights='PATH_TO_WEIGTHS/classifier_weights.hdf5',size=None):
    chexnet = base_model(chexnet_weights = chexnet_weights, size = size)
    back_bone = Model(inputs = chexnet.inputs, outputs=(chexnet.get_layer('pool3_conv').output,
                                                           chexnet.get_layer('pool4_conv').output,
                                                           chexnet.output),name=name)
    return back_bone
      
      



:





Model





Total params





Trainable params





Non-trainable params





DarkNet





61576342





61523734





52608





CheXNet





27993206





27892662





100544





, CheXNet 2 , DarkNet. CheXNet.





YOLOv3 CheXNet ( ).





, (1 ) (positive negative), , ( positive). YOLOv3 416 416 13 13 (416 / 32 = 13). 13 13. anchor box' 3, 13 13 3- anchor box'. 13 13 3 = 507 ( ). , 507 . positive ( ) 2 (), 2 507-2=505 . , . , "" .





, ImageDataGenerator . , ( ), .





# true_augmented_labels -  DataFrame,    
   (  ,  ()
datagen=ImageDataGenerator(
        rescale = 1. / 255.,
        validation_split = 0.20)
train_generator = datagen.flow_from_dataframe(
dataframe = true_augmented_labels,
x_col = "image_dir",
y_col = "Target",
subset = "training",
batch_size = 4,
seed = 42,
shuffle = True,
class_mode = "binary",
target_size = (416, 416))
valid_generator = datagen.flow_from_dataframe(
dataframe = true_augmented_labels,
x_col = "image_dir",
y_col = "Target",
subset = "validation",
batch_size = 4,
seed = 42,
shuffle = True,
class_mode = "binary",
target_size = (416, 416))
      
      



( positive, negative), .





#  brucechou1983_CheXNet_Keras_0.3.0_weights.h5  classifier_weights.hdf5
   https://www.kaggle.com/theewok/chexnet-keras-weights/version/1
  https://github.com/junaidnasirkhan/Replacing-YoloV3-Backbone-with-ChexNet-for-Pneumonia-Detection
dense_net_121 = DenseNet121(input_shape = [416,416] + [3], include_top = False, pooling = 'avg')
base_model_output = Dense(units = 14, activation = 'relu')(dense_net_121.output)
base_model = Model(inputs = dense_net_121.input, outputs = base_model_output)
 "" 
base_model.load_weights('brucechou1983_CheXNet_Keras_0.3.0_weights.h5')
   
for layer in base_model.layers[:10]:
    layer.trainable = False
      
output_layer = Dense(1, activation = 'sigmoid')(base_model.layers[-2].output)
model = Model(inputs = base_model.inputs, outputs = output_layer)
model.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy', f1_m]) 
checkpoint = ModelCheckpoint(filepath = 'classifier_weights.hdf5', monitor = 'val_accuracy',  verbose = 0, save_best_only = True, save_weights_only = True, mode = 'auto')
log_dir = "classifier_logs/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard = TensorBoard(log_dir = log_dir, histogram_freq = 1, write_graph = True, write_grads = True)
callback_list = [checkpoint, tensorboard]
 
model.fit(train_generator,
  validation_data = valid_generator,
  epochs = 1, #     3
  steps_per_epoch = len(train_generator),
  callbacks = callback_list)
      
      



positive ( ).





#       rsna_train_pos.tfrecord  rsna_val_pos.tfrecord
     .names (  )
  "opacity"  "no_opacity"
model = train(dataset = 'PATH_TO_TFRECORD/rsna_train_pos.tfrecord',
          val_dataset = 'PATH_TO_TFRECORD/rsna_val_pos.tfrecord',
          backbone = 'chexnet',
          classes = 'PATH_TO_CLASSES/RSNA_VOC.names', 
          size = 416,
          epochs = 30,
          batch_size = 16,          learning_rate = 1e-4,
          num_classes = 1)
      
      



hdf5.





(YOLOv3 CheXNet).





learning_rate = 1e-4, epoch = 20





loss'





learning_rate = 1e-4, epochs = 30





loss'





  • .





  • CheXNet DarkNet , CheXNet, DarkNet.





  • CheXNet 1 , 20 30 , .





  • , epoch, .





. :





  • ( , learning_rate)









  • CheXNet





  • Medium元記事へ





  • 私のGitHubへ








All Articles