欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

基于keras训练的h5模型进行批量预测

程序员文章站 2023-11-26 22:52:52
keras进行图片预测对单张图片进行预测进行批量预测功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入对单张图片进行预测你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器,...

对单张图片进行预测

我的项目是用keras分出4类有形成分图片,分别为CAOT(草酸钙),NSE(上皮细胞),RBC(红细胞),WBC(白细胞),所有图像都是150*150的三通道图片,对单张图像进行预测的原理是将训练好的h5模型用方法load_model加载出来,然后将图片进行一些预处理步骤,最后用model中的predict方法进行预测,代码如下:

from keras.models import load_model
from keras.preprocessing import image
import numpy as np

#加载模型
model = load_model("D:/keras/模型/cell.h5")
model.summary()

#图像预处理
file_path='D:/1_49.bmp'
img = image.load_img(file_path, target_size=(150, 150))
img_tensor = image.img_to_array(img)
img_tensor=np.expand_dims(img_tensor,axis=0)
img_tensor/=255.
print('该图像的尺寸为:',img_tensor.shape)

#模型预测
prediction=model.predict(img_tensor) %返回该图片属于每一类的概率值列表
print('每一类别的概率值:',prediction)
pre_y=np.argmax(prediction)
print("该图片为第%d类"%pre_y)

运行结果:

该图像的尺寸为: (1, 150, 150, 3)
每一类别的概率值: [[8.8744347e-14 1.0000000e+00 2.1419935e-13 1.8285983e-08]]
该图片为第1类

其中,0类代表CAOT,1类代表NSE,2类代表RBC,3类代表WBC

进行批量预测

由于数据集中图片数量较多,所以用一些简单的for循环来进行批量测试,我的项目中需要识别四种有形成分的数量分别为:CAOT(草酸钙)1087张,NSE(上皮细胞)940张,RBC(红细胞)10687张,WBC(白细胞)6747张,一共19461张。代码如下:

1、图像预处理

该函数使用了博客中的函数:利用keras加载训练好的.H5文件,并预测图片.

import matplotlib
matplotlib.use('Agg')
import os
from keras.models import load_model
import numpy as np
import cv2

def get_inputs(src=[]):  #预处理函数
    pre_x = []
    for s in src:
        input = cv2.imread(s)
        input = cv2.resize(input, (150, 150))
        input = cv2.cvtColor(input, cv2.COLOR_BGR2RGB)
        pre_x.append(input)  # input一张图片
    pre_x = np.array(pre_x) / 255.0
    return pre_x

2、测试函数

(1)首先加载模型,设置要预测图片集的路径

model = load_model("D:/keras/模型/cell.h5")  #加载模型h5文件
model.summary()
predict_dir = 'D:/validation222/'
test11 = os.listdir(predict_dir)  #test11是一个列表,以字符串形式包含了四类的标签
images = []   #新建一个列表保存预测图片的地址
#设置计数变量的初始值,仅因为本项目需要而设计:
c_c=0;c_n=0;c_r=0;c_w=0;n_c=0;n_n=0;n_r=0;n_w=0;r_c=0;r_n=0;r_r=0;r_w=0;w_c=0;w_n=0;w_r=0;w_w=0 

(2)定义测试函数:
在测试函数中,第一个for循环借鉴了博客 :keras中对多张输入图片进行预测并返回预测结果.中的一部分

#begin为测试开始处的图片索引值,boost为一次测试多少张图片,LABEL为输入的真实类别

def test(begin,boost,LABEL):
    #计数变量设为全局变量,仅本项目计数需要而设置
    global c_c,c_n,c_r,c_w,n_c,n_n,n_r,n_w,r_c,r_n,r_r,r_w,w_c,w_n,w_r,w_w
    
    boost=int(boost);begin=int(begin);LABEL=int(LABEL)
    for testpath in test11:  #得到每一张图片的路径
        for fn in os.listdir(os.path.join(predict_dir, testpath)):
            if fn.endswith('bmp'):
                fd = os.path.join(predict_dir, testpath, fn)
                images.append(fd)  #fd即为每张图片的路径

    for i in range(boost):  
        pre_x = get_inputs(images[begin:begin+boost]) #images为保存了每张图片路径的列表
        pre_y = model.predict(pre_x)
        pre_y=np.argmax(pre_y[i])  #取预测列表中的最大值作为预测标签
        print(pre_y)
        #以下均为计算每一类别的精准率和召回率而设置:
        if LABEL==0:
            if pre_y ==0:
                c_c +=1
            elif pre_y ==1:
                c_n +=1
            elif pre_y ==2:
                c_r+=1
            elif pre_y ==3:
                c_w+=1
        elif LABEL==1:
            if pre_y ==0:
                n_c +=1
            elif pre_y ==1:
                n_n +=1
            elif pre_y ==2:
                n_r+=1
            elif pre_y ==3:
                n_w+=1
        elif LABEL==2:
            if pre_y ==0:
                r_c +=1
            elif pre_y ==1:
                r_n +=1
            elif pre_y ==2:
                r_r+=1
            elif pre_y ==3:
                r_w+=1
        elif LABEL==3:
            if pre_y ==0:
                w_c +=1
            elif pre_y ==1:
                w_n +=1
            elif pre_y ==2:
                w_r+=1
            elif pre_y ==3:
                w_w+=1

3、主函数

主函数使用定义的test函数进行预测,并用for循环来遍历每一个类别

首先,刚才定义的test函数需要传入三个变量,begin是测试的起始图片索引值,boost是每次测试的图片数量,LABEL是测试图片的真实标签。而在本项目中,boost在本项目中取值均为10,而由于每一类别的图片总数不一定是10的整数倍数,所以需要将每一类别的图像总数对boost进行取余操作,即单独对图像总数的零头数目进行test函数预测。

例如:CAOT这一类别包含了1087张图片,从第0张开始预测,每次预测10张,一共要进行109轮预测才能全部预测完,那么进行到108轮预测时,最后一轮只剩了7张图片,若仍以10张的boost来进行预测,那么将会取出NSE这一类别中的前三张图片来使得最后一轮测试满足10张,所以这样程序会认为这三张图片是CAOT误判为了NSE,导致预测不准。解决: 将CAOT的总数1087张对boost(也就是10)进行取余运算,将余数赋值给变量x,这样便可以让最后一轮的预测采用以x为boost值传入test函数中进行预测,而前面108轮预测仍以10作为boost值进行预测。

代码如下:

if __name__ == '__main__':
    sum_caot=1087;sum_nse=940;sum_rbc=10687;sum_wbc=6747 # 每一类别的图像总数
    
    i=10;s=0;L=int(test11[0])  #设置传入test函数的三个变量初始值,其中test11=['0','1','2','3']
    a=sum_caot%i;b=sum_nse%i;c=sum_rbc%i;d=sum_wbc%i  #每一类别对boost值即变量i进行取余
    
#对CAOT进行测试:
    for w in range(int((sum_caot-a)/i+1)):  #循环的轮数=前面整数倍轮数+最后零头的1if s+i<=sum_caot-a:  #前面整数倍的轮数,对caot来说就是前面的108轮预测
            test(s,i,L)
            s+=i          #将test的起始位置定位到下一轮预测的起始位置      
            print('已测CAOT数目:',s)
        elif s<=sum_caot:   #最后零头的那1轮,对caot来说就是最后那包含7张图片的一轮
            test(s,a,L)
            s+=a
            print('已测CAOT数目:',s)
            
#对NSE进行测试:
    for w in range(int((sum_nse-b)/i+1)):
        if s+i-sum_caot<=sum_nse-b:
            L=int(test11[1])     #此时对NSE进行测试,真实标签变为1
            test(s,i,L)
            s+=i
            print('已测NSE数目:',s-sum_caot)    
        elif s-sum_caot<=sum_nse:
            test(s,b,L)
            s+=b
            print('已测NSE数目:',s-sum_caot)
            
#对RBC进行测试:
    for w in range(int((sum_rbc-c)/i+1)):
        if s+i-sum_caot-sum_nse<=sum_rbc-c:
            L=int(test11[2])
            test(s,i,L)
            s+=i
            print('已测RBC数目:',s-sum_caot-sum_nse)
        elif s-sum_caot-sum_nse<=sum_rbc:
            test(s,c,L)
            s+=c
            print('已测RBC数目:',s-sum_caot-sum_nse)
            
#对WBC进行测试:
    for w in range(int((sum_wbc-d)/i+1)):
        if s+i-sum_caot-sum_nse-sum_rbc<=sum_wbc-d:
            L=int(test11[3])
            test(s,i,L)
            s+=i
            print('已测WBC数目:',s-sum_caot-sum_nse-sum_rbc)
        elif s-sum_caot-sum_nse-sum_rbc<=sum_wbc:
            test(s,d,L)
            s+=d
            print('已测WBC数目:',s-sum_caot-sum_nse-sum_rbc)

然后就是主函数中的统计总数和计算精准率和召回率的部分了。

#最终统计部分,计算精准率和召回率:
    CAOT=c_c+n_c+r_c+w_c
    NSE=c_n+n_n+r_n+w_n
    RBC=c_r+n_r+r_r+w_r
    WBC=c_w+n_w+r_w+w_w

    ALL=CAOT+NSE+RBC+WBC

    print('CAOT预测总数:',CAOT)print('NSE预测总数:',NSE)
    print('RBC预测总数:',RBC)
    print('WBC预测总数:',WBC)
    print('已经检测细胞数:',ALL)
    
#某一类别判为其他类别的总数:
    c_o=c_n+c_r+c_w
    n_o=n_c+n_r+n_w
    r_o=r_c+r_n+r_w
    w_o=w_c+w_n+w_r
#其他类别判为某一类别的总数:
    o_c=n_c+r_c+w_c
    o_n=c_n+r_n+w_n
    o_r=c_r+n_r+w_r
    o_w=c_w+n_w+r_w

    try:
        pre_c=c_c/(c_c+o_c)
        pre_n=n_n/(n_n+o_n)
        pre_r=r_r/(r_r+o_r)
        pre_w=w_w/(w_w+o_w)
        pre_c = str(pre_c*100) + '%'   
        pre_n = str(pre_n*100) + '%'   
        pre_r = str(pre_r*100) + '%'   
        pre_w = str(pre_w*100) + '%'   

        recall_c=c_c/(c_c+c_o)
        recall_n=n_n/(n_n+n_o)
        recall_r=r_r/(r_r+r_o)
        recall_w=w_w/(w_w+w_o)
        recall_c = str(recall_c*100) + '%'   
        recall_n = str(recall_n*100) + '%'   
        recall_r = str(recall_r*100) + '%'   
        recall_w = str(recall_w*100) + '%'   

        print("CAOT精准率:",pre_c)
        print("NSE精准率:",pre_n)
        print("RBC精准率:",pre_r)
        print("WBC精准率:",pre_w)

        print("CAOT召回率:",recall_c)
        print("NSE召回率:",recall_n)
        print("RBC召回率:",recall_r)
        print("WBC召回率:",recall_w)
    except:
        pass

4、 运行结果
预测时:

0
0
0
2
0
2
0
0
0
0
已测CAOT数目: 1080
0
0
2
0
2
0
2
已测CAOT数目: 1087

可以看到,预测CAOT时,最后一轮预测只有7张,而预测CAOT时前面的108轮均有10张

问题

1、我是一个刚开始学习机器学习的小白,很多东西都不太懂,这也是第一次写博客,只是网上查了很久似乎没有我可以使用的批量预测程序,所以就写个博客记录一下,有什么地方不对的欢迎大佬指正!

2、速度问题:
其实我一开始使用的是tensorflow环境进行训练和预测,采用的预测方法是加载一次模型仅预测一张图片,然后将这个过程一直循环,直至数据集中所有图片循环完为止,这样预测速度极慢。

而现在使用keras中的predict方法进行预测,虽然使得预测速度提升了很多,但是也就是20帧左右的状态,速度也不算快,而一轮预测的图片数量设置较大时,也就是test函数中的boost取值较大时,例如boost=60,则预测速度将会变慢很多;且网络结构较复杂时,预测速度也会有所影响,目前还是不知道如何进行改进。

完整代码:

放在了GitHub上:链接: keras-batch-test.

本文地址:https://blog.csdn.net/weixin_44408590/article/details/107050005