Chuẩn bị dữ liệu

Bài viết sử dụng EfficientNetV2 để phân loại người bị viêm phổi có phải do covid hay không. Dữ liệu được lấy từ cuộc thi trên kaggle

Dữ liệu ảnh là file có định dạng DICOM, trong bài viết này Etrain sẽ sử dụng sẵn dữ liệu đã được chuyển thành JPG được tải về tại notebook này

Trong phần Input tải về train_image_level.csvtrain_study_level.csv. Phần output thì tải về meta.csvtrain.tar.gz. Ở đây etrain sẽ để toàn dữ liệu trên drive và sẽ có cấu trúc như sau

siim-covid
|-- train_image_level.csv
|-- train_study_level.csv
|-- train.tar.gz
|-- meta.csv

Giải nén thư mục train.tar.gz

!tar xzf file.tar.gz

Tạo dữ liệu huấn luyện cho model từ các dataframe

import pandas as pd

train_image_level = pd.read_csv("/content/drive/MyDrive/Etrain/siim-covid/train_image_level.csv")
train_study = pd.read_csv('/content/drive/MyDrive/Etrain/siim-covid/train_study_level.csv')

# merge study csv
train_study['StudyInstanceUID'] = train_study['id'].apply(lambda x: x.replace('_study', ''))
del train_study['id']
train = train_image_level.merge(train_study, on='StudyInstanceUID')

train = train.rename(columns={
    'Negative for Pneumonia': 'negative',
    'Typical Appearance': 'typical',
    'Indeterminate Appearance': 'indeterminate',
    'Atypical Appearance': 'atypical'
})

def get_image_name(image_id):
    image_name = image_id.split("_image")[0] + ".jpg"
    return image_name

train["image"] = train["id"].apply(get_image_name)

EfficientNetV2

Bài viết sử dụng mô hình EffNetV2-L và sử dụng pretrain efficientnetv2-l-21k-ft1k

EfficientNetV2

import tensorflow as tf
import tensorflow_hub as hub

print('TF version:', tf.__version__)
print('Hub version:', hub.__version__)
print('Phsical devices:', tf.config.list_physical_devices())

# Build model
hub_url = 'gs://cloud-tpu-checkpoints/efficientnet/v2/hub/efficientnetv2-l-21k-ft1k/feature-vector'
image_size = 480
batch_size = 4
labels = ["negative", "typical", "indeterminate", "atypical"]

tf.keras.backend.clear_session()
model = tf.keras.Sequential([
    # Explicitly define the input shape so the model can be properly
    # loaded by the TFLiteConverter
    tf.keras.layers.InputLayer(input_shape=[image_size, image_size, 3]),
    hub.KerasLayer(hub_url, trainable=True),
    tf.keras.layers.Dropout(rate=0.2),
    tf.keras.layers.Dense(
        len(labels),
        kernel_regularizer=tf.keras.regularizers.l2(0.0001),
        activation='sigmoid'
    )
])
model.build((None, image_size, image_size, 3))
model.summary()

Model Summary

Sử dụng ImageDataGenerator để tạo dữ liệu huấn luyện và xác thực theo tỷ lệ 80% huấn luyện và 20% xác thực. Chúng ta sẽ tăng dữ liệu huấn luyện bằng cách sử dụng 2 phương pháp là lật ảnh theo chiều dọc và chiều ngang.

datagen_kwargs = dict(rescale=1./255, validation_split=.20)
dataflow_kwargs = dict(target_size=(image_size, image_size),
                       batch_size=batch_size)

train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
      horizontal_flip=True,
      vertical_flip=True,
      **datagen_kwargs)

valid_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
    **datagen_kwargs)

image_path = '/content/drive/MyDrive/Etrain/siim-covid/train'

train_generator = train_datagen.flow_from_dataframe(
    train,
    directory=image_path,
    shuffle=True,
    class_mode="raw",
    color_mode="rgb",
    x_col="image",
    y_col=labels,
    subset="training",
    **dataflow_kwargs
)

valid_generator = valid_datagen.flow_from_dataframe(
    train,
    directory=image_path,
    shuffle=False,
    class_mode="raw",
    color_mode="rgb",
    x_col="image",
    y_col=labels,
    subset="validation",
    **dataflow_kwargs
)

Huấn luyện dữ liệu và lưu model với val_loss nhỏ nhất

model_checkpoint = tf.keras.callbacks.ModelCheckpoint(
    filepath="/content/drive/MyDrive/Etrain/siim-covid/efficientnetv2-l-21k-ft1k-study-level.h5", 
    monitor='val_loss',
    save_best_only=True,
    verbose=1,
    mode='min'
)

model.compile(
	optimizer=tf.keras.optimizers.SGD(learning_rate=0.005, momentum=0.9),
	loss=tf.keras.losses.BinaryCrossentropy(from_logits=False, label_smoothing=0.1),
	metrics=['accuracy']
)

hist = model.fit(
    train_generator,
    epochs=num_epochs,
    validation_data=valid_generator,
    callbacks=[model_checkpoint]).history

import matplotlib.pyplot as plt

plt.plot(hist['accuracy'])
plt.plot(hist['val_accuracy'])
plt.title('Model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'valid'], loc='upper left')
plt.show()

Training result

Bạn có thể xem hướng dẫn trong notebook này để xem kết quả dự đoán của model

Tài liệu tham khảo

EfficientNetV2