AI Studio精选项目 | 儿童X光胸部肺炎诊断,用飞桨四步搞定
点击左上方蓝字关注我们
还在愁如何入手二分类项目?今天小编给大家介绍一篇AI Studio的精品医疗行业二分类项目,只需4步即可达成,准确度达到95.5%以上。
项目介绍
肺炎是常见病,影像检查在肺炎诊断中不仅要发现病灶,还要鉴别是否为其他疾病,特别是与肺癌鉴别需要做胸部CT检查。在治疗中观察病灶的动态变化,胸片一般是最佳的检查方法。
本项目使用广州市妇女儿童医疗中心提供的儿童肺炎X光片数据集,所有X光片均为1~5岁儿童患者常规临床护理时采集项目使用的是儿童肺炎X光片数据集,其中肺炎的:3632张和正常的:1345张,共计4977张。图片为原始分辨率不规则的JPEG图片,两种图片分别被保存在pneumonia_和normal_文件夹中。在模型训练、评估阶段和验证阶段,按照8:1:1的比例将全部样本数据划分为训练集(3980张)、测试集(498张)和验证集(499张)。
下面对部分图片进行展示:
本项目是基于飞桨框架完成的,使用ResNet50网络作为训练模型,top1准确率达到了0.955,top5准确率达到了1.0。训练完成后对测试集进行预测,并可视化模型效果。通过模型就可以完成辅助CT检查,帮助医生快速对肺炎病例进行筛查。
数据处理
解压数据集并将数据集移动至指定位置,通过代码生成训练集文件夹、测试集文件夹、标签文件以及相应的路径txt文件,创建Dataset并可视化数据。主要代码如下:
# 定义DataSet
class XChestDateset(Dataset):def __init__(self, txt_path, transform=None,mode='train'):# 初始化函数super(XChestDateset, self).__init__()self.mode = modeself.data_list = []self.transform = transformif mode == 'train':self.data_list = np.loadtxt(txt_path, dtype='str')elif mode == 'valid':self.data_list = np.loadtxt(txt_path, dtype='str')elif mode == 'test':self.data_list = np.loadtxt(txt_path, dtype='str')def __getitem__(self, idx):# 读取图片,对图片进行归一化处理,返回图片和 标签img_path = self.data_list[idx][0]img = cv2.imread(img_path)img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)if self.transform:img = self.transform(img)return img, int(self.data_list[idx][1])def __len__(self):# 获取样本总数return self.data_list.shape[0]
可视化以后的数据
网络定义
本项目使用的是ResNet50 网络需要获取网络最后一个卷积层输出的特征图,然后计算它的梯度。所以网络设计的时候需要提供一个方法,用来获取最后一个卷积层的输出。主要代码如下:
# 定义ResNet模型
class ResNet(paddle.nn.Layer):def __init__(self, layers=50, class_dim=2):super(ResNet, self).__init__()self.layers = layerssupported_layers = [50, 101, 152]assert layers in supported_layers, \"supported layers are {} but input layer is {}".format(supported_layers, layers)if layers == 50:#ResNet50包含多个模块,其中第2到第5个模块分别包含3、4、6、3个残差块depth = [3, 4, 6, 3]elif layers == 101:#ResNet101包含多个模块,其中第2到第5个模块分别包含3、4、23、3个残差块depth = [3, 4, 23, 3]elif layers == 152:#ResNet152包含多个模块,其中第2到第5个模块分别包含3、8、36、3个残差块depth = [3, 8, 36, 3] # 残差块中使用到的卷积的输出通道数num_filters = [64, 128, 256, 512]# ResNet的第一个模块,包含1个7x7卷积,后面跟着1个最大池化层self.conv = ConvBNLayer(num_channels=3,num_filters=64,filter_size=7,stride=2,act='relu')self.pool2d_max = nn.MaxPool2D(kernel_size=3,stride=2,padding=1)# ResNet的第二到第五个模块c2、c3、c4、c5self.bottleneck_block_list = []num_channels = 64
………………………………………………………………………………………………def forward(self, inputs):conv = self.conv_layer(inputs)y = self.last_layer(conv)return y
网络的基础结构和参数信息:
moel = ResNet()
paddle.summary(moel, (16, 3, 224, 224))
使用summary 函数打印网络的基础结构和参数信息:
-------------------------------------------------------------------------------Layer (type) Input Shape Output Shape Param #
===============================================================================Conv2D-1 [[16, 3, 224, 224]] [16, 64, 112, 112] 9,408 BatchNorm2D-1 [[16, 64, 112, 112]] [16, 64, 112, 112] 256 ConvBNLayer-1 [[16, 3, 224, 224]] [16, 64, 112, 112] 0 MaxPool2D-1 [[16, 64, 112, 112]] [16, 64, 56, 56] 0 Conv2D-2 [[16, 64, 56, 56]] [16, 64, 56, 56] 4,096 BatchNorm2D-2 [[16, 64, 56, 56]] [16, 64, 56, 56] 256 ConvBNLayer-2 [[16, 64, 56, 56]] [16, 64, 56, 56] 0
…………………………………………………………………………………………………………………………………………………………………………………………………………BatchNorm2D-53 [[16, 2048, 7, 7]] [16, 2048, 7, 7] 8,192 ConvBNLayer-53 [[16, 512, 7, 7]] [16, 2048, 7, 7] 0
BottleneckBlock-16 [[16, 2048, 7, 7]] [16, 2048, 7, 7] 0
AdaptiveAvgPool2D-1 [[16, 2048, 7, 7]] [16, 2048, 1, 1] 0 Flatten-1 [[16, 2048, 1, 1]] [16, 2048] 0 Linear-1 [[16, 2048]] [16, 2] 4,098
===============================================================================
Total params: 23,565,250
Trainable params: 23,459,010
Non-trainable params: 106,240
-------------------------------------------------------------------------------
Input size (MB): 9.19
Forward/backward pass size (MB): 4768.81
Params size (MB): 89.89
Estimated Total Size (MB): 4867.89
-------------------------------------------------------------------------------
{'total_params': 23565250, 'trainable_params': 23459010
网络训练及验证
使用飞桨分布式训练API对网络进行训练,接着对网络进行验证,查看验证集得分,主要代码如下:
BATCH_SIZE = 16
EPOCHS = 30 #训练次数
decay_steps = int(len(trn_dateset)/BATCH_SIZE * EPOCHS)train_loader = DataLoader(trn_dateset, shuffle=True, batch_size=BATCH_SIZE )
valid_loader = DataLoader(val_dateset, shuffle=False, batch_size=BATCH_SIZE)model = paddle.Model(ResNet( class_dim=2))base_lr = 0.0125
lr = paddle.optimizer.lr.PolynomialDecay(base_lr, power=0.9, decay_steps=decay_steps, end_lr=0.0)
# 定义优化器
optimizer = paddle.optimizer.Momentum(learning_rate=lr,momentum=0.9,weight_decay=L2Decay(1e-4),parameters=model.parameters())
# 进行训练前准备
model.prepare(optimizer, CrossEntropyLoss(), Accuracy(topk=(1, 5)))
# 启动训练
model.fit(train_loader,valid_loader,epochs=EPOCHS,batch_size=BATCH_SIZE,eval_freq =5,#多少epoch 进行验证save_freq = 5,#多少epoch 进行模型保存log_freq =30,#多少steps 打印训练信息save_dir='/home/aistudio/checkpoint')#对验证集进行验证,查看验证集得分
model.evaluate(valid_loader, log_freq=30, verbose=2)
训练结果:
此处获得的效果比较好准确率在95.5%以上。
{'loss': [0.8956491], 'acc_top1': 0.9559118236472945, 'acc_top5': 1.0}
模型预测及
可视化模型效果
使用测试集进行预测,然后对准确率等指标进行处理获得混淆矩阵和ROC曲线等,通过绘制类激活图获得可视化模型效果图。我们从混淆矩阵中得知,通过ResNet50算法对3980张儿童X光胸片,其中肺炎有2905例,正常有1075例进行训练。在测试集上进行验证,其中肺炎有363例,正常有135例,ResNet50算法的准确率高达96.39%,真阳性率98.07%,真阴性率91.85%,AUC值为0.99。
一般肺炎在胸片上在两侧肺部表现出局部高密度影、肺纹理增粗、边缘模糊等征象,在类激活图中可见模型对肺炎类别的关注区域多在胸片上的两侧肺部,对于正常类别多在心脏或者非肺部区域。可见模型的关注区域符合诊断要求。
混淆矩阵:
confusion = confusion_matrix(true_label, pre_label)#计算混淆矩阵
plt.figure(figsize=(7,7))
sns.heatmap(confusion,cmap='Blues_r',annot=True,fmt='.20g',annot_kws={'size':20,'weight':'bold', })#绘制混淆矩阵
plt.xlabel('Predict')
plt.ylabel('True')
plt.show()
print("混淆矩阵为:\n{}".format(confusion))
print("\n计算各项指标:")
print(classification_report(true_label, pre_label,digits=4))
ROC曲线:
接受者操作特性曲线(ROC曲线)又称为感受性曲线曲线上各点反映着相同的感受性,它们都是对同一信号刺激的反应,只不过是在几种不同的判定标准下所得的结果而已。接受者操作特性曲线就是以FPR(假阳性概率)为横轴,TPR(真阳性概率)为纵所组成的坐标图,和被试在特定刺激条件下由于采用不同的判断标准得出的不同结果画出的曲线。
plt.figure(figsize=(8,8))
kind = {"normal":0,'pneumonia':1}
y_score = np.array(y_score)
fpr , tpr ,threshold = roc_curve(true_label, y_score[:,kind['normal']], pos_label=kind['normal'])
roc_auc = auc(fpr,tpr) ###计算auc的
fpr1 , tpr1 ,threshold = roc_curve(true_label, y_score[:,kind['pneumonia']], pos_label=kind['pneumonia'])
roc_auc1 = auc(fpr1,tpr1) ###计算auc的
plt.plot(fpr, tpr,marker='o', markersize=5,label='Normal')
plt.plot(fpr1, tpr1,marker='*', markersize=5,label='Pneumonia')
plt.title("Normal AUC:{:.4f}, Pneumonia AUC:{:.4f}".format(roc_auc,roc_auc1))
plt.xlabel('FPR')
plt.ylabel('TPR')
plt.legend(loc=4)
plt.show()
可视化模型效果:
将特征图的响应大小,映射到了原图能让读者更直观的了解模型的效果。
# 获取 Grad-CAM 类激活热图
def get_gradcam(model, data, label, class_dim=2):conv = model.conv_layer(data) # 得到模型最后一个卷积层的特征图predict = model.last_layer(conv) # 得到前向计算的结果label = paddle.reshape(label, [-1])predict_one_hot = paddle.nn.functional.one_hot(label, class_dim) * predict # 将模型输出转化为one-hot向量score = paddle.mean(predict_one_hot) # 得到预测结果中概率最高的那个分类的值score.backward() # 反向传播计算梯度grad_map = conv.grad # 得到目标类别的loss对最后一个卷积层输出的特征图的梯度grad = paddle.mean(paddle.to_tensor(grad_map), (2, 3), keepdim=True) # 对特征图的梯度进行GAP(全局平局池化)gradcam = paddle.sum(grad * conv, axis=1) # 将最后一个卷积层输出的特征图乘上从梯度求得权重进行各个通道的加和gradcam = paddle.maximum(gradcam, paddle.to_tensor(0.)) # 进行ReLU操作,小于0的值设为0for j in range(gradcam.shape[0]):gradcam[j] = gradcam[j] / paddle.max(gradcam[j]) # 分别归一化至[0, 1]return gradcam# 将 Grad-CAM 叠加在原图片上显示激活热图的效果
def show_gradcam(model, data, label, class_dim=2, pic_size=224):gradcams = get_gradcam(model, data, label,class_dim=class_dim)for i in range(data.shape[0]):img = (data[i].numpy() *127.5 +127.5).astype('uint8').transpose([1, 2, 0]) # 归一化至[0,255]区间,形状:[h,w,c]heatmap = cv2.resize(gradcams[i].numpy() * 255., (data.shape[2], data.shape[3])).astype('uint8') # 调整热图尺寸与图片一致、归一化heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET) # 将热图转化为“伪彩热图”显示模式superimposed_img = cv2.addWeighted(heatmap, .2, img, .8, 1.) # 将特图叠加到原图片上return superimposed_imgmodel_path = 'checkpoint/final.pdparams'
model = ResNet( class_dim=2)
para_state_dict = paddle.load(model_path)
model.set_dict(para_state_dict)
model.eval()test_txt = 'work/data/test_list.txt'
test_dataset = XChestDateset(test_txt,val_transform, 'test')
test_loader = DataLoader(test_dataset, shuffle=True, batch_size=16 )
dataiter = iter(test_loader)
images, labels = dataiter.next()
总结
本项目是经典的医学相关的二分类项目,使用飞桨框架完成,提供了一些常用的指标和图表例如ROC曲线、类激活图等。希望可以给大家踩平跨进深度学习实践的门槛。
·项目地址·
基于PaddlePaddle搭建儿童X光胸部肺炎分类项目:
https://aistudio.baidu.com/aistudio/projectdetail/2269806
·相关项目·
一文搞懂卷积网络之五:
https://aistudio.baidu.com/aistudio/projectdetail/1655497
AI Studio精品项目征集
AI Studio基于百度深度学习开源平台飞桨,为开发者免费提供功能强大的线上训练环境、云端超强GPU算力及存储资源。“精品项目征集”是AI Studio开展的原创项目扶持活动。贡献精品项目可以获得积分奖励(兑换礼品)、多平台推荐曝光、创作者核心群等多重福利,本季度还有罗技机械键盘、Apple Watch、树莓派等超多附加奖品!快来加入我们吧~
项目作者招募来啦!
扫描下方二维码即可报名
项目作者招募地址:
https://iwenjuan.baidu.com/?code=vtr6pz
项目投稿地址:
https://aistudio.baidu.com/paddle/forum/topic/show/989159
请点击“阅读原文”访问该精品项目。
飞桨(PaddlePaddle)以百度多年的深度学习技术研究和业务应用为基础,集深度学习核心训练和推理框架、基础模型库、端到端开发套件和丰富的工具组件于一体,是中国首个自主研发、功能丰富、开源开放的产业级深度学习平台。飞桨企业版针对企业级需求增强了相应特性,包含零门槛AI开发平台EasyDL和全功能AI开发平台BML。EasyDL主要面向中小企业,提供零门槛、预置丰富网络和模型、便捷高效的开发平台;BML是为大型企业提供的功能全面、可灵活定制和被深度集成的开发平台。
END
AI Studio精选项目 | 儿童X光胸部肺炎诊断,用飞桨四步搞定相关推荐
- 六一大放送: AI Studio精选用户项目推荐榜单
前菜 AI Studio经过一年多的建设,现已累计了数以万计的优质项目和数据集,首先感谢大家伴随我们成长~ 上次给大家推荐了PaddleCV方向精选项目合集,收到了大家的些许表扬,本次呢再接再厉,给大 ...
- 不必上抖音,AI Studio社区项目帮你完成简约风格迁移
点击左上方蓝字关注我们 AI Studio经过两年的建设,现已累计了数以万计的优质项目和数据集,首先感谢大家伴随我们成长~ 上次给大家推荐了用户项目精选项目合集,好评如潮~本次给大家带来近期平台热门优 ...
- AI Studio 精品项目 | 基于Few-shot Learning实现中文科学文献学科分类
点击左上方蓝字关注我们 AI Studio精品项目征集 AI Studio基于百度深度学习开源平台飞桨,为开发者免费提供功能强大的线上训练环境.云端超强GPU算力及存储资源.沉淀了90万+实训项目.5 ...
- AI Studio 精品项目 | PP-OCR的ONNXRunTime部署
点击左上方蓝字关注我们 AI Studio精品项目征集 AI Studio精品项目专栏汇集近300名核心开发者,就学习.实战.比赛.趣味等多个方向贡献实训项目,帮助广大人工智能初学者学习与实践. 贡献 ...
- AI Studio 精品项目 | 趣味项目之那些年的经典游戏
点击左上方蓝字关注我们 AI Studio精品项目征集 AI Studio基于百度深度学习平台飞桨,为开发者免费提供功能强大的线上训练环境.云端超强GPU算力及存储资源.沉淀了90万+实训项目.500 ...
- AI教程!6步搞定YOGA风爱心形状
Adobe illustrator,常被称为"AI",借助这款行业标准的矢量图形软件,您可以制作适用于印刷.Web.视频和移动设备的徽标.图标.绘图.版式和插图的矢量图设计软件.作 ...
- AI Studio 精品项目 | NLP实战合集
点击左上方蓝字关注我们 积小流成江海,在各位开发者的支持下,AI Studio积累了一批涵盖各个技术方向与行业场景的精品实训项目,成为无数小白同学进步的指明灯. NLP精品项目合集 随着基于深度学习的 ...
- 【机器学习】百度飞桨AI Studio平台项目:基于卷积神经网络分类方法的人脸颜值打分
基于卷积神经网络分类方法的人脸颜值打分 说在前面 实验数据 解决过程 1.Precondition 2.Dataset Preparation 3.Network Configuration 4.Mo ...
- 『NLP经典项目集』05:新年到,飞桨带你对对联
基于seq2seq的对联生成 对联,是汉族传统文化之一,是写在纸.布上或刻在竹子.木头.柱子上的对偶语句.对联对仗工整,平仄协调,是一字一音的汉语独特的艺术形式,是中国传统文化瑰宝.这里,我们将根据上 ...
最新文章
- PTA数据结构与算法题目集(中文)7-39
- 【工作感悟】mysql授权root远程访问
- Affinity Photo中文版
- 医生c语言测试卷b卷的答案,合肥工业大学C语言期中测试题_B卷
- vue项目中简单进行axios封装及响应状态码提示!
- 雪球:如果让你选择一本影响你一生的好书,你会选择哪一本
- Linux下的JDK1.5安装
- 2022 年 3 个推荐 AI 聊天机器人平台 「免费和付费」
- 向量积的二维物理意义,二维向量叉乘几何意义
- 计算机电缆对绞外径怎样算,电线电缆外径计算方法
- 帝国cms php替换,帝国cms怎么替换网址域名
- oracle把一列拆成多列,Oracle将一列分成多列
- [Tips]Ubuntu20.04域名解析失败或网速很慢
- SIP穿越NAT SIP穿越防火墙
- 读《禅与摩托车维修艺术》
- 数据可视化实验:python数据可视化-柱状图,条形图,直方图,饼图,棒图,散点图,气泡图,雷达图,箱线图,折线图
- 墨奇科技博客 | 计算机视觉在前端应用中的实践Ⅰ
- 给Java小白,整理一套能上手的简单编程算法题【含答案】!!!
- cocos2dx-js 初探 整体流程helloworld.html分析
- 瞧瞧你的指甲,看你身体还好不!