Эта статья была добавлена? Проект искусственного интеллекта Python, От новичка Python до бога ИИ — все необходимые знания находятся вздесь.
- автор:К одноклассник
- код: Все коды выложены в текст, так же можете зайти в мойGitHubскачать
Всем привет, я "К-одноклассник"!
Сегодня я познакомлю вас с применением глубокого обучения в области медицины.Идентификация опухоли головного мозга, Опухоль головного мозга, также известная как внутричерепная опухоль, является основным заболеванием внутричерепных объемных поражений, уступая только лейкемии в злокачественных поражениях, восприимчивых к детям. Статистика показывает, что в моей стране ежегодно появляется от 7000 до 8000 новых детей с опухолями головного мозга, и от 70% до 80% детских опухолей являются злокачественными. Потому что чем моложе возраст пациентов с опухолью головного мозга, тем быстрее скорость возникновения, тем выше степень злокачественности опухоли, поэтому раннее выявление. Лечение стало одним из важных способов снижения вреда от болезни.
На этот раз мыВсего было собрано 253 томограммы головного мозга.Данные, включая 155 изображений сканирования мозга пациентов с опухолями головного мозга и 98 изображений сканирования мозга нормальных людей. Используемый алгоритмMobileNetV2, итоговая точность распознавания90.0%, значение AUC равно0.869.
На этот раз в центре внимания:По сравнению с предыдущими случаями в «Глубоком обучении 100 случаев», на этот раз мы добавимИндекс оценки AUCЧтобы оценить эффект распознавания опухоли головного мозга, AUC (площадь под кривой ROC) представляет собой площадь под кривой ROC, которая является критерием оценки плюсов и минусов модели бинарного прогнозирования.
моя среда:
- Регион: Python3.8
- Компилятор: лаборатория Jupyter
- Среда глубокого обучения: TensorFlow2.4.1
Наша блок-схема кода выглядит так:
1. Настройте графический процессор
import tensorflow as tf
gpus = tf.config.list_physical_devices("GPU")
if gpus:
gpu0 = gpus[0] #如果有多个GPU,仅使用第0个GPU
tf.config.experimental.set_memory_growth(gpu0, True) #设置GPU显存用量按需使用
tf.config.set_visible_devices([gpu0],"GPU")
import matplotlib.pyplot as plt
import os,PIL,pathlib
import numpy as np
import pandas as pd
import warnings
from tensorflow import keras
warnings.filterwarnings("ignore") #忽略警告信息
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
2. Импорт данных
1. Импорт данных
import pathlib
data_dir = "./35-day-brain_tumor_dataset"
data_dir = pathlib.Path(data_dir)
image_count = len(list(data_dir.glob('*/*')))
print("图片总数为:",image_count)
图片总数为: 253
batch_size = 16
img_height = 224
img_width = 224
"""
关于image_dataset_from_directory()的详细介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/117018789
"""
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="training",
seed=12,
image_size=(img_height, img_width),
batch_size=batch_size)
Found 253 files belonging to 2 classes.
Using 203 files for training.
"""
关于image_dataset_from_directory()的详细介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/117018789
"""
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="validation",
seed=12,
image_size=(img_height, img_width),
batch_size=batch_size)
Found 253 files belonging to 2 classes.
Using 50 files for validation.
class_names = train_ds.class_names
print(class_names)
['no', 'yes']
2. Проверьте данные
for image_batch, labels_batch in train_ds:
print(image_batch.shape)
print(labels_batch.shape)
break
(16, 224, 224, 3)
(16,)
3. Настройте набор данных
- перемешать() :Перетасовать данные Подробное введение в эту функцию см.:zhuanlan.zhihu.com/p/42417456
- предварительная выборка() :Предварительная выборка данных и ускорение операции Подробное введение см. в двух моих предыдущих статьях, в которых все объясняется.
- кеш() :Кэшировать наборы данных в памяти для ускорения работы
AUTOTUNE = tf.data.AUTOTUNE
def train_preprocessing(image,label):
return (image/255.0,label)
train_ds = (
train_ds.cache()
.shuffle(1000)
.map(train_preprocessing) # 这里可以设置预处理函数
# .batch(batch_size) # 在image_dataset_from_directory处已经设置了batch_size
.prefetch(buffer_size=AUTOTUNE)
)
val_ds = (
val_ds.cache()
.shuffle(1000)
.map(train_preprocessing) # 这里可以设置预处理函数
# .batch(batch_size) # 在image_dataset_from_directory处已经设置了batch_size
.prefetch(buffer_size=AUTOTUNE)
)
4. Визуализация данных
plt.figure(figsize=(10, 8)) # 图形的宽为10高为5
plt.suptitle("公众号(K同学啊)回复:DL+35,获取数据")
class_names = ["脑肿瘤患者","正常人"]
for images, labels in train_ds.take(1):
for i in range(15):
plt.subplot(4, 5, i + 1)
plt.xticks([])
plt.yticks([])
plt.grid(False)
# 显示图片
plt.imshow(images[i])
# 显示标签
plt.xlabel(class_names[labels[i]-1])
plt.show()
3. Постройте модель
from tensorflow.keras import layers, models, Input
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, Dropout,BatchNormalization,Activation
# 加载预训练模型
base_model = tf.keras.applications.mobilenet_v2.MobileNetV2(weights='imagenet',
include_top=False,
input_shape=(img_width,img_height,3),
pooling='max')
for layer in base_model.layers:
layer.trainable = True
X = base_model.output
"""
注意到原模型(MobileNetV2)会发生过拟合现象,这里加上一个Dropout层
加上后,过拟合现象得到了明显的改善。
大家可以试着通过调整代码,观察一下注释Dropout层与不注释之间的差别
"""
X = Dropout(0.4)(X)
output = Dense(len(class_names), activation='softmax')(X)
model = Model(inputs=base_model.input, outputs=output)
# model.summary()
В-четвертых, компилировать
model.compile(optimizer="adam",
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
5. Обучение модели
from tensorflow.keras.callbacks import ModelCheckpoint, Callback, EarlyStopping, ReduceLROnPlateau, LearningRateScheduler
NO_EPOCHS = 50
PATIENCE = 10
VERBOSE = 1
# 设置动态学习率
annealer = LearningRateScheduler(lambda x: 1e-3 * 0.99 ** (x+NO_EPOCHS))
# 设置早停
earlystopper = EarlyStopping(monitor='val_acc', patience=PATIENCE, verbose=VERBOSE)
#
checkpointer = ModelCheckpoint('best_model.h5',
monitor='val_accuracy',
verbose=VERBOSE
save_best_only=True,
save_weights_only=True)
train_model = model.fit(train_ds,
epochs=NO_EPOCHS,
verbose=1,
validation_data=val_ds,
callbacks=[earlystopper, checkpointer, annealer])
Epoch 1/50
13/13 [==============================] - 7s 145ms/step - loss: 3.1000 - accuracy: 0.6700 - val_loss: 1.7745 - val_accuracy: 0.6400
WARNING:tensorflow:Early stopping conditioned on metric `val_acc` which is not available. Available metrics are: loss,accuracy,val_loss,val_accuracy
Epoch 00001: val_accuracy improved from -inf to 0.64000, saving model to best_model.h5
......
Epoch 49/50
13/13 [==============================] - 1s 60ms/step - loss: 3.0536e-08 - accuracy: 1.0000 - val_loss: 2.6647 - val_accuracy: 0.8800
WARNING:tensorflow:Early stopping conditioned on metric `val_acc` which is not available. Available metrics are: loss,accuracy,val_loss,val_accuracy
Epoch 00049: val_accuracy did not improve from 0.90000
Epoch 50/50
13/13 [==============================] - 1s 60ms/step - loss: 1.4094e-08 - accuracy: 1.0000 - val_loss: 2.6689 - val_accuracy: 0.8800
WARNING:tensorflow:Early stopping conditioned on metric `val_acc` which is not available. Available metrics are: loss,accuracy,val_loss,val_accuracy
Epoch 00050: val_accuracy did not improve from 0.90000
6. Оценка модели
1. Матрица путаницы
from sklearn.metrics import confusion_matrix
import seaborn as sns
import pandas as pd
# 定义一个绘制混淆矩阵图的函数
def plot_cm(labels, predictions):
# 生成混淆矩阵
conf_numpy = confusion_matrix(labels, predictions)
# 将矩阵转化为 DataFrame
conf_df = pd.DataFrame(conf_numpy, index=class_names ,columns=class_names)
plt.figure(figsize=(8,7))
sns.heatmap(conf_df, annot=True, fmt="d", cmap="BuPu")
plt.title('混淆矩阵',fontsize=15)
plt.ylabel('真实值',fontsize=14)
plt.xlabel('预测值',fontsize=14)
val_pre = []
val_label = []
for images, labels in val_ds:#这里可以取部分验证数据(.take(1))生成混淆矩阵
for image, label in zip(images, labels):
# 需要给图片增加一个维度
img_array = tf.expand_dims(image, 0)
# 使用模型预测图片中的人物
prediction = model.predict(img_array)
val_pre.append(class_names[np.argmax(prediction)])
val_label.append(class_names[label])
plot_cm(val_label, val_pre)
2. Оценка различных показателей
from sklearn import metrics
def test_accuracy_report(model):
print(metrics.classification_report(val_label, val_pre, target_names=class_names))
score = model.evaluate(val_ds, verbose=0)
print('Loss function: %s, accuracy:' % score[0], score[1])
test_accuracy_report(model)
precision recall f1-score support
脑肿瘤患者 0.94 0.89 0.92 37
正常人 0.73 0.85 0.79 13
accuracy 0.88 50
macro avg 0.84 0.87 0.85 50
weighted avg 0.89 0.88 0.88 50
Loss function: 2.668877601623535, accuracy: 0.8799999952316284
3. Оценка ППК
Введение в одно предложение: AUC (площадь под кривой ROC) — это площадь под кривой ROC, которая является стандартом для оценки плюсов и минусов двухклассовой модели прогнозирования.
- AUC = 1: идеальный классификатор В большинстве случаев прогнозирования идеального классификатора не существует.
- 0.5 < AUC < 1: Лучше, чем случайное угадывание.
- AUC = 0.5: Модель не имеет прогностической ценности, как и машина угадывает (например, подбрасывает монету).
- AUC < 0.5: хуже, чем случайное угадывание.
По оси абсцисс кривой ROC показана доля ложноположительных результатов.(также называемая ложноположительной ставкой, ложноположительной ставкой),Ордината - истинная положительная скорость(True Class Rate, True Positive Rate), соответственно есть True Negative Rate (True Negative Rate, True Negative Rate) и False Negative Rate (False Negative Rate, False Negative Rate). Эти четыре категории рассчитываются следующим образом:
- Ложноположительный показатель (FPR): соотношение ложноположительных результатов среди всех образцов, которые на самом деле были отрицательными.
- Истинная положительная скорость (TPR): соотношение всех образцов, которые были действительно положительными и которые были правильно признаны положительными.
- Частота ложноотрицательных результатов (FNR): соотношение ложно предсказанных отрицательных результатов среди всех образцов, которые на самом деле были положительными.
- Истинный отрицательный показатель (TNR): соотношение правильно предсказанных негативов среди всех фактических негативов.
val_pre = []
val_label = []
for images, labels in val_ds:#这里可以取部分验证数据(.take(1))生成混淆矩阵
for image, label in zip(images, labels):
# 需要给图片增加一个维度
img_array = tf.expand_dims(image, 0)
# 使用模型预测图片中的人物
prediction = model.predict(img_array)
val_pre.append(np.argmax(prediction))
val_label.append(label)
train_pre = []
train_label = []
for images, labels in train_ds:#这里可以取部分验证数据(.take(1))生成混淆矩阵
for image, label in zip(images, labels):
# 需要给图片增加一个维度
img_array = tf.expand_dims(image, 0)
# 使用模型预测图片中的人物
prediction = model.predict(img_array)
train_pre.append(np.argmax(prediction))
train_label.append(label)
sklearn.metrics.roc_curve()
: используется для рисования кривой ROC
Основные параметры:
-
y_true
: истинная метка образца, по умолчанию {0, 1} или {-1, 1}. Если он должен быть установлен на что-то другое, параметр pos_label должен быть установлен на определенное значение. Например, если метка образца {1, 2}, где 2 означает положительный образец, тогда pos_label=2. -
y_score
: результат прогнозирования для каждой выборки. -
pos_label
: Этикетки положительных образцов.
возвращаемое значение:
-
fpr
: Ложноположительный показатель. -
tpr
: Истинный положительный показатель. thresholds
def plot_roc(name, labels, predictions, **kwargs):
fp, tp, _ = metrics.roc_curve(labels, predictions)
plt.plot(fp, tp, label=name, linewidth=2, **kwargs)
plt.plot([0, 1], [0, 1], color='gray', linestyle='--')
plt.xlabel('False positives rate')
plt.ylabel('True positives rate')
ax = plt.gca()
ax.set_aspect('equal')
plot_roc("Train Baseline", train_label, train_pre, color="green", linestyle=':')
plot_roc("val Baseline", val_label, val_pre, color="red", linestyle='--')
plt.legend(loc='lower right')
auc_score = metrics.roc_auc_score(val_label, val_pre)
print("AUC值为:",auc_score)
AUC值为: 0.869022869022869