この記事はMediumのオリジナル記事のレビューです(一部条件を変更して実験中)。
医学におけるニューラル ネットワークの応用分野は急速に発展しています。この分野では、医師の仕事を容易にする課題が解決されています。特に、この領域で要求されるタスクの 1 つは、医用画像内のオブジェクトの検出です (これは、四角形が画像に重ねられている場合であり、オブジェクトが存在すると思われる領域を制限します)。そのような画像の例を以下に示します。
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 , 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
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
, YOLO , anchor boxes ( ). Medium. ( ) . , anchor boxes ( ) bounding box' COCO k-.
, . ? , . 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