由于2020年初新冠状病毒的肆虐,深刻威胁着全国人民的健康,并且由于患者较多,给医护人员带来了巨大的考验。本系统致力于使用深度学习的方法,使用计算机视觉分析X光胸片,给医护人员提供治疗建议,减轻医护人员的负担。
深度学习(DL, Deep Learning)是机器学习(ML, Machine Learning)领域中一个新的研究方向,它被引入机器学习使其更接近于最初的目标——人工智能(AI, Artificial Intelligence)。
深度学习是机器学习的一种,而机器学习是实现人工智能的必经路径。深度学习的概念源于人工神经网络的研究,含多个隐藏层的多层感知器就是一种深度学习结构。深度学习通过组合低层特征形成更加抽象的高层表示属性类别或特征,以发现数据的分布式特征表示。研究深度学习的动机在于建立模拟人脑进行分析学习的神经网络,它模仿人脑的机制来解释数据,例如图像,声音和文本等。(来自百度百科)
首先,我们需要取得需要用于训练的数据集,并且将数据集的70%划分为训练集,30%划分为测试集。数据集的获取可以在kaggle官网获取(kaggle)。
我们为了能将数据集中的图片喂入神经网络模型中,我们需要读取数据集并且预处理,在工程目录下面新建文件dataset.py,并写入以下内容。
import torch
from torch.utils.data import Dataset
from torchvision import transforms
from PIL import Image
class MyDataset(Dataset):
def __init__(self, txt_path, transform = None, target_transform = None):
fh = open(txt_path, 'r')
imgs = []
for line in fh:
line = line.rstrip()
words = line.split()
imgs.append((words[0], int(words[1])))
self.imgs = imgs
self.transform = transform
self.target_transform = target_transform
def __getitem__(self, index):
fn, label = self.imgs[index]
img = Image.open(fn).convert('RGB')
if self.transform is not None:
img = self.transform(img)
return img, label
def __len__(self):
return len(self.imgs)
def transform():
'''
处理原始数据
'''
tra = transforms.Compose([
transforms.Resize(size=(200,200)),
transforms.RandomRotation(90),#旋转,增加训练样本数量
transforms.RandomHorizontalFlip(0.5),#水平翻转,增加训练样本数量
transforms.RandomAffine(degrees=5, translate=(0.05, 0.05), scale=(0.95, 1.05), fillcolor=(0, 0, 0)),
transforms.ToTensor(), # 转化为tensor
transforms.Normalize((0.5,0.5,0.5), (0.5,0.5,0.5)) # 归一化
])
return tra
做好预处理数据集后就可以开始训练神经元网络了,在工程目录下新建文件夹train.py,并且导入对应的库
import torch
import torchvision
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
from torch.utils.data import DataLoader
import dataset
import matplotlib.pyplot as plt
然后我们设置一下网络的学习率等参数,学习率建议不要设得太大,在0.1到0.01之间即可,读者可以自己尝试改变EPOCH、BATCH_SIZE、LR等参数,可能会达到不同的学习效果。
EPOCH = 6 #训练的轮数
BATCH_SIZE = 32 #一次喂入神经网络的图片数
LR = 0.01 #学习率
LR_DECAY = 0.7 #学习率衰减率
CUDA = True #是否使用GPU
然后我们创建DataLoader,读取数据集。
transform = dataset.transform()
train_data = dataset.MyDataset('./data/train.txt', transform=transform)
train_loader = DataLoader(
train_data,
batch_size=BATCH_SIZE,
shuffle=True,
num_workers=0
)
在搭建网络的时候,我选择比较简单的Alexnet,这里可以使用pytorch的工具包torchvision来搭建,这样的话比较方便。
def alexnet(num_classes ,pretrained = False, cuda = False):
'''
num_classes: 分类数量\n
pretrained: 是否使用预训练模型\n
cuda: 是否使用GPU
'''
net = torchvision.models.AlexNet()
if pretrained == True:
pre = torch.load('你下载的预训练模型的文件地址')
net.load_state_dict(pre)
for param in net.parameters():
param.requires_grad = False
net.classifier = nn.Sequential(
nn.Dropout(),
nn.Linear(256 * 6 * 6, 4096),
nn.ReLU(inplace=True),
nn.Dropout(),
nn.Linear(4096, 4096),
nn.ReLU(inplace=True),
nn.Linear(4096, num_classes)
)
if cuda == True:
net.cuda()
return net
在这里我们要使用预训练模型和GPU,所以应该把pretrained和cuda都设置为True。由于我们的问题是二分类,所以应该将num_classes设置为2。
下面我们设置一下激活函数和loss_function。
loss_func = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=LR)
exp_lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=7, gamma=LR_DECAY)
最后,我们就可以开始训练了,并且将训练好的网络保存,下面是训练代码:
num = 0
y_loss = []
x_chart = []
print('开始训练!')
# !开始训练
for epoch in range(EPOCH):
print("*"*15,epoch,"*"*15)
# 开始训练
total = 0
accuracy = 0.0
for i, (x, y) in enumerate(train_loader, 0):
if CUDA:
x = x.cuda()
y = y.cuda()
inputs, labels = x, y
inputs, labels = Variable(inputs), Variable(labels)
label_prediction = net(inputs)
_,prediction = torch.max(label_prediction.data,1)
total += labels.size(0)
current_loss = loss_func(label_prediction,labels)
# 反向传播
optimizer.zero_grad()
current_loss.backward()
optimizer.step()
loss = current_loss.item()
accuracy += torch.sum(prediction == labels.data)
num += 1
if total % 5 ==0:
print("epoch:{},total {},train loss:{:.4f},train accuracy:{:.4f}".format(epoch,total,loss,100*accuracy/total))
y_loss.append(loss)
x_chart.append(num)
exp_lr_scheduler.step()
torch.save(net, 'save2.pkl')
print('训练完毕!')
plt.plot(x_chart, y_loss)
plt.show()
我们可以用下面的代码来测试网络的性能:
transform = dataset.transform()
test_data = MyDataset(txt_path='./data/test.txt', transform=transform)
test_loader = DataLoader(
test_data,
batch_size=100,
shuffle=True,
num_workers=0
)
net = torch.load('save2.pkl').cpu()
# print(net)
correct = 0
total =0
for data in test_loader:
img, label = data
outputs = net(Variable(img))
_, predicted = torch.max(outputs.data, 1)
total += label.size(0)
correct += (predicted == label).sum()
print('准确率为', 100*correct/total)
这样,我们的网络就训练好了,接下来就要考虑如何让labview读取并使用神经网络来预测新冠肺炎X光片。
新建一个文件,命名为app.py,将下列代码复制到文件下
import torch
import torchvision
from torch.autograd import Variable
import numpy as np
import cv2
import sys
classes = ('normal', 'pneumonia')
# 转换
to_tensor = torchvision.transforms.ToTensor()
normal = torchvision.transforms.Normalize((0.5,0.5,0.5), (0.5,0.5,0.5))
# 网络结构
net = torch.load('save1.pkl').eval().cpu()
def detect(x):
img = cv2.imdecode(np.fromfile(x, dtype=np.uint8), -1) #使用opencv读取图片
img = cv2.resize(img, (200, 200)) #修改图片大小
img = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB) #由于使用的是RGB图片训练的网络,所以要将灰度图转换为RGB图
img_tensor = to_tensor(img) #将图片转换为tensor格式
img_tensor = normal(img_tensor)
img_tensor = img_tensor.view(1, 3, 200, 200) #改变张量的维度
output = net(Variable(img_tensor)) #喂入网络
_, predicted = torch.max(output.data, 1) #获取预测结果
pred = classes[predicted]
probability = torch.nn.functional.softmax(output, dim=1)
probability = probability.detach().numpy()[0][predicted] #获取预测结果的概率
return pred, probability
if __name__ == '__main__':
a = sys.argv[1]
pred, prob = detect(a)
if pred == 'normal':
print('建议:没有患新型冠状病毒肺炎,置信度:{}'.format(prob))
elif pred == 'pneumonia':
print('建议:患新冠状病毒肺炎,需要接受治疗,置信度:{}'.format(prob))
else:
pass
在这里我们使用sys库中的argv方法,它可以获取在终端中输入的参数,这样的话我们就可以用labview调取终端,将需要预测的图片喂入网络中了。
然后我们来编写labview中的文件,我们首先读取图片文件,在前面板中绘制图片显示控件,使用绘制平滑像素图控件显示图片。然后调用终端,将图片喂入神经网络中,并且获取图片预测的结果,在前面板的文本显示框中显示出来。由于markdown文件不支持labview代码的编写,所以这里插入的是后面板的截图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OeiTn1v0-1591341049745)(D:\编程\labview-workplace\大作业\后面板.JPG)]
患有新冠肺炎的效果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JEINDpOJ-1591341049751)(.\患病.JPG)]
没有患新冠肺炎的效果如下:
写labview中的文件,我们首先读取图片文件,在前面板中绘制图片显示控件,使用绘制平滑像素图控件显示图片。然后调用终端,将图片喂入神经网络中,并且获取图片预测的结果,在前面板的文本显示框中显示出来。由于markdown文件不支持labview代码的编写,所以这里插入的是后面板的截图:
患有新冠肺炎的效果如下:
没有患新冠肺炎的效果如下: